pylint icon indicating copy to clipboard operation
pylint copied to clipboard

False positive ``no-member`` with ``@contextmanager`` decorated generators

Open ZeeD opened this issue 5 years ago • 7 comments

I have this little snippet:

import contextlib

@contextlib.contextmanager
def context_manager():
    try:
        yield
    finally:
        pass

cm = context_manager()
cm.__enter__()
cm.__exit__(None, None, None)

pylint signals the "direct" access to the __enter__ and __exit__ callables as an error:

contextmanaged.py:13:0: E1101: Generator 'generator' has no '__enter__' member (no-member)
contextmanaged.py:14:0: E1101: Generator 'generator' has no '__exit__' member (no-member)

while "uncommon" at least, I think it should not be marked as an error.

> pylint --version
pylint 2.1.1
astroid 2.0.4
Python 3.6.3 (v3.6.3:2c5fed8, Oct  3 2017, 18:11:49) [MSC v.1900 64 bit (AMD64)]

ZeeD avatar Oct 22 '18 08:10 ZeeD

Thanks for the report, definitely a bug.

PCManticore avatar Oct 26 '18 12:10 PCManticore

And for

import contextlib

@contextlib.contextmanager
def context_manager():
    try:
        yield
    finally:
        pass

with context_manager:
    pass

have an error

[E1129 not-context-manager] Context manager 'context_manager' doesn't implement __enter__ and __exit__.

Vihrastik avatar Jul 30 '19 14:07 Vihrastik

@Vihrastik You need to call context_manager for that to be valid, e.g.:

import contextlib

@contextlib.contextmanager
def context_manager():
    try:
        yield
    finally:
        pass

with context_manager(): # notice the function call
    pass

PCManticore avatar Jul 30 '19 14:07 PCManticore

@Vihrastik You need to call context_manager for that to be valid, e.g.:

import contextlib

@contextlib.contextmanager
def context_manager():
    try:
        yield
    finally:
        pass

with context_manager(): # notice the function call
    pass

no, i just forgot to write it in the example of code. this error is active with call.

Vihrastik avatar Jul 30 '19 14:07 Vihrastik

Hi. I wanted to work on this issue if nobody minds.

Regarding snippet

import contextlib

@contextlib.contextmanager
def context_manager():
    try:
        yield
    finally:
        pass

with context_manager():
    pass

which @Vihrastik reports to [E1129 not-context-manager] - I did not reproduce that with pylint 2.3.1 / astroid 2.2.5.

However when I created local env with pylint from master (2.4.0.dev0) / astroid 2.2.5 I receive error from #3022 about posonlyargs. Installing astroid from master fixes the issue.

gyermolenko avatar Aug 03 '19 16:08 gyermolenko

Hi @gyermolenko Feel free to tackle this issue! Regarding your issue with posonlyargs, pylint from master needs the up to date astroid.

PCManticore avatar Aug 06 '19 13:08 PCManticore

@Vihrastik You need to call context_manager for that to be valid, e.g.:

import contextlib

@contextlib.contextmanager
def context_manager():
    try:
        yield
    finally:
        pass

with context_manager(): # notice the function call
    pass

no, i just forgot to write it in the example of code. this error is active with call.

I'm not able to reproduce this second issue, but I am able to reproduce original issue raised at the top.

clavedeluna avatar Sep 20 '22 14:09 clavedeluna