Here is the code which hits false positive. Code runs fine, but hits pylint error for obj not being a contextmanager.
def contextmanagerdecorator(cls):
class DecoClass(cls):
def __enter__(self):
pass
def __exit__(self, *n, **kw):
pass
return DecoClass
@contextmanagerdecorator
class RegularClass(object):
pass
obj = RegularClass()
with obj:
pass
This is happening because we don't understand decorators yet. I'm working on bringing this into 2.0, I'll let you know when I have some results. In the mean time, disabling the error should be the way to go.
threading.Lock() is still not recognized as context manager:
import re
import threading
LOCK = threading.Lock()
with LOCK:
PAT = re.compile("foo", re.MULTILINE | re.DOTALL)
Pylint:
/tmp/test.py|5 col 1 error| [not-context-manager] Context manager 'lock' doesn't implement __enter__ and __exit__.
/tmp/test.py|6 col 29 error| [no-member] Module 're' has no 'MULTILINE' member
/tmp/test.py|6 col 44 error| [no-member] Module 're' has no 'DOTALL' member
Using current master of astroid and pylint:
$ pylint --version
pylint 2.0.0,
astroid 1.5.0
Python 3.6.0 (default, Dec 23 2016, 16:25:50)
Mocked https://github.com/PyCQA/astroid/blob/master/astroid/brain/brain_threading.py does not contain __enter__ and __exit__. May be fixed quite easily.
I can confirm that the following patch fixes no-context-manager error.
diff --git a/astroid/brain/brain_threading.py b/astroid/brain/brain_threading.py
index f2dfe60..4e95501 100644
--- a/astroid/brain/brain_threading.py
+++ b/astroid/brain/brain_threading.py
@@ -13,6 +13,10 @@ def _thread_transform():
pass
def release(self):
pass
+ def __enter__(self):
+ pass
+ def __exit__(self, type, value, tb):
+ pass
def Lock():
return lock()
I can submit a pull-request but I am unsure how to write a test for it. There is ThreadingBrainTest in unittest_brain.py but I do not know enough about pylint's and astroid's internal api.
https://github.com/PyCQA/astroid/blob/master/astroid/tests/unittest_brain.py#L362
You can see that there's a test for acquire and release attributes being a FunctionDefs. You can mimic those asserts to check if __enter__ and __exit__ attributes are also FunctionDefs.
Taking one step back - what about RLock, Condition, Semaphore etc. Quite a lot of threading is not covered in astroid.brain.
Well... I haven't followed through and this issue took its revenge by emitting false positive on my code base :) .
Let's mark it as contributor friendly, since pretty good explanation of steps needed to take is available in issue comments.
I'm getting this false positive with:
pylint-3 1.7.1,
astroid 1.5.2
Python 3.6.2 (default, Jul 30 2017, 17:42:38)
E: 10, 4: Context manager 'lock' doesn't implement __enter__ and __exit__. (not-context-manager)
This is the reproducer:
from threading import Lock
if __name__ == "__main__":
lock = Lock()
with lock:
print("A")
Ohh I see it is after 1.5.3 astroid version.