Pylint: Using contextlib.closing() ”removes” all attributes from argument

Created on 21 Apr 2017  ·  7Comments  ·  Source: PyCQA/pylint

Given this source:

import sqlite3
from contextlib import closing

with closing(sqlite3.connect(':memory:')) as connection:
    cursor = connection.cursor()

Pylint 1.7.1 finds:

$ pylint test.py
No config file found, using default configuration
************* Module test
C:  5, 0: Trailing whitespace (trailing-whitespace)
C:  1, 0: Missing module docstring (missing-docstring)
C:  5, 4: Invalid constant name "cursor" (invalid-name)
E:  5,13: Instance of 'closing' has no 'cursor' member (no-member)

The last error wasn't there with Pylint 1.6.3. It seems the closing() wrapper ”removes” all attributes from its argument although it is just a wrapper that virtually _adds_ the context manager magic methods. This repeats with the cursor object if used with with and closing(), resulting in a block of lines covered in false positives non-existent attributes.

pylint --version output

$ pylint --version
No config file found, using default configuration
pylint 1.7.1, 
astroid 1.5.2
Python 2.7.9 (default, Aug 13 2016, 17:56:53) 
[GCC 4.9.2]
bug

Most helpful comment

Also stumbled into this. A workaround for the specific contextlib.closing case, which avoids having to add a bunch of # pylint: disable=no-member comments:

connection = sqlite3.connect(':memory:')
with closing(connection):
    cursor = connection.cursor()

All 7 comments

Minimal example:

class ContextManager(object):
    def __init__(self, thing):
        self.thing = thing
    def __enter__(self):
        return self.thing
    def __exit__(self, *args):
        return

with ContextManager('hello') as thing:
    print thing.upper()

Result:

$ pylint --disable=C context.py
************* Module context
context.py:10:  E1101  no-member,    Instance of 'ContextManager' has no 'upper' member

------------------------------------------------------------------
Your code has been rated at 4.44/10 (previous run: 4.44/10, +0.00)

If ContextManager has no attributes, pylint generates no errors:

class ContextManager(object):
    def __init__(self, thing):
        pass
    def __enter__(self):
        return 'hello'
    def __exit__(self, *args):
        return

with ContextManager('hello') as thing:
    print thing.upper()

Also stumbled into this. A workaround for the specific contextlib.closing case, which avoids having to add a bunch of # pylint: disable=no-member comments:

connection = sqlite3.connect(':memory:')
with closing(connection):
    cursor = connection.cursor()

This is a duplicate of https://github.com/PyCQA/pylint/issues/1437 I think

I'm sure it is. It's exactly identical, down to the issue ID ;)

Sorry ^^
I meant https://github.com/PyCQA/astroid/issues/347
But this is not really a duplicate, it's just the upstream bug

Thank you very much for the workaround by the way !

Still an issue in:

pylint 2.1.1
astroid 2.0.2
Python 3.6.5 (default, Apr 1 2018, 05:46:30)
[GCC 7.3.0]

Was this page helpful?
0 / 5 - 0 ratings

Related issues

pylint-bot picture pylint-bot  ·  3Comments

jrial picture jrial  ·  3Comments

PCManticore picture PCManticore  ·  3Comments

Hubro picture Hubro  ·  3Comments

PCManticore picture PCManticore  ·  3Comments