1"""Python Enumerations"""
2
3import sys as _sys
4
5__all__ = ['Enum', 'IntEnum', 'unique']
6
7version = 1, 1, 6
8
9pyver = float('%s.%s' % _sys.version_info[:2])
10
11try:
12    any
13except NameError:
14    def any(iterable):
15        for element in iterable:
16            if element:
17                return True
18        return False
19
20try:
21    from collections import OrderedDict
22except ImportError:
23    OrderedDict = None
24
25try:
26    basestring
27except NameError:
28    # In Python 2 basestring is the ancestor of both str and unicode
29    # in Python 3 it's just str, but was missing in 3.1
30    basestring = str
31
32try:
33    unicode
34except NameError:
35    # In Python 3 unicode no longer exists (it's just str)
36    unicode = str
37
38class _RouteClassAttributeToGetattr(object):
39    """Route attribute access on a class to __getattr__.
40
41    This is a descriptor, used to define attributes that act differently when
42    accessed through an instance and through a class.  Instance access remains
43    normal, but access to an attribute through a class will be routed to the
44    class's __getattr__ method; this is done by raising AttributeError.
45
46    """
47    def __init__(self, fget=None):
48        self.fget = fget
49
50    def __get__(self, instance, ownerclass=None):
51        if instance is None:
52            raise AttributeError()
53        return self.fget(instance)
54
55    def __set__(self, instance, value):
56        raise AttributeError("can't set attribute")
57
58    def __delete__(self, instance):
59        raise AttributeError("can't delete attribute")
60
61
62def _is_descriptor(obj):
63    """Returns True if obj is a descriptor, False otherwise."""
64    return (
65            hasattr(obj, '__get__') or
66            hasattr(obj, '__set__') or
67            hasattr(obj, '__delete__'))
68
69
70def _is_dunder(name):
71    """Returns True if a __dunder__ name, False otherwise."""
72    return (name[:2] == name[-2:] == '__' and
73            name[2:3] != '_' and
74            name[-3:-2] != '_' and
75            len(name) > 4)
76
77
78def _is_sunder(name):
79    """Returns True if a _sunder_ name, False otherwise."""
80    return (name[0] == name[-1] == '_' and
81            name[1:2] != '_' and
82            name[-2:-1] != '_' and
83            len(name) > 2)
84
85
86def _make_class_unpicklable(cls):
87    """Make the given class un-picklable."""
88    def _break_on_call_reduce(self, protocol=None):
89        raise TypeError('%r cannot be pickled' % self)
90    cls.__reduce_ex__ = _break_on_call_reduce
91    cls.__module__ = '<unknown>'
92
93
94class _EnumDict(dict):
95    """Track enum member order and ensure member names are not reused.
96
97    EnumMeta will use the names found in self._member_names as the
98    enumeration member names.
99
100    """
101    def __init__(self):
102        super(_EnumDict, self).__init__()
103        self._member_names = []
104
105    def __setitem__(self, key, value):
106        """Changes anything not dundered or not a descriptor.
107
108        If a descriptor is added with the same name as an enum member, the name
109        is removed from _member_names (this may leave a hole in the numerical
110        sequence of values).
111
112        If an enum member name is used twice, an error is raised; duplicate
113        values are not checked for.
114
115        Single underscore (sunder) names are reserved.
116
117        Note:   in 3.x __order__ is simply discarded as a not necessary piece
118                leftover from 2.x
119
120        """
121        if pyver >= 3.0 and key in ('_order_', '__order__'):
122            return
123        elif key == '__order__':
124            key = '_order_'
125        if _is_sunder(key):
126            if key != '_order_':
127                raise ValueError('_names_ are reserved for future Enum use')
128        elif _is_dunder(key):
129            pass
130        elif key in self._member_names:
131            # descriptor overwriting an enum?
132            raise TypeError('Attempted to reuse key: %r' % key)
133        elif not _is_descriptor(value):
134            if key in self:
135                # enum overwriting a descriptor?
136                raise TypeError('Key already defined as: %r' % self[key])
137            self._member_names.append(key)
138        super(_EnumDict, self).__setitem__(key, value)
139
140
141# Dummy value for Enum as EnumMeta explicity checks for it, but of course until
142# EnumMeta finishes running the first time the Enum class doesn't exist.  This
143# is also why there are checks in EnumMeta like `if Enum is not None`
144Enum = None
145
146
147class EnumMeta(type):
148    """Metaclass for Enum"""
149    @classmethod
150    def __prepare__(metacls, cls, bases):
151        return _EnumDict()
152
153    def __new__(metacls, cls, bases, classdict):
154        # an Enum class is final once enumeration items have been defined; it
155        # cannot be mixed with other types (int, float, etc.) if it has an
156        # inherited __new__ unless a new __new__ is defined (or the resulting
157        # class will fail).
158        if type(classdict) is dict:
159            original_dict = classdict
160            classdict = _EnumDict()
161            for k, v in original_dict.items():
162                classdict[k] = v
163
164        member_type, first_enum = metacls._get_mixins_(bases)
165        __new__, save_new, use_args = metacls._find_new_(classdict, member_type,
166                                                        first_enum)
167        # save enum items into separate mapping so they don't get baked into
168        # the new class
169        members = dict((k, classdict[k]) for k in classdict._member_names)
170        for name in classdict._member_names:
171            del classdict[name]
172
173        # py2 support for definition order
174        _order_ = classdict.get('_order_')
175        if _order_ is None:
176            if pyver < 3.0:
177                try:
178                    _order_ = [name for (name, value) in sorted(members.items(), key=lambda item: item[1])]
179                except TypeError:
180                    _order_ = [name for name in sorted(members.keys())]
181            else:
182                _order_ = classdict._member_names
183        else:
184            del classdict['_order_']
185            if pyver < 3.0:
186                _order_ = _order_.replace(',', ' ').split()
187                aliases = [name for name in members if name not in _order_]
188                _order_ += aliases
189
190        # check for illegal enum names (any others?)
191        invalid_names = set(members) & set(['mro'])
192        if invalid_names:
193            raise ValueError('Invalid enum member name(s): %s' % (
194                ', '.join(invalid_names), ))
195
196        # save attributes from super classes so we know if we can take
197        # the shortcut of storing members in the class dict
198        base_attributes = set([a for b in bases for a in b.__dict__])
199        # create our new Enum type
200        enum_class = super(EnumMeta, metacls).__new__(metacls, cls, bases, classdict)
201        enum_class._member_names_ = []               # names in random order
202        if OrderedDict is not None:
203            enum_class._member_map_ = OrderedDict()
204        else:
205            enum_class._member_map_ = {}             # name->value map
206        enum_class._member_type_ = member_type
207
208        # Reverse value->name map for hashable values.
209        enum_class._value2member_map_ = {}
210
211        # instantiate them, checking for duplicates as we go
212        # we instantiate first instead of checking for duplicates first in case
213        # a custom __new__ is doing something funky with the values -- such as
214        # auto-numbering ;)
215        if __new__ is None:
216            __new__ = enum_class.__new__
217        for member_name in _order_:
218            value = members[member_name]
219            if not isinstance(value, tuple):
220                args = (value, )
221            else:
222                args = value
223            if member_type is tuple:   # special case for tuple enums
224                args = (args, )     # wrap it one more time
225            if not use_args or not args:
226                enum_member = __new__(enum_class)
227                if not hasattr(enum_member, '_value_'):
228                    enum_member._value_ = value
229            else:
230                enum_member = __new__(enum_class, *args)
231                if not hasattr(enum_member, '_value_'):
232                    enum_member._value_ = member_type(*args)
233            value = enum_member._value_
234            enum_member._name_ = member_name
235            enum_member.__objclass__ = enum_class
236            enum_member.__init__(*args)
237            # If another member with the same value was already defined, the
238            # new member becomes an alias to the existing one.
239            for name, canonical_member in enum_class._member_map_.items():
240                if canonical_member.value == enum_member._value_:
241                    enum_member = canonical_member
242                    break
243            else:
244                # Aliases don't appear in member names (only in __members__).
245                enum_class._member_names_.append(member_name)
246            # performance boost for any member that would not shadow
247            # a DynamicClassAttribute (aka _RouteClassAttributeToGetattr)
248            if member_name not in base_attributes:
249                setattr(enum_class, member_name, enum_member)
250            # now add to _member_map_
251            enum_class._member_map_[member_name] = enum_member
252            try:
253                # This may fail if value is not hashable. We can't add the value
254                # to the map, and by-value lookups for this value will be
255                # linear.
256                enum_class._value2member_map_[value] = enum_member
257            except TypeError:
258                pass
259
260
261        # If a custom type is mixed into the Enum, and it does not know how
262        # to pickle itself, pickle.dumps will succeed but pickle.loads will
263        # fail.  Rather than have the error show up later and possibly far
264        # from the source, sabotage the pickle protocol for this class so
265        # that pickle.dumps also fails.
266        #
267        # However, if the new class implements its own __reduce_ex__, do not
268        # sabotage -- it's on them to make sure it works correctly.  We use
269        # __reduce_ex__ instead of any of the others as it is preferred by
270        # pickle over __reduce__, and it handles all pickle protocols.
271        unpicklable = False
272        if '__reduce_ex__' not in classdict:
273            if member_type is not object:
274                methods = ('__getnewargs_ex__', '__getnewargs__',
275                        '__reduce_ex__', '__reduce__')
276                if not any(m in member_type.__dict__ for m in methods):
277                    _make_class_unpicklable(enum_class)
278                    unpicklable = True
279
280
281        # double check that repr and friends are not the mixin's or various
282        # things break (such as pickle)
283        for name in ('__repr__', '__str__', '__format__', '__reduce_ex__'):
284            class_method = getattr(enum_class, name)
285            obj_method = getattr(member_type, name, None)
286            enum_method = getattr(first_enum, name, None)
287            if name not in classdict and class_method is not enum_method:
288                if name == '__reduce_ex__' and unpicklable:
289                    continue
290                setattr(enum_class, name, enum_method)
291
292        # method resolution and int's are not playing nice
293        # Python's less than 2.6 use __cmp__
294
295        if pyver < 2.6:
296
297            if issubclass(enum_class, int):
298                setattr(enum_class, '__cmp__', getattr(int, '__cmp__'))
299
300        elif pyver < 3.0:
301
302            if issubclass(enum_class, int):
303                for method in (
304                        '__le__',
305                        '__lt__',
306                        '__gt__',
307                        '__ge__',
308                        '__eq__',
309                        '__ne__',
310                        '__hash__',
311                        ):
312                    setattr(enum_class, method, getattr(int, method))
313
314        # replace any other __new__ with our own (as long as Enum is not None,
315        # anyway) -- again, this is to support pickle
316        if Enum is not None:
317            # if the user defined their own __new__, save it before it gets
318            # clobbered in case they subclass later
319            if save_new:
320                setattr(enum_class, '__member_new__', enum_class.__dict__['__new__'])
321            setattr(enum_class, '__new__', Enum.__dict__['__new__'])
322        return enum_class
323
324    def __bool__(cls):
325        """
326        classes/types should always be True.
327        """
328        return True
329
330    def __call__(cls, value, names=None, module=None, type=None, start=1):
331        """Either returns an existing member, or creates a new enum class.
332
333        This method is used both when an enum class is given a value to match
334        to an enumeration member (i.e. Color(3)) and for the functional API
335        (i.e. Color = Enum('Color', names='red green blue')).
336
337        When used for the functional API: `module`, if set, will be stored in
338        the new class' __module__ attribute; `type`, if set, will be mixed in
339        as the first base class.
340
341        Note: if `module` is not set this routine will attempt to discover the
342        calling module by walking the frame stack; if this is unsuccessful
343        the resulting class will not be pickleable.
344
345        """
346        if names is None:  # simple value lookup
347            return cls.__new__(cls, value)
348        # otherwise, functional API: we're creating a new Enum type
349        return cls._create_(value, names, module=module, type=type, start=start)
350
351    def __contains__(cls, member):
352        return isinstance(member, cls) and member.name in cls._member_map_
353
354    def __delattr__(cls, attr):
355        # nicer error message when someone tries to delete an attribute
356        # (see issue19025).
357        if attr in cls._member_map_:
358            raise AttributeError(
359                    "%s: cannot delete Enum member." % cls.__name__)
360        super(EnumMeta, cls).__delattr__(attr)
361
362    def __dir__(self):
363        return (['__class__', '__doc__', '__members__', '__module__'] +
364                self._member_names_)
365
366    @property
367    def __members__(cls):
368        """Returns a mapping of member name->value.
369
370        This mapping lists all enum members, including aliases. Note that this
371        is a copy of the internal mapping.
372
373        """
374        return cls._member_map_.copy()
375
376    def __getattr__(cls, name):
377        """Return the enum member matching `name`
378
379        We use __getattr__ instead of descriptors or inserting into the enum
380        class' __dict__ in order to support `name` and `value` being both
381        properties for enum members (which live in the class' __dict__) and
382        enum members themselves.
383
384        """
385        if _is_dunder(name):
386            raise AttributeError(name)
387        try:
388            return cls._member_map_[name]
389        except KeyError:
390            raise AttributeError(name)
391
392    def __getitem__(cls, name):
393        return cls._member_map_[name]
394
395    def __iter__(cls):
396        return (cls._member_map_[name] for name in cls._member_names_)
397
398    def __reversed__(cls):
399        return (cls._member_map_[name] for name in reversed(cls._member_names_))
400
401    def __len__(cls):
402        return len(cls._member_names_)
403
404    __nonzero__ = __bool__
405
406    def __repr__(cls):
407        return "<enum %r>" % cls.__name__
408
409    def __setattr__(cls, name, value):
410        """Block attempts to reassign Enum members.
411
412        A simple assignment to the class namespace only changes one of the
413        several possible ways to get an Enum member from the Enum class,
414        resulting in an inconsistent Enumeration.
415
416        """
417        member_map = cls.__dict__.get('_member_map_', {})
418        if name in member_map:
419            raise AttributeError('Cannot reassign members.')
420        super(EnumMeta, cls).__setattr__(name, value)
421
422    def _create_(cls, class_name, names=None, module=None, type=None, start=1):
423        """Convenience method to create a new Enum class.
424
425        `names` can be:
426
427        * A string containing member names, separated either with spaces or
428          commas.  Values are auto-numbered from 1.
429        * An iterable of member names.  Values are auto-numbered from 1.
430        * An iterable of (member name, value) pairs.
431        * A mapping of member name -> value.
432
433        """
434        if pyver < 3.0:
435            # if class_name is unicode, attempt a conversion to ASCII
436            if isinstance(class_name, unicode):
437                try:
438                    class_name = class_name.encode('ascii')
439                except UnicodeEncodeError:
440                    raise TypeError('%r is not representable in ASCII' % class_name)
441        metacls = cls.__class__
442        if type is None:
443            bases = (cls, )
444        else:
445            bases = (type, cls)
446        classdict = metacls.__prepare__(class_name, bases)
447        _order_ = []
448
449        # special processing needed for names?
450        if isinstance(names, basestring):
451            names = names.replace(',', ' ').split()
452        if isinstance(names, (tuple, list)) and isinstance(names[0], basestring):
453            names = [(e, i+start) for (i, e) in enumerate(names)]
454
455        # Here, names is either an iterable of (name, value) or a mapping.
456        item = None  # in case names is empty
457        for item in names:
458            if isinstance(item, basestring):
459                member_name, member_value = item, names[item]
460            else:
461                member_name, member_value = item
462            classdict[member_name] = member_value
463            _order_.append(member_name)
464        # only set _order_ in classdict if name/value was not from a mapping
465        if not isinstance(item, basestring):
466            classdict['_order_'] = ' '.join(_order_)
467        enum_class = metacls.__new__(metacls, class_name, bases, classdict)
468
469        # TODO: replace the frame hack if a blessed way to know the calling
470        # module is ever developed
471        if module is None:
472            try:
473                module = _sys._getframe(2).f_globals['__name__']
474            except (AttributeError, ValueError):
475                pass
476        if module is None:
477            _make_class_unpicklable(enum_class)
478        else:
479            enum_class.__module__ = module
480
481        return enum_class
482
483    @staticmethod
484    def _get_mixins_(bases):
485        """Returns the type for creating enum members, and the first inherited
486        enum class.
487
488        bases: the tuple of bases that was given to __new__
489
490        """
491        if not bases or Enum is None:
492            return object, Enum
493
494
495        # double check that we are not subclassing a class with existing
496        # enumeration members; while we're at it, see if any other data
497        # type has been mixed in so we can use the correct __new__
498        member_type = first_enum = None
499        for base in bases:
500            if  (base is not Enum and
501                    issubclass(base, Enum) and
502                    base._member_names_):
503                raise TypeError("Cannot extend enumerations")
504        # base is now the last base in bases
505        if not issubclass(base, Enum):
506            raise TypeError("new enumerations must be created as "
507                    "`ClassName([mixin_type,] enum_type)`")
508
509        # get correct mix-in type (either mix-in type of Enum subclass, or
510        # first base if last base is Enum)
511        if not issubclass(bases[0], Enum):
512            member_type = bases[0]     # first data type
513            first_enum = bases[-1]  # enum type
514        else:
515            for base in bases[0].__mro__:
516                # most common: (IntEnum, int, Enum, object)
517                # possible:    (<Enum 'AutoIntEnum'>, <Enum 'IntEnum'>,
518                #               <class 'int'>, <Enum 'Enum'>,
519                #               <class 'object'>)
520                if issubclass(base, Enum):
521                    if first_enum is None:
522                        first_enum = base
523                else:
524                    if member_type is None:
525                        member_type = base
526
527        return member_type, first_enum
528
529    if pyver < 3.0:
530        @staticmethod
531        def _find_new_(classdict, member_type, first_enum):
532            """Returns the __new__ to be used for creating the enum members.
533
534            classdict: the class dictionary given to __new__
535            member_type: the data type whose __new__ will be used by default
536            first_enum: enumeration to check for an overriding __new__
537
538            """
539            # now find the correct __new__, checking to see of one was defined
540            # by the user; also check earlier enum classes in case a __new__ was
541            # saved as __member_new__
542            __new__ = classdict.get('__new__', None)
543            if __new__:
544                return None, True, True      # __new__, save_new, use_args
545
546            N__new__ = getattr(None, '__new__')
547            O__new__ = getattr(object, '__new__')
548            if Enum is None:
549                E__new__ = N__new__
550            else:
551                E__new__ = Enum.__dict__['__new__']
552            # check all possibles for __member_new__ before falling back to
553            # __new__
554            for method in ('__member_new__', '__new__'):
555                for possible in (member_type, first_enum):
556                    try:
557                        target = possible.__dict__[method]
558                    except (AttributeError, KeyError):
559                        target = getattr(possible, method, None)
560                    if target not in [
561                            None,
562                            N__new__,
563                            O__new__,
564                            E__new__,
565                            ]:
566                        if method == '__member_new__':
567                            classdict['__new__'] = target
568                            return None, False, True
569                        if isinstance(target, staticmethod):
570                            target = target.__get__(member_type)
571                        __new__ = target
572                        break
573                if __new__ is not None:
574                    break
575            else:
576                __new__ = object.__new__
577
578            # if a non-object.__new__ is used then whatever value/tuple was
579            # assigned to the enum member name will be passed to __new__ and to the
580            # new enum member's __init__
581            if __new__ is object.__new__:
582                use_args = False
583            else:
584                use_args = True
585
586            return __new__, False, use_args
587    else:
588        @staticmethod
589        def _find_new_(classdict, member_type, first_enum):
590            """Returns the __new__ to be used for creating the enum members.
591
592            classdict: the class dictionary given to __new__
593            member_type: the data type whose __new__ will be used by default
594            first_enum: enumeration to check for an overriding __new__
595
596            """
597            # now find the correct __new__, checking to see of one was defined
598            # by the user; also check earlier enum classes in case a __new__ was
599            # saved as __member_new__
600            __new__ = classdict.get('__new__', None)
601
602            # should __new__ be saved as __member_new__ later?
603            save_new = __new__ is not None
604
605            if __new__ is None:
606                # check all possibles for __member_new__ before falling back to
607                # __new__
608                for method in ('__member_new__', '__new__'):
609                    for possible in (member_type, first_enum):
610                        target = getattr(possible, method, None)
611                        if target not in (
612                                None,
613                                None.__new__,
614                                object.__new__,
615                                Enum.__new__,
616                                ):
617                            __new__ = target
618                            break
619                    if __new__ is not None:
620                        break
621                else:
622                    __new__ = object.__new__
623
624            # if a non-object.__new__ is used then whatever value/tuple was
625            # assigned to the enum member name will be passed to __new__ and to the
626            # new enum member's __init__
627            if __new__ is object.__new__:
628                use_args = False
629            else:
630                use_args = True
631
632            return __new__, save_new, use_args
633
634
635########################################################
636# In order to support Python 2 and 3 with a single
637# codebase we have to create the Enum methods separately
638# and then use the `type(name, bases, dict)` method to
639# create the class.
640########################################################
641temp_enum_dict = {}
642temp_enum_dict['__doc__'] = "Generic enumeration.\n\n    Derive from this class to define new enumerations.\n\n"
643
644def __new__(cls, value):
645    # all enum instances are actually created during class construction
646    # without calling this method; this method is called by the metaclass'
647    # __call__ (i.e. Color(3) ), and by pickle
648    if type(value) is cls:
649        # For lookups like Color(Color.red)
650        value = value.value
651        #return value
652    # by-value search for a matching enum member
653    # see if it's in the reverse mapping (for hashable values)
654    try:
655        if value in cls._value2member_map_:
656            return cls._value2member_map_[value]
657    except TypeError:
658        # not there, now do long search -- O(n) behavior
659        for member in cls._member_map_.values():
660            if member.value == value:
661                return member
662    raise ValueError("%s is not a valid %s" % (value, cls.__name__))
663temp_enum_dict['__new__'] = __new__
664del __new__
665
666def __repr__(self):
667    return "<%s.%s: %r>" % (
668            self.__class__.__name__, self._name_, self._value_)
669temp_enum_dict['__repr__'] = __repr__
670del __repr__
671
672def __str__(self):
673    return "%s.%s" % (self.__class__.__name__, self._name_)
674temp_enum_dict['__str__'] = __str__
675del __str__
676
677if pyver >= 3.0:
678    def __dir__(self):
679        added_behavior = [
680                m
681                for cls in self.__class__.mro()
682                for m in cls.__dict__
683                if m[0] != '_' and m not in self._member_map_
684                ]
685        return (['__class__', '__doc__', '__module__', ] + added_behavior)
686    temp_enum_dict['__dir__'] = __dir__
687    del __dir__
688
689def __format__(self, format_spec):
690    # mixed-in Enums should use the mixed-in type's __format__, otherwise
691    # we can get strange results with the Enum name showing up instead of
692    # the value
693
694    # pure Enum branch
695    if self._member_type_ is object:
696        cls = str
697        val = str(self)
698    # mix-in branch
699    else:
700        cls = self._member_type_
701        val = self.value
702    return cls.__format__(val, format_spec)
703temp_enum_dict['__format__'] = __format__
704del __format__
705
706
707####################################
708# Python's less than 2.6 use __cmp__
709
710if pyver < 2.6:
711
712    def __cmp__(self, other):
713        if type(other) is self.__class__:
714            if self is other:
715                return 0
716            return -1
717        return NotImplemented
718        raise TypeError("unorderable types: %s() and %s()" % (self.__class__.__name__, other.__class__.__name__))
719    temp_enum_dict['__cmp__'] = __cmp__
720    del __cmp__
721
722else:
723
724    def __le__(self, other):
725        raise TypeError("unorderable types: %s() <= %s()" % (self.__class__.__name__, other.__class__.__name__))
726    temp_enum_dict['__le__'] = __le__
727    del __le__
728
729    def __lt__(self, other):
730        raise TypeError("unorderable types: %s() < %s()" % (self.__class__.__name__, other.__class__.__name__))
731    temp_enum_dict['__lt__'] = __lt__
732    del __lt__
733
734    def __ge__(self, other):
735        raise TypeError("unorderable types: %s() >= %s()" % (self.__class__.__name__, other.__class__.__name__))
736    temp_enum_dict['__ge__'] = __ge__
737    del __ge__
738
739    def __gt__(self, other):
740        raise TypeError("unorderable types: %s() > %s()" % (self.__class__.__name__, other.__class__.__name__))
741    temp_enum_dict['__gt__'] = __gt__
742    del __gt__
743
744
745def __eq__(self, other):
746    if type(other) is self.__class__:
747        return self is other
748    return NotImplemented
749temp_enum_dict['__eq__'] = __eq__
750del __eq__
751
752def __ne__(self, other):
753    if type(other) is self.__class__:
754        return self is not other
755    return NotImplemented
756temp_enum_dict['__ne__'] = __ne__
757del __ne__
758
759def __hash__(self):
760    return hash(self._name_)
761temp_enum_dict['__hash__'] = __hash__
762del __hash__
763
764def __reduce_ex__(self, proto):
765    return self.__class__, (self._value_, )
766temp_enum_dict['__reduce_ex__'] = __reduce_ex__
767del __reduce_ex__
768
769# _RouteClassAttributeToGetattr is used to provide access to the `name`
770# and `value` properties of enum members while keeping some measure of
771# protection from modification, while still allowing for an enumeration
772# to have members named `name` and `value`.  This works because enumeration
773# members are not set directly on the enum class -- __getattr__ is
774# used to look them up.
775
776@_RouteClassAttributeToGetattr
777def name(self):
778    return self._name_
779temp_enum_dict['name'] = name
780del name
781
782@_RouteClassAttributeToGetattr
783def value(self):
784    return self._value_
785temp_enum_dict['value'] = value
786del value
787
788@classmethod
789def _convert(cls, name, module, filter, source=None):
790    """
791    Create a new Enum subclass that replaces a collection of global constants
792    """
793    # convert all constants from source (or module) that pass filter() to
794    # a new Enum called name, and export the enum and its members back to
795    # module;
796    # also, replace the __reduce_ex__ method so unpickling works in
797    # previous Python versions
798    module_globals = vars(_sys.modules[module])
799    if source:
800        source = vars(source)
801    else:
802        source = module_globals
803    members = dict((name, value) for name, value in source.items() if filter(name))
804    cls = cls(name, members, module=module)
805    cls.__reduce_ex__ = _reduce_ex_by_name
806    module_globals.update(cls.__members__)
807    module_globals[name] = cls
808    return cls
809temp_enum_dict['_convert'] = _convert
810del _convert
811
812Enum = EnumMeta('Enum', (object, ), temp_enum_dict)
813del temp_enum_dict
814
815# Enum has now been created
816###########################
817
818class IntEnum(int, Enum):
819    """Enum where members are also (and must be) ints"""
820
821def _reduce_ex_by_name(self, proto):
822    return self.name
823
824def unique(enumeration):
825    """Class decorator that ensures only unique members exist in an enumeration."""
826    duplicates = []
827    for name, member in enumeration.__members__.items():
828        if name != member.name:
829            duplicates.append((name, member.name))
830    if duplicates:
831        duplicate_names = ', '.join(
832                ["%s -> %s" % (alias, name) for (alias, name) in duplicates]
833                )
834        raise ValueError('duplicate names found in %r: %s' %
835                (enumeration, duplicate_names)
836                )
837    return enumeration
838