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