Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Double inheritance of enum.Enum -> false __members__ is unsubscriptable #3535

Closed
mhooreman opened this issue Apr 28, 2020 · 1 comment · Fixed by #4473
Closed

Double inheritance of enum.Enum -> false __members__ is unsubscriptable #3535

mhooreman opened this issue Apr 28, 2020 · 1 comment · Fixed by #4473
Labels
Astroid Related to astroid Bug 🪲

Comments

@mhooreman
Copy link

mhooreman commented Apr 28, 2020

Hello,

When we inherit of a class which itself inherits of enum.Enum, the members are detected as unsubscriptable.

Note: I use this because I define a "enum with additional features".

Steps to reproduce

import enum

class A(enum.Enum):
    pass

class B(A):
    x = enum.auto()

print(B.__members__['x'])

Current behavior

Value 'B.__members__' is unsubscriptable

Expected behavior

No such issue

pylint --version output

pylint 2.5.0
astroid 2.4.0
Python 3.7.4 (v3.7.4:e09359112e, Jul  8 2019, 14:54:52) 
[Clang 6.0 (clang-600.0.57)]
@PCManticore PCManticore added Astroid Related to astroid Bug 🪲 labels May 2, 2020
@tillhainbach
Copy link

Also throws an error if one try's to use the .keys()-method. (Iterating over names and aliases). Additionally, throws an error if one creates "mixed-in" enums (e.g. as mentioned in the official python docs: https://docs.python.org/3/library/enum.html#others).

Example:

"""Just an example"""

from enum import Enum

class StrEnum(str, Enum):
    """Self-declared mixed-in enum (like IntEnum)"""

class MyEnum(StrEnum):
    """An Enum with aliases"""
    my_value = 1
    my_other_value = 2
    my_alias = 1

def filter_names_in_my_enum(names):
    """Get an overview of all names in Enum with aliases."""
    names = (name for name in names if name in MyEnum.__members__.keys())
    return names

def main():
    """Main method"""
    names = ['my_value', 'my_int', 'my_alias']
    print(list(filter_names_in_my_enum(names)))


if __name__ == '__main__':
    main()
% pylint example.py
example.py:16:47: E1101: Function '__members__' has no 'keys' member (no-member)
------------------------------------------------------------------
Your code has been rated at 6.43/10
% python example.py
['my_value', 'my_alias']

For some reason, this works:

"""Just an example2"""

from enum import Enum

class StrEnum(str, Enum):
    """Self-declared mixed-in enum (like IntEnum)"""

class MyEnum(StrEnum):
    """An Enum with aliases"""
    my_value = 1
    my_other_value = 2
    my_alias = 1

def filter_names_in_the_enum(names, the_enum):
    """Get an overview of all names in Enum with aliases."""
    # call .__members__.keys() on function argument
    names = (name for name in names if name in the_enum.__members__.keys())
    return names

def main():
    """Main method"""
    names = ['my_value', 'my_int', 'my_alias']
    # pass MyEnum as argument to function
    print(list(filter_names_in_the_enum(names, MyEnum)))


if __name__ == '__main__':
    main()
% pylint example2.py

--------------------------------------------------------------------
Your code has been rated at 10.00/10 

% python example2.py
['my_value', 'my_alias']

nelfin added a commit to nelfin/astroid that referenced this issue May 13, 2021
Ref pylint-dev/pylint#2626. Ref pylint-dev/pylint#3535. Ref pylint-dev/pylint#4358.
This updates the namedtuple/enum brain to add a dictionary for
__members__
nelfin added a commit to nelfin/astroid that referenced this issue May 13, 2021
Ref pylint-dev/pylint#2626. Ref pylint-dev/pylint#3535. Ref pylint-dev/pylint#4358.
This updates the namedtuple/enum brain to add a dictionary for
__members__
nelfin added a commit to nelfin/astroid that referenced this issue May 14, 2021
Ref pylint-dev/pylint#3535. Ref pylint-dev/pylint#4358. This updates the
namedtuple/enum brain to add a dictionary for __members__
cdce8p pushed a commit to pylint-dev/astroid that referenced this issue May 15, 2021
#941)

* Add tests of failing property inference

Ref #940

* Fix inference of properties in a class context

Ref #940. If we are accessing an attribute and it is found on
type(A).__dict__ *and* it is a data descriptor, then we resolve that
descriptor. For the case of inferring a property which is accessed as a
class attribute, this equates to the property being defined on the
metaclass (which may be anywhere in the class hierarchy).

* Fix inference of Enum.__members__ property for subclasses

Ref pylint-dev/pylint#3535. Ref pylint-dev/pylint#4358. This updates the
namedtuple/enum brain to add a dictionary for __members__
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Astroid Related to astroid Bug 🪲
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants