mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-30 05:44:56 +00:00
[ty] Detect enums if metaclass is a subtype of EnumType/EnumMeta (#19481)
## Summary This PR implements the following section from the [typing spec on enums](https://typing.python.org/en/latest/spec/enums.html#enum-definition): > Enum classes can also be defined using a subclass of `enum.Enum` **or any class that uses `enum.EnumType` (or a subclass thereof) as a metaclass**. Note that `enum.EnumType` was named `enum.EnumMeta` prior to Python 3.11. part of https://github.com/astral-sh/ty/issues/183 ## Test Plan New Markdown tests
This commit is contained in:
parent
ba070bb6d5
commit
385d6fa608
3 changed files with 104 additions and 4 deletions
|
@ -561,7 +561,83 @@ reveal_type(enum_members(Answer))
|
|||
|
||||
## Custom enum types
|
||||
|
||||
To do: <https://typing.python.org/en/latest/spec/enums.html#enum-definition>
|
||||
Enum classes can also be defined using a subclass of `enum.Enum` or any class that uses
|
||||
`enum.EnumType` (or a subclass thereof) as a metaclass. `enum.EnumType` was called `enum.EnumMeta`
|
||||
prior to Python 3.11.
|
||||
|
||||
### Subclasses of `Enum`
|
||||
|
||||
```py
|
||||
from enum import Enum, EnumMeta
|
||||
|
||||
class CustomEnumSubclass(Enum):
|
||||
def custom_method(self) -> int:
|
||||
return 0
|
||||
|
||||
class EnumWithCustomEnumSubclass(CustomEnumSubclass):
|
||||
NO = 0
|
||||
YES = 1
|
||||
|
||||
reveal_type(EnumWithCustomEnumSubclass.NO) # revealed: Literal[EnumWithCustomEnumSubclass.NO]
|
||||
reveal_type(EnumWithCustomEnumSubclass.NO.custom_method()) # revealed: int
|
||||
```
|
||||
|
||||
### Enums with (subclasses of) `EnumMeta` as metaclass
|
||||
|
||||
```toml
|
||||
[environment]
|
||||
python-version = "3.9"
|
||||
```
|
||||
|
||||
```py
|
||||
from enum import Enum, EnumMeta
|
||||
|
||||
class EnumWithEnumMetaMetaclass(metaclass=EnumMeta):
|
||||
NO = 0
|
||||
YES = 1
|
||||
|
||||
reveal_type(EnumWithEnumMetaMetaclass.NO) # revealed: Literal[EnumWithEnumMetaMetaclass.NO]
|
||||
|
||||
class SubclassOfEnumMeta(EnumMeta): ...
|
||||
|
||||
class EnumWithSubclassOfEnumMetaMetaclass(metaclass=SubclassOfEnumMeta):
|
||||
NO = 0
|
||||
YES = 1
|
||||
|
||||
reveal_type(EnumWithSubclassOfEnumMetaMetaclass.NO) # revealed: Literal[EnumWithSubclassOfEnumMetaMetaclass.NO]
|
||||
|
||||
# Attributes like `.value` can *not* be accessed on members of these enums:
|
||||
# error: [unresolved-attribute]
|
||||
EnumWithSubclassOfEnumMetaMetaclass.NO.value
|
||||
```
|
||||
|
||||
### Enums with (subclasses of) `EnumType` as metaclass
|
||||
|
||||
```toml
|
||||
[environment]
|
||||
python-version = "3.11"
|
||||
```
|
||||
|
||||
```py
|
||||
from enum import Enum, EnumType
|
||||
|
||||
class EnumWithEnumMetaMetaclass(metaclass=EnumType):
|
||||
NO = 0
|
||||
YES = 1
|
||||
|
||||
reveal_type(EnumWithEnumMetaMetaclass.NO) # revealed: Literal[EnumWithEnumMetaMetaclass.NO]
|
||||
|
||||
class SubclassOfEnumMeta(EnumType): ...
|
||||
|
||||
class EnumWithSubclassOfEnumMetaMetaclass(metaclass=SubclassOfEnumMeta):
|
||||
NO = 0
|
||||
YES = 1
|
||||
|
||||
reveal_type(EnumWithSubclassOfEnumMetaMetaclass.NO) # revealed: Literal[EnumWithSubclassOfEnumMetaMetaclass.NO]
|
||||
|
||||
# error: [unresolved-attribute]
|
||||
EnumWithSubclassOfEnumMetaMetaclass.NO.value
|
||||
```
|
||||
|
||||
## Function syntax
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue