Skip to content

Commit

Permalink
Exclude the _ignore_ attribute from the __members__ container. (
Browse files Browse the repository at this point in the history
#2289)


Refs pylint-dev/pylint#9015

* Fix a false positive for ``no-member`` when accessing the ``_name_`` and ``_value_`` sunders of an Enum member value.

Refs pylint-dev/pylint#7402
  • Loading branch information
mbyrnepr2 committed Sep 12, 2023
1 parent 2288d7f commit 43b7f9a
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 1 deletion.
5 changes: 5 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,11 @@ Release date: TBA

Closes pylint-dev/pylint#8802


* Fix false positives for ``no-member`` and ``invalid-name`` when using the ``_name_``, ``_value_`` and ``_ignore_`` sunders in Enums.

Closes pylint-dev/pylint#9015

* Fix inference of functions with ``@functools.lru_cache`` decorators without
parentheses.

Expand Down
11 changes: 10 additions & 1 deletion astroid/brain/brain_namedtuple_enum.py
Original file line number Diff line number Diff line change
Expand Up @@ -403,7 +403,10 @@ def infer_enum_class(node: nodes.ClassDef) -> nodes.ClassDef:
dunder_members = {}
target_names = set()
for local, values in node.locals.items():
if any(not isinstance(value, nodes.AssignName) for value in values):
if (
any(not isinstance(value, nodes.AssignName) for value in values)
or local == "_ignore_"
):
continue

stmt = values[0].statement()
Expand Down Expand Up @@ -440,8 +443,14 @@ class {name}({types}):
def value(self):
return {return_value}
@property
def _value_(self):
return {return_value}
@property
def name(self):
return "{name}"
@property
def _name_(self):
return "{name}"
""".format(
name=target.name,
types=", ".join(node.basenames),
Expand Down
42 changes: 42 additions & 0 deletions tests/brain/test_enum.py
Original file line number Diff line number Diff line change
Expand Up @@ -521,3 +521,45 @@ def __init__(self, mass, radius):
mars, radius = enum_members.items
assert mars[1].name == "MARS"
assert radius[1].name == "radius"

def test_enum_with_ignore(self) -> None:
"""Exclude ``_ignore_`` from the ``__members__`` container
Originally reported in https://github.com/pylint-dev/pylint/issues/9015
"""

ast_node: nodes.Attribute = builder.extract_node(
"""
import enum
class MyEnum(enum.Enum):
FOO = enum.auto()
BAR = enum.auto()
_ignore_ = ["BAZ"]
BAZ = 42
MyEnum.__members__
"""
)
inferred = next(ast_node.infer())
members_names = [const_node.value for const_node, name_obj in inferred.items]
assert members_names == ["FOO", "BAR", "BAZ"]

def test_enum_sunder_names(self) -> None:
"""Test that both `_name_` and `_value_` sunder names exist"""

sunder_name, sunder_value = builder.extract_node(
"""
import enum
class MyEnum(enum.Enum):
APPLE = 42
MyEnum.APPLE._name_ #@
MyEnum.APPLE._value_ #@
"""
)
inferred_name = next(sunder_name.infer())
assert inferred_name.value == "APPLE"

inferred_value = next(sunder_value.infer())
assert inferred_value.value == 42

0 comments on commit 43b7f9a

Please sign in to comment.