-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Dynamic __getattr__
still leads to no-member
if inference is ambiguous
#9833
Comments
Let's hear from another maintainer, but I feel this is too dynamic for static analysis and should be handled with the 'generated-member' option. I think we'll have to realistically closes as 'won't fix'. |
There are a couple things going on here:
The first one is not in scope for pylint: we're not going to start trusting user type annotations. pylint is the tool you want when you want to test your annotations. The second one is in scope, but will need a new astroid constraint. If you don't mind, I'll refocus this issue on that. |
if a == b:
)
Thank you for your replies. I disagree with refocusing on the second option, though. My example might be a bit oversimplified. In my real-world case I have a class which generates its attributes from a dynamic configuration; there is no realistic way to determine the control flow there. (But I won't deny that it might be helpful in other cases) Concerning the first option, I might have misunderstood why pylint shows an error at all - adding an annotation seems not to change its behaviour at all, which might be ok. But from my point of view there is an inconsistency in pylint's behaviour, which I do not understand (yet?). Please consider the following set of examples, where I eliminated the possibility to determine the code flow. """
************* Module test
test.py:47:6: E1101: Instance of 'A' has no 'any' member (no-member)
"""
# pylint: disable=too-few-public-methods
from time import time
class A:
"""class without attributes"""
class B:
"""class with 'any' attribute"""
any = 1
def a_or_b() -> A | B:
"""function, which may return an instance of A or B"""
if int(time()) % 2:
return A()
return B()
x = a_or_b()
print(x.any) # no pylint error
class C:
"""class with any attribute"""
def __getattr__(self, attr):
return None
y = C()
print(y.any) # no pylint error
def a_or_c() -> A | C:
"""function, which may return an instance of A or C"""
if int(time()) % 2:
return A()
return C()
z = a_or_c()
print(z.any) # E1101: Instance of 'A' has no 'any' member (no-member) |
Thanks for the follow-up. I'm happy to refocus on that last issue with pylint/pylint/checkers/typecheck.py Line 471 in a48cd4c
... it then proceeds to ignore that inference result (C), rather than bailing out of the check entirely. So no message is emitted for C only, but for A or C, it's as if C never happened, so an error is emitted for A. I suggest moving that |
if a == b:
)__getattr__
still leads to no-member
if inference is ambiguous
I had a short peek into the code base and tests and found everything very well organized and readable! |
Bug description
Configuration
No response
Command used
Pylint output
Expected behavior
no error
Pylint version
OS / Environment
$ uname -a
Linux xxx 5.15.0-112-generic #122-Ubuntu SMP Thu May 23 07:48:21 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux
Additional dependencies
No response
The text was updated successfully, but these errors were encountered: