eric6/ThirdParty/enum/__init__.py

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

eric ide

mercurial