Open jmehnle opened 3 years ago
Concour, facing the same issue.
The previous issue was closed because inferring attributes created dynamically is hard to program and then computationally intensive. But let's keep this one open and see if someone is interested to create the feature.
Meanwhile, the configuration to disable the checks is
[TYPECHECK]
# List of decorators that produce context managers, such as
# contextlib.contextmanager. Add to this list to register other decorators that
# produce valid context managers.
contextmanager-decorators=contextlib.contextmanager
# List of members which are set dynamically and missed by pylint inference
# system, and so shouldn't trigger E1101 when accessed. Python regular
# expressions are accepted.
generated-members=
# Tells whether to warn about missing members when the owner of the attribute
# is inferred to be None.
ignore-none=yes
# This flag controls whether pylint should warn about no-member and similar
# checks whenever an opaque object is returned when inferring. The inference
# can return multiple potential results while evaluating a Python object, but
# some branches might not be evaluated, which results in partial inference. In
# that case, it might be useful to still emit no-member and other checks for
# the rest of the inferred objects.
ignore-on-opaque-inference=yes
# List of class names for which member attributes should not be checked (useful
# for classes with dynamically set attributes). This supports the use of
# qualified names.
ignored-classes=optparse.Values,thread._local,_thread._local
# List of module names for which member attributes should not be checked
# (useful for modules/projects where namespaces are manipulated during runtime
# and thus existing member attributes cannot be deduced by static analysis). It
# supports qualified module names, as well as Unix pattern matching.
ignored-modules=
PSA for others facing this problem: if you are a library author using dynamically defined attributes, and you want to avoid spamming your users with false positives, then, if you know the names of the dynamically defined attributes, you can use variable annotations to skirt the issue:
# project/__init__.py
foo: Any # !!!! ESSENTIAL !!!!
bar = 1
_DEPRECATED = {
"foo": ("bar", bar)
}
def __getattr__(name):
if name in _DEPRECATED:
new_name, val = _DEPRECATED[name]
warnings.warn(f"{name} is deprecated, use {new_name} instead")
return val
else:
raise AttributeError(f"No attribute named {name}")
This works, but pylint does not understand it.
# some/file.py
# Without our "foo: Any" variable annotation above, pylint will raise error E0611 no-name-in-module.
# With the annotation, no error, and everything works.
from project import foo
foo # => 1 # code works fine
Steps to reproduce
Current behavior
Expected behavior
Unfortunately the current behavior ignores PEP 562, which officially provides a way to dynamically define module contents.
pylint
should inhibit E0611 for such modules.(A related issue was previously logged as https://github.com/PyCQA/pylint/issues/1704.)
pylint --version output
Result of
pylint --version
output: