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

Indexing a Type Alias of an Enum yields false error #7568

Open
brianjyoung opened this issue Sep 27, 2019 · 5 comments
Open

Indexing a Type Alias of an Enum yields false error #7568

brianjyoung opened this issue Sep 27, 2019 · 5 comments
Labels
bug mypy got something wrong false-positive mypy gave an error on correct code priority-2-low topic-enum topic-metaclasses

Comments

@brianjyoung
Copy link

Minimum [not-]working product:

Ah, good old Enums:

from enum import Enum
class EnumClass(Enum):
    one = 1

EnumAlias = EnumClass
EnumAlias['one']
test.py:6: error: Type application targets a non-generic function or class
test.py:6: error: Name 'one' is not defined

I'm fairly certain this is not an intentional design choice. Just to be sure, according to documentation:

A type alias does not create a new type. It’s just a shorthand notation for another type – it’s equivalent to the target type except for generic aliases.

Now, Enums actually can't be generic, so I certainly expect the alias to be equivalent. So I think this code should pass (regardless of its usefulness... who wants to alias an Enum anyways?).

Possible Causes

I'm no expert, but I think this is happening because the semantic analyzer deems any IndexExpr a TypeApplication if it has a TypeAlias as a base. Once it's marked as analyzed, it doesn't reach the stage of the expression checker where the Enum type would be recognized and the indexing processed as valid. Whatever the root of the problem, I think there's only one spot where the expression checker actually looks at is_enum to handle Enum indexing, so the alias isn't making it there one way or another.

@ilevkivskyi
Copy link
Member

I think we can disambiguate this with a bunch special-casing, but it looks like a low priority one. Also using EnumAlias.one works.

@ilevkivskyi ilevkivskyi added false-positive mypy gave an error on correct code priority-2-low bug mypy got something wrong labels Sep 27, 2019
@colincadams
Copy link

Is there a reasonable way to work around this?

@hauntsaninja
Copy link
Collaborator

EnumAlias.one as Ivan mentioned seems like a reasonable workaround.

@colincadams
Copy link

colincadams commented May 11, 2021

Yeah sorry my question wasn't super clear.

I was more asking if there was a way to type hint the EnumAlias = EnumOne line such that mypy would understand the EnumAlias is actually an enum and still know it had the values from EnumOne. EnumAlias.one won't work if you only know which one you want at runtime, which is typically when you would use the indexing syntax anyway. And mypy won't give an error on getattr(EnumAlias, 'one') necessarily but it also won't know the return type.

edit: context being this beauty here 😬 Recidiviz/pulse-data@89194d5#diff-22f9225176675edc49e87018bebeb7ce175edee19946eb0aadc7eba6222746d6R266

@hauntsaninja
Copy link
Collaborator

from typing import Type
from enum import Enum
class EnumClass(Enum):
    one = 1

EnumAlias: Type[EnumClass] = EnumClass
reveal_type(EnumClass['one'])
reveal_type(EnumAlias['one'])
reveal_type(EnumClass.one)
reveal_type(EnumAlias.one)

This seemed to do what I'd expect, not sure if there are any sharp edges still lurking.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug mypy got something wrong false-positive mypy gave an error on correct code priority-2-low topic-enum topic-metaclasses
Projects
None yet
Development

No branches or pull requests

5 participants