FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

Update enum from CPython 3.15.0rc2 by youknowdot · Pull Request #8942 · RustPython/RustPython · GitHub

Repository navigation

Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension .py  (2) All 1 file type selected
Viewed files
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Unified
Split
Hide whitespace
Diff view
Unified
Split
Hide whitespace
43 changes: 36 additions & 7 deletions Lib/enum.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,15 @@
'FlagBoundary', 'STRICT', 'CONFORM', 'EJECT', 'KEEP',
'global_flag_repr', 'global_enum_repr', 'global_str', 'global_enum',
'EnumCheck', 'CONTINUOUS', 'NAMED_FLAGS', 'UNIQUE',
'pickle_by_global_name', 'pickle_by_enum_name',
'pickle_by_global_name', 'pickle_by_enum_name', 'show_flag_values',
'bin',
]


# Dummy value for Enum and Flag as there are explicit checks for them
# before they have been created.
# This is also why there are checks in EnumType like `if Enum is not None`
Enum = Flag = EJECT = _stdlib_enums = ReprEnum = None
Enum = Flag = EJECT = ReprEnum = None

class nonmember(object):
"""
Expand Down Expand Up @@ -536,7 +537,7 @@ def __new__(metacls, cls, bases, classdict, *, boundary=None, _simple=False, **k
# now set the __repr__ for the value
classdict['_value_repr_'] = metacls._find_data_repr_(cls, bases)
#
# Flag structures (will be removed if final class is not a Flag
# Flag structures (will be removed if final class is not a Flag)
classdict['_boundary_'] = (
boundary
or getattr(first_enum, '_boundary_', None)
Expand All @@ -545,6 +546,29 @@ def __new__(metacls, cls, bases, classdict, *, boundary=None, _simple=False, **k
classdict['_singles_mask_'] = 0
classdict['_all_bits_'] = 0
classdict['_inverted_'] = None
# check for negative flag values and invert if found (using _proto_members)
if Flag is not None and bases and issubclass(bases[-1], Flag):
bits = 0
inverted = []
for n in member_names:
p = classdict[n]
if isinstance(p.value, int):
if p.value < 0:
inverted.append(p)
else:
bits |= p.value
elif p.value is None:
pass
elif isinstance(p.value, tuple) and p.value and isinstance(p.value[0], int):
if p.value[0] < 0:
inverted.append(p)
else:
bits |= p.value[0]
for p in inverted:
if isinstance(p.value, int):
p.value = bits & p.value
else:
p.value = (bits & p.value[0], ) + p.value[1:]
try:
classdict['_%s__in_progress' % cls] = True
enum_class = super().__new__(metacls, cls, bases, classdict, **kwds)
Expand Down Expand Up @@ -752,12 +776,16 @@ def __delattr__(cls, attr):
super().__delattr__(attr)

def __dir__(cls):
if issubclass(cls, Flag):
members = list(cls._member_map_.keys())
else:
members = cls._member_names_
interesting = set([
'__class__', '__contains__', '__doc__', '__getitem__',
'__iter__', '__len__', '__members__', '__module__',
'__name__', '__qualname__',
]
+ cls._member_names_
+ members
)
if cls._new_member_ is not object.__new__:
interesting.add('__new__')
Expand Down Expand Up @@ -1489,7 +1517,10 @@ def _missing_(cls, value):
)
if value < 0:
neg_value = value
value = all_bits + 1 + value
if cls._boundary_ in (EJECT, KEEP):
value = all_bits + 1 + value
else:
value = singles_mask & value
# get members and unknown
unknown = value & ~flag_mask
aliases = value & ~singles_mask
Expand Down Expand Up @@ -2165,5 +2196,3 @@ def _old_convert_(etype, name, module, filter, source=None, *, boundary=None):
members.sort(key=lambda t: t[0])
cls = etype(name, members, module=module, boundary=boundary or KEEP)
return cls

_stdlib_enums = IntEnum, StrEnum, IntFlag
47 changes: 44 additions & 3 deletions Lib/test/test_enum.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -1002,12 +1002,18 @@ class OpenAB(self.enum_type):
self.assertIs(~(A|B), OpenAB(252))
self.assertIs(~AB_MASK, OpenAB(0))
self.assertIs(~OpenAB(0), AB_MASK)
self.assertIs(OpenAB(~4), OpenAB(251))
else:
self.assertIs(~A, B)
self.assertIs(~B, A)
self.assertIs(OpenAB(~1), B)
self.assertIs(OpenAB(~2), A)
self.assertIs(~(A|B), OpenAB(0))
self.assertIs(~AB_MASK, OpenAB(0))
self.assertIs(~OpenAB(0), (A|B))
self.assertIs(OpenAB(~3), OpenAB(0))
self.assertIs(OpenAB(~4), OpenAB(3))
self.assertIs(OpenAB(~33), B)
#
class OpenXYZ(self.enum_type):
X = 4
Expand All @@ -1031,13 +1037,38 @@ class OpenXYZ(self.enum_type):
self.assertIs(~X, Y|Z)
self.assertIs(~Y, X|Z)
self.assertIs(~Z, X|Y)
self.assertIs(OpenXYZ(~4), Y|Z)
self.assertIs(OpenXYZ(~2), X|Z)
self.assertIs(OpenXYZ(~1), X|Y)
self.assertIs(~(X|Y), Z)
self.assertIs(~(X|Z), Y)
self.assertIs(~(Y|Z), X)
self.assertIs(~(X|Y|Z), OpenXYZ(0))
self.assertIs(~XYZ_MASK, OpenXYZ(0))
self.assertTrue(~OpenXYZ(0), (X|Y|Z))

def test_assigned_negative_value(self):
class X(self.enum_type):
A = auto()
B = auto()
C = A | B
D = ~A
self.assertEqual(list(X), [X.A, X.B])
self.assertIs(~X.A, X.B)
self.assertIs(X.D, X.B)
self.assertEqual(X.D.value, 2)
#
class Y(self.enum_type):
A = auto()
B = auto()
C = A | B
D = ~A
E = auto()
self.assertEqual(list(Y), [Y.A, Y.B, Y.E])
self.assertIs(~Y.A, Y.B|Y.E)
self.assertIs(Y.D, Y.B|Y.E)
self.assertEqual(Y.D.value, 6)


class TestPlainEnumClass(_EnumTests, _PlainOutputTests, unittest.TestCase):
enum_type = Enum
Expand Down Expand Up @@ -3682,6 +3713,8 @@ class SkipFlag(enum.Flag):
C = 4 | B
#
self.assertTrue(SkipFlag.C in (SkipFlag.A|SkipFlag.C))
self.assertTrue(SkipFlag.B in SkipFlag.C)
self.assertIs(SkipFlag(~1), SkipFlag.B)
self.assertRaisesRegex(ValueError, 'SkipFlag.. invalid value 42', SkipFlag, 42)
#
class SkipIntFlag(enum.IntFlag):
Expand All @@ -3690,6 +3723,8 @@ class SkipIntFlag(enum.IntFlag):
C = 4 | B
#
self.assertTrue(SkipIntFlag.C in (SkipIntFlag.A|SkipIntFlag.C))
self.assertTrue(SkipIntFlag.B in SkipIntFlag.C)
self.assertIs(SkipIntFlag(~1), SkipIntFlag.B|SkipIntFlag.C)
self.assertEqual(SkipIntFlag(42).value, 42)
#
class MethodHint(Flag):
Expand Down Expand Up @@ -4729,6 +4764,8 @@ class Color(Flag):
BLUE = 4
WHITE = -1
# no error means success
self.assertEqual(list(Color.WHITE), [Color.RED, Color.GREEN, Color.BLUE])
self.assertEqual(Color.WHITE.value, 7)


class TestInternals(unittest.TestCase):
Expand Down Expand Up @@ -4852,7 +4889,7 @@ class Color(Enum):
def _generate_next_value_(name, start, count, last):
return name

def test_auto_order_wierd(self):
def test_auto_order_weird(self):
weird_auto = auto()
weird_auto.value = 'pathological case'
class Color(Enum):
Expand Down Expand Up @@ -5289,7 +5326,7 @@ def __new__(cls, value, label):
class MiscTestCase(unittest.TestCase):

def test__all__(self):
support.check__all__(self, enum, not_exported={'bin', 'show_flag_values'})
support.check__all__(self, enum)

@cpython_only
def test_lazy_import(self):
Expand Down Expand Up @@ -5494,12 +5531,16 @@ def test_enum_dict_standalone(self):
# helpers

def enum_dir(cls):
if issubclass(cls, Flag):
members = list(cls._member_map_.keys())
else:
members = cls._member_names_
interesting = set([
'__class__', '__contains__', '__doc__', '__getitem__',
'__iter__', '__len__', '__members__', '__module__',
'__name__', '__qualname__',
]
+ cls._member_names_
+ members
)
if cls._new_member_ is not object.__new__:
interesting.add('__new__')
Expand Down
Loading

Back | FazBrowse Home | New Git URL