Skip to content

Commit 1f62beb

Browse files
Infer user-defined enum classes by checking if the class is a subtype of enum.Enum (#2277) (#2298)
(cherry picked from commit c5352d5) Co-authored-by: Jacob Walls <jacobtylerwalls@gmail.com> Co-authored-by: Mark Byrne <31762852+mbyrnepr2@users.noreply.github.com>
1 parent 0e0dd9c commit 1f62beb

File tree

3 files changed

+41
-17
lines changed

3 files changed

+41
-17
lines changed

ChangeLog

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ Release date: TBA
2020

2121
Closes pylint-dev/pylint#8802
2222

23+
* Infer user-defined enum classes by checking if the class is a subtype of ``enum.Enum``.
24+
25+
Closes pylint-dev/pylint#8897
26+
2327
* Fix inference of functions with ``@functools.lru_cache`` decorators without
2428
parentheses.
2529

astroid/brain/brain_namedtuple_enum.py

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
AstroidTypeError,
2121
AstroidValueError,
2222
InferenceError,
23-
MroError,
2423
UseInferenceDefault,
2524
)
2625
from astroid.manager import AstroidManager
@@ -31,14 +30,6 @@
3130
from typing_extensions import Final
3231

3332

34-
ENUM_BASE_NAMES = {
35-
"Enum",
36-
"IntEnum",
37-
"enum.Enum",
38-
"enum.IntEnum",
39-
"IntFlag",
40-
"enum.IntFlag",
41-
}
4233
ENUM_QNAME: Final[str] = "enum.Enum"
4334
TYPING_NAMEDTUPLE_QUALIFIED: Final = {
4435
"typing.NamedTuple",
@@ -606,14 +597,7 @@ def _get_namedtuple_fields(node: nodes.Call) -> str:
606597

607598
def _is_enum_subclass(cls: astroid.ClassDef) -> bool:
608599
"""Return whether cls is a subclass of an Enum."""
609-
try:
610-
return any(
611-
klass.name in ENUM_BASE_NAMES
612-
and getattr(klass.root(), "name", None) == "enum"
613-
for klass in cls.mro()
614-
)
615-
except MroError:
616-
return False
600+
return cls.is_subtype_of("enum.Enum")
617601

618602

619603
AstroidManager().register_transform(

tests/brain/test_enum.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -493,3 +493,39 @@ def pear(self):
493493
for node in (attribute_nodes[1], name_nodes[1]):
494494
with pytest.raises(InferenceError):
495495
node.inferred()
496+
497+
def test_local_enum_child_class_inference(self) -> None:
498+
"""Originally reported in https://github.com/pylint-dev/pylint/issues/8897
499+
500+
Test that a user-defined enum class is inferred when it subclasses
501+
another user-defined enum class.
502+
"""
503+
enum_class_node, enum_member_value_node = astroid.extract_node(
504+
"""
505+
import sys
506+
507+
from enum import Enum
508+
509+
if sys.version_info >= (3, 11):
510+
from enum import StrEnum
511+
else:
512+
class StrEnum(str, Enum):
513+
pass
514+
515+
516+
class Color(StrEnum): #@
517+
RED = "red"
518+
519+
520+
Color.RED.value #@
521+
"""
522+
)
523+
assert "RED" in enum_class_node.locals
524+
525+
enum_members = enum_class_node.locals["__members__"][0].items
526+
assert len(enum_members) == 1
527+
_, name = enum_members[0]
528+
assert name.name == "RED"
529+
530+
inferred_enum_member_value_node = next(enum_member_value_node.infer())
531+
assert inferred_enum_member_value_node.value == "red"

0 commit comments

Comments
 (0)