Pylint: False Positive E1129 (Not Context Manager) with class decorators

Created on 13 Jan 2016  路  7Comments  路  Source: PyCQA/pylint

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
contributor friendly help wanted minor

All 7 comments

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.

Was this page helpful?
0 / 5 - 0 ratings