diff options
Diffstat (limited to 'Lib/enum.py')
| -rw-r--r-- | Lib/enum.py | 34 | 
1 files changed, 23 insertions, 11 deletions
| diff --git a/Lib/enum.py b/Lib/enum.py index 7cb9d45b32..b8787d19b8 100644 --- a/Lib/enum.py +++ b/Lib/enum.py @@ -106,12 +106,20 @@ class EnumMeta(type):              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)          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.          enum_class._value2member_map_ = {} @@ -165,6 +173,11 @@ 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 @@ -199,7 +212,7 @@ class EnumMeta(type):          """          return True -    def __call__(cls, value, names=None, *, module=None, qualname=None, type=None): +    def __call__(cls, value, names=None, *, module=None, qualname=None, type=None, start=1):          """Either returns an existing member, or creates a new enum class.          This method is used both when an enum class is given a value to match @@ -211,7 +224,7 @@ class EnumMeta(type):          `value` will be the name of the new class.          `names` should be either a string of white-space/comma delimited names -        (values will start at 1), or an iterator/mapping of name, value pairs. +        (values will start at `start`), or an iterator/mapping of name, value pairs.          `module` should be set to the module this class is being created in;          if it is not set, an attempt to find that module will be made, but if @@ -227,7 +240,7 @@ class EnumMeta(type):          if names is None:  # simple value lookup              return cls.__new__(cls, value)          # otherwise, functional API: we're creating a new Enum type -        return cls._create_(value, names, module=module, qualname=qualname, type=type) +        return cls._create_(value, names, module=module, qualname=qualname, type=type, start=start)      def __contains__(cls, member):          return isinstance(member, cls) and member._name_ in cls._member_map_ @@ -298,16 +311,16 @@ class EnumMeta(type):              raise AttributeError('Cannot reassign members.')          super().__setattr__(name, value) -    def _create_(cls, class_name, names=None, *, module=None, qualname=None, type=None): +    def _create_(cls, class_name, names=None, *, module=None, qualname=None, type=None, start=1):          """Convenience method to create a new Enum class.          `names` can be:          * A string containing member names, separated either with spaces or -          commas.  Values are auto-numbered from 1. -        * An iterable of member names.  Values are auto-numbered from 1. +          commas.  Values are incremented by 1 from `start`. +        * An iterable of member names.  Values are incremented by 1 from `start`.          * An iterable of (member name, value) pairs. -        * A mapping of member name -> value. +        * A mapping of member name -> value pairs.          """          metacls = cls.__class__ @@ -318,7 +331,7 @@ class EnumMeta(type):          if isinstance(names, str):              names = names.replace(',', ' ').split()          if isinstance(names, (tuple, list)) and isinstance(names[0], str): -            names = [(e, i) for (i, e) in enumerate(names, 1)] +            names = [(e, i) for (i, e) in enumerate(names, start)]          # Here, names is either an iterable of (name, value) or a mapping.          for item in names: @@ -474,10 +487,9 @@ class Enum(metaclass=EnumMeta):                  m                  for cls in self.__class__.mro()                  for m in cls.__dict__ -                if m[0] != '_' +                if m[0] != '_' and m not in self._member_map_                  ] -        return (['__class__', '__doc__', '__module__', 'name', 'value'] + -                added_behavior) +        return (['__class__', '__doc__', '__module__'] + added_behavior)      def __format__(self, format_spec):          # mixed-in Enums should use the mixed-in type's __format__, otherwise | 
