lib.enum: honor enum.nonmember.

Use _EnumDict._member_names to determine which members to consider.
This way we don't need to redo sunder/dunder checks, and `nonmember`s
(introduced in py3.11) are correctly excluded.

This is a defacto public API, given it remains usable from py3.8
until py3.12 inclusive.  (_member_names changes from a list to a
keys-only dict for performance reasons in py3.11, but they iterate the
same.) In current Python main (i.e. what will most likely be 3.13), a
"member_names" property is added which returns those keys.
This commit is contained in:
Amelia Cuss 2024-02-19 18:45:44 +11:00 committed by Catherine
parent 890e099ec3
commit c40cfc9fb5
2 changed files with 24 additions and 3 deletions

View file

@ -41,9 +41,9 @@ class EnumMeta(ShapeCastable, py_enum.EnumMeta):
# Prepare enumeration members for instantiation. This logic is unfortunately very
# convoluted because it supports two very different code paths that need to share
# the emitted warnings.
for member_name, member_value in namespace.items():
if py_enum._is_sunder(member_name) or py_enum._is_dunder(member_name):
continue
# TODO(py3.13): can use `namespace.member_names` property.
for member_name in namespace._member_names:
member_value = namespace[member_name]
# If a shape is specified ("Amaranth mode" of amaranth.lib.enum.Enum), then every
# member value must be a constant-castable expression. Otherwise ("Python mode" of
# amaranth.lib.enum.Enum) any value goes, since all enumerations accepted by