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

(🐞) Enum.name is Any in 3.11 / support enum.property #12483

Closed
KotlinIsland opened this issue Mar 29, 2022 · 6 comments · Fixed by #14133
Closed

(🐞) Enum.name is Any in 3.11 / support enum.property #12483

KotlinIsland opened this issue Mar 29, 2022 · 6 comments · Fixed by #14133
Labels
bug mypy got something wrong topic-enum

Comments

@KotlinIsland
Copy link
Contributor

KotlinIsland commented Mar 29, 2022

from enum import Enum

value: Enum

reveal_type(value)
reveal_type(value.name)
> mypy --python-version 3.10 test.py
test.py:5: note: Revealed type is "enum.Enum"
test.py:6: note: Revealed type is "str"
Success: no issues found in 1 source file

> mypy --python-version 3.11 test.py
test.py:5: note: Revealed type is "enum.Enum"
test.py:6: note: Revealed type is "Any"
Success: no issues found in 1 source file

in 3.11 name is decorated with enum.property which is a subtype of types.DynamicClassAttribute (aka, builtins.property)

from python/typeshed#7564
Related #12220

@KotlinIsland KotlinIsland added the bug mypy got something wrong label Mar 29, 2022
@KotlinIsland KotlinIsland changed the title (🐞) Enum.name is Any in 3.11 / support enum.property (🐞) Enum.name/Enum.value is Any in 3.11 / support enum.property Mar 29, 2022
@KotlinIsland KotlinIsland changed the title (🐞) Enum.name/Enum.value is Any in 3.11 / support enum.property (🐞) Enum.name is Any in 3.11 / support enum.property Mar 29, 2022
@jhance
Copy link
Collaborator

jhance commented Mar 29, 2022

To paraphase in a way others won't need to dig throuhg typeshed, typeshed does this:

if sys.version_info >= (3, 11):
    class property(types.DynamicClassAttribute):
        ...
    _magic_enum_attr = property
else:
    _magic_enum_attr = types.DynamicClassAttribute

@JelleZijlstra
Copy link
Member

And types.DynamicClassAttribute is an alias for builtins.property.

@AlexWaygood
Copy link
Member

It might be worth pointing out that mypy doesn't get the behaviour precisely correct on Python <=3.10 either:

from enum import Enum

class Foo(Enum):
    BAR = 'bar'
    BAZ = 'baz'

reveal_type(Foo.name)  # No error from mypy, raises AttributeError at runtime
reveal_type(Foo.value)  # No error from mypy, raises AttributeError at runtime

On Python <= 3.10, Enum.name and Enum.value are special-cased by the enum module to allow this magical behaviour, where name and value are read-only properties that raise AttributeError if accessed from the class rather than an instance. This is to allow enumerations where members have name or value as their names:

>>> from enum import Enum
>>> class Dictionary(Enum):
...     name = 'a word used to identify something'
...     animal = 'a living creature'
...
>>> Dictionary.name
<Dictionary.name: 'a word used to identify something'>
>>> Dictionary.name.name
'name'

In Python 3.11, name and value are no longer special-cased by the enum module. Instead, the new enum.property class generalises this behaviour, so that users can create their own "magic enum properties":

>>> import enum
>>> class CustomEnum(enum.Enum):
...     @enum.property
...     def foo(self):
...         return 'MAGIC'
...
>>> class MyEnum(CustomEnum):
...     foo = 'foo'
...
>>> MyEnum.foo
<MyEnum.foo: 'foo'>
>>> MyEnum.foo.foo
'MAGIC'

@AlexWaygood
Copy link
Member

Here's the dedicated issue regarding the incorrect behaviour on <=3.10: #4654

eli-schwartz added a commit to eli-schwartz/meson that referenced this issue Nov 4, 2022
mypy has a bug when running on/for 3.11 which results in incorrect
analysis of the codebase, specifically due to enum.Enum's self.name

See:

python/typeshed#7564
python/mypy#12483
eli-schwartz added a commit to eli-schwartz/meson that referenced this issue Nov 6, 2022
mypy has a bug when running on/for 3.11 which results in incorrect
analysis of the codebase, specifically due to enum.Enum's self.name

See:

python/typeshed#7564
python/mypy#12483
@playpauseandstop
Copy link

playpauseandstop commented Nov 17, 2022

Hope this is proper place to report, as I have experienced another issue related to Enum.name behaviour after upgrading my codebase to Python 3.11 (and latest mypy 0.991).

With Python 3.10 following code checked OK,

from enum import Enum, unique


@unique
class SortEnum(Enum):
     name = "name"
     name_desc = "-name"
❯ pipx run mypy==0.991 --python-version=3.10 test.py
Success: no issues found in 1 source file

But with Python 3.11 it throwing,

