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
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]
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]
This has been fixed since astroid v2.3.0 by https://github.com/PyCQA/astroid/commit/e0a298df55b15abcb77c2a93253f5ab7be52d0fb
Most helpful comment
Also stumbled into this. A workaround for the specific
contextlib.closingcase, which avoids having to add a bunch of# pylint: disable=no-membercomments: