summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHuw Jones <huw@huwcbjones.co.uk>2022-06-06 04:21:54 +0100
committerPierre Sassoulas <pierre.sassoulas@gmail.com>2022-06-06 22:27:46 +0200
commit5913cb7cd7cde24ccea6bcd6b4b8a80961a4d1c2 (patch)
tree9e437174e2a138edd02f1788c4fb3c945b15c629
parent4621ad5a0d66f529a4c71b5e18382a44760c7b43 (diff)
downloadpylint-git-5913cb7cd7cde24ccea6bcd6b4b8a80961a4d1c2.tar.gz
Fix a crash when linting ``__new__()`` methods that return a call (#6822)
Only check for Enum attributes when metaclass is an Enum metaclass
-rw-r--r--doc/whatsnew/2/2.14/full.rst4
-rw-r--r--pylint/checkers/typecheck.py8
-rw-r--r--tests/functional/e/enum_self_defined_member_6805.py43
-rw-r--r--tests/functional/e/enum_self_defined_member_6805.txt1
4 files changed, 52 insertions, 4 deletions
diff --git a/doc/whatsnew/2/2.14/full.rst b/doc/whatsnew/2/2.14/full.rst
index 46eebb217..524c759bd 100644
--- a/doc/whatsnew/2/2.14/full.rst
+++ b/doc/whatsnew/2/2.14/full.rst
@@ -14,6 +14,10 @@ Release date: TBA
Closes #6800
+* Fixed a crash when linting ``__new__()`` methods that return a call expression.
+
+ Closes #6805
+
* Don't crash if we can't find the user's home directory.
Closes #6802
diff --git a/pylint/checkers/typecheck.py b/pylint/checkers/typecheck.py
index 413a93c3b..0a1307ffe 100644
--- a/pylint/checkers/typecheck.py
+++ b/pylint/checkers/typecheck.py
@@ -451,10 +451,10 @@ def _emit_no_member(
except astroid.MroError:
return False
if metaclass:
- if _enum_has_attribute(owner, node):
- return False
# Renamed in Python 3.10 to `EnumType`
- return metaclass.qname() in {"enum.EnumMeta", "enum.EnumType"}
+ if metaclass.qname() in {"enum.EnumMeta", "enum.EnumType"}:
+ return not _enum_has_attribute(owner, node)
+ return False
return False
if not has_known_bases(owner):
return False
@@ -583,7 +583,7 @@ def _enum_has_attribute(
(c.value for c in dunder_new.get_children() if isinstance(c, nodes.Return)),
None,
)
- if returned_obj_name is not None:
+ if isinstance(returned_obj_name, nodes.Name):
# Find all attribute assignments to the returned object
enum_attributes |= _get_all_attribute_assignments(
dunder_new, returned_obj_name.name
diff --git a/tests/functional/e/enum_self_defined_member_6805.py b/tests/functional/e/enum_self_defined_member_6805.py
new file mode 100644
index 000000000..bcf0c8e10
--- /dev/null
+++ b/tests/functional/e/enum_self_defined_member_6805.py
@@ -0,0 +1,43 @@
+"""Tests for self-defined Enum members (https://github.com/PyCQA/pylint/issues/6805)"""
+# pylint: disable=missing-docstring
+# pylint: disable=too-few-public-methods
+from enum import IntEnum
+
+
+class Foo(type):
+ pass
+
+
+class Parent:
+ def __new__(cls, *_args, **_kwargs):
+ return object.__new__(cls)
+
+
+class NotEnumHasDynamicGetAttrMetaclass(metaclass=Foo):
+ def __new__(cls):
+ return Parent.__new__(cls)
+
+ def __getattr__(self, item):
+ return item
+
+ def magic(self):
+ return self.dynamic
+
+
+NotEnumHasDynamicGetAttrMetaclass().magic()
+
+
+class Day(IntEnum):
+ MONDAY = (1, "Mon")
+ TUESDAY = (2, "Tue")
+ WEDNESDAY = (3, "Wed")
+ THURSDAY = (4, "Thu")
+ FRIDAY = (5, "Fri")
+ SATURDAY = (6, "Sat")
+ SUNDAY = (7, "Sun")
+
+ def __new__(cls, value, _abbr=None):
+ return int.__new__(cls, value)
+
+
+print(Day.FRIDAY.foo) # [no-member]
diff --git a/tests/functional/e/enum_self_defined_member_6805.txt b/tests/functional/e/enum_self_defined_member_6805.txt
new file mode 100644
index 000000000..f7e1c1e13
--- /dev/null
+++ b/tests/functional/e/enum_self_defined_member_6805.txt
@@ -0,0 +1 @@
+no-member:43:6:43:20::Instance of 'FRIDAY' has no 'foo' member:INFERENCE