❯ pipx run mypy==0.991 --python-version=3.11 test.py
test.py:6:12: error: Incompatible types in assignment (expression has type "str", base class "Enum" defined the type as "Callable[[Enum], str]")  [assignment]
Found 1 error in 1 file (checked 1 source file)

As a quick workaround it might be possible to rename SortEnum.name to SortEnum.name_asc, and in meantime looking forward to proper fix 🙏

ilevkivskyi added a commit that referenced this issue Nov 18, 2022
Fixes #12483
Fixes python/typeshed#7564
Ref #12841

The fix is straightforward. I can't use a unit test for this because
there are some builtins fixtures that don't have tuple, so I can't do
version check.
nirbheek pushed a commit to mesonbuild/meson that referenced this issue Nov 21, 2022
mypy has a bug when running on/for 3.11 which results in incorrect
analysis of the codebase, specifically due to enum.Enum's self.name

See:

python/typeshed#7564
python/mypy#12483
@gimbo
Copy link

gimbo commented Feb 8, 2023

name is still problematic in that it can't be used with an auto() value:

from enum import Enum, auto


class E(Enum):
    name = auto()
$ mypy /tmp/foo.py
/tmp/foo.py:5: error: Incompatible types in assignment (expression has type "auto", base class "Enum" defined the type as "str")  [assignment]
Found 1 error in 1 file (checked 1 source file)

(Not a problem for me btw — I just happened to notice.)

$ python --version
Python 3.11.1

$ mypy --version
mypy 1.0.0 (compiled: yes)

rswarbrick added a commit to rswarbrick/opentitan that referenced this issue Jul 12, 2023
Fix some mypy errors in the reggen library. It looks like the version
of MyPy that we're using in CI at the moment isn't new enough to
notice the problems, so we won't really see much change from this
commit. However, these changes fix things with 1.0.1 (the latest
release), which spat out lots of messages without them.

Getting things happy again is mostly a case of adding some types to
guide the tool so that it knows what's going on. There's also a small
re-write in gen_selfdoc.py: there, the doc_tbl_head() function used an
optional int as a way of encoding a bool. This seemed a bit silly (and
hard to encode!), so I've switched it to use True/False instead.

Finally, we fix a type error in register.py, where the code was
missing some parentheses and testing a function (rather than its
return value) against None.

One slightly odd thing is the change to access.py. There, the problem
was that self.value[1].name wasn't known to be a string. It turns out
that this depends on the Python version(!) and is tracked in
python/mypy#12483. Using a do-nothing cast
with str() silences things.

Signed-off-by: Rupert Swarbrick <rswarbrick@lowrisc.org>
rswarbrick added a commit to rswarbrick/opentitan that referenced this issue Jul 12, 2023
Fix some mypy errors in the reggen library. It looks like the version
of MyPy that we're using in CI at the moment isn't new enough to
notice the problems, so we won't really see much change from this
commit. However, these changes fix things with 1.0.1 (the latest
release), which spat out lots of messages without them.

Getting things happy again is mostly a case of adding some types to
guide the tool so that it knows what's going on. There's also a small
re-write in gen_selfdoc.py: there, the doc_tbl_head() function used an
optional int as a way of encoding a bool. This seemed a bit silly (and
hard to encode!), so I've switched it to use True/False instead.

Finally, we fix a type error in register.py, where the code was
missing some parentheses and testing a function (rather than its
return value) against None.

One slightly odd thing is the change to access.py. There, the problem
was that self.value[1].name wasn't known to be a string. It turns out
that this depends on the Python version(!) and is tracked in
python/mypy#12483. Using a do-nothing cast
with str() silences things.

Signed-off-by: Rupert Swarbrick <rswarbrick@lowrisc.org>
rswarbrick added a commit to lowRISC/opentitan that referenced this issue Jul 13, 2023
Fix some mypy errors in the reggen library. It looks like the version
of MyPy that we're using in CI at the moment isn't new enough to
notice the problems, so we won't really see much change from this
commit. However, these changes fix things with 1.0.1 (the latest
release), which spat out lots of messages without them.

Getting things happy again is mostly a case of adding some types to
guide the tool so that it knows what's going on. There's also a small
re-write in gen_selfdoc.py: there, the doc_tbl_head() function used an
optional int as a way of encoding a bool. This seemed a bit silly (and
hard to encode!), so I've switched it to use True/False instead.

Finally, we fix a type error in register.py, where the code was
missing some parentheses and testing a function (rather than its
return value) against None.

One slightly odd thing is the change to access.py. There, the problem
was that self.value[1].name wasn't known to be a string. It turns out
that this depends on the Python version(!) and is tracked in
python/mypy#12483. Using a do-nothing cast
with str() silences things.

Signed-off-by: Rupert Swarbrick <rswarbrick@lowrisc.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug mypy got something wrong topic-enum
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants