diff options
Diffstat (limited to 'modules/language/python/module/enum.py')
-rw-r--r-- | modules/language/python/module/enum.py | 47 |
1 files changed, 24 insertions, 23 deletions
diff --git a/modules/language/python/module/enum.py b/modules/language/python/module/enum.py index 0f623f0..723fab7 100644 --- a/modules/language/python/module/enum.py +++ b/modules/language/python/module/enum.py @@ -50,14 +50,12 @@ def _make_class_unpicklable(cls): _auto_null = object() - class auto: """ Instances are replaced with an appropriate value in Enum class suites. """ value = _auto_null - class _EnumDict(dict): """Track enum member order and ensure member names are not reused. @@ -90,10 +88,10 @@ class _EnumDict(dict): elif _is_dunder(key): if key == '__order__': key = '_order_' - elif key in self._member_names: + elif (key in self._member_names): # descriptor overwriting an enum? raise TypeError('Attempted to reuse key: %r' % key) - elif not _is_descriptor(value): + elif (not _is_descriptor(value)): if key in self: # enum overwriting a descriptor? raise TypeError('%r already defined as: %r' % (key, self[key])) @@ -105,13 +103,12 @@ class _EnumDict(dict): self._last_values.append(value) super().__setitem__(key, value) - # Dummy value for Enum as EnumMeta explicitly checks for it, but of course # until EnumMeta finishes running the first time the Enum class doesn't exist. # This is also why there are checks in EnumMeta like `if Enum is not None` Enum = None - +pk('EnumMeta') class EnumMeta(type): """Metaclass for Enum""" @classmethod @@ -132,13 +129,15 @@ class EnumMeta(type): # cannot be mixed with other types (int, float, etc.) if it has an # inherited __new__ unless a new __new__ is defined (or the resulting # class will fail). + member_type, first_enum = metacls._get_mixins_(bases) - __new__, save_new, use_args = metacls._find_new_(classdict, member_type, - first_enum) + new, save_new, use_args = metacls._find_new_(classdict, member_type, + first_enum) # save enum items into separate mapping so they don't get baked into # the new class enum_members = {k: classdict[k] for k in classdict._member_names} + for name in classdict._member_names: del classdict[name] @@ -150,21 +149,19 @@ class EnumMeta(type): if invalid_names: raise ValueError('Invalid enum member name: {0}'.format( ','.join(invalid_names))) - + # create a default docstring if one has not been provided if '__doc__' not in classdict: classdict['__doc__'] = 'An enumeration.' # create our new Enum type enum_class = super().__new__(metacls, cls, bases, classdict) - pk(enum_class) enum_class._member_names_ = [] # names in definition order enum_class._member_map_ = OrderedDict() # name->value map enum_class._member_type_ = member_type # save attributes from super classes so we know if we can take # the shortcut of storing members in the class dict - base_attributes = {a for b in enum_class.mro() for a in b.__dict__} # Reverse value->name map for hashable values. @@ -197,14 +194,16 @@ class EnumMeta(type): args = (value, ) else: args = value + if member_type is tuple: # special case for tuple enums args = (args, ) # wrap it one more time + if not use_args: - enum_member = __new__(enum_class) + enum_member = new(enum_class) if not hasattr(enum_member, '_value_'): enum_member._value_ = value else: - enum_member = __new__(enum_class, *args) + enum_member = new(enum_class, *args) if not hasattr(enum_member, '_value_'): if member_type is object: enum_member._value_ = value @@ -214,6 +213,7 @@ class EnumMeta(type): enum_member._name_ = member_name enum_member.__objclass__ = enum_class enum_member.__init__(*args) + # If another member with the same value was already defined, the # new member becomes an alias to the existing one. for name, canonical_member in enum_class._member_map_.items(): @@ -223,11 +223,13 @@ class EnumMeta(type): else: # Aliases don't appear in member names (only in __members__). enum_class._member_names_.append(member_name) + # performance boost for any member that would not shadow # a DynamicClassAttribute if member_name not in base_attributes: setattr(enum_class, member_name, enum_member) # now add to _member_map_ + enum_class._member_map_[member_name] = enum_member try: # This may fail if value is not hashable. We can't add the value @@ -370,8 +372,6 @@ class EnumMeta(type): if name in member_map: raise AttributeError('Cannot reassign members.') - pk('set',name) - super().__setattr__(name, value) @@ -522,6 +522,7 @@ class EnumMeta(type): return __new__, save_new, use_args +pk('enum') class Enum(metaclass=EnumMeta): """Generic enumeration. @@ -529,7 +530,6 @@ class Enum(metaclass=EnumMeta): Derive from this class to define new enumerations. """ - pk(1) def __new__(cls, value): # all enum instances are actually created during class construction @@ -551,8 +551,6 @@ class Enum(metaclass=EnumMeta): # still not found -- try _missing_ hook return cls._missing_(value) - pk(2) - def _generate_next_value_(name, start, count, last_values): for last_value in reversed(last_values): try: @@ -562,8 +560,6 @@ class Enum(metaclass=EnumMeta): else: return start - pk(3) - @classmethod def _missing_(cls, value): raise ValueError("%r is not a valid %s" % (value, cls.__name__)) @@ -583,7 +579,7 @@ class Enum(metaclass=EnumMeta): if m[0] != '_' and m not in self._member_map_ ] return (['__class__', '__doc__', '__module__'] + added_behavior) - pk(4) + def __format__(self, format_spec): # mixed-in Enums should use the mixed-in type's __format__, otherwise # we can get strange results with the Enum name showing up instead of @@ -611,7 +607,7 @@ class Enum(metaclass=EnumMeta): # to have members named `name` and `value`. This works because enumeration # members are not set directly on the enum class -- __getattr__ is # used to look them up. - pk(5) + @DynamicClassAttribute def name(self): """The name of the Enum member.""" @@ -658,6 +654,7 @@ class Enum(metaclass=EnumMeta): module_globals[name] = cls return cls +pk('intenum') class IntEnum(int, Enum): """Enum where members are also (and must be) ints""" @@ -666,6 +663,7 @@ class IntEnum(int, Enum): def _reduce_ex_by_name(self, proto): return self.name +pk('flag') class Flag(Enum): """Support for flags""" @@ -773,7 +771,8 @@ class Flag(Enum): ] inverted = reduce(_or_, inverted_members, self.__class__(0)) return self.__class__(inverted) - + +pk('intflag') class IntFlag(int, Flag): """Support for integer-based Flags""" @@ -837,6 +836,8 @@ class IntFlag(int, Flag): def __invert__(self): result = self.__class__(~self._value_) return result + +pk('rest') def _high_bit(value): """returns index of highest bit, or -1 if value is zero or negative""" |