summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog10
-rw-r--r--pylint/checkers/typecheck.py13
-rw-r--r--pylint/test/functional/member_checks.py12
-rw-r--r--pylint/test/functional/member_checks.txt3
4 files changed, 34 insertions, 4 deletions
diff --git a/ChangeLog b/ChangeLog
index eb005cb47..c20111daa 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -39,6 +39,16 @@ Release date: TBA
Close #2494
+* ``no-member`` is emitted for enums when they lack a member
+
+ Previously we weren't doing this because we detected a
+ ``__getattr__`` implementation on the ``Enum`` class
+ (and this check is skipped for classes with ``__getattr__``),
+ but that is fine for Enums, given that they are inferred in a customised
+ way in astroid.
+
+ Close #2565
+
What's New in Pylint 2.2.2?
===========================
diff --git a/pylint/checkers/typecheck.py b/pylint/checkers/typecheck.py
index c3ef6b490..976e7fa89 100644
--- a/pylint/checkers/typecheck.py
+++ b/pylint/checkers/typecheck.py
@@ -404,7 +404,17 @@ def _emit_no_member(node, owner, owner_name, ignored_mixins=True, ignored_none=T
if isinstance(owner, astroid.FunctionDef) and owner.decorators:
return False
if isinstance(owner, (astroid.Instance, astroid.ClassDef)):
- if owner.has_dynamic_getattr() or not has_known_bases(owner):
+ if owner.has_dynamic_getattr():
+ # Issue #2565: Don't ignore enums, as they have a `__getattr__` but it's not
+ # invoked at this point.
+ try:
+ metaclass = owner.metaclass()
+ except exceptions.MroError:
+ return False
+ if metaclass:
+ return metaclass.qname() == "enum.EnumMeta"
+ return False
+ if not has_known_bases(owner):
return False
if isinstance(owner, objects.Super):
# Verify if we are dealing with an invalid Super object.
@@ -886,7 +896,6 @@ accessed. Python regular expressions are accepted.",
ignored_mixins=self.config.ignore_mixin_members,
ignored_none=self.config.ignore_none,
):
-
continue
missingattr.add((owner, name))
continue
diff --git a/pylint/test/functional/member_checks.py b/pylint/test/functional/member_checks.py
index d4aef7c5f..cb6062676 100644
--- a/pylint/test/functional/member_checks.py
+++ b/pylint/test/functional/member_checks.py
@@ -1,5 +1,5 @@
# pylint: disable=print-statement,missing-docstring,no-self-use,too-few-public-methods,bare-except,broad-except, useless-object-inheritance
-# pylint: disable=using-constant-test,expression-not-assigned, assigning-non-slot, unused-variable,pointless-statement
+# pylint: disable=using-constant-test,expression-not-assigned, assigning-non-slot, unused-variable,pointless-statement, wrong-import-order, wrong-import-position
from __future__ import print_function
import six
class Provider(object):
@@ -197,3 +197,13 @@ class ClassWithMangledAttribute(object):
print(self.name + "xD")
ClassWithMangledAttribute()._ClassWithMangledAttribute__bar() # pylint: disable=protected-access
+
+
+import enum
+
+
+class Cls(enum.IntEnum):
+ Bar = 0
+
+
+SOME_VALUE = Cls.Baz # [no-member]
diff --git a/pylint/test/functional/member_checks.txt b/pylint/test/functional/member_checks.txt
index bf5f2c2c8..dd2c927b9 100644
--- a/pylint/test/functional/member_checks.txt
+++ b/pylint/test/functional/member_checks.txt
@@ -15,4 +15,5 @@ no-member:134::Class 'Client' has no 'ala' member:INFERENCE
no-member:135::Class 'dict' has no 'bala' member:INFERENCE
no-member:136::Class 'str' has no 'portocala' member:INFERENCE
no-member:171:NoDunderNameInInstance.__init__:Instance of 'NoDunderNameInInstance' has no '__name__' member:INFERENCE
-no-member:177:InvalidAccessBySlots.__init__:Instance of 'InvalidAccessBySlots' has no 'teta' member:INFERENCE \ No newline at end of file
+no-member:177:InvalidAccessBySlots.__init__:Instance of 'InvalidAccessBySlots' has no 'teta' member:INFERENCE
+no-member:209::Class 'Cls' has no 'Baz' member; maybe 'Bar'?:INFERENCE