pylint
pylint copied to clipboard
Incorrect type detected when @contextmanager uses a subgenerator
Bug description
The following raises a E1101: Generator 'generator' has no 'bit_count' member (no-member):
#pylint: disable=C0114,C0116
from contextlib import contextmanager
from typing import Generator
def subgenerator() -> Generator[int, None, None]:
yield 0
@contextmanager
def context_manager() -> Generator[int, None, None]:
# does not work:
yield from subgenerator()
# works:
#for x in subgenerator():
# yield x
with context_manager() as cm:
print(cm.bit_count())
Configuration
No response
Command used
pylint test.py
Pylint output
************* Module test
test.py:17:10: E1101: Generator 'generator' has no 'bit_count' member (no-member)
------------------------------------------------------------------
Your code has been rated at 3.75/10 (previous run: 7.85/10, -4.10)
Expected behavior
Same as commented code path : Pylint should detect that the context type is int and not Generator and hence it should not raise no-member
Pylint version
$ pylint --version
pylint 3.0.2
astroid 3.0.1
Python 3.11.6 (main, Oct 3 2023, 00:00:00) [GCC 13.2.1 20230728 (Red Hat 13.2.1-1)]
OS / Environment
No response
Additional dependencies
No response
With the latest version (pylint 3.2.0) this issue got worse because using the workaround mentioned above now results in the following pylint error:
R1737: Use 'yield from' directly instead of yielding each element one by one (use-yield-from)
Thank you for update @PascalHonegger. I think you should disable the message locally with # pylint: disable=no-member if it's a false positive instead of doing a workaround that can make the code worst.
Thank you for update @PascalHonegger. I think you should disable the message locally with
# pylint: disable=no-memberif it's a false positive instead of doing a workaround that can make the code worst.
The problem there is that you need to disable it at every call site, also isn't ideal :disappointed:
If something is generated dynamically, pylint won't be able to understand the code from your library (c-extension or not). You can then specify generated attributes with the generated-members option. For example if cv2.LINE_AA and sphinx.generated_member create false positives for no-member, you can do: $ pylint --generated-member=cv2.LINE_AA,sphinx.generated_member
https://pylint.readthedocs.io/en/stable/user_guide/messages/error/no-member.html