From 23249c07a9a035bff1ee0da468d2d1bf2883a6d3 Mon Sep 17 00:00:00 2001 From: Alex Waygood Date: Mon, 11 Sep 2023 11:26:18 +0100 Subject: [PATCH] Update `enum` for py312 (#10670) --- stdlib/enum.pyi | 22 ++++++++++++++++++++-- test_cases/stdlib/check_enum.py | 25 +++++++++++++++++++++++++ tests/stubtest_allowlists/py312.txt | 6 ------ 3 files changed, 45 insertions(+), 8 deletions(-) diff --git a/stdlib/enum.pyi b/stdlib/enum.pyi index e6eaf6c41..10ea19257 100644 --- a/stdlib/enum.pyi +++ b/stdlib/enum.pyi @@ -119,10 +119,12 @@ class EnumMeta(type): def __len__(self) -> int: ... def __bool__(self) -> Literal[True]: ... def __dir__(self) -> list[str]: ... - # Simple value lookup + + # Overload 1: Value lookup on an already existing enum class (simple case) @overload def __call__(cls: type[_EnumMemberT], value: Any, names: None = None) -> _EnumMemberT: ... - # Functional Enum API + + # Overload 2: Functional API for constructing new enum classes. if sys.version_info >= (3, 11): @overload def __call__( @@ -148,6 +150,18 @@ class EnumMeta(type): type: type | None = None, start: int = 1, ) -> type[Enum]: ... + + # Overload 3 (py312+ only): Value lookup on an already existing enum class (complex case) + # + # >>> class Foo(enum.Enum): + # ... X = 1, 2, 3 + # >>> Foo(1, 2, 3) + # + # + if sys.version_info >= (3, 12): + @overload + def __call__(cls: type[_EnumMemberT], value: Any, *values: Any) -> _EnumMemberT: ... + _member_names_: list[str] # undocumented _member_map_: dict[str, Enum] # undocumented _value2member_map_: dict[Any, Enum] # undocumented @@ -160,6 +174,7 @@ if sys.version_info >= (3, 11): def __set_name__(self, ownerclass: type[Enum], name: str) -> None: ... name: str clsname: str + member: Enum | None _magic_enum_attr = property else: _magic_enum_attr = types.DynamicClassAttribute @@ -191,6 +206,9 @@ class Enum(metaclass=EnumMeta): if sys.version_info >= (3, 11): def __copy__(self) -> Self: ... def __deepcopy__(self, memo: Any) -> Self: ... + if sys.version_info >= (3, 12): + @classmethod + def __signature__(cls) -> str: ... if sys.version_info >= (3, 11): class ReprEnum(Enum): ... diff --git a/test_cases/stdlib/check_enum.py b/test_cases/stdlib/check_enum.py index a93e1fae1..69c31ffe7 100644 --- a/test_cases/stdlib/check_enum.py +++ b/test_cases/stdlib/check_enum.py @@ -2,8 +2,33 @@ from __future__ import annotations import enum import sys +from typing import Type from typing_extensions import Literal, assert_type +A = enum.Enum("A", "spam eggs bacon") +B = enum.Enum("B", ["spam", "eggs", "bacon"]) +C = enum.Enum("Bar", [("spam", 1), ("eggs", 2), ("bacon", 3)]) +D = enum.Enum("Bar", {"spam": 1, "eggs": 2}) + +assert_type(A, Type[A]) +assert_type(B, Type[B]) +assert_type(C, Type[C]) +assert_type(D, Type[D]) + + +class EnumOfTuples(enum.Enum): + X = 1, 2, 3 + Y = 4, 5, 6 + + +assert_type(EnumOfTuples((1, 2, 3)), EnumOfTuples) + +# TODO: ideally this test would pass: +# +# if sys.version_info >= (3, 12): +# assert_type(EnumOfTuples(1, 2, 3), EnumOfTuples) + + if sys.version_info >= (3, 11): class Foo(enum.StrEnum): diff --git a/tests/stubtest_allowlists/py312.txt b/tests/stubtest_allowlists/py312.txt index 606c63212..80e6e1721 100644 --- a/tests/stubtest_allowlists/py312.txt +++ b/tests/stubtest_allowlists/py312.txt @@ -1,9 +1,3 @@ -# Uncategorised, from Python 3.12 -enum.Enum.__signature__ -enum.EnumMeta.__call__ -enum.EnumType.__call__ -enum.property.member - # Errors that also existed on Python 3.11 _collections_abc.AsyncIterable.__class_getitem__ _collections_abc.Awaitable.__class_getitem__