enum34-1.1.6/0000775000175000017500000000000012716237137013065 5ustar ethanethan00000000000000enum34-1.1.6/enum/0000775000175000017500000000000012716237137014031 5ustar ethanethan00000000000000enum34-1.1.6/enum/LICENSE0000664000175000017500000000274412716237133015041 0ustar ethanethan00000000000000Copyright (c) 2013, Ethan Furman. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name Ethan Furman nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. enum34-1.1.6/enum/__init__.py0000664000175000017500000007451612716237133016153 0ustar ethanethan00000000000000"""Python Enumerations""" import sys as _sys __all__ = ['Enum', 'IntEnum', 'unique'] version = 1, 1, 6 pyver = float('%s.%s' % _sys.version_info[:2]) try: any except NameError: def any(iterable): for element in iterable: if element: return True return False try: from collections import OrderedDict except ImportError: OrderedDict = None try: basestring except NameError: # In Python 2 basestring is the ancestor of both str and unicode # in Python 3 it's just str, but was missing in 3.1 basestring = str try: unicode except NameError: # In Python 3 unicode no longer exists (it's just str) unicode = str class _RouteClassAttributeToGetattr(object): """Route attribute access on a class to __getattr__. This is a descriptor, used to define attributes that act differently when accessed through an instance and through a class. Instance access remains normal, but access to an attribute through a class will be routed to the class's __getattr__ method; this is done by raising AttributeError. """ def __init__(self, fget=None): self.fget = fget def __get__(self, instance, ownerclass=None): if instance is None: raise AttributeError() return self.fget(instance) def __set__(self, instance, value): raise AttributeError("can't set attribute") def __delete__(self, instance): raise AttributeError("can't delete attribute") def _is_descriptor(obj): """Returns True if obj is a descriptor, False otherwise.""" return ( hasattr(obj, '__get__') or hasattr(obj, '__set__') or hasattr(obj, '__delete__')) def _is_dunder(name): """Returns True if a __dunder__ name, False otherwise.""" return (name[:2] == name[-2:] == '__' and name[2:3] != '_' and name[-3:-2] != '_' and len(name) > 4) def _is_sunder(name): """Returns True if a _sunder_ name, False otherwise.""" return (name[0] == name[-1] == '_' and name[1:2] != '_' and name[-2:-1] != '_' and len(name) > 2) def _make_class_unpicklable(cls): """Make the given class un-picklable.""" def _break_on_call_reduce(self, protocol=None): raise TypeError('%r cannot be pickled' % self) cls.__reduce_ex__ = _break_on_call_reduce cls.__module__ = '' class _EnumDict(dict): """Track enum member order and ensure member names are not reused. EnumMeta will use the names found in self._member_names as the enumeration member names. """ def __init__(self): super(_EnumDict, self).__init__() self._member_names = [] def __setitem__(self, key, value): """Changes anything not dundered or not a descriptor. If a descriptor is added with the same name as an enum member, the name is removed from _member_names (this may leave a hole in the numerical sequence of values). If an enum member name is used twice, an error is raised; duplicate values are not checked for. Single underscore (sunder) names are reserved. Note: in 3.x __order__ is simply discarded as a not necessary piece leftover from 2.x """ if pyver >= 3.0 and key in ('_order_', '__order__'): return elif key == '__order__': key = '_order_' if _is_sunder(key): if key != '_order_': raise ValueError('_names_ are reserved for future Enum use') elif _is_dunder(key): pass elif key in self._member_names: # descriptor overwriting an enum? raise TypeError('Attempted to reuse key: %r' % key) elif not _is_descriptor(value): if key in self: # enum overwriting a descriptor? raise TypeError('Key already defined as: %r' % self[key]) self._member_names.append(key) super(_EnumDict, self).__setitem__(key, value) # Dummy value for Enum as EnumMeta explicity checks for it, but of course until # EnumMeta finishes running the first time the Enum class doesn't exist. This # is also why there are checks in EnumMeta like `if Enum is not None` Enum = None class EnumMeta(type): """Metaclass for Enum""" @classmethod def __prepare__(metacls, cls, bases): return _EnumDict() def __new__(metacls, cls, bases, classdict): # an Enum class is final once enumeration items have been defined; it # cannot be mixed with other types (int, float, etc.) if it has an # inherited __new__ unless a new __new__ is defined (or the resulting # class will fail). if type(classdict) is dict: original_dict = classdict classdict = _EnumDict() for k, v in original_dict.items(): classdict[k] = v member_type, first_enum = metacls._get_mixins_(bases) __new__, save_new, use_args = metacls._find_new_(classdict, member_type, first_enum) # save enum items into separate mapping so they don't get baked into # the new class members = dict((k, classdict[k]) for k in classdict._member_names) for name in classdict._member_names: del classdict[name] # py2 support for definition order _order_ = classdict.get('_order_') if _order_ is None: if pyver < 3.0: try: _order_ = [name for (name, value) in sorted(members.items(), key=lambda item: item[1])] except TypeError: _order_ = [name for name in sorted(members.keys())] else: _order_ = classdict._member_names else: del classdict['_order_'] if pyver < 3.0: _order_ = _order_.replace(',', ' ').split() aliases = [name for name in members if name not in _order_] _order_ += aliases # check for illegal enum names (any others?) invalid_names = set(members) & set(['mro']) if invalid_names: raise ValueError('Invalid enum member name(s): %s' % ( ', '.join(invalid_names), )) # save attributes from super classes so we know if we can take # the shortcut of storing members in the class dict base_attributes = set([a for b in bases for a in b.__dict__]) # create our new Enum type enum_class = super(EnumMeta, metacls).__new__(metacls, cls, bases, classdict) enum_class._member_names_ = [] # names in random order if OrderedDict is not None: enum_class._member_map_ = OrderedDict() else: enum_class._member_map_ = {} # name->value map enum_class._member_type_ = member_type # Reverse value->name map for hashable values. enum_class._value2member_map_ = {} # instantiate them, checking for duplicates as we go # we instantiate first instead of checking for duplicates first in case # a custom __new__ is doing something funky with the values -- such as # auto-numbering ;) if __new__ is None: __new__ = enum_class.__new__ for member_name in _order_: value = members[member_name] if not isinstance(value, tuple): args = (value, ) else: args = value if member_type is tuple: # special case for tuple enums args = (args, ) # wrap it one more time if not use_args or not args: enum_member = __new__(enum_class) if not hasattr(enum_member, '_value_'): enum_member._value_ = value else: enum_member = __new__(enum_class, *args) if not hasattr(enum_member, '_value_'): enum_member._value_ = member_type(*args) value = enum_member._value_ enum_member._name_ = member_name enum_member.__objclass__ = enum_class enum_member.__init__(*args) # If another member with the same value was already defined, the # new member becomes an alias to the existing one. for name, canonical_member in enum_class._member_map_.items(): if canonical_member.value == enum_member._value_: enum_member = canonical_member break else: # Aliases don't appear in member names (only in __members__). enum_class._member_names_.append(member_name) # performance boost for any member that would not shadow # a DynamicClassAttribute (aka _RouteClassAttributeToGetattr) if member_name not in base_attributes: setattr(enum_class, member_name, enum_member) # now add to _member_map_ enum_class._member_map_[member_name] = enum_member try: # This may fail if value is not hashable. We can't add the value # to the map, and by-value lookups for this value will be # linear. enum_class._value2member_map_[value] = enum_member except TypeError: pass # If a custom type is mixed into the Enum, and it does not know how # to pickle itself, pickle.dumps will succeed but pickle.loads will # fail. Rather than have the error show up later and possibly far # from the source, sabotage the pickle protocol for this class so # that pickle.dumps also fails. # # However, if the new class implements its own __reduce_ex__, do not # sabotage -- it's on them to make sure it works correctly. We use # __reduce_ex__ instead of any of the others as it is preferred by # pickle over __reduce__, and it handles all pickle protocols. unpicklable = False if '__reduce_ex__' not in classdict: if member_type is not object: methods = ('__getnewargs_ex__', '__getnewargs__', '__reduce_ex__', '__reduce__') if not any(m in member_type.__dict__ for m in methods): _make_class_unpicklable(enum_class) unpicklable = True # double check that repr and friends are not the mixin's or various # things break (such as pickle) for name in ('__repr__', '__str__', '__format__', '__reduce_ex__'): class_method = getattr(enum_class, name) obj_method = getattr(member_type, name, None) enum_method = getattr(first_enum, name, None) if name not in classdict and class_method is not enum_method: if name == '__reduce_ex__' and unpicklable: continue setattr(enum_class, name, enum_method) # method resolution and int's are not playing nice # Python's less than 2.6 use __cmp__ if pyver < 2.6: if issubclass(enum_class, int): setattr(enum_class, '__cmp__', getattr(int, '__cmp__')) elif pyver < 3.0: if issubclass(enum_class, int): for method in ( '__le__', '__lt__', '__gt__', '__ge__', '__eq__', '__ne__', '__hash__', ): setattr(enum_class, method, getattr(int, method)) # replace any other __new__ with our own (as long as Enum is not None, # anyway) -- again, this is to support pickle if Enum is not None: # if the user defined their own __new__, save it before it gets # clobbered in case they subclass later if save_new: setattr(enum_class, '__member_new__', enum_class.__dict__['__new__']) setattr(enum_class, '__new__', Enum.__dict__['__new__']) return enum_class def __bool__(cls): """ classes/types should always be True. """ return True def __call__(cls, value, names=None, module=None, type=None, start=1): """Either returns an existing member, or creates a new enum class. This method is used both when an enum class is given a value to match to an enumeration member (i.e. Color(3)) and for the functional API (i.e. Color = Enum('Color', names='red green blue')). When used for the functional API: `module`, if set, will be stored in the new class' __module__ attribute; `type`, if set, will be mixed in as the first base class. Note: if `module` is not set this routine will attempt to discover the calling module by walking the frame stack; if this is unsuccessful the resulting class will not be pickleable. """ if names is None: # simple value lookup return cls.__new__(cls, value) # otherwise, functional API: we're creating a new Enum type return cls._create_(value, names, module=module, type=type, start=start) def __contains__(cls, member): return isinstance(member, cls) and member.name in cls._member_map_ def __delattr__(cls, attr): # nicer error message when someone tries to delete an attribute # (see issue19025). if attr in cls._member_map_: raise AttributeError( "%s: cannot delete Enum member." % cls.__name__) super(EnumMeta, cls).__delattr__(attr) def __dir__(self): return (['__class__', '__doc__', '__members__', '__module__'] + self._member_names_) @property def __members__(cls): """Returns a mapping of member name->value. This mapping lists all enum members, including aliases. Note that this is a copy of the internal mapping. """ return cls._member_map_.copy() def __getattr__(cls, name): """Return the enum member matching `name` We use __getattr__ instead of descriptors or inserting into the enum class' __dict__ in order to support `name` and `value` being both properties for enum members (which live in the class' __dict__) and enum members themselves. """ if _is_dunder(name): raise AttributeError(name) try: return cls._member_map_[name] except KeyError: raise AttributeError(name) def __getitem__(cls, name): return cls._member_map_[name] def __iter__(cls): return (cls._member_map_[name] for name in cls._member_names_) def __reversed__(cls): return (cls._member_map_[name] for name in reversed(cls._member_names_)) def __len__(cls): return len(cls._member_names_) __nonzero__ = __bool__ def __repr__(cls): return "" % cls.__name__ def __setattr__(cls, name, value): """Block attempts to reassign Enum members. A simple assignment to the class namespace only changes one of the several possible ways to get an Enum member from the Enum class, resulting in an inconsistent Enumeration. """ member_map = cls.__dict__.get('_member_map_', {}) if name in member_map: raise AttributeError('Cannot reassign members.') super(EnumMeta, cls).__setattr__(name, value) def _create_(cls, class_name, names=None, module=None, type=None, start=1): """Convenience method to create a new Enum class. `names` can be: * A string containing member names, separated either with spaces or commas. Values are auto-numbered from 1. * An iterable of member names. Values are auto-numbered from 1. * An iterable of (member name, value) pairs. * A mapping of member name -> value. """ if pyver < 3.0: # if class_name is unicode, attempt a conversion to ASCII if isinstance(class_name, unicode): try: class_name = class_name.encode('ascii') except UnicodeEncodeError: raise TypeError('%r is not representable in ASCII' % class_name) metacls = cls.__class__ if type is None: bases = (cls, ) else: bases = (type, cls) classdict = metacls.__prepare__(class_name, bases) _order_ = [] # special processing needed for names? if isinstance(names, basestring): names = names.replace(',', ' ').split() if isinstance(names, (tuple, list)) and isinstance(names[0], basestring): names = [(e, i+start) for (i, e) in enumerate(names)] # Here, names is either an iterable of (name, value) or a mapping. item = None # in case names is empty for item in names: if isinstance(item, basestring): member_name, member_value = item, names[item] else: member_name, member_value = item classdict[member_name] = member_value _order_.append(member_name) # only set _order_ in classdict if name/value was not from a mapping if not isinstance(item, basestring): classdict['_order_'] = ' '.join(_order_) enum_class = metacls.__new__(metacls, class_name, bases, classdict) # TODO: replace the frame hack if a blessed way to know the calling # module is ever developed if module is None: try: module = _sys._getframe(2).f_globals['__name__'] except (AttributeError, ValueError): pass if module is None: _make_class_unpicklable(enum_class) else: enum_class.__module__ = module return enum_class @staticmethod def _get_mixins_(bases): """Returns the type for creating enum members, and the first inherited enum class. bases: the tuple of bases that was given to __new__ """ if not bases or Enum is None: return object, Enum # double check that we are not subclassing a class with existing # enumeration members; while we're at it, see if any other data # type has been mixed in so we can use the correct __new__ member_type = first_enum = None for base in bases: if (base is not Enum and issubclass(base, Enum) and base._member_names_): raise TypeError("Cannot extend enumerations") # base is now the last base in bases if not issubclass(base, Enum): raise TypeError("new enumerations must be created as " "`ClassName([mixin_type,] enum_type)`") # get correct mix-in type (either mix-in type of Enum subclass, or # first base if last base is Enum) if not issubclass(bases[0], Enum): member_type = bases[0] # first data type first_enum = bases[-1] # enum type else: for base in bases[0].__mro__: # most common: (IntEnum, int, Enum, object) # possible: (, , # , , # ) if issubclass(base, Enum): if first_enum is None: first_enum = base else: if member_type is None: member_type = base return member_type, first_enum if pyver < 3.0: @staticmethod def _find_new_(classdict, member_type, first_enum): """Returns the __new__ to be used for creating the enum members. classdict: the class dictionary given to __new__ member_type: the data type whose __new__ will be used by default first_enum: enumeration to check for an overriding __new__ """ # now find the correct __new__, checking to see of one was defined # by the user; also check earlier enum classes in case a __new__ was # saved as __member_new__ __new__ = classdict.get('__new__', None) if __new__: return None, True, True # __new__, save_new, use_args N__new__ = getattr(None, '__new__') O__new__ = getattr(object, '__new__') if Enum is None: E__new__ = N__new__ else: E__new__ = Enum.__dict__['__new__'] # check all possibles for __member_new__ before falling back to # __new__ for method in ('__member_new__', '__new__'): for possible in (member_type, first_enum): try: target = possible.__dict__[method] except (AttributeError, KeyError): target = getattr(possible, method, None) if target not in [ None, N__new__, O__new__, E__new__, ]: if method == '__member_new__': classdict['__new__'] = target return None, False, True if isinstance(target, staticmethod): target = target.__get__(member_type) __new__ = target break if __new__ is not None: break else: __new__ = object.__new__ # if a non-object.__new__ is used then whatever value/tuple was # assigned to the enum member name will be passed to __new__ and to the # new enum member's __init__ if __new__ is object.__new__: use_args = False else: use_args = True return __new__, False, use_args else: @staticmethod def _find_new_(classdict, member_type, first_enum): """Returns the __new__ to be used for creating the enum members. classdict: the class dictionary given to __new__ member_type: the data type whose __new__ will be used by default first_enum: enumeration to check for an overriding __new__ """ # now find the correct __new__, checking to see of one was defined # by the user; also check earlier enum classes in case a __new__ was # saved as __member_new__ __new__ = classdict.get('__new__', None) # should __new__ be saved as __member_new__ later? save_new = __new__ is not None if __new__ is None: # check all possibles for __member_new__ before falling back to # __new__ for method in ('__member_new__', '__new__'): for possible in (member_type, first_enum): target = getattr(possible, method, None) if target not in ( None, None.__new__, object.__new__, Enum.__new__, ): __new__ = target break if __new__ is not None: break else: __new__ = object.__new__ # if a non-object.__new__ is used then whatever value/tuple was # assigned to the enum member name will be passed to __new__ and to the # new enum member's __init__ if __new__ is object.__new__: use_args = False else: use_args = True return __new__, save_new, use_args ######################################################## # In order to support Python 2 and 3 with a single # codebase we have to create the Enum methods separately # and then use the `type(name, bases, dict)` method to # create the class. ######################################################## temp_enum_dict = {} temp_enum_dict['__doc__'] = "Generic enumeration.\n\n Derive from this class to define new enumerations.\n\n" def __new__(cls, value): # all enum instances are actually created during class construction # without calling this method; this method is called by the metaclass' # __call__ (i.e. Color(3) ), and by pickle if type(value) is cls: # For lookups like Color(Color.red) value = value.value #return value # by-value search for a matching enum member # see if it's in the reverse mapping (for hashable values) try: if value in cls._value2member_map_: return cls._value2member_map_[value] except TypeError: # not there, now do long search -- O(n) behavior for member in cls._member_map_.values(): if member.value == value: return member raise ValueError("%s is not a valid %s" % (value, cls.__name__)) temp_enum_dict['__new__'] = __new__ del __new__ def __repr__(self): return "<%s.%s: %r>" % ( self.__class__.__name__, self._name_, self._value_) temp_enum_dict['__repr__'] = __repr__ del __repr__ def __str__(self): return "%s.%s" % (self.__class__.__name__, self._name_) temp_enum_dict['__str__'] = __str__ del __str__ if pyver >= 3.0: def __dir__(self): added_behavior = [ m for cls in self.__class__.mro() for m in cls.__dict__ if m[0] != '_' and m not in self._member_map_ ] return (['__class__', '__doc__', '__module__', ] + added_behavior) temp_enum_dict['__dir__'] = __dir__ del __dir__ def __format__(self, format_spec): # mixed-in Enums should use the mixed-in type's __format__, otherwise # we can get strange results with the Enum name showing up instead of # the value # pure Enum branch if self._member_type_ is object: cls = str val = str(self) # mix-in branch else: cls = self._member_type_ val = self.value return cls.__format__(val, format_spec) temp_enum_dict['__format__'] = __format__ del __format__ #################################### # Python's less than 2.6 use __cmp__ if pyver < 2.6: def __cmp__(self, other): if type(other) is self.__class__: if self is other: return 0 return -1 return NotImplemented raise TypeError("unorderable types: %s() and %s()" % (self.__class__.__name__, other.__class__.__name__)) temp_enum_dict['__cmp__'] = __cmp__ del __cmp__ else: def __le__(self, other): raise TypeError("unorderable types: %s() <= %s()" % (self.__class__.__name__, other.__class__.__name__)) temp_enum_dict['__le__'] = __le__ del __le__ def __lt__(self, other): raise TypeError("unorderable types: %s() < %s()" % (self.__class__.__name__, other.__class__.__name__)) temp_enum_dict['__lt__'] = __lt__ del __lt__ def __ge__(self, other): raise TypeError("unorderable types: %s() >= %s()" % (self.__class__.__name__, other.__class__.__name__)) temp_enum_dict['__ge__'] = __ge__ del __ge__ def __gt__(self, other): raise TypeError("unorderable types: %s() > %s()" % (self.__class__.__name__, other.__class__.__name__)) temp_enum_dict['__gt__'] = __gt__ del __gt__ def __eq__(self, other): if type(other) is self.__class__: return self is other return NotImplemented temp_enum_dict['__eq__'] = __eq__ del __eq__ def __ne__(self, other): if type(other) is self.__class__: return self is not other return NotImplemented temp_enum_dict['__ne__'] = __ne__ del __ne__ def __hash__(self): return hash(self._name_) temp_enum_dict['__hash__'] = __hash__ del __hash__ def __reduce_ex__(self, proto): return self.__class__, (self._value_, ) temp_enum_dict['__reduce_ex__'] = __reduce_ex__ del __reduce_ex__ # _RouteClassAttributeToGetattr is used to provide access to the `name` # and `value` properties of enum members while keeping some measure of # protection from modification, while still allowing for an enumeration # to have members named `name` and `value`. This works because enumeration # members are not set directly on the enum class -- __getattr__ is # used to look them up. @_RouteClassAttributeToGetattr def name(self): return self._name_ temp_enum_dict['name'] = name del name @_RouteClassAttributeToGetattr def value(self): return self._value_ temp_enum_dict['value'] = value del value @classmethod def _convert(cls, name, module, filter, source=None): """ Create a new Enum subclass that replaces a collection of global constants """ # convert all constants from source (or module) that pass filter() to # a new Enum called name, and export the enum and its members back to # module; # also, replace the __reduce_ex__ method so unpickling works in # previous Python versions module_globals = vars(_sys.modules[module]) if source: source = vars(source) else: source = module_globals members = dict((name, value) for name, value in source.items() if filter(name)) cls = cls(name, members, module=module) cls.__reduce_ex__ = _reduce_ex_by_name module_globals.update(cls.__members__) module_globals[name] = cls return cls temp_enum_dict['_convert'] = _convert del _convert Enum = EnumMeta('Enum', (object, ), temp_enum_dict) del temp_enum_dict # Enum has now been created ########################### class IntEnum(int, Enum): """Enum where members are also (and must be) ints""" def _reduce_ex_by_name(self, proto): return self.name def unique(enumeration): """Class decorator that ensures only unique members exist in an enumeration.""" duplicates = [] for name, member in enumeration.__members__.items(): if name != member.name: duplicates.append((name, member.name)) if duplicates: duplicate_names = ', '.join( ["%s -> %s" % (alias, name) for (alias, name) in duplicates] ) raise ValueError('duplicate names found in %r: %s' % (enumeration, duplicate_names) ) return enumeration enum34-1.1.6/enum/test.py0000664000175000017500000020342112716237133015360 0ustar ethanethan00000000000000from pickle import dumps, loads, PicklingError, HIGHEST_PROTOCOL import sys import unittest pyver = float('%s.%s' % sys.version_info[:2]) if pyver < 2.5: sys.path.insert(0, '.') import enum from enum import Enum, IntEnum, unique, EnumMeta if pyver < 2.6: from __builtin__ import enumerate as bltin_enumerate def enumerate(thing, start=0): result = [] for i, item in bltin_enumerate(thing): i = i + start result.append((i, item)) return result try: any except NameError: def any(iterable): for element in iterable: if element: return True return False try: unicode except NameError: unicode = str try: from collections import OrderedDict except ImportError: OrderedDict = None # for pickle tests try: class Stooges(Enum): LARRY = 1 CURLY = 2 MOE = 3 except Exception: Stooges = sys.exc_info()[1] try: class IntStooges(int, Enum): LARRY = 1 CURLY = 2 MOE = 3 except Exception: IntStooges = sys.exc_info()[1] try: class FloatStooges(float, Enum): LARRY = 1.39 CURLY = 2.72 MOE = 3.142596 except Exception: FloatStooges = sys.exc_info()[1] # for pickle test and subclass tests try: class StrEnum(str, Enum): 'accepts only string values' class Name(StrEnum): BDFL = 'Guido van Rossum' FLUFL = 'Barry Warsaw' except Exception: Name = sys.exc_info()[1] try: Question = Enum('Question', 'who what when where why', module=__name__) except Exception: Question = sys.exc_info()[1] try: Answer = Enum('Answer', 'him this then there because') except Exception: Answer = sys.exc_info()[1] try: Theory = Enum('Theory', 'rule law supposition', qualname='spanish_inquisition') except Exception: Theory = sys.exc_info()[1] # for doctests try: class Fruit(Enum): tomato = 1 banana = 2 cherry = 3 except Exception: pass def test_pickle_dump_load(assertion, source, target=None, protocol=(0, HIGHEST_PROTOCOL)): start, stop = protocol failures = [] for protocol in range(start, stop+1): try: if target is None: assertion(loads(dumps(source, protocol=protocol)) is source) else: assertion(loads(dumps(source, protocol=protocol)), target) except Exception: exc, tb = sys.exc_info()[1:] failures.append('%2d: %s' %(protocol, exc)) if failures: raise ValueError('Failed with protocols: %s' % ', '.join(failures)) def test_pickle_exception(assertion, exception, obj, protocol=(0, HIGHEST_PROTOCOL)): start, stop = protocol failures = [] for protocol in range(start, stop+1): try: assertion(exception, dumps, obj, protocol=protocol) except Exception: exc = sys.exc_info()[1] failures.append('%d: %s %s' % (protocol, exc.__class__.__name__, exc)) if failures: raise ValueError('Failed with protocols: %s' % ', '.join(failures)) class TestHelpers(unittest.TestCase): # _is_descriptor, _is_sunder, _is_dunder def test_is_descriptor(self): class foo: pass for attr in ('__get__','__set__','__delete__'): obj = foo() self.assertFalse(enum._is_descriptor(obj)) setattr(obj, attr, 1) self.assertTrue(enum._is_descriptor(obj)) def test_is_sunder(self): for s in ('_a_', '_aa_'): self.assertTrue(enum._is_sunder(s)) for s in ('a', 'a_', '_a', '__a', 'a__', '__a__', '_a__', '__a_', '_', '__', '___', '____', '_____',): self.assertFalse(enum._is_sunder(s)) def test_is_dunder(self): for s in ('__a__', '__aa__'): self.assertTrue(enum._is_dunder(s)) for s in ('a', 'a_', '_a', '__a', 'a__', '_a_', '_a__', '__a_', '_', '__', '___', '____', '_____',): self.assertFalse(enum._is_dunder(s)) class TestEnum(unittest.TestCase): def setUp(self): class Season(Enum): SPRING = 1 SUMMER = 2 AUTUMN = 3 WINTER = 4 self.Season = Season class Konstants(float, Enum): E = 2.7182818 PI = 3.1415926 TAU = 2 * PI self.Konstants = Konstants class Grades(IntEnum): A = 5 B = 4 C = 3 D = 2 F = 0 self.Grades = Grades class Directional(str, Enum): EAST = 'east' WEST = 'west' NORTH = 'north' SOUTH = 'south' self.Directional = Directional from datetime import date class Holiday(date, Enum): NEW_YEAR = 2013, 1, 1 IDES_OF_MARCH = 2013, 3, 15 self.Holiday = Holiday if pyver >= 3.0: # do not specify custom `dir` on previous versions def test_dir_on_class(self): Season = self.Season self.assertEqual( set(dir(Season)), set(['__class__', '__doc__', '__members__', '__module__', 'SPRING', 'SUMMER', 'AUTUMN', 'WINTER']), ) def test_dir_on_item(self): Season = self.Season self.assertEqual( set(dir(Season.WINTER)), set(['__class__', '__doc__', '__module__', 'name', 'value']), ) def test_dir_with_added_behavior(self): class Test(Enum): this = 'that' these = 'those' def wowser(self): return ("Wowser! I'm %s!" % self.name) self.assertEqual( set(dir(Test)), set(['__class__', '__doc__', '__members__', '__module__', 'this', 'these']), ) self.assertEqual( set(dir(Test.this)), set(['__class__', '__doc__', '__module__', 'name', 'value', 'wowser']), ) def test_dir_on_sub_with_behavior_on_super(self): # see issue22506 class SuperEnum(Enum): def invisible(self): return "did you see me?" class SubEnum(SuperEnum): sample = 5 self.assertEqual( set(dir(SubEnum.sample)), set(['__class__', '__doc__', '__module__', 'name', 'value', 'invisible']), ) if pyver >= 2.7: # OrderedDict first available here def test_members_is_ordereddict_if_ordered(self): class Ordered(Enum): __order__ = 'first second third' first = 'bippity' second = 'boppity' third = 'boo' self.assertTrue(type(Ordered.__members__) is OrderedDict) def test_members_is_ordereddict_if_not_ordered(self): class Unordered(Enum): this = 'that' these = 'those' self.assertTrue(type(Unordered.__members__) is OrderedDict) if pyver >= 3.0: # all objects are ordered in Python 2.x def test_members_is_always_ordered(self): class AlwaysOrdered(Enum): first = 1 second = 2 third = 3 self.assertTrue(type(AlwaysOrdered.__members__) is OrderedDict) def test_comparisons(self): def bad_compare(): Season.SPRING > 4 Season = self.Season self.assertNotEqual(Season.SPRING, 1) self.assertRaises(TypeError, bad_compare) class Part(Enum): SPRING = 1 CLIP = 2 BARREL = 3 self.assertNotEqual(Season.SPRING, Part.SPRING) def bad_compare(): Season.SPRING < Part.CLIP self.assertRaises(TypeError, bad_compare) def test_enum_in_enum_out(self): Season = self.Season self.assertTrue(Season(Season.WINTER) is Season.WINTER) def test_enum_value(self): Season = self.Season self.assertEqual(Season.SPRING.value, 1) def test_intenum_value(self): self.assertEqual(IntStooges.CURLY.value, 2) def test_enum(self): Season = self.Season lst = list(Season) self.assertEqual(len(lst), len(Season)) self.assertEqual(len(Season), 4, Season) self.assertEqual( [Season.SPRING, Season.SUMMER, Season.AUTUMN, Season.WINTER], lst) for i, season in enumerate('SPRING SUMMER AUTUMN WINTER'.split()): i += 1 e = Season(i) self.assertEqual(e, getattr(Season, season)) self.assertEqual(e.value, i) self.assertNotEqual(e, i) self.assertEqual(e.name, season) self.assertTrue(e in Season) self.assertTrue(type(e) is Season) self.assertTrue(isinstance(e, Season)) self.assertEqual(str(e), 'Season.' + season) self.assertEqual( repr(e), '' % (season, i), ) def test_value_name(self): Season = self.Season self.assertEqual(Season.SPRING.name, 'SPRING') self.assertEqual(Season.SPRING.value, 1) def set_name(obj, new_value): obj.name = new_value def set_value(obj, new_value): obj.value = new_value self.assertRaises(AttributeError, set_name, Season.SPRING, 'invierno', ) self.assertRaises(AttributeError, set_value, Season.SPRING, 2) def test_attribute_deletion(self): class Season(Enum): SPRING = 1 SUMMER = 2 AUTUMN = 3 WINTER = 4 def spam(cls): pass self.assertTrue(hasattr(Season, 'spam')) del Season.spam self.assertFalse(hasattr(Season, 'spam')) self.assertRaises(AttributeError, delattr, Season, 'SPRING') self.assertRaises(AttributeError, delattr, Season, 'DRY') self.assertRaises(AttributeError, delattr, Season.SPRING, 'name') def test_bool_of_class(self): class Empty(Enum): pass self.assertTrue(bool(Empty)) def test_bool_of_member(self): class Count(Enum): zero = 0 one = 1 two = 2 for member in Count: self.assertTrue(bool(member)) def test_invalid_names(self): def create_bad_class_1(): class Wrong(Enum): mro = 9 def create_bad_class_2(): class Wrong(Enum): _reserved_ = 3 self.assertRaises(ValueError, create_bad_class_1) self.assertRaises(ValueError, create_bad_class_2) def test_contains(self): Season = self.Season self.assertTrue(Season.AUTUMN in Season) self.assertTrue(3 not in Season) val = Season(3) self.assertTrue(val in Season) class OtherEnum(Enum): one = 1; two = 2 self.assertTrue(OtherEnum.two not in Season) if pyver >= 2.6: # when `format` came into being def test_format_enum(self): Season = self.Season self.assertEqual('{0}'.format(Season.SPRING), '{0}'.format(str(Season.SPRING))) self.assertEqual( '{0:}'.format(Season.SPRING), '{0:}'.format(str(Season.SPRING))) self.assertEqual('{0:20}'.format(Season.SPRING), '{0:20}'.format(str(Season.SPRING))) self.assertEqual('{0:^20}'.format(Season.SPRING), '{0:^20}'.format(str(Season.SPRING))) self.assertEqual('{0:>20}'.format(Season.SPRING), '{0:>20}'.format(str(Season.SPRING))) self.assertEqual('{0:<20}'.format(Season.SPRING), '{0:<20}'.format(str(Season.SPRING))) def test_format_enum_custom(self): class TestFloat(float, Enum): one = 1.0 two = 2.0 def __format__(self, spec): return 'TestFloat success!' self.assertEqual('{0}'.format(TestFloat.one), 'TestFloat success!') def assertFormatIsValue(self, spec, member): self.assertEqual(spec.format(member), spec.format(member.value)) def test_format_enum_date(self): Holiday = self.Holiday self.assertFormatIsValue('{0}', Holiday.IDES_OF_MARCH) self.assertFormatIsValue('{0:}', Holiday.IDES_OF_MARCH) self.assertFormatIsValue('{0:20}', Holiday.IDES_OF_MARCH) self.assertFormatIsValue('{0:^20}', Holiday.IDES_OF_MARCH) self.assertFormatIsValue('{0:>20}', Holiday.IDES_OF_MARCH) self.assertFormatIsValue('{0:<20}', Holiday.IDES_OF_MARCH) self.assertFormatIsValue('{0:%Y %m}', Holiday.IDES_OF_MARCH) self.assertFormatIsValue('{0:%Y %m %M:00}', Holiday.IDES_OF_MARCH) def test_format_enum_float(self): Konstants = self.Konstants self.assertFormatIsValue('{0}', Konstants.TAU) self.assertFormatIsValue('{0:}', Konstants.TAU) self.assertFormatIsValue('{0:20}', Konstants.TAU) self.assertFormatIsValue('{0:^20}', Konstants.TAU) self.assertFormatIsValue('{0:>20}', Konstants.TAU) self.assertFormatIsValue('{0:<20}', Konstants.TAU) self.assertFormatIsValue('{0:n}', Konstants.TAU) self.assertFormatIsValue('{0:5.2}', Konstants.TAU) self.assertFormatIsValue('{0:f}', Konstants.TAU) def test_format_enum_int(self): Grades = self.Grades self.assertFormatIsValue('{0}', Grades.C) self.assertFormatIsValue('{0:}', Grades.C) self.assertFormatIsValue('{0:20}', Grades.C) self.assertFormatIsValue('{0:^20}', Grades.C) self.assertFormatIsValue('{0:>20}', Grades.C) self.assertFormatIsValue('{0:<20}', Grades.C) self.assertFormatIsValue('{0:+}', Grades.C) self.assertFormatIsValue('{0:08X}', Grades.C) self.assertFormatIsValue('{0:b}', Grades.C) def test_format_enum_str(self): Directional = self.Directional self.assertFormatIsValue('{0}', Directional.WEST) self.assertFormatIsValue('{0:}', Directional.WEST) self.assertFormatIsValue('{0:20}', Directional.WEST) self.assertFormatIsValue('{0:^20}', Directional.WEST) self.assertFormatIsValue('{0:>20}', Directional.WEST) self.assertFormatIsValue('{0:<20}', Directional.WEST) def test_hash(self): Season = self.Season dates = {} dates[Season.WINTER] = '1225' dates[Season.SPRING] = '0315' dates[Season.SUMMER] = '0704' dates[Season.AUTUMN] = '1031' self.assertEqual(dates[Season.AUTUMN], '1031') def test_enum_duplicates(self): _order_ = "SPRING SUMMER AUTUMN WINTER" class Season(Enum): SPRING = 1 SUMMER = 2 AUTUMN = FALL = 3 WINTER = 4 ANOTHER_SPRING = 1 lst = list(Season) self.assertEqual( lst, [Season.SPRING, Season.SUMMER, Season.AUTUMN, Season.WINTER, ]) self.assertTrue(Season.FALL is Season.AUTUMN) self.assertEqual(Season.FALL.value, 3) self.assertEqual(Season.AUTUMN.value, 3) self.assertTrue(Season(3) is Season.AUTUMN) self.assertTrue(Season(1) is Season.SPRING) self.assertEqual(Season.FALL.name, 'AUTUMN') self.assertEqual( set([k for k,v in Season.__members__.items() if v.name != k]), set(['FALL', 'ANOTHER_SPRING']), ) if pyver >= 3.0: cls = vars() result = {'Enum':Enum} exec("""def test_duplicate_name(self): with self.assertRaises(TypeError): class Color(Enum): red = 1 green = 2 blue = 3 red = 4 with self.assertRaises(TypeError): class Color(Enum): red = 1 green = 2 blue = 3 def red(self): return 'red' with self.assertRaises(TypeError): class Color(Enum): @property def red(self): return 'redder' red = 1 green = 2 blue = 3""", result) cls['test_duplicate_name'] = result['test_duplicate_name'] def test_enum_with_value_name(self): class Huh(Enum): name = 1 value = 2 self.assertEqual( list(Huh), [Huh.name, Huh.value], ) self.assertTrue(type(Huh.name) is Huh) self.assertEqual(Huh.name.name, 'name') self.assertEqual(Huh.name.value, 1) def test_intenum_from_scratch(self): class phy(int, Enum): pi = 3 tau = 2 * pi self.assertTrue(phy.pi < phy.tau) def test_intenum_inherited(self): class IntEnum(int, Enum): pass class phy(IntEnum): pi = 3 tau = 2 * pi self.assertTrue(phy.pi < phy.tau) def test_floatenum_from_scratch(self): class phy(float, Enum): pi = 3.1415926 tau = 2 * pi self.assertTrue(phy.pi < phy.tau) def test_floatenum_inherited(self): class FloatEnum(float, Enum): pass class phy(FloatEnum): pi = 3.1415926 tau = 2 * pi self.assertTrue(phy.pi < phy.tau) def test_strenum_from_scratch(self): class phy(str, Enum): pi = 'Pi' tau = 'Tau' self.assertTrue(phy.pi < phy.tau) def test_strenum_inherited(self): class StrEnum(str, Enum): pass class phy(StrEnum): pi = 'Pi' tau = 'Tau' self.assertTrue(phy.pi < phy.tau) def test_intenum(self): class WeekDay(IntEnum): SUNDAY = 1 MONDAY = 2 TUESDAY = 3 WEDNESDAY = 4 THURSDAY = 5 FRIDAY = 6 SATURDAY = 7 self.assertEqual(['a', 'b', 'c'][WeekDay.MONDAY], 'c') self.assertEqual([i for i in range(WeekDay.TUESDAY)], [0, 1, 2]) lst = list(WeekDay) self.assertEqual(len(lst), len(WeekDay)) self.assertEqual(len(WeekDay), 7) target = 'SUNDAY MONDAY TUESDAY WEDNESDAY THURSDAY FRIDAY SATURDAY' target = target.split() for i, weekday in enumerate(target): i += 1 e = WeekDay(i) self.assertEqual(e, i) self.assertEqual(int(e), i) self.assertEqual(e.name, weekday) self.assertTrue(e in WeekDay) self.assertEqual(lst.index(e)+1, i) self.assertTrue(0 < e < 8) self.assertTrue(type(e) is WeekDay) self.assertTrue(isinstance(e, int)) self.assertTrue(isinstance(e, Enum)) def test_intenum_duplicates(self): class WeekDay(IntEnum): __order__ = 'SUNDAY MONDAY TUESDAY WEDNESDAY THURSDAY FRIDAY SATURDAY' SUNDAY = 1 MONDAY = 2 TUESDAY = TEUSDAY = 3 WEDNESDAY = 4 THURSDAY = 5 FRIDAY = 6 SATURDAY = 7 self.assertTrue(WeekDay.TEUSDAY is WeekDay.TUESDAY) self.assertEqual(WeekDay(3).name, 'TUESDAY') self.assertEqual([k for k,v in WeekDay.__members__.items() if v.name != k], ['TEUSDAY', ]) def test_pickle_enum(self): if isinstance(Stooges, Exception): raise Stooges test_pickle_dump_load(self.assertTrue, Stooges.CURLY) test_pickle_dump_load(self.assertTrue, Stooges) def test_pickle_int(self): if isinstance(IntStooges, Exception): raise IntStooges test_pickle_dump_load(self.assertTrue, IntStooges.CURLY) test_pickle_dump_load(self.assertTrue, IntStooges) def test_pickle_float(self): if isinstance(FloatStooges, Exception): raise FloatStooges test_pickle_dump_load(self.assertTrue, FloatStooges.CURLY) test_pickle_dump_load(self.assertTrue, FloatStooges) def test_pickle_enum_function(self): if isinstance(Answer, Exception): raise Answer test_pickle_dump_load(self.assertTrue, Answer.him) test_pickle_dump_load(self.assertTrue, Answer) def test_pickle_enum_function_with_module(self): if isinstance(Question, Exception): raise Question test_pickle_dump_load(self.assertTrue, Question.who) test_pickle_dump_load(self.assertTrue, Question) if pyver == 3.4: def test_class_nested_enum_and_pickle_protocol_four(self): # would normally just have this directly in the class namespace class NestedEnum(Enum): twigs = 'common' shiny = 'rare' self.__class__.NestedEnum = NestedEnum self.NestedEnum.__qualname__ = '%s.NestedEnum' % self.__class__.__name__ test_pickle_exception( self.assertRaises, PicklingError, self.NestedEnum.twigs, protocol=(0, 3)) test_pickle_dump_load(self.assertTrue, self.NestedEnum.twigs, protocol=(4, HIGHEST_PROTOCOL)) elif pyver == 3.5: def test_class_nested_enum_and_pickle_protocol_four(self): # would normally just have this directly in the class namespace class NestedEnum(Enum): twigs = 'common' shiny = 'rare' self.__class__.NestedEnum = NestedEnum self.NestedEnum.__qualname__ = '%s.NestedEnum' % self.__class__.__name__ test_pickle_dump_load(self.assertTrue, self.NestedEnum.twigs, protocol=(0, HIGHEST_PROTOCOL)) def test_exploding_pickle(self): BadPickle = Enum('BadPickle', 'dill sweet bread-n-butter') enum._make_class_unpicklable(BadPickle) globals()['BadPickle'] = BadPickle test_pickle_exception(self.assertRaises, TypeError, BadPickle.dill) test_pickle_exception(self.assertRaises, PicklingError, BadPickle) def test_string_enum(self): class SkillLevel(str, Enum): master = 'what is the sound of one hand clapping?' journeyman = 'why did the chicken cross the road?' apprentice = 'knock, knock!' self.assertEqual(SkillLevel.apprentice, 'knock, knock!') def test_getattr_getitem(self): class Period(Enum): morning = 1 noon = 2 evening = 3 night = 4 self.assertTrue(Period(2) is Period.noon) self.assertTrue(getattr(Period, 'night') is Period.night) self.assertTrue(Period['morning'] is Period.morning) def test_getattr_dunder(self): Season = self.Season self.assertTrue(getattr(Season, '__hash__')) def test_iteration_order(self): class Season(Enum): _order_ = 'SUMMER WINTER AUTUMN SPRING' SUMMER = 2 WINTER = 4 AUTUMN = 3 SPRING = 1 self.assertEqual( list(Season), [Season.SUMMER, Season.WINTER, Season.AUTUMN, Season.SPRING], ) def test_iteration_order_reversed(self): self.assertEqual( list(reversed(self.Season)), [self.Season.WINTER, self.Season.AUTUMN, self.Season.SUMMER, self.Season.SPRING] ) def test_iteration_order_with_unorderable_values(self): class Complex(Enum): a = complex(7, 9) b = complex(3.14, 2) c = complex(1, -1) d = complex(-77, 32) self.assertEqual( list(Complex), [Complex.a, Complex.b, Complex.c, Complex.d], ) def test_programatic_function_string(self): SummerMonth = Enum('SummerMonth', 'june july august') lst = list(SummerMonth) self.assertEqual(len(lst), len(SummerMonth)) self.assertEqual(len(SummerMonth), 3, SummerMonth) self.assertEqual( [SummerMonth.june, SummerMonth.july, SummerMonth.august], lst, ) for i, month in enumerate('june july august'.split()): i += 1 e = SummerMonth(i) self.assertEqual(int(e.value), i) self.assertNotEqual(e, i) self.assertEqual(e.name, month) self.assertTrue(e in SummerMonth) self.assertTrue(type(e) is SummerMonth) def test_programatic_function_string_with_start(self): SummerMonth = Enum('SummerMonth', 'june july august', start=10) lst = list(SummerMonth) self.assertEqual(len(lst), len(SummerMonth)) self.assertEqual(len(SummerMonth), 3, SummerMonth) self.assertEqual( [SummerMonth.june, SummerMonth.july, SummerMonth.august], lst, ) for i, month in enumerate('june july august'.split(), 10): e = SummerMonth(i) self.assertEqual(int(e.value), i) self.assertNotEqual(e, i) self.assertEqual(e.name, month) self.assertTrue(e in SummerMonth) self.assertTrue(type(e) is SummerMonth) def test_programatic_function_string_list(self): SummerMonth = Enum('SummerMonth', ['june', 'july', 'august']) lst = list(SummerMonth) self.assertEqual(len(lst), len(SummerMonth)) self.assertEqual(len(SummerMonth), 3, SummerMonth) self.assertEqual( [SummerMonth.june, SummerMonth.july, SummerMonth.august], lst, ) for i, month in enumerate('june july august'.split()): i += 1 e = SummerMonth(i) self.assertEqual(int(e.value), i) self.assertNotEqual(e, i) self.assertEqual(e.name, month) self.assertTrue(e in SummerMonth) self.assertTrue(type(e) is SummerMonth) def test_programatic_function_string_list_with_start(self): SummerMonth = Enum('SummerMonth', ['june', 'july', 'august'], start=20) lst = list(SummerMonth) self.assertEqual(len(lst), len(SummerMonth)) self.assertEqual(len(SummerMonth), 3, SummerMonth) self.assertEqual( [SummerMonth.june, SummerMonth.july, SummerMonth.august], lst, ) for i, month in enumerate('june july august'.split(), 20): e = SummerMonth(i) self.assertEqual(int(e.value), i) self.assertNotEqual(e, i) self.assertEqual(e.name, month) self.assertTrue(e in SummerMonth) self.assertTrue(type(e) is SummerMonth) def test_programatic_function_iterable(self): SummerMonth = Enum( 'SummerMonth', (('june', 1), ('july', 2), ('august', 3)) ) lst = list(SummerMonth) self.assertEqual(len(lst), len(SummerMonth)) self.assertEqual(len(SummerMonth), 3, SummerMonth) self.assertEqual( [SummerMonth.june, SummerMonth.july, SummerMonth.august], lst, ) for i, month in enumerate('june july august'.split()): i += 1 e = SummerMonth(i) self.assertEqual(int(e.value), i) self.assertNotEqual(e, i) self.assertEqual(e.name, month) self.assertTrue(e in SummerMonth) self.assertTrue(type(e) is SummerMonth) def test_programatic_function_from_dict(self): SummerMonth = Enum( 'SummerMonth', dict((('june', 1), ('july', 2), ('august', 3))) ) lst = list(SummerMonth) self.assertEqual(len(lst), len(SummerMonth)) self.assertEqual(len(SummerMonth), 3, SummerMonth) if pyver < 3.0: self.assertEqual( [SummerMonth.june, SummerMonth.july, SummerMonth.august], lst, ) for i, month in enumerate('june july august'.split()): i += 1 e = SummerMonth(i) self.assertEqual(int(e.value), i) self.assertNotEqual(e, i) self.assertEqual(e.name, month) self.assertTrue(e in SummerMonth) self.assertTrue(type(e) is SummerMonth) def test_programatic_function_type(self): SummerMonth = Enum('SummerMonth', 'june july august', type=int) lst = list(SummerMonth) self.assertEqual(len(lst), len(SummerMonth)) self.assertEqual(len(SummerMonth), 3, SummerMonth) self.assertEqual( [SummerMonth.june, SummerMonth.july, SummerMonth.august], lst, ) for i, month in enumerate('june july august'.split()): i += 1 e = SummerMonth(i) self.assertEqual(e, i) self.assertEqual(e.name, month) self.assertTrue(e in SummerMonth) self.assertTrue(type(e) is SummerMonth) def test_programatic_function_type_with_start(self): SummerMonth = Enum('SummerMonth', 'june july august', type=int, start=30) lst = list(SummerMonth) self.assertEqual(len(lst), len(SummerMonth)) self.assertEqual(len(SummerMonth), 3, SummerMonth) self.assertEqual( [SummerMonth.june, SummerMonth.july, SummerMonth.august], lst, ) for i, month in enumerate('june july august'.split(), 30): e = SummerMonth(i) self.assertEqual(e, i) self.assertEqual(e.name, month) self.assertTrue(e in SummerMonth) self.assertTrue(type(e) is SummerMonth) def test_programatic_function_type_from_subclass(self): SummerMonth = IntEnum('SummerMonth', 'june july august') lst = list(SummerMonth) self.assertEqual(len(lst), len(SummerMonth)) self.assertEqual(len(SummerMonth), 3, SummerMonth) self.assertEqual( [SummerMonth.june, SummerMonth.july, SummerMonth.august], lst, ) for i, month in enumerate('june july august'.split()): i += 1 e = SummerMonth(i) self.assertEqual(e, i) self.assertEqual(e.name, month) self.assertTrue(e in SummerMonth) self.assertTrue(type(e) is SummerMonth) def test_programatic_function_type_from_subclass_with_start(self): SummerMonth = IntEnum('SummerMonth', 'june july august', start=40) lst = list(SummerMonth) self.assertEqual(len(lst), len(SummerMonth)) self.assertEqual(len(SummerMonth), 3, SummerMonth) self.assertEqual( [SummerMonth.june, SummerMonth.july, SummerMonth.august], lst, ) for i, month in enumerate('june july august'.split(), 40): e = SummerMonth(i) self.assertEqual(e, i) self.assertEqual(e.name, month) self.assertTrue(e in SummerMonth) self.assertTrue(type(e) is SummerMonth) def test_programatic_function_unicode(self): SummerMonth = Enum('SummerMonth', unicode('june july august')) lst = list(SummerMonth) self.assertEqual(len(lst), len(SummerMonth)) self.assertEqual(len(SummerMonth), 3, SummerMonth) self.assertEqual( [SummerMonth.june, SummerMonth.july, SummerMonth.august], lst, ) for i, month in enumerate(unicode('june july august').split()): i += 1 e = SummerMonth(i) self.assertEqual(int(e.value), i) self.assertNotEqual(e, i) self.assertEqual(e.name, month) self.assertTrue(e in SummerMonth) self.assertTrue(type(e) is SummerMonth) def test_programatic_function_unicode_list(self): SummerMonth = Enum('SummerMonth', [unicode('june'), unicode('july'), unicode('august')]) lst = list(SummerMonth) self.assertEqual(len(lst), len(SummerMonth)) self.assertEqual(len(SummerMonth), 3, SummerMonth) self.assertEqual( [SummerMonth.june, SummerMonth.july, SummerMonth.august], lst, ) for i, month in enumerate(unicode('june july august').split()): i += 1 e = SummerMonth(i) self.assertEqual(int(e.value), i) self.assertNotEqual(e, i) self.assertEqual(e.name, month) self.assertTrue(e in SummerMonth) self.assertTrue(type(e) is SummerMonth) def test_programatic_function_unicode_iterable(self): SummerMonth = Enum( 'SummerMonth', ((unicode('june'), 1), (unicode('july'), 2), (unicode('august'), 3)) ) lst = list(SummerMonth) self.assertEqual(len(lst), len(SummerMonth)) self.assertEqual(len(SummerMonth), 3, SummerMonth) self.assertEqual( [SummerMonth.june, SummerMonth.july, SummerMonth.august], lst, ) for i, month in enumerate(unicode('june july august').split()): i += 1 e = SummerMonth(i) self.assertEqual(int(e.value), i) self.assertNotEqual(e, i) self.assertEqual(e.name, month) self.assertTrue(e in SummerMonth) self.assertTrue(type(e) is SummerMonth) def test_programatic_function_from_unicode_dict(self): SummerMonth = Enum( 'SummerMonth', dict(((unicode('june'), 1), (unicode('july'), 2), (unicode('august'), 3))) ) lst = list(SummerMonth) self.assertEqual(len(lst), len(SummerMonth)) self.assertEqual(len(SummerMonth), 3, SummerMonth) if pyver < 3.0: self.assertEqual( [SummerMonth.june, SummerMonth.july, SummerMonth.august], lst, ) for i, month in enumerate(unicode('june july august').split()): i += 1 e = SummerMonth(i) self.assertEqual(int(e.value), i) self.assertNotEqual(e, i) self.assertEqual(e.name, month) self.assertTrue(e in SummerMonth) self.assertTrue(type(e) is SummerMonth) def test_programatic_function_unicode_type(self): SummerMonth = Enum('SummerMonth', unicode('june july august'), type=int) lst = list(SummerMonth) self.assertEqual(len(lst), len(SummerMonth)) self.assertEqual(len(SummerMonth), 3, SummerMonth) self.assertEqual( [SummerMonth.june, SummerMonth.july, SummerMonth.august], lst, ) for i, month in enumerate(unicode('june july august').split()): i += 1 e = SummerMonth(i) self.assertEqual(e, i) self.assertEqual(e.name, month) self.assertTrue(e in SummerMonth) self.assertTrue(type(e) is SummerMonth) def test_programatic_function_unicode_type_from_subclass(self): SummerMonth = IntEnum('SummerMonth', unicode('june july august')) lst = list(SummerMonth) self.assertEqual(len(lst), len(SummerMonth)) self.assertEqual(len(SummerMonth), 3, SummerMonth) self.assertEqual( [SummerMonth.june, SummerMonth.july, SummerMonth.august], lst, ) for i, month in enumerate(unicode('june july august').split()): i += 1 e = SummerMonth(i) self.assertEqual(e, i) self.assertEqual(e.name, month) self.assertTrue(e in SummerMonth) self.assertTrue(type(e) is SummerMonth) def test_programmatic_function_unicode_class(self): if pyver < 3.0: class_names = unicode('SummerMonth'), 'S\xfcmm\xe9rM\xf6nth'.decode('latin1') else: class_names = 'SummerMonth', 'S\xfcmm\xe9rM\xf6nth' for i, class_name in enumerate(class_names): if pyver < 3.0 and i == 1: self.assertRaises(TypeError, Enum, class_name, unicode('june july august')) else: SummerMonth = Enum(class_name, unicode('june july august')) lst = list(SummerMonth) self.assertEqual(len(lst), len(SummerMonth)) self.assertEqual(len(SummerMonth), 3, SummerMonth) self.assertEqual( [SummerMonth.june, SummerMonth.july, SummerMonth.august], lst, ) for i, month in enumerate(unicode('june july august').split()): i += 1 e = SummerMonth(i) self.assertEqual(e.value, i) self.assertEqual(e.name, month) self.assertTrue(e in SummerMonth) self.assertTrue(type(e) is SummerMonth) def test_subclassing(self): if isinstance(Name, Exception): raise Name self.assertEqual(Name.BDFL, 'Guido van Rossum') self.assertTrue(Name.BDFL, Name('Guido van Rossum')) self.assertTrue(Name.BDFL is getattr(Name, 'BDFL')) test_pickle_dump_load(self.assertTrue, Name.BDFL) def test_extending(self): def bad_extension(): class Color(Enum): red = 1 green = 2 blue = 3 class MoreColor(Color): cyan = 4 magenta = 5 yellow = 6 self.assertRaises(TypeError, bad_extension) def test_exclude_methods(self): class whatever(Enum): this = 'that' these = 'those' def really(self): return 'no, not %s' % self.value self.assertFalse(type(whatever.really) is whatever) self.assertEqual(whatever.this.really(), 'no, not that') def test_wrong_inheritance_order(self): def wrong_inherit(): class Wrong(Enum, str): NotHere = 'error before this point' self.assertRaises(TypeError, wrong_inherit) def test_intenum_transitivity(self): class number(IntEnum): one = 1 two = 2 three = 3 class numero(IntEnum): uno = 1 dos = 2 tres = 3 self.assertEqual(number.one, numero.uno) self.assertEqual(number.two, numero.dos) self.assertEqual(number.three, numero.tres) def test_introspection(self): class Number(IntEnum): one = 100 two = 200 self.assertTrue(Number.one._member_type_ is int) self.assertTrue(Number._member_type_ is int) class String(str, Enum): yarn = 'soft' rope = 'rough' wire = 'hard' self.assertTrue(String.yarn._member_type_ is str) self.assertTrue(String._member_type_ is str) class Plain(Enum): vanilla = 'white' one = 1 self.assertTrue(Plain.vanilla._member_type_ is object) self.assertTrue(Plain._member_type_ is object) def test_wrong_enum_in_call(self): class Monochrome(Enum): black = 0 white = 1 class Gender(Enum): male = 0 female = 1 self.assertRaises(ValueError, Monochrome, Gender.male) def test_wrong_enum_in_mixed_call(self): class Monochrome(IntEnum): black = 0 white = 1 class Gender(Enum): male = 0 female = 1 self.assertRaises(ValueError, Monochrome, Gender.male) def test_mixed_enum_in_call_1(self): class Monochrome(IntEnum): black = 0 white = 1 class Gender(IntEnum): male = 0 female = 1 self.assertTrue(Monochrome(Gender.female) is Monochrome.white) def test_mixed_enum_in_call_2(self): class Monochrome(Enum): black = 0 white = 1 class Gender(IntEnum): male = 0 female = 1 self.assertTrue(Monochrome(Gender.male) is Monochrome.black) def test_flufl_enum(self): class Fluflnum(Enum): def __int__(self): return int(self.value) class MailManOptions(Fluflnum): option1 = 1 option2 = 2 option3 = 3 self.assertEqual(int(MailManOptions.option1), 1) def test_no_such_enum_member(self): class Color(Enum): red = 1 green = 2 blue = 3 self.assertRaises(ValueError, Color, 4) self.assertRaises(KeyError, Color.__getitem__, 'chartreuse') def test_new_repr(self): class Color(Enum): red = 1 green = 2 blue = 3 def __repr__(self): return "don't you just love shades of %s?" % self.name self.assertEqual( repr(Color.blue), "don't you just love shades of blue?", ) def test_inherited_repr(self): class MyEnum(Enum): def __repr__(self): return "My name is %s." % self.name class MyIntEnum(int, MyEnum): this = 1 that = 2 theother = 3 self.assertEqual(repr(MyIntEnum.that), "My name is that.") def test_multiple_mixin_mro(self): class auto_enum(EnumMeta): def __new__(metacls, cls, bases, classdict): original_dict = classdict classdict = enum._EnumDict() for k, v in original_dict.items(): classdict[k] = v temp = type(classdict)() names = set(classdict._member_names) i = 0 for k in classdict._member_names: v = classdict[k] if v == (): v = i else: i = v i += 1 temp[k] = v for k, v in classdict.items(): if k not in names: temp[k] = v return super(auto_enum, metacls).__new__( metacls, cls, bases, temp) AutoNumberedEnum = auto_enum('AutoNumberedEnum', (Enum,), {}) AutoIntEnum = auto_enum('AutoIntEnum', (IntEnum,), {}) class TestAutoNumber(AutoNumberedEnum): a = () b = 3 c = () class TestAutoInt(AutoIntEnum): a = () b = 3 c = () def test_subclasses_with_getnewargs(self): class NamedInt(int): __qualname__ = 'NamedInt' # needed for pickle protocol 4 def __new__(cls, *args): _args = args if len(args) < 1: raise TypeError("name and value must be specified") name, args = args[0], args[1:] self = int.__new__(cls, *args) self._intname = name self._args = _args return self def __getnewargs__(self): return self._args @property def __name__(self): return self._intname def __repr__(self): # repr() is updated to include the name and type info return "%s(%r, %s)" % (type(self).__name__, self.__name__, int.__repr__(self)) def __str__(self): # str() is unchanged, even if it relies on the repr() fallback base = int base_str = base.__str__ if base_str.__objclass__ is object: return base.__repr__(self) return base_str(self) # for simplicity, we only define one operator that # propagates expressions def __add__(self, other): temp = int(self) + int( other) if isinstance(self, NamedInt) and isinstance(other, NamedInt): return NamedInt( '(%s + %s)' % (self.__name__, other.__name__), temp ) else: return temp class NEI(NamedInt, Enum): __qualname__ = 'NEI' # needed for pickle protocol 4 x = ('the-x', 1) y = ('the-y', 2) self.assertTrue(NEI.__new__ is Enum.__new__) self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)") globals()['NamedInt'] = NamedInt globals()['NEI'] = NEI NI5 = NamedInt('test', 5) self.assertEqual(NI5, 5) test_pickle_dump_load(self.assertTrue, NI5, 5) self.assertEqual(NEI.y.value, 2) test_pickle_dump_load(self.assertTrue, NEI.y) if pyver >= 3.4: def test_subclasses_with_getnewargs_ex(self): class NamedInt(int): __qualname__ = 'NamedInt' # needed for pickle protocol 4 def __new__(cls, *args): _args = args if len(args) < 2: raise TypeError("name and value must be specified") name, args = args[0], args[1:] self = int.__new__(cls, *args) self._intname = name self._args = _args return self def __getnewargs_ex__(self): return self._args, {} @property def __name__(self): return self._intname def __repr__(self): # repr() is updated to include the name and type info return "{}({!r}, {})".format(type(self).__name__, self.__name__, int.__repr__(self)) def __str__(self): # str() is unchanged, even if it relies on the repr() fallback base = int base_str = base.__str__ if base_str.__objclass__ is object: return base.__repr__(self) return base_str(self) # for simplicity, we only define one operator that # propagates expressions def __add__(self, other): temp = int(self) + int( other) if isinstance(self, NamedInt) and isinstance(other, NamedInt): return NamedInt( '({0} + {1})'.format(self.__name__, other.__name__), temp ) else: return temp class NEI(NamedInt, Enum): __qualname__ = 'NEI' # needed for pickle protocol 4 x = ('the-x', 1) y = ('the-y', 2) self.assertIs(NEI.__new__, Enum.__new__) self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)") globals()['NamedInt'] = NamedInt globals()['NEI'] = NEI NI5 = NamedInt('test', 5) self.assertEqual(NI5, 5) test_pickle_dump_load(self.assertEqual, NI5, 5, protocol=(4, HIGHEST_PROTOCOL)) self.assertEqual(NEI.y.value, 2) test_pickle_dump_load(self.assertTrue, NEI.y, protocol=(4, HIGHEST_PROTOCOL)) def test_subclasses_with_reduce(self): class NamedInt(int): __qualname__ = 'NamedInt' # needed for pickle protocol 4 def __new__(cls, *args): _args = args if len(args) < 1: raise TypeError("name and value must be specified") name, args = args[0], args[1:] self = int.__new__(cls, *args) self._intname = name self._args = _args return self def __reduce__(self): return self.__class__, self._args @property def __name__(self): return self._intname def __repr__(self): # repr() is updated to include the name and type info return "%s(%r, %s)" % (type(self).__name__, self.__name__, int.__repr__(self)) def __str__(self): # str() is unchanged, even if it relies on the repr() fallback base = int base_str = base.__str__ if base_str.__objclass__ is object: return base.__repr__(self) return base_str(self) # for simplicity, we only define one operator that # propagates expressions def __add__(self, other): temp = int(self) + int( other) if isinstance(self, NamedInt) and isinstance(other, NamedInt): return NamedInt( '(%s + %s)' % (self.__name__, other.__name__), temp ) else: return temp class NEI(NamedInt, Enum): __qualname__ = 'NEI' # needed for pickle protocol 4 x = ('the-x', 1) y = ('the-y', 2) self.assertTrue(NEI.__new__ is Enum.__new__) self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)") globals()['NamedInt'] = NamedInt globals()['NEI'] = NEI NI5 = NamedInt('test', 5) self.assertEqual(NI5, 5) test_pickle_dump_load(self.assertEqual, NI5, 5) self.assertEqual(NEI.y.value, 2) test_pickle_dump_load(self.assertTrue, NEI.y) def test_subclasses_with_reduce_ex(self): class NamedInt(int): __qualname__ = 'NamedInt' # needed for pickle protocol 4 def __new__(cls, *args): _args = args if len(args) < 1: raise TypeError("name and value must be specified") name, args = args[0], args[1:] self = int.__new__(cls, *args) self._intname = name self._args = _args return self def __reduce_ex__(self, proto): return self.__class__, self._args @property def __name__(self): return self._intname def __repr__(self): # repr() is updated to include the name and type info return "%s(%r, %s)" % (type(self).__name__, self.__name__, int.__repr__(self)) def __str__(self): # str() is unchanged, even if it relies on the repr() fallback base = int base_str = base.__str__ if base_str.__objclass__ is object: return base.__repr__(self) return base_str(self) # for simplicity, we only define one operator that # propagates expressions def __add__(self, other): temp = int(self) + int( other) if isinstance(self, NamedInt) and isinstance(other, NamedInt): return NamedInt( '(%s + %s)' % (self.__name__, other.__name__), temp ) else: return temp class NEI(NamedInt, Enum): __qualname__ = 'NEI' # needed for pickle protocol 4 x = ('the-x', 1) y = ('the-y', 2) self.assertTrue(NEI.__new__ is Enum.__new__) self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)") globals()['NamedInt'] = NamedInt globals()['NEI'] = NEI NI5 = NamedInt('test', 5) self.assertEqual(NI5, 5) test_pickle_dump_load(self.assertEqual, NI5, 5) self.assertEqual(NEI.y.value, 2) test_pickle_dump_load(self.assertTrue, NEI.y) def test_subclasses_without_direct_pickle_support(self): class NamedInt(int): __qualname__ = 'NamedInt' def __new__(cls, *args): _args = args name, args = args[0], args[1:] if len(args) == 0: raise TypeError("name and value must be specified") self = int.__new__(cls, *args) self._intname = name self._args = _args return self @property def __name__(self): return self._intname def __repr__(self): # repr() is updated to include the name and type info return "%s(%r, %s)" % (type(self).__name__, self.__name__, int.__repr__(self)) def __str__(self): # str() is unchanged, even if it relies on the repr() fallback base = int base_str = base.__str__ if base_str.__objclass__ is object: return base.__repr__(self) return base_str(self) # for simplicity, we only define one operator that # propagates expressions def __add__(self, other): temp = int(self) + int( other) if isinstance(self, NamedInt) and isinstance(other, NamedInt): return NamedInt( '(%s + %s)' % (self.__name__, other.__name__), temp ) else: return temp class NEI(NamedInt, Enum): __qualname__ = 'NEI' x = ('the-x', 1) y = ('the-y', 2) self.assertTrue(NEI.__new__ is Enum.__new__) self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)") globals()['NamedInt'] = NamedInt globals()['NEI'] = NEI NI5 = NamedInt('test', 5) self.assertEqual(NI5, 5) self.assertEqual(NEI.y.value, 2) test_pickle_exception(self.assertRaises, TypeError, NEI.x) test_pickle_exception(self.assertRaises, PicklingError, NEI) def test_subclasses_without_direct_pickle_support_using_name(self): class NamedInt(int): __qualname__ = 'NamedInt' def __new__(cls, *args): _args = args name, args = args[0], args[1:] if len(args) == 0: raise TypeError("name and value must be specified") self = int.__new__(cls, *args) self._intname = name self._args = _args return self @property def __name__(self): return self._intname def __repr__(self): # repr() is updated to include the name and type info return "%s(%r, %s)" % (type(self).__name__, self.__name__, int.__repr__(self)) def __str__(self): # str() is unchanged, even if it relies on the repr() fallback base = int base_str = base.__str__ if base_str.__objclass__ is object: return base.__repr__(self) return base_str(self) # for simplicity, we only define one operator that # propagates expressions def __add__(self, other): temp = int(self) + int( other) if isinstance(self, NamedInt) and isinstance(other, NamedInt): return NamedInt( '(%s + %s)' % (self.__name__, other.__name__), temp ) else: return temp class NEI(NamedInt, Enum): __qualname__ = 'NEI' x = ('the-x', 1) y = ('the-y', 2) def __reduce_ex__(self, proto): return getattr, (self.__class__, self._name_) self.assertTrue(NEI.__new__ is Enum.__new__) self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)") globals()['NamedInt'] = NamedInt globals()['NEI'] = NEI NI5 = NamedInt('test', 5) self.assertEqual(NI5, 5) self.assertEqual(NEI.y.value, 2) test_pickle_dump_load(self.assertTrue, NEI.y) test_pickle_dump_load(self.assertTrue, NEI) def test_tuple_subclass(self): class SomeTuple(tuple, Enum): __qualname__ = 'SomeTuple' first = (1, 'for the money') second = (2, 'for the show') third = (3, 'for the music') self.assertTrue(type(SomeTuple.first) is SomeTuple) self.assertTrue(isinstance(SomeTuple.second, tuple)) self.assertEqual(SomeTuple.third, (3, 'for the music')) globals()['SomeTuple'] = SomeTuple test_pickle_dump_load(self.assertTrue, SomeTuple.first) def test_duplicate_values_give_unique_enum_items(self): class AutoNumber(Enum): __order__ = 'enum_m enum_d enum_y' enum_m = () enum_d = () enum_y = () def __new__(cls): value = len(cls.__members__) + 1 obj = object.__new__(cls) obj._value_ = value return obj def __int__(self): return int(self._value_) self.assertEqual(int(AutoNumber.enum_d), 2) self.assertEqual(AutoNumber.enum_y.value, 3) self.assertTrue(AutoNumber(1) is AutoNumber.enum_m) self.assertEqual( list(AutoNumber), [AutoNumber.enum_m, AutoNumber.enum_d, AutoNumber.enum_y], ) def test_inherited_new_from_enhanced_enum(self): class AutoNumber2(Enum): def __new__(cls): value = len(cls.__members__) + 1 obj = object.__new__(cls) obj._value_ = value return obj def __int__(self): return int(self._value_) class Color(AutoNumber2): _order_ = 'red green blue' red = () green = () blue = () self.assertEqual(len(Color), 3, "wrong number of elements: %d (should be %d)" % (len(Color), 3)) self.assertEqual(list(Color), [Color.red, Color.green, Color.blue]) if pyver >= 3.0: self.assertEqual(list(map(int, Color)), [1, 2, 3]) def test_inherited_new_from_mixed_enum(self): class AutoNumber3(IntEnum): def __new__(cls): value = len(cls.__members__) + 1 obj = int.__new__(cls, value) obj._value_ = value return obj class Color(AutoNumber3): red = () green = () blue = () self.assertEqual(len(Color), 3, "wrong number of elements: %d (should be %d)" % (len(Color), 3)) Color.red Color.green Color.blue def test_equality(self): class AlwaysEqual: def __eq__(self, other): return True class OrdinaryEnum(Enum): a = 1 self.assertEqual(AlwaysEqual(), OrdinaryEnum.a) self.assertEqual(OrdinaryEnum.a, AlwaysEqual()) def test_ordered_mixin(self): class OrderedEnum(Enum): def __ge__(self, other): if self.__class__ is other.__class__: return self._value_ >= other._value_ return NotImplemented def __gt__(self, other): if self.__class__ is other.__class__: return self._value_ > other._value_ return NotImplemented def __le__(self, other): if self.__class__ is other.__class__: return self._value_ <= other._value_ return NotImplemented def __lt__(self, other): if self.__class__ is other.__class__: return self._value_ < other._value_ return NotImplemented class Grade(OrderedEnum): __order__ = 'A B C D F' A = 5 B = 4 C = 3 D = 2 F = 1 self.assertEqual(list(Grade), [Grade.A, Grade.B, Grade.C, Grade.D, Grade.F]) self.assertTrue(Grade.A > Grade.B) self.assertTrue(Grade.F <= Grade.C) self.assertTrue(Grade.D < Grade.A) self.assertTrue(Grade.B >= Grade.B) def test_extending2(self): def bad_extension(): class Shade(Enum): def shade(self): print(self.name) class Color(Shade): red = 1 green = 2 blue = 3 class MoreColor(Color): cyan = 4 magenta = 5 yellow = 6 self.assertRaises(TypeError, bad_extension) def test_extending3(self): class Shade(Enum): def shade(self): return self.name class Color(Shade): def hex(self): return '%s hexlified!' % self.value class MoreColor(Color): cyan = 4 magenta = 5 yellow = 6 self.assertEqual(MoreColor.magenta.hex(), '5 hexlified!') def test_no_duplicates(self): def bad_duplicates(): class UniqueEnum(Enum): def __init__(self, *args): cls = self.__class__ if any(self.value == e.value for e in cls): a = self.name e = cls(self.value).name raise ValueError( "aliases not allowed in UniqueEnum: %r --> %r" % (a, e) ) class Color(UniqueEnum): red = 1 green = 2 blue = 3 class Color(UniqueEnum): red = 1 green = 2 blue = 3 grene = 2 self.assertRaises(ValueError, bad_duplicates) def test_init(self): class Planet(Enum): MERCURY = (3.303e+23, 2.4397e6) VENUS = (4.869e+24, 6.0518e6) EARTH = (5.976e+24, 6.37814e6) MARS = (6.421e+23, 3.3972e6) JUPITER = (1.9e+27, 7.1492e7) SATURN = (5.688e+26, 6.0268e7) URANUS = (8.686e+25, 2.5559e7) NEPTUNE = (1.024e+26, 2.4746e7) def __init__(self, mass, radius): self.mass = mass # in kilograms self.radius = radius # in meters @property def surface_gravity(self): # universal gravitational constant (m3 kg-1 s-2) G = 6.67300E-11 return G * self.mass / (self.radius * self.radius) self.assertEqual(round(Planet.EARTH.surface_gravity, 2), 9.80) self.assertEqual(Planet.EARTH.value, (5.976e+24, 6.37814e6)) def test_nonhash_value(self): class AutoNumberInAList(Enum): def __new__(cls): value = [len(cls.__members__) + 1] obj = object.__new__(cls) obj._value_ = value return obj class ColorInAList(AutoNumberInAList): _order_ = 'red green blue' red = () green = () blue = () self.assertEqual(list(ColorInAList), [ColorInAList.red, ColorInAList.green, ColorInAList.blue]) self.assertEqual(ColorInAList.red.value, [1]) self.assertEqual(ColorInAList([1]), ColorInAList.red) def test_conflicting_types_resolved_in_new(self): class LabelledIntEnum(int, Enum): def __new__(cls, *args): value, label = args obj = int.__new__(cls, value) obj.label = label obj._value_ = value return obj class LabelledList(LabelledIntEnum): unprocessed = (1, "Unprocessed") payment_complete = (2, "Payment Complete") self.assertEqual(list(LabelledList), [LabelledList.unprocessed, LabelledList.payment_complete]) self.assertEqual(LabelledList.unprocessed, 1) self.assertEqual(LabelledList(1), LabelledList.unprocessed) def test_empty_with_functional_api(self): empty = enum.IntEnum('Foo', {}) self.assertEqual(len(empty), 0) class TestUnique(unittest.TestCase): """2.4 doesn't allow class decorators, use function syntax.""" def test_unique_clean(self): class Clean(Enum): one = 1 two = 'dos' tres = 4.0 unique(Clean) class Cleaner(IntEnum): single = 1 double = 2 triple = 3 unique(Cleaner) def test_unique_dirty(self): try: class Dirty(Enum): __order__ = 'one two tres' one = 1 two = 'dos' tres = 1 unique(Dirty) except ValueError: exc = sys.exc_info()[1] message = exc.args[0] self.assertTrue('tres -> one' in message) try: class Dirtier(IntEnum): _order_ = 'single double triple turkey' single = 1 double = 1 triple = 3 turkey = 3 unique(Dirtier) except ValueError: exc = sys.exc_info()[1] message = exc.args[0] self.assertTrue('double -> single' in message) self.assertTrue('turkey -> triple' in message) class TestMe(unittest.TestCase): pass if __name__ == '__main__': unittest.main() enum34-1.1.6/enum/README0000664000175000017500000000023512716237133014705 0ustar ethanethan00000000000000enum34 is the new Python stdlib enum module available in Python 3.4 backported for previous versions of Python from 2.4 to 3.3. tested on 2.6, 2.7, and 3.3+ enum34-1.1.6/enum/doc/0000775000175000017500000000000012716237137014576 5ustar ethanethan00000000000000enum34-1.1.6/enum/doc/enum.rst0000664000175000017500000005366012716237133016302 0ustar ethanethan00000000000000``enum`` --- support for enumerations ======================================== .. :synopsis: enumerations are sets of symbolic names bound to unique, constant values. .. :moduleauthor:: Ethan Furman .. :sectionauthor:: Barry Warsaw , .. :sectionauthor:: Eli Bendersky , .. :sectionauthor:: Ethan Furman ---------------- An enumeration is a set of symbolic names (members) bound to unique, constant values. Within an enumeration, the members can be compared by identity, and the enumeration itself can be iterated over. Module Contents --------------- This module defines two enumeration classes that can be used to define unique sets of names and values: ``Enum`` and ``IntEnum``. It also defines one decorator, ``unique``. ``Enum`` Base class for creating enumerated constants. See section `Functional API`_ for an alternate construction syntax. ``IntEnum`` Base class for creating enumerated constants that are also subclasses of ``int``. ``unique`` Enum class decorator that ensures only one name is bound to any one value. Creating an Enum ---------------- Enumerations are created using the ``class`` syntax, which makes them easy to read and write. An alternative creation method is described in `Functional API`_. To define an enumeration, subclass ``Enum`` as follows:: >>> from enum import Enum >>> class Color(Enum): ... red = 1 ... green = 2 ... blue = 3 Note: Nomenclature - The class ``Color`` is an *enumeration* (or *enum*) - The attributes ``Color.red``, ``Color.green``, etc., are *enumeration members* (or *enum members*). - The enum members have *names* and *values* (the name of ``Color.red`` is ``red``, the value of ``Color.blue`` is ``3``, etc.) Note: Even though we use the ``class`` syntax to create Enums, Enums are not normal Python classes. See `How are Enums different?`_ for more details. Enumeration members have human readable string representations:: >>> print(Color.red) Color.red ...while their ``repr`` has more information:: >>> print(repr(Color.red)) The *type* of an enumeration member is the enumeration it belongs to:: >>> type(Color.red) >>> isinstance(Color.green, Color) True >>> Enum members also have a property that contains just their item name:: >>> print(Color.red.name) red Enumerations support iteration. In Python 3.x definition order is used; in Python 2.x the definition order is not available, but class attribute ``__order__`` is supported; otherwise, value order is used:: >>> class Shake(Enum): ... __order__ = 'vanilla chocolate cookies mint' # only needed in 2.x ... vanilla = 7 ... chocolate = 4 ... cookies = 9 ... mint = 3 ... >>> for shake in Shake: ... print(shake) ... Shake.vanilla Shake.chocolate Shake.cookies Shake.mint The ``__order__`` attribute is always removed, and in 3.x it is also ignored (order is definition order); however, in the stdlib version it will be ignored but not removed. Enumeration members are hashable, so they can be used in dictionaries and sets:: >>> apples = {} >>> apples[Color.red] = 'red delicious' >>> apples[Color.green] = 'granny smith' >>> apples == {Color.red: 'red delicious', Color.green: 'granny smith'} True Programmatic access to enumeration members and their attributes --------------------------------------------------------------- Sometimes it's useful to access members in enumerations programmatically (i.e. situations where ``Color.red`` won't do because the exact color is not known at program-writing time). ``Enum`` allows such access:: >>> Color(1) >>> Color(3) If you want to access enum members by *name*, use item access:: >>> Color['red'] >>> Color['green'] If have an enum member and need its ``name`` or ``value``:: >>> member = Color.red >>> member.name 'red' >>> member.value 1 Duplicating enum members and values ----------------------------------- Having two enum members (or any other attribute) with the same name is invalid; in Python 3.x this would raise an error, but in Python 2.x the second member simply overwrites the first:: >>> # python 2.x >>> class Shape(Enum): ... square = 2 ... square = 3 ... >>> Shape.square >>> # python 3.x >>> class Shape(Enum): ... square = 2 ... square = 3 Traceback (most recent call last): ... TypeError: Attempted to reuse key: 'square' However, two enum members are allowed to have the same value. Given two members A and B with the same value (and A defined first), B is an alias to A. By-value lookup of the value of A and B will return A. By-name lookup of B will also return A:: >>> class Shape(Enum): ... __order__ = 'square diamond circle alias_for_square' # only needed in 2.x ... square = 2 ... diamond = 1 ... circle = 3 ... alias_for_square = 2 ... >>> Shape.square >>> Shape.alias_for_square >>> Shape(2) Allowing aliases is not always desirable. ``unique`` can be used to ensure that none exist in a particular enumeration:: >>> from enum import unique >>> @unique ... class Mistake(Enum): ... __order__ = 'one two three four' # only needed in 2.x ... one = 1 ... two = 2 ... three = 3 ... four = 3 Traceback (most recent call last): ... ValueError: duplicate names found in : four -> three Iterating over the members of an enum does not provide the aliases:: >>> list(Shape) [, , ] The special attribute ``__members__`` is a dictionary mapping names to members. It includes all names defined in the enumeration, including the aliases:: >>> for name, member in sorted(Shape.__members__.items()): ... name, member ... ('alias_for_square', ) ('circle', ) ('diamond', ) ('square', ) The ``__members__`` attribute can be used for detailed programmatic access to the enumeration members. For example, finding all the aliases:: >>> [name for name, member in Shape.__members__.items() if member.name != name] ['alias_for_square'] Comparisons ----------- Enumeration members are compared by identity:: >>> Color.red is Color.red True >>> Color.red is Color.blue False >>> Color.red is not Color.blue True Ordered comparisons between enumeration values are *not* supported. Enum members are not integers (but see `IntEnum`_ below):: >>> Color.red < Color.blue Traceback (most recent call last): File "", line 1, in TypeError: unorderable types: Color() < Color() .. warning:: In Python 2 *everything* is ordered, even though the ordering may not make sense. If you want your enumerations to have a sensible ordering check out the `OrderedEnum`_ recipe below. Equality comparisons are defined though:: >>> Color.blue == Color.red False >>> Color.blue != Color.red True >>> Color.blue == Color.blue True Comparisons against non-enumeration values will always compare not equal (again, ``IntEnum`` was explicitly designed to behave differently, see below):: >>> Color.blue == 2 False Allowed members and attributes of enumerations ---------------------------------------------- The examples above use integers for enumeration values. Using integers is short and handy (and provided by default by the `Functional API`_), but not strictly enforced. In the vast majority of use-cases, one doesn't care what the actual value of an enumeration is. But if the value *is* important, enumerations can have arbitrary values. Enumerations are Python classes, and can have methods and special methods as usual. If we have this enumeration:: >>> class Mood(Enum): ... funky = 1 ... happy = 3 ... ... def describe(self): ... # self is the member here ... return self.name, self.value ... ... def __str__(self): ... return 'my custom str! {0}'.format(self.value) ... ... @classmethod ... def favorite_mood(cls): ... # cls here is the enumeration ... return cls.happy Then:: >>> Mood.favorite_mood() >>> Mood.happy.describe() ('happy', 3) >>> str(Mood.funky) 'my custom str! 1' The rules for what is allowed are as follows: _sunder_ names (starting and ending with a single underscore) are reserved by enum and cannot be used; all other attributes defined within an enumeration will become members of this enumeration, with the exception of *__dunder__* names and descriptors (methods are also descriptors). Note: If your enumeration defines ``__new__`` and/or ``__init__`` then whatever value(s) were given to the enum member will be passed into those methods. See `Planet`_ for an example. Restricted subclassing of enumerations -------------------------------------- Subclassing an enumeration is allowed only if the enumeration does not define any members. So this is forbidden:: >>> class MoreColor(Color): ... pink = 17 Traceback (most recent call last): ... TypeError: Cannot extend enumerations But this is allowed:: >>> class Foo(Enum): ... def some_behavior(self): ... pass ... >>> class Bar(Foo): ... happy = 1 ... sad = 2 ... Allowing subclassing of enums that define members would lead to a violation of some important invariants of types and instances. On the other hand, it makes sense to allow sharing some common behavior between a group of enumerations. (See `OrderedEnum`_ for an example.) Pickling -------- Enumerations can be pickled and unpickled:: >>> from enum.test_enum import Fruit >>> from pickle import dumps, loads >>> Fruit.tomato is loads(dumps(Fruit.tomato, 2)) True The usual restrictions for pickling apply: picklable enums must be defined in the top level of a module, since unpickling requires them to be importable from that module. Note: With pickle protocol version 4 (introduced in Python 3.4) it is possible to easily pickle enums nested in other classes. Functional API -------------- The ``Enum`` class is callable, providing the following functional API:: >>> Animal = Enum('Animal', 'ant bee cat dog') >>> Animal >>> Animal.ant >>> Animal.ant.value 1 >>> list(Animal) [, , , ] The semantics of this API resemble ``namedtuple``. The first argument of the call to ``Enum`` is the name of the enumeration. The second argument is the *source* of enumeration member names. It can be a whitespace-separated string of names, a sequence of names, a sequence of 2-tuples with key/value pairs, or a mapping (e.g. dictionary) of names to values. The last two options enable assigning arbitrary values to enumerations; the others auto-assign increasing integers starting with 1. A new class derived from ``Enum`` is returned. In other words, the above assignment to ``Animal`` is equivalent to:: >>> class Animals(Enum): ... ant = 1 ... bee = 2 ... cat = 3 ... dog = 4 Pickling enums created with the functional API can be tricky as frame stack implementation details are used to try and figure out which module the enumeration is being created in (e.g. it will fail if you use a utility function in separate module, and also may not work on IronPython or Jython). The solution is to specify the module name explicitly as follows:: >>> Animals = Enum('Animals', 'ant bee cat dog', module=__name__) Derived Enumerations -------------------- IntEnum ^^^^^^^ A variation of ``Enum`` is provided which is also a subclass of ``int``. Members of an ``IntEnum`` can be compared to integers; by extension, integer enumerations of different types can also be compared to each other:: >>> from enum import IntEnum >>> class Shape(IntEnum): ... circle = 1 ... square = 2 ... >>> class Request(IntEnum): ... post = 1 ... get = 2 ... >>> Shape == 1 False >>> Shape.circle == 1 True >>> Shape.circle == Request.post True However, they still can't be compared to standard ``Enum`` enumerations:: >>> class Shape(IntEnum): ... circle = 1 ... square = 2 ... >>> class Color(Enum): ... red = 1 ... green = 2 ... >>> Shape.circle == Color.red False ``IntEnum`` values behave like integers in other ways you'd expect:: >>> int(Shape.circle) 1 >>> ['a', 'b', 'c'][Shape.circle] 'b' >>> [i for i in range(Shape.square)] [0, 1] For the vast majority of code, ``Enum`` is strongly recommended, since ``IntEnum`` breaks some semantic promises of an enumeration (by being comparable to integers, and thus by transitivity to other unrelated enumerations). It should be used only in special cases where there's no other choice; for example, when integer constants are replaced with enumerations and backwards compatibility is required with code that still expects integers. Others ^^^^^^ While ``IntEnum`` is part of the ``enum`` module, it would be very simple to implement independently:: class IntEnum(int, Enum): pass This demonstrates how similar derived enumerations can be defined; for example a ``StrEnum`` that mixes in ``str`` instead of ``int``. Some rules: 1. When subclassing ``Enum``, mix-in types must appear before ``Enum`` itself in the sequence of bases, as in the ``IntEnum`` example above. 2. While ``Enum`` can have members of any type, once you mix in an additional type, all the members must have values of that type, e.g. ``int`` above. This restriction does not apply to mix-ins which only add methods and don't specify another data type such as ``int`` or ``str``. 3. When another data type is mixed in, the ``value`` attribute is *not the same* as the enum member itself, although it is equivalant and will compare equal. 4. %-style formatting: ``%s`` and ``%r`` call ``Enum``'s ``__str__`` and ``__repr__`` respectively; other codes (such as ``%i`` or ``%h`` for IntEnum) treat the enum member as its mixed-in type. Note: Prior to Python 3.4 there is a bug in ``str``'s %-formatting: ``int`` subclasses are printed as strings and not numbers when the ``%d``, ``%i``, or ``%u`` codes are used. 5. ``str.__format__`` (or ``format``) will use the mixed-in type's ``__format__``. If the ``Enum``'s ``str`` or ``repr`` is desired use the ``!s`` or ``!r`` ``str`` format codes. Decorators ---------- unique ^^^^^^ A ``class`` decorator specifically for enumerations. It searches an enumeration's ``__members__`` gathering any aliases it finds; if any are found ``ValueError`` is raised with the details:: >>> @unique ... class NoDupes(Enum): ... first = 'one' ... second = 'two' ... third = 'two' Traceback (most recent call last): ... ValueError: duplicate names found in : third -> second Interesting examples -------------------- While ``Enum`` and ``IntEnum`` are expected to cover the majority of use-cases, they cannot cover them all. Here are recipes for some different types of enumerations that can be used directly, or as examples for creating one's own. AutoNumber ^^^^^^^^^^ Avoids having to specify the value for each enumeration member:: >>> class AutoNumber(Enum): ... def __new__(cls): ... value = len(cls.__members__) + 1 ... obj = object.__new__(cls) ... obj._value_ = value ... return obj ... >>> class Color(AutoNumber): ... __order__ = "red green blue" # only needed in 2.x ... red = () ... green = () ... blue = () ... >>> Color.green.value == 2 True Note: The `__new__` method, if defined, is used during creation of the Enum members; it is then replaced by Enum's `__new__` which is used after class creation for lookup of existing members. Due to the way Enums are supposed to behave, there is no way to customize Enum's `__new__`. UniqueEnum ^^^^^^^^^^ Raises an error if a duplicate member name is found instead of creating an alias:: >>> class UniqueEnum(Enum): ... def __init__(self, *args): ... cls = self.__class__ ... if any(self.value == e.value for e in cls): ... a = self.name ... e = cls(self.value).name ... raise ValueError( ... "aliases not allowed in UniqueEnum: %r --> %r" ... % (a, e)) ... >>> class Color(UniqueEnum): ... red = 1 ... green = 2 ... blue = 3 ... grene = 2 Traceback (most recent call last): ... ValueError: aliases not allowed in UniqueEnum: 'grene' --> 'green' OrderedEnum ^^^^^^^^^^^ An ordered enumeration that is not based on ``IntEnum`` and so maintains the normal ``Enum`` invariants (such as not being comparable to other enumerations):: >>> class OrderedEnum(Enum): ... def __ge__(self, other): ... if self.__class__ is other.__class__: ... return self._value_ >= other._value_ ... return NotImplemented ... def __gt__(self, other): ... if self.__class__ is other.__class__: ... return self._value_ > other._value_ ... return NotImplemented ... def __le__(self, other): ... if self.__class__ is other.__class__: ... return self._value_ <= other._value_ ... return NotImplemented ... def __lt__(self, other): ... if self.__class__ is other.__class__: ... return self._value_ < other._value_ ... return NotImplemented ... >>> class Grade(OrderedEnum): ... __ordered__ = 'A B C D F' ... A = 5 ... B = 4 ... C = 3 ... D = 2 ... F = 1 ... >>> Grade.C < Grade.A True Planet ^^^^^^ If ``__new__`` or ``__init__`` is defined the value of the enum member will be passed to those methods:: >>> class Planet(Enum): ... MERCURY = (3.303e+23, 2.4397e6) ... VENUS = (4.869e+24, 6.0518e6) ... EARTH = (5.976e+24, 6.37814e6) ... MARS = (6.421e+23, 3.3972e6) ... JUPITER = (1.9e+27, 7.1492e7) ... SATURN = (5.688e+26, 6.0268e7) ... URANUS = (8.686e+25, 2.5559e7) ... NEPTUNE = (1.024e+26, 2.4746e7) ... def __init__(self, mass, radius): ... self.mass = mass # in kilograms ... self.radius = radius # in meters ... @property ... def surface_gravity(self): ... # universal gravitational constant (m3 kg-1 s-2) ... G = 6.67300E-11 ... return G * self.mass / (self.radius * self.radius) ... >>> Planet.EARTH.value (5.976e+24, 6378140.0) >>> Planet.EARTH.surface_gravity 9.802652743337129 How are Enums different? ------------------------ Enums have a custom metaclass that affects many aspects of both derived Enum classes and their instances (members). Enum Classes ^^^^^^^^^^^^ The ``EnumMeta`` metaclass is responsible for providing the ``__contains__``, ``__dir__``, ``__iter__`` and other methods that allow one to do things with an ``Enum`` class that fail on a typical class, such as ``list(Color)`` or ``some_var in Color``. ``EnumMeta`` is responsible for ensuring that various other methods on the final ``Enum`` class are correct (such as ``__new__``, ``__getnewargs__``, ``__str__`` and ``__repr__``). .. note:: ``__dir__`` is not changed in the Python 2 line as it messes up some of the decorators included in the stdlib. Enum Members (aka instances) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The most interesting thing about Enum members is that they are singletons. ``EnumMeta`` creates them all while it is creating the ``Enum`` class itself, and then puts a custom ``__new__`` in place to ensure that no new ones are ever instantiated by returning only the existing member instances. Finer Points ^^^^^^^^^^^^ ``Enum`` members are instances of an ``Enum`` class, and even though they are accessible as `EnumClass.member1.member2`, they should not be accessed directly from the member as that lookup may fail or, worse, return something besides the ``Enum`` member you were looking for (changed in version 1.1.1):: >>> class FieldTypes(Enum): ... name = 1 ... value = 2 ... size = 3 ... >>> FieldTypes.value.size >>> FieldTypes.size.value 3 The ``__members__`` attribute is only available on the class. In Python 3.x ``__members__`` is always an ``OrderedDict``, with the order being the definition order. In Python 2.7 ``__members__`` is an ``OrderedDict`` if ``__order__`` was specified, and a plain ``dict`` otherwise. In all other Python 2.x versions ``__members__`` is a plain ``dict`` even if ``__order__`` was specified as the ``OrderedDict`` type didn't exist yet. If you give your ``Enum`` subclass extra methods, like the `Planet`_ class above, those methods will show up in a `dir` of the member, but not of the class:: >>> dir(Planet) ['EARTH', 'JUPITER', 'MARS', 'MERCURY', 'NEPTUNE', 'SATURN', 'URANUS', 'VENUS', '__class__', '__doc__', '__members__', '__module__'] >>> dir(Planet.EARTH) ['__class__', '__doc__', '__module__', 'name', 'surface_gravity', 'value'] A ``__new__`` method will only be used for the creation of the ``Enum`` members -- after that it is replaced. This means if you wish to change how ``Enum`` members are looked up you either have to write a helper function or a ``classmethod``. enum34-1.1.6/enum/doc/enum.pdf0000664000175000017500000021104012716237137016233 0ustar ethanethan00000000000000%PDF-1.4 %“Œ‹ž ReportLab Generated PDF document http://www.reportlab.com 1 0 obj << /F1 2 0 R /F2 3 0 R /F3 4 0 R /F4 5 0 R /F5 8 0 R /F6 15 0 R >> endobj 2 0 obj << /BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font >> endobj 3 0 obj << /BaseFont /Courier-Bold /Encoding /WinAnsiEncoding /Name /F2 /Subtype /Type1 /Type /Font >> endobj 4 0 obj << /BaseFont /Helvetica-Bold /Encoding /WinAnsiEncoding /Name /F3 /Subtype /Type1 /Type /Font >> endobj 5 0 obj << /BaseFont /Courier /Encoding /WinAnsiEncoding /Name /F4 /Subtype /Type1 /Type /Font >> endobj 6 0 obj << /Border [ 0 0 0 ] /Contents () /Dest [ 22 0 R /XYZ 62.69291 639.3236 0 ] /Rect [ 335.1805 574.4272 405.2473 586.4272 ] /Subtype /Link /Type /Annot >> endobj 7 0 obj << /Border [ 0 0 0 ] /Contents () /Dest [ 22 0 R /XYZ 62.69291 639.3236 0 ] /Rect [ 255.9742 427.4272 321.5378 439.4272 ] /Subtype /Link /Type /Annot >> endobj 8 0 obj << /BaseFont /Helvetica-Oblique /Encoding /WinAnsiEncoding /Name /F5 /Subtype /Type1 /Type /Font >> endobj 9 0 obj << /Border [ 0 0 0 ] /Contents () /Dest [ 26 0 R /XYZ 62.69291 278.1236 0 ] /Rect [ 82.69291 182.2272 201.0729 194.2272 ] /Subtype /Link /Type /Annot >> endobj 10 0 obj << /Annots [ 6 0 R 7 0 R 9 0 R ] /Contents 56 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 55 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >> /Type /Page >> endobj 11 0 obj << /Contents 57 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 55 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >> /Type /Page >> endobj 12 0 obj << /Contents 58 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 55 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >> /Type /Page >> endobj 13 0 obj << /Contents 59 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 55 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >> /Type /Page >> endobj 14 0 obj << /Border [ 0 0 0 ] /Contents () /Dest [ 22 0 R /XYZ 62.69291 157.2236 0 ] /Rect [ 101.6029 741.7736 141.6229 753.7736 ] /Subtype /Link /Type /Annot >> endobj 15 0 obj << /BaseFont /Helvetica-BoldOblique /Encoding /WinAnsiEncoding /Name /F6 /Subtype /Type1 /Type /Font >> endobj 16 0 obj << /Border [ 0 0 0 ] /Contents () /Dest [ 25 0 R /XYZ 62.69291 359.6236 0 ] /Rect [ 327.1529 585.5736 392.7329 597.5736 ] /Subtype /Link /Type /Annot >> endobj 17 0 obj << /Border [ 0 0 0 ] /Contents () /Dest [ 22 0 R /XYZ 62.69291 639.3236 0 ] /Rect [ 181.1917 312.1736 246.4634 324.1736 ] /Subtype /Link /Type /Annot >> endobj 18 0 obj << /Annots [ 14 0 R 16 0 R 17 0 R ] /Contents 60 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 55 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >> /Type /Page >> endobj 19 0 obj << /Border [ 0 0 0 ] /Contents () /Dest [ 26 0 R /XYZ 62.69291 610.8236 0 ] /Rect [ 326.1329 511.3736 357.2629 523.3736 ] /Subtype /Link /Type /Annot >> endobj 20 0 obj << /Border [ 0 0 0 ] /Contents () /Dest [ 25 0 R /XYZ 62.69291 359.6236 0 ] /Rect [ 241.1229 185.9736 306.7029 197.9736 ] /Subtype /Link /Type /Annot >> endobj 21 0 obj << /Annots [ 19 0 R 20 0 R ] /Contents 61 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 55 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >> /Type /Page >> endobj 22 0 obj << /Contents 62 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 55 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >> /Type /Page >> endobj 23 0 obj << /Contents 63 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 55 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >> /Type /Page >> endobj 24 0 obj << /Contents 64 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 55 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >> /Type /Page >> endobj 25 0 obj << /Contents 65 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 55 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >> /Type /Page >> endobj 26 0 obj << /Contents 66 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 55 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >> /Type /Page >> endobj 27 0 obj << /Border [ 0 0 0 ] /Contents () /Dest [ 26 0 R /XYZ 62.69291 610.8236 0 ] /Rect [ 309.4094 299.5736 340.6461 311.5736 ] /Subtype /Link /Type /Annot >> endobj 28 0 obj << /Annots [ 27 0 R ] /Contents 67 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 55 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >> /Type /Page >> endobj 29 0 obj << /Outlines 31 0 R /PageLabels 68 0 R /PageMode /UseNone /Pages 55 0 R /Type /Catalog >> endobj 30 0 obj << /Author () /CreationDate (D:20160515202831+08'00') /Creator (\(unspecified\)) /Keywords () /Producer (ReportLab PDF Library - www.reportlab.com) /Subject (\(unspecified\)) /Title (enum --- support for enumerations) >> endobj 31 0 obj << /Count 27 /First 32 0 R /Last 51 0 R /Type /Outlines >> endobj 32 0 obj << /Dest [ 10 0 R /XYZ 62.69291 660.6772 0 ] /Next 33 0 R /Parent 31 0 R /Title (Module Contents) >> endobj 33 0 obj << /Dest [ 10 0 R /XYZ 62.69291 477.6772 0 ] /Next 34 0 R /Parent 31 0 R /Prev 32 0 R /Title (Creating an Enum) >> endobj 34 0 obj << /Dest [ 11 0 R /XYZ 62.69291 197.0236 0 ] /Next 35 0 R /Parent 31 0 R /Prev 33 0 R /Title (Programmatic access to enumeration members and their attributes) >> endobj 35 0 obj << /Dest [ 12 0 R /XYZ 62.69291 501.4236 0 ] /Next 36 0 R /Parent 31 0 R /Prev 34 0 R /Title (Duplicating enum members and values) >> endobj 36 0 obj << /Dest [ 13 0 R /XYZ 62.69291 215.0236 0 ] /Next 37 0 R /Parent 31 0 R /Prev 35 0 R /Title (Comparisons) >> endobj 37 0 obj << /Dest [ 18 0 R /XYZ 62.69291 362.4236 0 ] /Next 38 0 R /Parent 31 0 R /Prev 36 0 R /Title (Allowed members and attributes of enumerations) >> endobj 38 0 obj << /Dest [ 21 0 R /XYZ 62.69291 498.6236 0 ] /Next 39 0 R /Parent 31 0 R /Prev 37 0 R /Title (Restricted subclassing of enumerations) >> endobj 39 0 obj << /Dest [ 21 0 R /XYZ 62.69291 173.2236 0 ] /Next 40 0 R /Parent 31 0 R /Prev 38 0 R /Title (Pickling) >> endobj 40 0 obj << /Dest [ 22 0 R /XYZ 62.69291 635.8236 0 ] /Next 41 0 R /Parent 31 0 R /Prev 39 0 R /Title (Functional API) >> endobj 41 0 obj << /Count 2 /Dest [ 22 0 R /XYZ 62.69291 187.2236 0 ] /First 42 0 R /Last 43 0 R /Next 44 0 R /Parent 31 0 R /Prev 40 0 R /Title (Derived Enumerations) >> endobj 42 0 obj << /Dest [ 22 0 R /XYZ 62.69291 154.2236 0 ] /Next 43 0 R /Parent 41 0 R /Title (IntEnum) >> endobj 43 0 obj << /Dest [ 23 0 R /XYZ 62.69291 217.4236 0 ] /Parent 41 0 R /Prev 42 0 R /Title (Others) >> endobj 44 0 obj << /Count 1 /Dest [ 24 0 R /XYZ 62.69291 567.0236 0 ] /First 45 0 R /Last 45 0 R /Next 46 0 R /Parent 31 0 R /Prev 41 0 R /Title (Decorators) >> endobj 45 0 obj << /Dest [ 24 0 R /XYZ 62.69291 534.0236 0 ] /Parent 44 0 R /Title (unique) >> endobj 46 0 obj << /Count 4 /Dest [ 24 0 R /XYZ 62.69291 356.8236 0 ] /First 47 0 R /Last 50 0 R /Next 51 0 R /Parent 31 0 R /Prev 44 0 R /Title (Interesting examples) >> endobj 47 0 obj << /Dest [ 24 0 R /XYZ 62.69291 281.8236 0 ] /Next 48 0 R /Parent 46 0 R /Title (AutoNumber) >> endobj 48 0 obj << /Dest [ 25 0 R /XYZ 62.69291 641.8236 0 ] /Next 49 0 R /Parent 46 0 R /Prev 47 0 R /Title (UniqueEnum) >> endobj 49 0 obj << /Dest [ 25 0 R /XYZ 62.69291 356.6236 0 ] /Next 50 0 R /Parent 46 0 R /Prev 48 0 R /Title (OrderedEnum) >> endobj 50 0 obj << /Dest [ 26 0 R /XYZ 62.69291 607.8236 0 ] /Parent 46 0 R /Prev 49 0 R /Title (Planet) >> endobj 51 0 obj << /Count 3 /Dest [ 26 0 R /XYZ 62.69291 274.6236 0 ] /First 52 0 R /Last 54 0 R /Parent 31 0 R /Prev 46 0 R /Title (How are Enums different?) >> endobj 52 0 obj << /Dest [ 26 0 R /XYZ 62.69291 211.6236 0 ] /Next 53 0 R /Parent 51 0 R /Title (Enum Classes) >> endobj 53 0 obj << /Dest [ 28 0 R /XYZ 62.69291 664.0236 0 ] /Next 54 0 R /Parent 51 0 R /Prev 52 0 R /Title (Enum Members \(aka instances\)) >> endobj 54 0 obj << /Dest [ 28 0 R /XYZ 62.69291 592.0236 0 ] /Parent 51 0 R /Prev 53 0 R /Title (Finer Points) >> endobj 55 0 obj << /Count 12 /Kids [ 10 0 R 11 0 R 12 0 R 13 0 R 18 0 R 21 0 R 22 0 R 23 0 R 24 0 R 25 0 R 26 0 R 28 0 R ] /Type /Pages >> endobj 56 0 obj << /Length 6458 >> stream 1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET q 1 0 0 1 62.69291 741.0236 cm q BT 1 0 0 1 0 4 Tm 73.71488 0 Td 24 TL /F2 20 Tf 0 0 0 rg (enum ) Tj /F3 20 Tf 0 0 0 rg (--- support for enumerations) Tj T* -73.71488 0 Td ET Q Q q 1 0 0 1 62.69291 702.6772 cm n 0 14.17323 m 469.8898 14.17323 l S Q q 1 0 0 1 62.69291 672.6772 cm q BT 1 0 0 1 0 14 Tm 2.091318 Tw 12 TL /F1 10 Tf 0 0 0 rg (An enumeration is a set of symbolic names \(members\) bound to unique, constant values. Within an) Tj T* 0 Tw (enumeration, the members can be compared by identity, and the enumeration itself can be iterated over.) Tj T* ET Q Q q 1 0 0 1 62.69291 639.6772 cm q BT 1 0 0 1 0 3.5 Tm 21 TL /F3 17.5 Tf 0 0 0 rg (Module Contents) Tj T* ET Q Q q 1 0 0 1 62.69291 609.6772 cm q BT 1 0 0 1 0 14 Tm 2.027485 Tw 12 TL /F1 10 Tf 0 0 0 rg (This module defines two enumeration classes that can be used to define unique sets of names and) Tj T* 0 Tw (values: ) Tj /F4 10 Tf 0 0 0 rg (Enum ) Tj /F1 10 Tf 0 0 0 rg (and ) Tj /F4 10 Tf 0 0 0 rg (IntEnum) Tj /F1 10 Tf 0 0 0 rg (. It also defines one decorator, ) Tj /F4 10 Tf 0 0 0 rg (unique) Tj /F1 10 Tf 0 0 0 rg (.) Tj T* ET Q Q q 1 0 0 1 62.69291 591.6772 cm q 0 0 0 rg BT 1 0 0 1 0 2 Tm /F4 10 Tf 12 TL (Enum) Tj T* ET Q Q q 1 0 0 1 62.69291 561.6772 cm q BT 1 0 0 1 0 14 Tm 1.128443 Tw 12 TL /F1 10 Tf 0 0 0 rg (Base class for creating enumerated constants. See section ) Tj 0 0 .501961 rg (Functional API ) Tj 0 0 0 rg (for an alternate construction) Tj T* 0 Tw (syntax.) Tj T* ET Q Q q 1 0 0 1 62.69291 543.6772 cm q 0 0 0 rg BT 1 0 0 1 0 2 Tm /F4 10 Tf 12 TL (IntEnum) Tj T* ET Q Q q 1 0 0 1 62.69291 525.6772 cm q BT 1 0 0 1 0 2 Tm 12 TL /F1 10 Tf 0 0 0 rg (Base class for creating enumerated constants that are also subclasses of ) Tj /F4 10 Tf 0 0 0 rg (int) Tj /F1 10 Tf 0 0 0 rg (.) Tj T* ET Q Q q 1 0 0 1 62.69291 507.6772 cm q 0 0 0 rg BT 1 0 0 1 0 2 Tm /F4 10 Tf 12 TL (unique) Tj T* ET Q Q q 1 0 0 1 62.69291 489.6772 cm q 0 0 0 rg BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Enum class decorator that ensures only one name is bound to any one value.) Tj T* ET Q Q q 1 0 0 1 62.69291 456.6772 cm q BT 1 0 0 1 0 3.5 Tm 21 TL /F3 17.5 Tf 0 0 0 rg (Creating an Enum) Tj T* ET Q Q q 1 0 0 1 62.69291 414.6772 cm q BT 1 0 0 1 0 26 Tm 2.432651 Tw 12 TL /F1 10 Tf 0 0 0 rg (Enumerations are created using the ) Tj /F4 10 Tf 0 0 0 rg (class ) Tj /F1 10 Tf 0 0 0 rg (syntax, which makes them easy to read and write. An) Tj T* 0 Tw .533555 Tw (alternative creation method is described in ) Tj 0 0 .501961 rg (Functional API) Tj 0 0 0 rg (. To define an enumeration, subclass ) Tj /F4 10 Tf 0 0 0 rg (Enum ) Tj /F1 10 Tf 0 0 0 rg (as) Tj T* 0 Tw (follows:) Tj T* ET Q Q q 1 0 0 1 62.69291 333.4772 cm q q 1 0 0 1 0 0 cm q 1 0 0 1 6.6 6.6 cm q .662745 .662745 .662745 RG .5 w .960784 .960784 .862745 rg n -6 -6 468.6898 72 re B* Q q BT 1 0 0 1 0 50 Tm 12 TL /F4 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( from enum import Enum) Tj T* (>) Tj (>) Tj (>) Tj ( class Color\(Enum\):) Tj T* (... red = 1) Tj T* (... green = 2) Tj T* (... blue = 3) Tj T* ET Q Q Q Q Q q 1 0 0 1 62.69291 313.4772 cm q 0 0 0 rg BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Note: Nomenclature) Tj T* ET Q Q q 1 0 0 1 62.69291 307.4772 cm Q q 1 0 0 1 62.69291 229.4772 cm 0 0 0 rg BT /F1 10 Tf 12 TL ET BT 1 0 0 1 0 2 Tm T* ET q 1 0 0 1 20 72 cm Q q 1 0 0 1 20 72 cm Q q 1 0 0 1 20 60 cm 0 0 0 rg BT /F1 10 Tf 12 TL ET q 1 0 0 1 6 -3 cm q 0 0 0 rg BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET Q Q q 1 0 0 1 23 -3 cm q BT 1 0 0 1 0 2 Tm 12 TL /F1 10 Tf 0 0 0 rg (The class ) Tj /F4 10 Tf 0 0 0 rg (Color ) Tj /F1 10 Tf 0 0 0 rg (is an ) Tj /F5 10 Tf (enumeration ) Tj /F1 10 Tf (\(or ) Tj /F5 10 Tf (enum) Tj /F1 10 Tf (\)) Tj T* ET Q Q q Q Q q 1 0 0 1 20 54 cm Q q 1 0 0 1 20 30 cm 0 0 0 rg BT /F1 10 Tf 12 TL ET q 1 0 0 1 6 9 cm q 0 0 0 rg BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET Q Q q 1 0 0 1 23 -3 cm q BT 1 0 0 1 0 14 Tm 5.568863 Tw 12 TL /F1 10 Tf 0 0 0 rg (The attributes ) Tj /F4 10 Tf 0 0 0 rg (Color.red) Tj /F1 10 Tf 0 0 0 rg (, ) Tj /F4 10 Tf 0 0 0 rg (Color.green) Tj /F1 10 Tf 0 0 0 rg (, etc., are ) Tj /F5 10 Tf (enumeration members ) Tj /F1 10 Tf (\(or ) Tj /F5 10 Tf (enum) Tj T* 0 Tw (members) Tj /F1 10 Tf (\).) Tj T* ET Q Q q Q Q q 1 0 0 1 20 24 cm Q q 1 0 0 1 20 0 cm 0 0 0 rg BT /F1 10 Tf 12 TL ET q 1 0 0 1 6 9 cm q 0 0 0 rg BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET Q Q q 1 0 0 1 23 -3 cm q BT 1 0 0 1 0 14 Tm 1.471318 Tw 12 TL /F1 10 Tf 0 0 0 rg (The enum members have ) Tj /F5 10 Tf (names ) Tj /F1 10 Tf (and ) Tj /F5 10 Tf (values ) Tj /F1 10 Tf (\(the name of ) Tj /F4 10 Tf 0 0 0 rg (Color.red ) Tj /F1 10 Tf 0 0 0 rg (is ) Tj /F4 10 Tf 0 0 0 rg (red) Tj /F1 10 Tf 0 0 0 rg (, the value of) Tj T* 0 Tw /F4 10 Tf 0 0 0 rg (Color.blue ) Tj /F1 10 Tf 0 0 0 rg (is ) Tj /F4 10 Tf 0 0 0 rg (3) Tj /F1 10 Tf 0 0 0 rg (, etc.\)) Tj T* ET Q Q q Q Q q 1 0 0 1 20 0 cm Q q Q Q q 1 0 0 1 62.69291 229.4772 cm Q q 1 0 0 1 62.69291 211.4772 cm q 0 0 0 rg BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Note:) Tj T* ET Q Q q 1 0 0 1 62.69291 205.4772 cm Q q 1 0 0 1 62.69291 181.4772 cm 0 0 0 rg BT /F1 10 Tf 12 TL ET BT 1 0 0 1 0 2 Tm T* ET q 1 0 0 1 20 0 cm q BT 1 0 0 1 0 14 Tm .126235 Tw 12 TL /F1 10 Tf 0 0 0 rg (Even though we use the ) Tj /F4 10 Tf 0 0 0 rg (class ) Tj /F1 10 Tf 0 0 0 rg (syntax to create Enums, Enums are not normal Python classes. See) Tj T* 0 Tw 0 0 .501961 rg (How are Enums different? ) Tj 0 0 0 rg (for more details.) Tj T* ET Q Q q Q Q q 1 0 0 1 62.69291 181.4772 cm Q q 1 0 0 1 62.69291 163.4772 cm q 0 0 0 rg BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Enumeration members have human readable string representations:) Tj T* ET Q Q q 1 0 0 1 62.69291 118.2772 cm q q 1 0 0 1 0 0 cm q 1 0 0 1 6.6 6.6 cm q .662745 .662745 .662745 RG .5 w .960784 .960784 .862745 rg n -6 -6 468.6898 36 re B* Q q BT 1 0 0 1 0 14 Tm 12 TL /F4 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( print\(Color.red\)) Tj T* (Color.red) Tj T* ET Q Q Q Q Q q 1 0 0 1 62.69291 98.27717 cm q BT 1 0 0 1 0 2 Tm 12 TL /F1 10 Tf 0 0 0 rg (...while their ) Tj /F4 10 Tf 0 0 0 rg (repr ) Tj /F1 10 Tf 0 0 0 rg (has more information:) Tj T* ET Q Q endstream endobj 57 0 obj << /Length 4174 >> stream 1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET q 1 0 0 1 62.69291 727.8236 cm q q 1 0 0 1 0 0 cm q 1 0 0 1 6.6 6.6 cm q .662745 .662745 .662745 RG .5 w .960784 .960784 .862745 rg n -6 -6 468.6898 36 re B* Q q BT 1 0 0 1 0 14 Tm 12 TL /F4 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( print\(repr\(Color.red\)\)) Tj T* (<) Tj (Color.red: 1) Tj (>) Tj T* ET Q Q Q Q Q q 1 0 0 1 62.69291 707.8236 cm q BT 1 0 0 1 0 2 Tm 12 TL /F1 10 Tf 0 0 0 rg (The ) Tj /F5 10 Tf (type ) Tj /F1 10 Tf (of an enumeration member is the enumeration it belongs to:) Tj T* ET Q Q q 1 0 0 1 62.69291 626.6236 cm q q 1 0 0 1 0 0 cm q 1 0 0 1 6.6 6.6 cm q .662745 .662745 .662745 RG .5 w .960784 .960784 .862745 rg n -6 -6 468.6898 72 re B* Q q BT 1 0 0 1 0 50 Tm 12 TL /F4 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( type\(Color.red\)) Tj T* (<) Tj (enum 'Color') Tj (>) Tj T* (>) Tj (>) Tj (>) Tj ( isinstance\(Color.green, Color\)) Tj T* (True) Tj T* (>) Tj (>) Tj (>) Tj T* ET Q Q Q Q Q q 1 0 0 1 62.69291 606.6236 cm q 0 0 0 rg BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Enum members also have a property that contains just their item name:) Tj T* ET Q Q q 1 0 0 1 62.69291 561.4236 cm q q 1 0 0 1 0 0 cm q 1 0 0 1 6.6 6.6 cm q .662745 .662745 .662745 RG .5 w .960784 .960784 .862745 rg n -6 -6 468.6898 36 re B* Q q BT 1 0 0 1 0 14 Tm 12 TL /F4 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( print\(Color.red.name\)) Tj T* (red) Tj T* ET Q Q Q Q Q q 1 0 0 1 62.69291 529.4236 cm q BT 1 0 0 1 0 14 Tm .464985 Tw 12 TL /F1 10 Tf 0 0 0 rg (Enumerations support iteration. In Python 3.x definition order is used; in Python 2.x the definition order is) Tj T* 0 Tw (not available, but class attribute ) Tj /F4 10 Tf 0 0 0 rg (__order__ ) Tj /F1 10 Tf 0 0 0 rg (is supported; otherwise, value order is used:) Tj T* ET Q Q q 1 0 0 1 62.69291 340.2236 cm q q 1 0 0 1 0 0 cm q 1 0 0 1 6.6 6.6 cm q .662745 .662745 .662745 RG .5 w .960784 .960784 .862745 rg n -6 -6 468.6898 180 re B* Q q BT 1 0 0 1 0 158 Tm 12 TL /F4 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( class Shake\(Enum\):) Tj T* (... __order__ = 'vanilla chocolate cookies mint' # only needed in 2.x) Tj T* (... vanilla = 7) Tj T* (... chocolate = 4) Tj T* (... cookies = 9) Tj T* (... mint = 3) Tj T* (...) Tj T* (>) Tj (>) Tj (>) Tj ( for shake in Shake:) Tj T* (... print\(shake\)) Tj T* (...) Tj T* (Shake.vanilla) Tj T* (Shake.chocolate) Tj T* (Shake.cookies) Tj T* (Shake.mint) Tj T* ET Q Q Q Q Q q 1 0 0 1 62.69291 308.2236 cm q BT 1 0 0 1 0 14 Tm 1.893735 Tw 12 TL /F1 10 Tf 0 0 0 rg (The ) Tj /F4 10 Tf 0 0 0 rg (__order__ ) Tj /F1 10 Tf 0 0 0 rg (attribute is always removed, and in 3.x it is also ignored \(order is definition order\);) Tj T* 0 Tw (however, in the stdlib version it will be ignored but not removed.) Tj T* ET Q Q q 1 0 0 1 62.69291 290.2236 cm q 0 0 0 rg BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Enumeration members are hashable, so they can be used in dictionaries and sets:) Tj T* ET Q Q q 1 0 0 1 62.69291 209.0236 cm q q 1 0 0 1 0 0 cm q 1 0 0 1 6.6 6.6 cm q .662745 .662745 .662745 RG .5 w .960784 .960784 .862745 rg n -6 -6 468.6898 72 re B* Q q BT 1 0 0 1 0 50 Tm 12 TL /F4 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( apples = {}) Tj T* (>) Tj (>) Tj (>) Tj ( apples[Color.red] = 'red delicious') Tj T* (>) Tj (>) Tj (>) Tj ( apples[Color.green] = 'granny smith') Tj T* (>) Tj (>) Tj (>) Tj ( apples == {Color.red: 'red delicious', Color.green: 'granny smith'}) Tj T* (True) Tj T* ET Q Q Q Q Q q 1 0 0 1 62.69291 155.0236 cm q BT 1 0 0 1 0 24.5 Tm 21 TL /F3 17.5 Tf 0 0 0 rg (Programmatic access to enumeration members and) Tj T* (their attributes) Tj T* ET Q Q q 1 0 0 1 62.69291 113.0236 cm q BT 1 0 0 1 0 26 Tm 3.541797 Tw 12 TL /F1 10 Tf 0 0 0 rg (Sometimes it's useful to access members in enumerations programmatically \(i.e. situations where) Tj T* 0 Tw .922651 Tw /F4 10 Tf 0 0 0 rg (Color.red ) Tj /F1 10 Tf 0 0 0 rg (won't do because the exact color is not known at program-writing time\). ) Tj /F4 10 Tf 0 0 0 rg (Enum ) Tj /F1 10 Tf 0 0 0 rg (allows such) Tj T* 0 Tw (access:) Tj T* ET Q Q endstream endobj 58 0 obj << /Length 3791 >> stream 1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET q 1 0 0 1 62.69291 703.8236 cm q q 1 0 0 1 0 0 cm q 1 0 0 1 6.6 6.6 cm q .662745 .662745 .662745 RG .5 w .960784 .960784 .862745 rg n -6 -6 468.6898 60 re B* Q q BT 1 0 0 1 0 38 Tm 12 TL /F4 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( Color\(1\)) Tj T* (<) Tj (Color.red: 1) Tj (>) Tj T* (>) Tj (>) Tj (>) Tj ( Color\(3\)) Tj T* (<) Tj (Color.blue: 3) Tj (>) Tj T* ET Q Q Q Q Q q 1 0 0 1 62.69291 683.8236 cm q BT 1 0 0 1 0 2 Tm 12 TL /F1 10 Tf 0 0 0 rg (If you want to access enum members by ) Tj /F5 10 Tf (name) Tj /F1 10 Tf (, use item access:) Tj T* ET Q Q q 1 0 0 1 62.69291 614.6236 cm q q 1 0 0 1 0 0 cm q 1 0 0 1 6.6 6.6 cm q .662745 .662745 .662745 RG .5 w .960784 .960784 .862745 rg n -6 -6 468.6898 60 re B* Q q BT 1 0 0 1 0 38 Tm 12 TL /F4 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( Color['red']) Tj T* (<) Tj (Color.red: 1) Tj (>) Tj T* (>) Tj (>) Tj (>) Tj ( Color['green']) Tj T* (<) Tj (Color.green: 2) Tj (>) Tj T* ET Q Q Q Q Q q 1 0 0 1 62.69291 594.6236 cm q BT 1 0 0 1 0 2 Tm 12 TL /F1 10 Tf 0 0 0 rg (If have an enum member and need its ) Tj /F4 10 Tf 0 0 0 rg (name ) Tj /F1 10 Tf 0 0 0 rg (or ) Tj /F4 10 Tf 0 0 0 rg (value) Tj /F1 10 Tf 0 0 0 rg (:) Tj T* ET Q Q q 1 0 0 1 62.69291 513.4236 cm q q 1 0 0 1 0 0 cm q 1 0 0 1 6.6 6.6 cm q .662745 .662745 .662745 RG .5 w .960784 .960784 .862745 rg n -6 -6 468.6898 72 re B* Q q BT 1 0 0 1 0 50 Tm 12 TL /F4 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( member = Color.red) Tj T* (>) Tj (>) Tj (>) Tj ( member.name) Tj T* ('red') Tj T* (>) Tj (>) Tj (>) Tj ( member.value) Tj T* (1) Tj T* ET Q Q Q Q Q q 1 0 0 1 62.69291 480.4236 cm q BT 1 0 0 1 0 3.5 Tm 21 TL /F3 17.5 Tf 0 0 0 rg (Duplicating enum members and values) Tj T* ET Q Q q 1 0 0 1 62.69291 450.4236 cm q 0 0 0 rg BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL .13832 Tw (Having two enum members \(or any other attribute\) with the same name is invalid; in Python 3.x this would) Tj T* 0 Tw (raise an error, but in Python 2.x the second member simply overwrites the first:) Tj T* ET Q Q q 1 0 0 1 62.69291 249.2236 cm q q 1 0 0 1 0 0 cm q 1 0 0 1 6.6 6.6 cm q .662745 .662745 .662745 RG .5 w .960784 .960784 .862745 rg n -6 -6 468.6898 192 re B* Q q BT 1 0 0 1 0 170 Tm 12 TL /F4 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( # python 2.x) Tj T* (>) Tj (>) Tj (>) Tj ( class Shape\(Enum\):) Tj T* (... square = 2) Tj T* (... square = 3) Tj T* (...) Tj T* (>) Tj (>) Tj (>) Tj ( Shape.square) Tj T* (<) Tj (Shape.square: 3) Tj (>) Tj T* T* (>) Tj (>) Tj (>) Tj ( # python 3.x) Tj T* (>) Tj (>) Tj (>) Tj ( class Shape\(Enum\):) Tj T* (... square = 2) Tj T* (... square = 3) Tj T* (Traceback \(most recent call last\):) Tj T* (...) Tj T* (TypeError: Attempted to reuse key: 'square') Tj T* ET Q Q Q Q Q q 1 0 0 1 62.69291 205.2236 cm q 0 0 0 rg BT 1 0 0 1 0 26 Tm /F1 10 Tf 12 TL .384987 Tw (However, two enum members are allowed to have the same value. Given two members A and B with the) Tj T* 0 Tw .444772 Tw (same value \(and A defined first\), B is an alias to A. By-value lookup of the value of A and B will return A.) Tj T* 0 Tw (By-name lookup of B will also return A:) Tj T* ET Q Q q 1 0 0 1 62.69291 88.02362 cm q q 1 0 0 1 0 0 cm q 1 0 0 1 6.6 6.6 cm q .662745 .662745 .662745 RG .5 w .960784 .960784 .862745 rg n -6 -6 492 108 re B* Q q BT 1 0 0 1 0 86 Tm 12 TL /F4 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( class Shape\(Enum\):) Tj T* (... __order__ = 'square diamond circle alias_for_square' # only needed in 2.x) Tj T* (... square = 2) Tj T* (... diamond = 1) Tj T* (... circle = 3) Tj T* (... alias_for_square = 2) Tj T* (...) Tj T* (>) Tj (>) Tj (>) Tj ( Shape.square) Tj T* ET Q Q Q Q Q endstream endobj 59 0 obj << /Length 4406 >> stream 1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET q 1 0 0 1 62.69291 691.8236 cm q q 1 0 0 1 0 0 cm q 1 0 0 1 6.6 6.6 cm q .662745 .662745 .662745 RG .5 w .960784 .960784 .862745 rg n -6 -6 468.6898 72 re B* Q q BT 1 0 0 1 0 50 Tm 12 TL /F4 10 Tf 0 0 0 rg (<) Tj (Shape.square: 2) Tj (>) Tj T* (>) Tj (>) Tj (>) Tj ( Shape.alias_for_square) Tj T* (<) Tj (Shape.square: 2) Tj (>) Tj T* (>) Tj (>) Tj (>) Tj ( Shape\(2\)) Tj T* (<) Tj (Shape.square: 2) Tj (>) Tj T* ET Q Q Q Q Q q 1 0 0 1 62.69291 659.8236 cm q BT 1 0 0 1 0 14 Tm 1.074104 Tw 12 TL /F1 10 Tf 0 0 0 rg (Allowing aliases is not always desirable. ) Tj /F4 10 Tf 0 0 0 rg (unique ) Tj /F1 10 Tf 0 0 0 rg (can be used to ensure that none exist in a particular) Tj T* 0 Tw (enumeration:) Tj T* ET Q Q q 1 0 0 1 62.69291 506.6236 cm q q 1 0 0 1 0 0 cm q 1 0 0 1 6.6 6.6 cm q .662745 .662745 .662745 RG .5 w .960784 .960784 .862745 rg n -6 -6 468.6898 144 re B* Q q BT 1 0 0 1 0 122 Tm 12 TL /F4 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( from enum import unique) Tj T* (>) Tj (>) Tj (>) Tj ( @unique) Tj T* (... class Mistake\(Enum\):) Tj T* (... __order__ = 'one two three four' # only needed in 2.x) Tj T* (... one = 1) Tj T* (... two = 2) Tj T* (... three = 3) Tj T* (... four = 3) Tj T* (Traceback \(most recent call last\):) Tj T* (...) Tj T* (ValueError: duplicate names found in ) Tj (<) Tj (enum 'Mistake') Tj (>) Tj (: four -) Tj (>) Tj ( three) Tj T* ET Q Q Q Q Q q 1 0 0 1 62.69291 486.6236 cm q 0 0 0 rg BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Iterating over the members of an enum does not provide the aliases:) Tj T* ET Q Q q 1 0 0 1 62.69291 441.4236 cm q q 1 0 0 1 0 0 cm q 1 0 0 1 6.6 6.6 cm q .662745 .662745 .662745 RG .5 w .960784 .960784 .862745 rg n -6 -6 468.6898 36 re B* Q q BT 1 0 0 1 0 14 Tm 12 TL /F4 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( list\(Shape\)) Tj T* ([) Tj (<) Tj (Shape.square: 2) Tj (>) Tj (, ) Tj (<) Tj (Shape.diamond: 1) Tj (>) Tj (, ) Tj (<) Tj (Shape.circle: 3) Tj (>) Tj (]) Tj T* ET Q Q Q Q Q q 1 0 0 1 62.69291 409.4236 cm q BT 1 0 0 1 0 14 Tm 1.307126 Tw 12 TL /F1 10 Tf 0 0 0 rg (The special attribute ) Tj /F4 10 Tf 0 0 0 rg (__members__ ) Tj /F1 10 Tf 0 0 0 rg (is a dictionary mapping names to members. It includes all names) Tj T* 0 Tw (defined in the enumeration, including the aliases:) Tj T* ET Q Q q 1 0 0 1 62.69291 304.2236 cm q q 1 0 0 1 0 0 cm q 1 0 0 1 6.6 6.6 cm q .662745 .662745 .662745 RG .5 w .960784 .960784 .862745 rg n -6 -6 468.6898 96 re B* Q q BT 1 0 0 1 0 74 Tm 12 TL /F4 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( for name, member in sorted\(Shape.__members__.items\(\)\):) Tj T* (... name, member) Tj T* (...) Tj T* (\('alias_for_square', ) Tj (<) Tj (Shape.square: 2) Tj (>) Tj (\)) Tj T* (\('circle', ) Tj (<) Tj (Shape.circle: 3) Tj (>) Tj (\)) Tj T* (\('diamond', ) Tj (<) Tj (Shape.diamond: 1) Tj (>) Tj (\)) Tj T* (\('square', ) Tj (<) Tj (Shape.square: 2) Tj (>) Tj (\)) Tj T* ET Q Q Q Q Q q 1 0 0 1 62.69291 272.2236 cm q BT 1 0 0 1 0 14 Tm .080751 Tw 12 TL /F1 10 Tf 0 0 0 rg (The ) Tj /F4 10 Tf 0 0 0 rg (__members__ ) Tj /F1 10 Tf 0 0 0 rg (attribute can be used for detailed programmatic access to the enumeration members.) Tj T* 0 Tw (For example, finding all the aliases:) Tj T* ET Q Q q 1 0 0 1 62.69291 227.0236 cm q q 1 0 0 1 0 0 cm q 1 0 0 1 6.6 6.6 cm q .662745 .662745 .662745 RG .5 w .960784 .960784 .862745 rg n -6 -6 486 36 re B* Q q BT 1 0 0 1 0 14 Tm 12 TL /F4 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( [name for name, member in Shape.__members__.items\(\) if member.name != name]) Tj T* (['alias_for_square']) Tj T* ET Q Q Q Q Q q 1 0 0 1 62.69291 194.0236 cm q BT 1 0 0 1 0 3.5 Tm 21 TL /F3 17.5 Tf 0 0 0 rg (Comparisons) Tj T* ET Q Q q 1 0 0 1 62.69291 176.0236 cm q 0 0 0 rg BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Enumeration members are compared by identity:) Tj T* ET Q Q q 1 0 0 1 62.69291 82.82362 cm q q 1 0 0 1 0 0 cm q 1 0 0 1 6.6 6.6 cm q .662745 .662745 .662745 RG .5 w .960784 .960784 .862745 rg n -6 -6 468.6898 84 re B* Q q BT 1 0 0 1 0 62 Tm 12 TL /F4 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( Color.red is Color.red) Tj T* (True) Tj T* (>) Tj (>) Tj (>) Tj ( Color.red is Color.blue) Tj T* (False) Tj T* (>) Tj (>) Tj (>) Tj ( Color.red is not Color.blue) Tj T* (True) Tj T* ET Q Q Q Q Q endstream endobj 60 0 obj << /Length 4521 >> stream 1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET q 1 0 0 1 62.69291 741.0236 cm q BT 1 0 0 1 0 14 Tm 1.131647 Tw 12 TL /F1 10 Tf 0 0 0 rg (Ordered comparisons between enumeration values are ) Tj /F5 10 Tf (not ) Tj /F1 10 Tf (supported. Enum members are not integers) Tj T* 0 Tw (\(but see ) Tj 0 0 .501961 rg (IntEnum ) Tj 0 0 0 rg (below\):) Tj T* ET Q Q q 1 0 0 1 62.69291 671.8236 cm q q 1 0 0 1 0 0 cm q 1 0 0 1 6.6 6.6 cm q .662745 .662745 .662745 RG .5 w .960784 .960784 .862745 rg n -6 -6 468.6898 60 re B* Q q BT 1 0 0 1 0 38 Tm 12 TL /F4 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( Color.red ) Tj (<) Tj ( Color.blue) Tj T* (Traceback \(most recent call last\):) Tj T* ( File ") Tj (<) Tj (stdin) Tj (>) Tj (", line 1, in ) Tj (<) Tj (module) Tj (>) Tj T* (TypeError: unorderable types: Color\(\) ) Tj (<) Tj ( Color\(\)) Tj T* ET Q Q Q Q Q q 1 0 0 1 62.69291 651.8236 cm Q q 1 0 0 1 62.69291 568.8236 cm .960784 .960784 .862745 rg n 0 83 469.8898 -83 re f* 0 0 0 rg BT /F1 10 Tf 12 TL ET BT 1 0 0 1 6 57 Tm T* ET q 1 0 0 1 16 52 cm q 0 0 0 rg BT 1 0 0 1 0 2.5 Tm /F6 12.5 Tf 15 TL (Warning) Tj T* ET Q Q q 1 0 0 1 16 16 cm q BT 1 0 0 1 0 14 Tm .189398 Tw 12 TL /F1 10 Tf 0 0 0 rg (In Python 2 ) Tj /F5 10 Tf (everything ) Tj /F1 10 Tf (is ordered, even though the ordering may not make sense. If you want your) Tj T* 0 Tw (enumerations to have a sensible ordering check out the ) Tj 0 0 .501961 rg (OrderedEnum ) Tj 0 0 0 rg (recipe below.) Tj T* ET Q Q q 1 J 1 j .662745 .662745 .662745 RG .5 w n 0 83 m 469.8898 83 l S n 0 0 m 469.8898 0 l S n 0 0 m 0 83 l S n 469.8898 0 m 469.8898 83 l S Q Q q 1 0 0 1 62.69291 562.8236 cm Q q 1 0 0 1 62.69291 544.8236 cm q 0 0 0 rg BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Equality comparisons are defined though:) Tj T* ET Q Q q 1 0 0 1 62.69291 451.6236 cm q q 1 0 0 1 0 0 cm q 1 0 0 1 6.6 6.6 cm q .662745 .662745 .662745 RG .5 w .960784 .960784 .862745 rg n -6 -6 468.6898 84 re B* Q q BT 1 0 0 1 0 62 Tm 12 TL /F4 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( Color.blue == Color.red) Tj T* (False) Tj T* (>) Tj (>) Tj (>) Tj ( Color.blue != Color.red) Tj T* (True) Tj T* (>) Tj (>) Tj (>) Tj ( Color.blue == Color.blue) Tj T* (True) Tj T* ET Q Q Q Q Q q 1 0 0 1 62.69291 419.6236 cm q BT 1 0 0 1 0 14 Tm 2.582706 Tw 12 TL /F1 10 Tf 0 0 0 rg (Comparisons against non-enumeration values will always compare not equal \(again, ) Tj /F4 10 Tf 0 0 0 rg (IntEnum ) Tj /F1 10 Tf 0 0 0 rg (was) Tj T* 0 Tw (explicitly designed to behave differently, see below\):) Tj T* ET Q Q q 1 0 0 1 62.69291 374.4236 cm q q 1 0 0 1 0 0 cm q 1 0 0 1 6.6 6.6 cm q .662745 .662745 .662745 RG .5 w .960784 .960784 .862745 rg n -6 -6 468.6898 36 re B* Q q BT 1 0 0 1 0 14 Tm 12 TL /F4 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( Color.blue == 2) Tj T* (False) Tj T* ET Q Q Q Q Q q 1 0 0 1 62.69291 341.4236 cm q BT 1 0 0 1 0 3.5 Tm 21 TL /F3 17.5 Tf 0 0 0 rg (Allowed members and attributes of enumerations) Tj T* ET Q Q q 1 0 0 1 62.69291 287.4236 cm q BT 1 0 0 1 0 38 Tm 2.755697 Tw 12 TL /F1 10 Tf 0 0 0 rg (The examples above use integers for enumeration values. Using integers is short and handy \(and) Tj T* 0 Tw .241751 Tw (provided by default by the ) Tj 0 0 .501961 rg (Functional API) Tj 0 0 0 rg (\), but not strictly enforced. In the vast majority of use-cases, one) Tj T* 0 Tw .848221 Tw (doesn't care what the actual value of an enumeration is. But if the value ) Tj /F5 10 Tf (is ) Tj /F1 10 Tf (important, enumerations can) Tj T* 0 Tw (have arbitrary values.) Tj T* ET Q Q q 1 0 0 1 62.69291 257.4236 cm q 0 0 0 rg BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL .638735 Tw (Enumerations are Python classes, and can have methods and special methods as usual. If we have this) Tj T* 0 Tw (enumeration:) Tj T* ET Q Q q 1 0 0 1 62.69291 80.22362 cm q q 1 0 0 1 0 0 cm q 1 0 0 1 6.6 6.6 cm q .662745 .662745 .662745 RG .5 w .960784 .960784 .862745 rg n -6 -6 468.6898 168 re B* Q q BT 1 0 0 1 0 146 Tm 12 TL /F4 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( class Mood\(Enum\):) Tj T* (... funky = 1) Tj T* (... happy = 3) Tj T* (...) Tj T* (... def describe\(self\):) Tj T* (... # self is the member here) Tj T* (... return self.name, self.value) Tj T* (...) Tj T* (... def __str__\(self\):) Tj T* (... return 'my custom str! {0}'.format\(self.value\)) Tj T* (...) Tj T* (... @classmethod) Tj T* (... def favorite_mood\(cls\):) Tj T* ET Q Q Q Q Q endstream endobj 61 0 obj << /Length 4627 >> stream 1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET q 1 0 0 1 62.69291 727.8236 cm q q 1 0 0 1 0 0 cm q 1 0 0 1 6.6 6.6 cm q .662745 .662745 .662745 RG .5 w .960784 .960784 .862745 rg n -6 -6 468.6898 36 re B* Q q BT 1 0 0 1 0 14 Tm 12 TL /F4 10 Tf 0 0 0 rg (... # cls here is the enumeration) Tj T* (... return cls.happy) Tj T* ET Q Q Q Q Q q 1 0 0 1 62.69291 707.8236 cm q 0 0 0 rg BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Then:) Tj T* ET Q Q q 1 0 0 1 62.69291 614.6236 cm q q 1 0 0 1 0 0 cm q 1 0 0 1 6.6 6.6 cm q .662745 .662745 .662745 RG .5 w .960784 .960784 .862745 rg n -6 -6 468.6898 84 re B* Q q BT 1 0 0 1 0 62 Tm 12 TL /F4 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( Mood.favorite_mood\(\)) Tj T* (<) Tj (Mood.happy: 3) Tj (>) Tj T* (>) Tj (>) Tj (>) Tj ( Mood.happy.describe\(\)) Tj T* (\('happy', 3\)) Tj T* (>) Tj (>) Tj (>) Tj ( str\(Mood.funky\)) Tj T* ('my custom str! 1') Tj T* ET Q Q Q Q Q q 1 0 0 1 62.69291 558.6236 cm q BT 1 0 0 1 0 38 Tm 3.14186 Tw 12 TL /F1 10 Tf 0 0 0 rg (The rules for what is allowed are as follows: _sunder_ names \(starting and ending with a single) Tj T* 0 Tw .310651 Tw (underscore\) are reserved by enum and cannot be used; all other attributes defined within an enumeration) Tj T* 0 Tw 2.199213 Tw (will become members of this enumeration, with the exception of ) Tj /F5 10 Tf (__dunder__ ) Tj /F1 10 Tf (names and descriptors) Tj T* 0 Tw (\(methods are also descriptors\).) Tj T* ET Q Q q 1 0 0 1 62.69291 540.6236 cm q 0 0 0 rg BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Note:) Tj T* ET Q Q q 1 0 0 1 62.69291 534.6236 cm Q q 1 0 0 1 62.69291 510.6236 cm 0 0 0 rg BT /F1 10 Tf 12 TL ET BT 1 0 0 1 0 2 Tm T* ET q 1 0 0 1 20 0 cm q BT 1 0 0 1 0 14 Tm .979213 Tw 12 TL /F1 10 Tf 0 0 0 rg (If your enumeration defines ) Tj /F4 10 Tf 0 0 0 rg (__new__ ) Tj /F1 10 Tf 0 0 0 rg (and/or ) Tj /F4 10 Tf 0 0 0 rg (__init__ ) Tj /F1 10 Tf 0 0 0 rg (then whatever value\(s\) were given to the) Tj T* 0 Tw (enum member will be passed into those methods. See ) Tj 0 0 .501961 rg (Planet ) Tj 0 0 0 rg (for an example.) Tj T* ET Q Q q Q Q q 1 0 0 1 62.69291 510.6236 cm Q q 1 0 0 1 62.69291 477.6236 cm q BT 1 0 0 1 0 3.5 Tm 21 TL /F3 17.5 Tf 0 0 0 rg (Restricted subclassing of enumerations) Tj T* ET Q Q q 1 0 0 1 62.69291 447.6236 cm q 0 0 0 rg BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL .778735 Tw (Subclassing an enumeration is allowed only if the enumeration does not define any members. So this is) Tj T* 0 Tw (forbidden:) Tj T* ET Q Q q 1 0 0 1 62.69291 366.4236 cm q q 1 0 0 1 0 0 cm q 1 0 0 1 6.6 6.6 cm q .662745 .662745 .662745 RG .5 w .960784 .960784 .862745 rg n -6 -6 468.6898 72 re B* Q q BT 1 0 0 1 0 50 Tm 12 TL /F4 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( class MoreColor\(Color\):) Tj T* (... pink = 17) Tj T* (Traceback \(most recent call last\):) Tj T* (...) Tj T* (TypeError: Cannot extend enumerations) Tj T* ET Q Q Q Q Q q 1 0 0 1 62.69291 346.4236 cm q 0 0 0 rg BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (But this is allowed:) Tj T* ET Q Q q 1 0 0 1 62.69291 229.2236 cm q q 1 0 0 1 0 0 cm q 1 0 0 1 6.6 6.6 cm q .662745 .662745 .662745 RG .5 w .960784 .960784 .862745 rg n -6 -6 468.6898 108 re B* Q q BT 1 0 0 1 0 86 Tm 12 TL /F4 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( class Foo\(Enum\):) Tj T* (... def some_behavior\(self\):) Tj T* (... pass) Tj T* (...) Tj T* (>) Tj (>) Tj (>) Tj ( class Bar\(Foo\):) Tj T* (... happy = 1) Tj T* (... sad = 2) Tj T* (...) Tj T* ET Q Q Q Q Q q 1 0 0 1 62.69291 185.2236 cm q BT 1 0 0 1 0 26 Tm .127984 Tw 12 TL /F1 10 Tf 0 0 0 rg (Allowing subclassing of enums that define members would lead to a violation of some important invariants) Tj T* 0 Tw 1.889985 Tw (of types and instances. On the other hand, it makes sense to allow sharing some common behavior) Tj T* 0 Tw (between a group of enumerations. \(See ) Tj 0 0 .501961 rg (OrderedEnum ) Tj 0 0 0 rg (for an example.\)) Tj T* ET Q Q q 1 0 0 1 62.69291 152.2236 cm q BT 1 0 0 1 0 3.5 Tm 21 TL /F3 17.5 Tf 0 0 0 rg (Pickling) Tj T* ET Q Q q 1 0 0 1 62.69291 134.2236 cm q 0 0 0 rg BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Enumerations can be pickled and unpickled:) Tj T* ET Q Q q 1 0 0 1 62.69291 89.02362 cm q q 1 0 0 1 0 0 cm q 1 0 0 1 6.6 6.6 cm q .662745 .662745 .662745 RG .5 w .960784 .960784 .862745 rg n -6 -6 468.6898 36 re B* Q q BT 1 0 0 1 0 14 Tm 12 TL /F4 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( from enum.test_enum import Fruit) Tj T* (>) Tj (>) Tj (>) Tj ( from pickle import dumps, loads) Tj T* ET Q Q Q Q Q endstream endobj 62 0 obj << /Length 5372 >> stream 1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET q 1 0 0 1 62.69291 727.8236 cm q q 1 0 0 1 0 0 cm q 1 0 0 1 6.6 6.6 cm q .662745 .662745 .662745 RG .5 w .960784 .960784 .862745 rg n -6 -6 468.6898 36 re B* Q q BT 1 0 0 1 0 14 Tm 12 TL /F4 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( Fruit.tomato is loads\(dumps\(Fruit.tomato, 2\)\)) Tj T* (True) Tj T* ET Q Q Q Q Q q 1 0 0 1 62.69291 695.8236 cm q 0 0 0 rg BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL 1.256457 Tw (The usual restrictions for pickling apply: picklable enums must be defined in the top level of a module,) Tj T* 0 Tw (since unpickling requires them to be importable from that module.) Tj T* ET Q Q q 1 0 0 1 62.69291 677.8236 cm q 0 0 0 rg BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Note:) Tj T* ET Q Q q 1 0 0 1 62.69291 671.8236 cm Q q 1 0 0 1 62.69291 647.8236 cm 0 0 0 rg BT /F1 10 Tf 12 TL ET BT 1 0 0 1 0 2 Tm T* ET q 1 0 0 1 20 0 cm q 0 0 0 rg BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL .081163 Tw (With pickle protocol version 4 \(introduced in Python 3.4\) it is possible to easily pickle enums nested in) Tj T* 0 Tw (other classes.) Tj T* ET Q Q q Q Q q 1 0 0 1 62.69291 647.8236 cm Q q 1 0 0 1 62.69291 614.8236 cm q BT 1 0 0 1 0 3.5 Tm 21 TL /F3 17.5 Tf 0 0 0 rg (Functional API) Tj T* ET Q Q q 1 0 0 1 62.69291 596.8236 cm q BT 1 0 0 1 0 2 Tm 12 TL /F1 10 Tf 0 0 0 rg (The ) Tj /F4 10 Tf 0 0 0 rg (Enum ) Tj /F1 10 Tf 0 0 0 rg (class is callable, providing the following functional API:) Tj T* ET Q Q q 1 0 0 1 62.69291 467.6236 cm q q 1 0 0 1 0 0 cm q 1 0 0 1 6.6 6.6 cm q .662745 .662745 .662745 RG .5 w .960784 .960784 .862745 rg n -6 -6 468.6898 120 re B* Q q BT 1 0 0 1 0 98 Tm 12 TL /F4 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( Animal = Enum\('Animal', 'ant bee cat dog'\)) Tj T* (>) Tj (>) Tj (>) Tj ( Animal) Tj T* (<) Tj (enum 'Animal') Tj (>) Tj T* (>) Tj (>) Tj (>) Tj ( Animal.ant) Tj T* (<) Tj (Animal.ant: 1) Tj (>) Tj T* (>) Tj (>) Tj (>) Tj ( Animal.ant.value) Tj T* (1) Tj T* (>) Tj (>) Tj (>) Tj ( list\(Animal\)) Tj T* ([) Tj (<) Tj (Animal.ant: 1) Tj (>) Tj (, ) Tj (<) Tj (Animal.bee: 2) Tj (>) Tj (, ) Tj (<) Tj (Animal.cat: 3) Tj (>) Tj (, ) Tj (<) Tj (Animal.dog: 4) Tj (>) Tj (]) Tj T* ET Q Q Q Q Q q 1 0 0 1 62.69291 435.6236 cm q BT 1 0 0 1 0 14 Tm .602209 Tw 12 TL /F1 10 Tf 0 0 0 rg (The semantics of this API resemble ) Tj /F4 10 Tf 0 0 0 rg (namedtuple) Tj /F1 10 Tf 0 0 0 rg (. The first argument of the call to ) Tj /F4 10 Tf 0 0 0 rg (Enum ) Tj /F1 10 Tf 0 0 0 rg (is the name of) Tj T* 0 Tw (the enumeration.) Tj T* ET Q Q q 1 0 0 1 62.69291 369.6236 cm q BT 1 0 0 1 0 50 Tm 1.326412 Tw 12 TL /F1 10 Tf 0 0 0 rg (The second argument is the ) Tj /F5 10 Tf (source ) Tj /F1 10 Tf (of enumeration member names. It can be a whitespace-separated) Tj T* 0 Tw .993516 Tw (string of names, a sequence of names, a sequence of 2-tuples with key/value pairs, or a mapping \(e.g.) Tj T* 0 Tw 1.168555 Tw (dictionary\) of names to values. The last two options enable assigning arbitrary values to enumerations;) Tj T* 0 Tw .537485 Tw (the others auto-assign increasing integers starting with 1. A new class derived from ) Tj /F4 10 Tf 0 0 0 rg (Enum ) Tj /F1 10 Tf 0 0 0 rg (is returned. In) Tj T* 0 Tw (other words, the above assignment to ) Tj /F4 10 Tf 0 0 0 rg (Animal ) Tj /F1 10 Tf 0 0 0 rg (is equivalent to:) Tj T* ET Q Q q 1 0 0 1 62.69291 288.4236 cm q q 1 0 0 1 0 0 cm q 1 0 0 1 6.6 6.6 cm q .662745 .662745 .662745 RG .5 w .960784 .960784 .862745 rg n -6 -6 468.6898 72 re B* Q q BT 1 0 0 1 0 50 Tm 12 TL /F4 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( class Animals\(Enum\):) Tj T* (... ant = 1) Tj T* (... bee = 2) Tj T* (... cat = 3) Tj T* (... dog = 4) Tj T* ET Q Q Q Q Q q 1 0 0 1 62.69291 232.4236 cm q 0 0 0 rg BT 1 0 0 1 0 38 Tm /F1 10 Tf 12 TL 1.239984 Tw (Pickling enums created with the functional API can be tricky as frame stack implementation details are) Tj T* 0 Tw .937132 Tw (used to try and figure out which module the enumeration is being created in \(e.g. it will fail if you use a) Tj T* 0 Tw 1.321163 Tw (utility function in separate module, and also may not work on IronPython or Jython\). The solution is to) Tj T* 0 Tw (specify the module name explicitly as follows:) Tj T* ET Q Q q 1 0 0 1 62.69291 199.2236 cm q q 1 0 0 1 0 0 cm q 1 0 0 1 6.6 6.6 cm q .662745 .662745 .662745 RG .5 w .960784 .960784 .862745 rg n -6 -6 468.6898 24 re B* Q q BT 1 0 0 1 0 2 Tm 12 TL /F4 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( Animals = Enum\('Animals', 'ant bee cat dog', module=__name__\)) Tj T* ET Q Q Q Q Q q 1 0 0 1 62.69291 166.2236 cm q BT 1 0 0 1 0 3.5 Tm 21 TL /F3 17.5 Tf 0 0 0 rg (Derived Enumerations) Tj T* ET Q Q q 1 0 0 1 62.69291 136.2236 cm q BT 1 0 0 1 0 3 Tm 18 TL /F3 15 Tf 0 0 0 rg (IntEnum) Tj T* ET Q Q q 1 0 0 1 62.69291 94.22362 cm q BT 1 0 0 1 0 26 Tm 1.99832 Tw 12 TL /F1 10 Tf 0 0 0 rg (A variation of ) Tj /F4 10 Tf 0 0 0 rg (Enum ) Tj /F1 10 Tf 0 0 0 rg (is provided which is also a subclass of ) Tj /F4 10 Tf 0 0 0 rg (int) Tj /F1 10 Tf 0 0 0 rg (. Members of an ) Tj /F4 10 Tf 0 0 0 rg (IntEnum ) Tj /F1 10 Tf 0 0 0 rg (can be) Tj T* 0 Tw .087984 Tw (compared to integers; by extension, integer enumerations of different types can also be compared to each) Tj T* 0 Tw (other:) Tj T* ET Q Q endstream endobj 63 0 obj << /Length 4141 >> stream 1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET q 1 0 0 1 62.69291 571.8236 cm q q 1 0 0 1 0 0 cm q 1 0 0 1 6.6 6.6 cm q .662745 .662745 .662745 RG .5 w .960784 .960784 .862745 rg n -6 -6 468.6898 192 re B* Q q BT 1 0 0 1 0 170 Tm 12 TL /F4 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( from enum import IntEnum) Tj T* (>) Tj (>) Tj (>) Tj ( class Shape\(IntEnum\):) Tj T* (... circle = 1) Tj T* (... square = 2) Tj T* (...) Tj T* (>) Tj (>) Tj (>) Tj ( class Request\(IntEnum\):) Tj T* (... post = 1) Tj T* (... get = 2) Tj T* (...) Tj T* (>) Tj (>) Tj (>) Tj ( Shape == 1) Tj T* (False) Tj T* (>) Tj (>) Tj (>) Tj ( Shape.circle == 1) Tj T* (True) Tj T* (>) Tj (>) Tj (>) Tj ( Shape.circle == Request.post) Tj T* (True) Tj T* ET Q Q Q Q Q q 1 0 0 1 62.69291 551.8236 cm q BT 1 0 0 1 0 2 Tm 12 TL /F1 10 Tf 0 0 0 rg (However, they still can't be compared to standard ) Tj /F4 10 Tf 0 0 0 rg (Enum ) Tj /F1 10 Tf 0 0 0 rg (enumerations:) Tj T* ET Q Q q 1 0 0 1 62.69291 410.6236 cm q q 1 0 0 1 0 0 cm q 1 0 0 1 6.6 6.6 cm q .662745 .662745 .662745 RG .5 w .960784 .960784 .862745 rg n -6 -6 468.6898 132 re B* Q q BT 1 0 0 1 0 110 Tm 12 TL /F4 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( class Shape\(IntEnum\):) Tj T* (... circle = 1) Tj T* (... square = 2) Tj T* (...) Tj T* (>) Tj (>) Tj (>) Tj ( class Color\(Enum\):) Tj T* (... red = 1) Tj T* (... green = 2) Tj T* (...) Tj T* (>) Tj (>) Tj (>) Tj ( Shape.circle == Color.red) Tj T* (False) Tj T* ET Q Q Q Q Q q 1 0 0 1 62.69291 390.6236 cm q BT 1 0 0 1 0 2 Tm 12 TL /F4 10 Tf 0 0 0 rg (IntEnum ) Tj /F1 10 Tf 0 0 0 rg (values behave like integers in other ways you'd expect:) Tj T* ET Q Q q 1 0 0 1 62.69291 297.4236 cm q q 1 0 0 1 0 0 cm q 1 0 0 1 6.6 6.6 cm q .662745 .662745 .662745 RG .5 w .960784 .960784 .862745 rg n -6 -6 468.6898 84 re B* Q q BT 1 0 0 1 0 62 Tm 12 TL /F4 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( int\(Shape.circle\)) Tj T* (1) Tj T* (>) Tj (>) Tj (>) Tj ( ['a', 'b', 'c'][Shape.circle]) Tj T* ('b') Tj T* (>) Tj (>) Tj (>) Tj ( [i for i in range\(Shape.square\)]) Tj T* ([0, 1]) Tj T* ET Q Q Q Q Q q 1 0 0 1 62.69291 229.4236 cm q BT 1 0 0 1 0 50 Tm 1.197126 Tw 12 TL /F1 10 Tf 0 0 0 rg (For the vast majority of code, ) Tj /F4 10 Tf 0 0 0 rg (Enum ) Tj /F1 10 Tf 0 0 0 rg (is strongly recommended, since ) Tj /F4 10 Tf 0 0 0 rg (IntEnum ) Tj /F1 10 Tf 0 0 0 rg (breaks some semantic) Tj T* 0 Tw .793318 Tw (promises of an enumeration \(by being comparable to integers, and thus by transitivity to other unrelated) Tj T* 0 Tw .554985 Tw (enumerations\). It should be used only in special cases where there's no other choice; for example, when) Tj T* 0 Tw .746136 Tw (integer constants are replaced with enumerations and backwards compatibility is required with code that) Tj T* 0 Tw (still expects integers.) Tj T* ET Q Q q 1 0 0 1 62.69291 199.4236 cm q BT 1 0 0 1 0 3 Tm 18 TL /F3 15 Tf 0 0 0 rg (Others) Tj T* ET Q Q q 1 0 0 1 62.69291 181.4236 cm q BT 1 0 0 1 0 2 Tm 12 TL /F1 10 Tf 0 0 0 rg (While ) Tj /F4 10 Tf 0 0 0 rg (IntEnum ) Tj /F1 10 Tf 0 0 0 rg (is part of the ) Tj /F4 10 Tf 0 0 0 rg (enum ) Tj /F1 10 Tf 0 0 0 rg (module, it would be very simple to implement independently:) Tj T* ET Q Q q 1 0 0 1 62.69291 136.2236 cm q q 1 0 0 1 0 0 cm q 1 0 0 1 6.6 6.6 cm q .662745 .662745 .662745 RG .5 w .960784 .960784 .862745 rg n -6 -6 468.6898 36 re B* Q q 0 0 0 rg BT 1 0 0 1 0 14 Tm /F4 10 Tf 12 TL (class IntEnum\(int, Enum\):) Tj T* ( pass) Tj T* ET Q Q Q Q Q q 1 0 0 1 62.69291 104.2236 cm q BT 1 0 0 1 0 14 Tm .361412 Tw 12 TL /F1 10 Tf 0 0 0 rg (This demonstrates how similar derived enumerations can be defined; for example a ) Tj /F4 10 Tf 0 0 0 rg (StrEnum ) Tj /F1 10 Tf 0 0 0 rg (that mixes) Tj T* 0 Tw (in ) Tj /F4 10 Tf 0 0 0 rg (str ) Tj /F1 10 Tf 0 0 0 rg (instead of ) Tj /F4 10 Tf 0 0 0 rg (int) Tj /F1 10 Tf 0 0 0 rg (.) Tj T* ET Q Q q 1 0 0 1 62.69291 86.22362 cm q 0 0 0 rg BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Some rules:) Tj T* ET Q Q q 1 0 0 1 62.69291 80.22362 cm Q q 1 0 0 1 62.69291 80.22362 cm Q endstream endobj 64 0 obj << /Length 7108 >> stream 1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET q 1 0 0 1 62.69291 741.0236 cm 0 0 0 rg BT /F1 10 Tf 12 TL ET q 1 0 0 1 6 9 cm q 0 0 0 rg BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 5.66 0 Td (1.) Tj T* -5.66 0 Td ET Q Q q 1 0 0 1 23 -3 cm q BT 1 0 0 1 0 14 Tm .477318 Tw 12 TL /F1 10 Tf 0 0 0 rg (When subclassing ) Tj /F4 10 Tf 0 0 0 rg (Enum) Tj /F1 10 Tf 0 0 0 rg (, mix-in types must appear before ) Tj /F4 10 Tf 0 0 0 rg (Enum ) Tj /F1 10 Tf 0 0 0 rg (itself in the sequence of bases, as) Tj T* 0 Tw (in the ) Tj /F4 10 Tf 0 0 0 rg (IntEnum ) Tj /F1 10 Tf 0 0 0 rg (example above.) Tj T* ET Q Q q Q Q q 1 0 0 1 62.69291 735.0236 cm Q q 1 0 0 1 62.69291 699.0236 cm 0 0 0 rg BT /F1 10 Tf 12 TL ET q 1 0 0 1 6 21 cm q 0 0 0 rg BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 5.66 0 Td (2.) Tj T* -5.66 0 Td ET Q Q q 1 0 0 1 23 -3 cm q BT 1 0 0 1 0 26 Tm 1.147045 Tw 12 TL /F1 10 Tf 0 0 0 rg (While ) Tj /F4 10 Tf 0 0 0 rg (Enum ) Tj /F1 10 Tf 0 0 0 rg (can have members of any type, once you mix in an additional type, all the members) Tj T* 0 Tw .420574 Tw (must have values of that type, e.g. ) Tj /F4 10 Tf 0 0 0 rg (int ) Tj /F1 10 Tf 0 0 0 rg (above. This restriction does not apply to mix-ins which only) Tj T* 0 Tw (add methods and don't specify another data type such as ) Tj /F4 10 Tf 0 0 0 rg (int ) Tj /F1 10 Tf 0 0 0 rg (or ) Tj /F4 10 Tf 0 0 0 rg (str) Tj /F1 10 Tf 0 0 0 rg (.) Tj T* ET Q Q q Q Q q 1 0 0 1 62.69291 693.0236 cm Q q 1 0 0 1 62.69291 669.0236 cm 0 0 0 rg BT /F1 10 Tf 12 TL ET q 1 0 0 1 6 9 cm q 0 0 0 rg BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 5.66 0 Td (3.) Tj T* -5.66 0 Td ET Q Q q 1 0 0 1 23 -3 cm q BT 1 0 0 1 0 14 Tm .100542 Tw 12 TL /F1 10 Tf 0 0 0 rg (When another data type is mixed in, the ) Tj /F4 10 Tf 0 0 0 rg (value ) Tj /F1 10 Tf 0 0 0 rg (attribute is ) Tj /F5 10 Tf (not the same ) Tj /F1 10 Tf (as the enum member itself,) Tj T* 0 Tw (although it is equivalant and will compare equal.) Tj T* ET Q Q q Q Q q 1 0 0 1 62.69291 663.0236 cm Q q 1 0 0 1 62.69291 609.0236 cm 0 0 0 rg BT /F1 10 Tf 12 TL ET q 1 0 0 1 6 39 cm q 0 0 0 rg BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 5.66 0 Td (4.) Tj T* -5.66 0 Td ET Q Q q 1 0 0 1 23 27 cm q BT 1 0 0 1 0 14 Tm 1.85998 Tw 12 TL /F1 10 Tf 0 0 0 rg (%-style formatting: ) Tj /F4 10 Tf 0 0 0 rg (%s ) Tj /F1 10 Tf 0 0 0 rg (and ) Tj /F4 10 Tf 0 0 0 rg (%r ) Tj /F1 10 Tf 0 0 0 rg (call ) Tj /F4 10 Tf 0 0 0 rg (Enum) Tj /F1 10 Tf 0 0 0 rg ('s ) Tj /F4 10 Tf 0 0 0 rg (__str__ ) Tj /F1 10 Tf 0 0 0 rg (and ) Tj /F4 10 Tf 0 0 0 rg (__repr__ ) Tj /F1 10 Tf 0 0 0 rg (respectively; other codes) Tj T* 0 Tw (\(such as ) Tj /F4 10 Tf 0 0 0 rg (%i ) Tj /F1 10 Tf 0 0 0 rg (or ) Tj /F4 10 Tf 0 0 0 rg (%h ) Tj /F1 10 Tf 0 0 0 rg (for IntEnum\) treat the enum member as its mixed-in type.) Tj T* ET Q Q q 1 0 0 1 23 -3 cm q BT 1 0 0 1 0 14 Tm .067045 Tw 12 TL /F1 10 Tf 0 0 0 rg (Note: Prior to Python 3.4 there is a bug in ) Tj /F4 10 Tf 0 0 0 rg (str) Tj /F1 10 Tf 0 0 0 rg ('s %-formatting: ) Tj /F4 10 Tf 0 0 0 rg (int ) Tj /F1 10 Tf 0 0 0 rg (subclasses are printed as strings) Tj T* 0 Tw (and not numbers when the ) Tj /F4 10 Tf 0 0 0 rg (%d) Tj /F1 10 Tf 0 0 0 rg (, ) Tj /F4 10 Tf 0 0 0 rg (%i) Tj /F1 10 Tf 0 0 0 rg (, or ) Tj /F4 10 Tf 0 0 0 rg (%u ) Tj /F1 10 Tf 0 0 0 rg (codes are used.) Tj T* ET Q Q q Q Q q 1 0 0 1 62.69291 603.0236 cm Q q 1 0 0 1 62.69291 579.0236 cm 0 0 0 rg BT /F1 10 Tf 12 TL ET q 1 0 0 1 6 9 cm q 0 0 0 rg BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 5.66 0 Td (5.) Tj T* -5.66 0 Td ET Q Q q 1 0 0 1 23 -3 cm q BT 1 0 0 1 0 14 Tm 1.880751 Tw 12 TL /F4 10 Tf 0 0 0 rg (str.__format__ ) Tj /F1 10 Tf 0 0 0 rg (\(or ) Tj /F4 10 Tf 0 0 0 rg (format) Tj /F1 10 Tf 0 0 0 rg (\) will use the mixed-in type's ) Tj /F4 10 Tf 0 0 0 rg (__format__) Tj /F1 10 Tf 0 0 0 rg (. If the ) Tj /F4 10 Tf 0 0 0 rg (Enum) Tj /F1 10 Tf 0 0 0 rg ('s ) Tj /F4 10 Tf 0 0 0 rg (str ) Tj /F1 10 Tf 0 0 0 rg (or) Tj T* 0 Tw /F4 10 Tf 0 0 0 rg (repr ) Tj /F1 10 Tf 0 0 0 rg (is desired use the ) Tj /F4 10 Tf 0 0 0 rg (!s ) Tj /F1 10 Tf 0 0 0 rg (or ) Tj /F4 10 Tf 0 0 0 rg (!r) Tj /F1 10 Tf 0 0 0 rg ( ) Tj /F4 10 Tf 0 0 0 rg (str ) Tj /F1 10 Tf 0 0 0 rg (format codes.) Tj T* ET Q Q q Q Q q 1 0 0 1 62.69291 579.0236 cm Q q 1 0 0 1 62.69291 546.0236 cm q BT 1 0 0 1 0 3.5 Tm 21 TL /F3 17.5 Tf 0 0 0 rg (Decorators) Tj T* ET Q Q q 1 0 0 1 62.69291 516.0236 cm q BT 1 0 0 1 0 3 Tm 18 TL /F3 15 Tf 0 0 0 rg (unique) Tj T* ET Q Q q 1 0 0 1 62.69291 486.0236 cm q BT 1 0 0 1 0 14 Tm .287251 Tw 12 TL /F1 10 Tf 0 0 0 rg (A ) Tj /F4 10 Tf 0 0 0 rg (class ) Tj /F1 10 Tf 0 0 0 rg (decorator specifically for enumerations. It searches an enumeration's ) Tj /F4 10 Tf 0 0 0 rg (__members__ ) Tj /F1 10 Tf 0 0 0 rg (gathering) Tj T* 0 Tw (any aliases it finds; if any are found ) Tj /F4 10 Tf 0 0 0 rg (ValueError ) Tj /F1 10 Tf 0 0 0 rg (is raised with the details:) Tj T* ET Q Q q 1 0 0 1 62.69291 368.8236 cm q q 1 0 0 1 0 0 cm q 1 0 0 1 6.6 6.6 cm q .662745 .662745 .662745 RG .5 w .960784 .960784 .862745 rg n -6 -6 468.6898 108 re B* Q q BT 1 0 0 1 0 86 Tm 12 TL /F4 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( @unique) Tj T* (... class NoDupes\(Enum\):) Tj T* (... first = 'one') Tj T* (... second = 'two') Tj T* (... third = 'two') Tj T* (Traceback \(most recent call last\):) Tj T* (...) Tj T* (ValueError: duplicate names found in ) Tj (<) Tj (enum 'NoDupes') Tj (>) Tj (: third -) Tj (>) Tj ( second) Tj T* ET Q Q Q Q Q q 1 0 0 1 62.69291 335.8236 cm q BT 1 0 0 1 0 3.5 Tm 21 TL /F3 17.5 Tf 0 0 0 rg (Interesting examples) Tj T* ET Q Q q 1 0 0 1 62.69291 293.8236 cm q BT 1 0 0 1 0 26 Tm .593735 Tw 12 TL /F1 10 Tf 0 0 0 rg (While ) Tj /F4 10 Tf 0 0 0 rg (Enum ) Tj /F1 10 Tf 0 0 0 rg (and ) Tj /F4 10 Tf 0 0 0 rg (IntEnum ) Tj /F1 10 Tf 0 0 0 rg (are expected to cover the majority of use-cases, they cannot cover them all.) Tj T* 0 Tw .897045 Tw (Here are recipes for some different types of enumerations that can be used directly, or as examples for) Tj T* 0 Tw (creating one's own.) Tj T* ET Q Q q 1 0 0 1 62.69291 263.8236 cm q BT 1 0 0 1 0 3 Tm 18 TL /F3 15 Tf 0 0 0 rg (AutoNumber) Tj T* ET Q Q q 1 0 0 1 62.69291 245.8236 cm q 0 0 0 rg BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Avoids having to specify the value for each enumeration member:) Tj T* ET Q Q q 1 0 0 1 62.69291 80.62362 cm q q 1 0 0 1 0 0 cm q 1 0 0 1 6.6 6.6 cm q .662745 .662745 .662745 RG .5 w .960784 .960784 .862745 rg n -6 -6 468.6898 156 re B* Q q BT 1 0 0 1 0 134 Tm 12 TL /F4 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( class AutoNumber\(Enum\):) Tj T* (... def __new__\(cls\):) Tj T* (... value = len\(cls.__members__\) + 1) Tj T* (... obj = object.__new__\(cls\)) Tj T* (... obj._value_ = value) Tj T* (... return obj) Tj T* (...) Tj T* (>) Tj (>) Tj (>) Tj ( class Color\(AutoNumber\):) Tj T* (... __order__ = "red green blue" # only needed in 2.x) Tj T* (... red = \(\)) Tj T* (... green = \(\)) Tj T* (... blue = \(\)) Tj T* ET Q Q Q Q Q endstream endobj 65 0 obj << /Length 4158 >> stream 1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET q 1 0 0 1 62.69291 715.8236 cm q q 1 0 0 1 0 0 cm q 1 0 0 1 6.6 6.6 cm q .662745 .662745 .662745 RG .5 w .960784 .960784 .862745 rg n -6 -6 468.6898 48 re B* Q q BT 1 0 0 1 0 26 Tm 12 TL /F4 10 Tf 0 0 0 rg (...) Tj T* (>) Tj (>) Tj (>) Tj ( Color.green.value == 2) Tj T* (True) Tj T* ET Q Q Q Q Q q 1 0 0 1 62.69291 695.8236 cm q 0 0 0 rg BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Note:) Tj T* ET Q Q q 1 0 0 1 62.69291 689.8236 cm Q q 1 0 0 1 62.69291 653.8236 cm 0 0 0 rg BT /F1 10 Tf 12 TL ET BT 1 0 0 1 0 2 Tm T* ET q 1 0 0 1 20 0 cm q BT 1 0 0 1 0 26 Tm .144104 Tw 12 TL /F1 10 Tf 0 0 0 rg (The ) Tj /F5 10 Tf 0 0 0 rg (__new__ ) Tj /F1 10 Tf 0 0 0 rg (method, if defined, is used during creation of the Enum members; it is then replaced by) Tj T* 0 Tw .799985 Tw (Enum's ) Tj /F5 10 Tf 0 0 0 rg (__new__ ) Tj /F1 10 Tf 0 0 0 rg (which is used after class creation for lookup of existing members. Due to the way) Tj T* 0 Tw (Enums are supposed to behave, there is no way to customize Enum's ) Tj /F5 10 Tf 0 0 0 rg (__new__) Tj /F1 10 Tf 0 0 0 rg (.) Tj T* ET Q Q q Q Q q 1 0 0 1 62.69291 653.8236 cm Q q 1 0 0 1 62.69291 623.8236 cm q BT 1 0 0 1 0 3 Tm 18 TL /F3 15 Tf 0 0 0 rg (UniqueEnum) Tj T* ET Q Q q 1 0 0 1 62.69291 605.8236 cm q 0 0 0 rg BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Raises an error if a duplicate member name is found instead of creating an alias:) Tj T* ET Q Q q 1 0 0 1 62.69291 368.6236 cm q q 1 0 0 1 0 0 cm q 1 0 0 1 6.6 6.6 cm q .662745 .662745 .662745 RG .5 w .960784 .960784 .862745 rg n -6 -6 468.6898 228 re B* Q q BT 1 0 0 1 0 206 Tm 12 TL /F4 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( class UniqueEnum\(Enum\):) Tj T* (... def __init__\(self, *args\):) Tj T* (... cls = self.__class__) Tj T* (... if any\(self.value == e.value for e in cls\):) Tj T* (... a = self.name) Tj T* (... e = cls\(self.value\).name) Tj T* (... raise ValueError\() Tj T* (... "aliases not allowed in UniqueEnum: %r --) Tj (>) Tj ( %r") Tj T* (... % \(a, e\)\)) Tj T* (...) Tj T* (>) Tj (>) Tj (>) Tj ( class Color\(UniqueEnum\):) Tj T* (... red = 1) Tj T* (... green = 2) Tj T* (... blue = 3) Tj T* (... grene = 2) Tj T* (Traceback \(most recent call last\):) Tj T* (...) Tj T* (ValueError: aliases not allowed in UniqueEnum: 'grene' --) Tj (>) Tj ( 'green') Tj T* ET Q Q Q Q Q q 1 0 0 1 62.69291 338.6236 cm q BT 1 0 0 1 0 3 Tm 18 TL /F3 15 Tf 0 0 0 rg (OrderedEnum) Tj T* ET Q Q q 1 0 0 1 62.69291 308.6236 cm q BT 1 0 0 1 0 14 Tm 1.335984 Tw 12 TL /F1 10 Tf 0 0 0 rg (An ordered enumeration that is not based on ) Tj /F4 10 Tf 0 0 0 rg (IntEnum ) Tj /F1 10 Tf 0 0 0 rg (and so maintains the normal ) Tj /F4 10 Tf 0 0 0 rg (Enum ) Tj /F1 10 Tf 0 0 0 rg (invariants) Tj T* 0 Tw (\(such as not being comparable to other enumerations\):) Tj T* ET Q Q q 1 0 0 1 62.69291 83.42362 cm q q 1 0 0 1 0 0 cm q 1 0 0 1 6.6 6.6 cm q .662745 .662745 .662745 RG .5 w .960784 .960784 .862745 rg n -6 -6 468.6898 216 re B* Q q BT 1 0 0 1 0 194 Tm 12 TL /F4 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( class OrderedEnum\(Enum\):) Tj T* (... def __ge__\(self, other\):) Tj T* (... if self.__class__ is other.__class__:) Tj T* (... return self._value_ ) Tj (>) Tj (= other._value_) Tj T* (... return NotImplemented) Tj T* (... def __gt__\(self, other\):) Tj T* (... if self.__class__ is other.__class__:) Tj T* (... return self._value_ ) Tj (>) Tj ( other._value_) Tj T* (... return NotImplemented) Tj T* (... def __le__\(self, other\):) Tj T* (... if self.__class__ is other.__class__:) Tj T* (... return self._value_ ) Tj (<) Tj (= other._value_) Tj T* (... return NotImplemented) Tj T* (... def __lt__\(self, other\):) Tj T* (... if self.__class__ is other.__class__:) Tj T* (... return self._value_ ) Tj (<) Tj ( other._value_) Tj T* (... return NotImplemented) Tj T* ET Q Q Q Q Q endstream endobj 66 0 obj << /Length 4039 >> stream 1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET q 1 0 0 1 62.69291 619.8236 cm q q 1 0 0 1 0 0 cm q 1 0 0 1 6.6 6.6 cm q .662745 .662745 .662745 RG .5 w .960784 .960784 .862745 rg n -6 -6 468.6898 144 re B* Q q BT 1 0 0 1 0 122 Tm 12 TL /F4 10 Tf 0 0 0 rg (...) Tj T* (>) Tj (>) Tj (>) Tj ( class Grade\(OrderedEnum\):) Tj T* (... __ordered__ = 'A B C D F') Tj T* (... A = 5) Tj T* (... B = 4) Tj T* (... C = 3) Tj T* (... D = 2) Tj T* (... F = 1) Tj T* (...) Tj T* (>) Tj (>) Tj (>) Tj ( Grade.C ) Tj (<) Tj ( Grade.A) Tj T* (True) Tj T* ET Q Q Q Q Q q 1 0 0 1 62.69291 589.8236 cm q BT 1 0 0 1 0 3 Tm 18 TL /F3 15 Tf 0 0 0 rg (Planet) Tj T* ET Q Q q 1 0 0 1 62.69291 571.8236 cm q BT 1 0 0 1 0 2 Tm 12 TL /F1 10 Tf 0 0 0 rg (If ) Tj /F4 10 Tf 0 0 0 rg (__new__ ) Tj /F1 10 Tf 0 0 0 rg (or ) Tj /F4 10 Tf 0 0 0 rg (__init__ ) Tj /F1 10 Tf 0 0 0 rg (is defined the value of the enum member will be passed to those methods:) Tj T* ET Q Q q 1 0 0 1 62.69291 286.6236 cm q q 1 0 0 1 0 0 cm q 1 0 0 1 6.6 6.6 cm q .662745 .662745 .662745 RG .5 w .960784 .960784 .862745 rg n -6 -6 468.6898 276 re B* Q q BT 1 0 0 1 0 254 Tm 12 TL /F4 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( class Planet\(Enum\):) Tj T* (... MERCURY = \(3.303e+23, 2.4397e6\)) Tj T* (... VENUS = \(4.869e+24, 6.0518e6\)) Tj T* (... EARTH = \(5.976e+24, 6.37814e6\)) Tj T* (... MARS = \(6.421e+23, 3.3972e6\)) Tj T* (... JUPITER = \(1.9e+27, 7.1492e7\)) Tj T* (... SATURN = \(5.688e+26, 6.0268e7\)) Tj T* (... URANUS = \(8.686e+25, 2.5559e7\)) Tj T* (... NEPTUNE = \(1.024e+26, 2.4746e7\)) Tj T* (... def __init__\(self, mass, radius\):) Tj T* (... self.mass = mass # in kilograms) Tj T* (... self.radius = radius # in meters) Tj T* (... @property) Tj T* (... def surface_gravity\(self\):) Tj T* (... # universal gravitational constant \(m3 kg-1 s-2\)) Tj T* (... G = 6.67300E-11) Tj T* (... return G * self.mass / \(self.radius * self.radius\)) Tj T* (...) Tj T* (>) Tj (>) Tj (>) Tj ( Planet.EARTH.value) Tj T* (\(5.976e+24, 6378140.0\)) Tj T* (>) Tj (>) Tj (>) Tj ( Planet.EARTH.surface_gravity) Tj T* (9.802652743337129) Tj T* ET Q Q Q Q Q q 1 0 0 1 62.69291 253.6236 cm q BT 1 0 0 1 0 3.5 Tm 21 TL /F3 17.5 Tf 0 0 0 rg (How are Enums different?) Tj T* ET Q Q q 1 0 0 1 62.69291 223.6236 cm q 0 0 0 rg BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL 2.090651 Tw (Enums have a custom metaclass that affects many aspects of both derived Enum classes and their) Tj T* 0 Tw (instances \(members\).) Tj T* ET Q Q q 1 0 0 1 62.69291 193.6236 cm q BT 1 0 0 1 0 3 Tm 18 TL /F3 15 Tf 0 0 0 rg (Enum Classes) Tj T* ET Q Q q 1 0 0 1 62.69291 127.6236 cm q BT 1 0 0 1 0 50 Tm 1.263615 Tw 12 TL /F1 10 Tf 0 0 0 rg (The ) Tj /F4 10 Tf 0 0 0 rg (EnumMeta ) Tj /F1 10 Tf 0 0 0 rg (metaclass is responsible for providing the ) Tj /F4 10 Tf 0 0 0 rg (__contains__) Tj /F1 10 Tf 0 0 0 rg (, ) Tj /F4 10 Tf 0 0 0 rg (__dir__) Tj /F1 10 Tf 0 0 0 rg (, ) Tj /F4 10 Tf 0 0 0 rg (__iter__ ) Tj /F1 10 Tf 0 0 0 rg (and) Tj T* 0 Tw 2.264724 Tw (other methods that allow one to do things with an ) Tj /F4 10 Tf 0 0 0 rg (Enum ) Tj /F1 10 Tf 0 0 0 rg (class that fail on a typical class, such as) Tj T* 0 Tw 2.594147 Tw /F4 10 Tf 0 0 0 rg (list\(Color\) ) Tj /F1 10 Tf 0 0 0 rg (or ) Tj /F4 10 Tf 0 0 0 rg (some_var) Tj ( ) Tj (in) Tj ( ) Tj (Color) Tj /F1 10 Tf 0 0 0 rg (. ) Tj /F4 10 Tf 0 0 0 rg (EnumMeta ) Tj /F1 10 Tf 0 0 0 rg (is responsible for ensuring that various other) Tj T* 0 Tw 2.196905 Tw (methods on the final ) Tj /F4 10 Tf 0 0 0 rg (Enum ) Tj /F1 10 Tf 0 0 0 rg (class are correct \(such as ) Tj /F4 10 Tf 0 0 0 rg (__new__) Tj /F1 10 Tf 0 0 0 rg (, ) Tj /F4 10 Tf 0 0 0 rg (__getnewargs__) Tj /F1 10 Tf 0 0 0 rg (, ) Tj /F4 10 Tf 0 0 0 rg (__str__ ) Tj /F1 10 Tf 0 0 0 rg (and) Tj T* 0 Tw /F4 10 Tf 0 0 0 rg (__repr__) Tj /F1 10 Tf 0 0 0 rg (\).) Tj T* ET Q Q q 1 0 0 1 62.69291 115.6236 cm Q endstream endobj 67 0 obj << /Length 5453 >> stream 1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET q 1 0 0 1 62.69291 682.0236 cm .960784 .960784 .862745 rg n 0 83 469.8898 -83 re f* 0 0 0 rg BT /F1 10 Tf 12 TL ET BT 1 0 0 1 6 57 Tm T* ET q 1 0 0 1 16 52 cm q 0 0 0 rg BT 1 0 0 1 0 2.5 Tm /F6 12.5 Tf 15 TL (Note) Tj T* ET Q Q q 1 0 0 1 16 16 cm q BT 1 0 0 1 0 14 Tm .686654 Tw 12 TL /F4 10 Tf 0 0 0 rg (__dir__ ) Tj /F1 10 Tf 0 0 0 rg (is not changed in the Python 2 line as it messes up some of the decorators included in) Tj T* 0 Tw (the stdlib.) Tj T* ET Q Q q 1 J 1 j .662745 .662745 .662745 RG .5 w n 0 83 m 469.8898 83 l S n 0 0 m 469.8898 0 l S n 0 0 m 0 83 l S n 469.8898 0 m 469.8898 83 l S Q Q q 1 0 0 1 62.69291 676.0236 cm Q q 1 0 0 1 62.69291 646.0236 cm q BT 1 0 0 1 0 3 Tm 18 TL /F3 15 Tf 0 0 0 rg (Enum Members \(aka instances\)) Tj T* ET Q Q q 1 0 0 1 62.69291 604.0236 cm q BT 1 0 0 1 0 26 Tm .491984 Tw 12 TL /F1 10 Tf 0 0 0 rg (The most interesting thing about Enum members is that they are singletons. ) Tj /F4 10 Tf 0 0 0 rg (EnumMeta ) Tj /F1 10 Tf 0 0 0 rg (creates them all) Tj T* 0 Tw .084988 Tw (while it is creating the ) Tj /F4 10 Tf 0 0 0 rg (Enum ) Tj /F1 10 Tf 0 0 0 rg (class itself, and then puts a custom ) Tj /F4 10 Tf 0 0 0 rg (__new__ ) Tj /F1 10 Tf 0 0 0 rg (in place to ensure that no new) Tj T* 0 Tw (ones are ever instantiated by returning only the existing member instances.) Tj T* ET Q Q q 1 0 0 1 62.69291 574.0236 cm q BT 1 0 0 1 0 3 Tm 18 TL /F3 15 Tf 0 0 0 rg (Finer Points) Tj T* ET Q Q q 1 0 0 1 62.69291 520.0236 cm q BT 1 0 0 1 0 38 Tm 5.488555 Tw 12 TL /F4 10 Tf 0 0 0 rg (Enum ) Tj /F1 10 Tf 0 0 0 rg (members are instances of an ) Tj /F4 10 Tf 0 0 0 rg (Enum ) Tj /F1 10 Tf 0 0 0 rg (class, and even though they are accessible as) Tj T* 0 Tw 1.504147 Tw /F5 10 Tf 0 0 0 rg (EnumClass.member1.member2) Tj /F1 10 Tf 0 0 0 rg (, they should not be accessed directly from the member as that lookup) Tj T* 0 Tw .329985 Tw (may fail or, worse, return something besides the ) Tj /F4 10 Tf 0 0 0 rg (Enum ) Tj /F1 10 Tf 0 0 0 rg (member you were looking for \(changed in version) Tj T* 0 Tw (1.1.1\):) Tj T* ET Q Q q 1 0 0 1 62.69291 390.8236 cm q q 1 0 0 1 0 0 cm q 1 0 0 1 6.6 6.6 cm q .662745 .662745 .662745 RG .5 w .960784 .960784 .862745 rg n -6 -6 468.6898 120 re B* Q q BT 1 0 0 1 0 98 Tm 12 TL /F4 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( class FieldTypes\(Enum\):) Tj T* (... name = 1) Tj T* (... value = 2) Tj T* (... size = 3) Tj T* (...) Tj T* (>) Tj (>) Tj (>) Tj ( FieldTypes.value.size) Tj T* (<) Tj (FieldTypes.size: 3) Tj (>) Tj T* (>) Tj (>) Tj (>) Tj ( FieldTypes.size.value) Tj T* (3) Tj T* ET Q Q Q Q Q q 1 0 0 1 62.69291 370.8236 cm q BT 1 0 0 1 0 2 Tm 12 TL /F1 10 Tf 0 0 0 rg (The ) Tj /F4 10 Tf 0 0 0 rg (__members__ ) Tj /F1 10 Tf 0 0 0 rg (attribute is only available on the class.) Tj T* ET Q Q q 1 0 0 1 62.69291 316.8236 cm q BT 1 0 0 1 0 38 Tm 1.374651 Tw 12 TL /F1 10 Tf 0 0 0 rg (In Python 3.x ) Tj /F4 10 Tf 0 0 0 rg (__members__ ) Tj /F1 10 Tf 0 0 0 rg (is always an ) Tj /F4 10 Tf 0 0 0 rg (OrderedDict) Tj /F1 10 Tf 0 0 0 rg (, with the order being the definition order. In) Tj T* 0 Tw 3.009213 Tw (Python 2.7 ) Tj /F4 10 Tf 0 0 0 rg (__members__ ) Tj /F1 10 Tf 0 0 0 rg (is an ) Tj /F4 10 Tf 0 0 0 rg (OrderedDict ) Tj /F1 10 Tf 0 0 0 rg (if ) Tj /F4 10 Tf 0 0 0 rg (__order__ ) Tj /F1 10 Tf 0 0 0 rg (was specified, and a plain ) Tj /F4 10 Tf 0 0 0 rg (dict) Tj T* 0 Tw 1.851318 Tw /F1 10 Tf 0 0 0 rg (otherwise. In all other Python 2.x versions ) Tj /F4 10 Tf 0 0 0 rg (__members__ ) Tj /F1 10 Tf 0 0 0 rg (is a plain ) Tj /F4 10 Tf 0 0 0 rg (dict ) Tj /F1 10 Tf 0 0 0 rg (even if ) Tj /F4 10 Tf 0 0 0 rg (__order__ ) Tj /F1 10 Tf 0 0 0 rg (was) Tj T* 0 Tw (specified as the ) Tj /F4 10 Tf 0 0 0 rg (OrderedDict ) Tj /F1 10 Tf 0 0 0 rg (type didn't exist yet.) Tj T* ET Q Q q 1 0 0 1 62.69291 286.8236 cm q BT 1 0 0 1 0 14 Tm .106654 Tw 12 TL /F1 10 Tf 0 0 0 rg (If you give your ) Tj /F4 10 Tf 0 0 0 rg (Enum ) Tj /F1 10 Tf 0 0 0 rg (subclass extra methods, like the ) Tj 0 0 .501961 rg (Planet ) Tj 0 0 0 rg (class above, those methods will show up in) Tj T* 0 Tw (a ) Tj /F5 10 Tf 0 0 0 rg (dir ) Tj /F1 10 Tf 0 0 0 rg (of the member, but not of the class:) Tj T* ET Q Q q 1 0 0 1 62.69291 205.6236 cm q q 1 0 0 1 0 0 cm q 1 0 0 1 6.6 6.6 cm q .662745 .662745 .662745 RG .5 w .960784 .960784 .862745 rg n -6 -6 468.6898 72 re B* Q q BT 1 0 0 1 0 50 Tm 12 TL /F4 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( dir\(Planet\)) Tj T* (['EARTH', 'JUPITER', 'MARS', 'MERCURY', 'NEPTUNE', 'SATURN', 'URANUS',) Tj T* ('VENUS', '__class__', '__doc__', '__members__', '__module__']) Tj T* (>) Tj (>) Tj (>) Tj ( dir\(Planet.EARTH\)) Tj T* (['__class__', '__doc__', '__module__', 'name', 'surface_gravity', 'value']) Tj T* ET Q Q Q Q Q q 1 0 0 1 62.69291 161.6236 cm q BT 1 0 0 1 0 26 Tm .938935 Tw 12 TL /F1 10 Tf 0 0 0 rg (A ) Tj /F4 10 Tf 0 0 0 rg (__new__ ) Tj /F1 10 Tf 0 0 0 rg (method will only be used for the creation of the ) Tj /F4 10 Tf 0 0 0 rg (Enum ) Tj /F1 10 Tf 0 0 0 rg (members -- after that it is replaced.) Tj T* 0 Tw .949461 Tw (This means if you wish to change how ) Tj /F4 10 Tf 0 0 0 rg (Enum ) Tj /F1 10 Tf 0 0 0 rg (members are looked up you either have to write a helper) Tj T* 0 Tw (function or a ) Tj /F4 10 Tf 0 0 0 rg (classmethod) Tj /F1 10 Tf 0 0 0 rg (.) Tj T* ET Q Q endstream endobj 68 0 obj << /Nums [ 0 69 0 R 1 70 0 R 2 71 0 R 3 72 0 R 4 73 0 R 5 74 0 R 6 75 0 R 7 76 0 R 8 77 0 R 9 78 0 R 10 79 0 R 11 80 0 R ] >> endobj 69 0 obj << /S /D /St 1 >> endobj 70 0 obj << /S /D /St 2 >> endobj 71 0 obj << /S /D /St 3 >> endobj 72 0 obj << /S /D /St 4 >> endobj 73 0 obj << /S /D /St 5 >> endobj 74 0 obj << /S /D /St 6 >> endobj 75 0 obj << /S /D /St 7 >> endobj 76 0 obj << /S /D /St 8 >> endobj 77 0 obj << /S /D /St 9 >> endobj 78 0 obj << /S /D /St 10 >> endobj 79 0 obj << /S /D /St 11 >> endobj 80 0 obj << /S /D /St 12 >> endobj xref 0 81 0000000000 65535 f 0000000075 00000 n 0000000160 00000 n 0000000270 00000 n 0000000383 00000 n 0000000498 00000 n 0000000606 00000 n 0000000777 00000 n 0000000948 00000 n 0000001066 00000 n 0000001237 00000 n 0000001477 00000 n 0000001687 00000 n 0000001897 00000 n 0000002107 00000 n 0000002279 00000 n 0000002402 00000 n 0000002574 00000 n 0000002746 00000 n 0000002989 00000 n 0000003161 00000 n 0000003333 00000 n 0000003569 00000 n 0000003779 00000 n 0000003989 00000 n 0000004199 00000 n 0000004409 00000 n 0000004619 00000 n 0000004791 00000 n 0000005020 00000 n 0000005129 00000 n 0000005373 00000 n 0000005451 00000 n 0000005571 00000 n 0000005705 00000 n 0000005886 00000 n 0000006039 00000 n 0000006168 00000 n 0000006332 00000 n 0000006488 00000 n 0000006614 00000 n 0000006746 00000 n 0000006924 00000 n 0000007036 00000 n 0000007147 00000 n 0000007315 00000 n 0000007413 00000 n 0000007591 00000 n 0000007706 00000 n 0000007834 00000 n 0000007963 00000 n 0000008074 00000 n 0000008243 00000 n 0000008360 00000 n 0000008508 00000 n 0000008625 00000 n 0000008771 00000 n 0000015286 00000 n 0000019517 00000 n 0000023365 00000 n 0000027828 00000 n 0000032406 00000 n 0000037090 00000 n 0000042519 00000 n 0000046717 00000 n 0000053882 00000 n 0000058097 00000 n 0000062193 00000 n 0000067703 00000 n 0000067856 00000 n 0000067893 00000 n 0000067930 00000 n 0000067967 00000 n 0000068004 00000 n 0000068041 00000 n 0000068078 00000 n 0000068115 00000 n 0000068152 00000 n 0000068189 00000 n 0000068227 00000 n 0000068265 00000 n trailer << /ID % ReportLab generated PDF document -- digest (http://www.reportlab.com) [(<}|~gm\352\320\235=\001p\220v\224\336) (<}|~gm\352\320\235=\001p\220v\224\336)] /Info 30 0 R /Root 29 0 R /Size 81 >> startxref 68303 %%EOF enum34-1.1.6/setup.cfg0000664000175000017500000000007312716237137014706 0ustar ethanethan00000000000000[egg_info] tag_build = tag_date = 0 tag_svn_revision = 0 enum34-1.1.6/MANIFEST.in0000664000175000017500000000027212716237133014620 0ustar ethanethan00000000000000exclude enum/* include setup.py include README include enum/__init__.py include enum/test.py include enum/LICENSE include enum/README include enum/doc/enum.pdf include enum/doc/enum.rst enum34-1.1.6/enum34.egg-info/0000775000175000017500000000000012716237137015672 5ustar ethanethan00000000000000enum34-1.1.6/enum34.egg-info/dependency_links.txt0000664000175000017500000000000112716237137021740 0ustar ethanethan00000000000000 enum34-1.1.6/enum34.egg-info/PKG-INFO0000664000175000017500000000373412716237137016776 0ustar ethanethan00000000000000Metadata-Version: 1.1 Name: enum34 Version: 1.1.6 Summary: Python 3.4 Enum backported to 3.3, 3.2, 3.1, 2.7, 2.6, 2.5, and 2.4 Home-page: https://bitbucket.org/stoneleaf/enum34 Author: Ethan Furman Author-email: ethan@stoneleaf.us License: BSD License Description: enum --- support for enumerations ======================================== An enumeration is a set of symbolic names (members) bound to unique, constant values. Within an enumeration, the members can be compared by identity, and the enumeration itself can be iterated over. from enum import Enum class Fruit(Enum): apple = 1 banana = 2 orange = 3 list(Fruit) # [, , ] len(Fruit) # 3 Fruit.banana # Fruit['banana'] # Fruit(2) # Fruit.banana is Fruit['banana'] is Fruit(2) # True Fruit.banana.name # 'banana' Fruit.banana.value # 2 Repository and Issue Tracker at https://bitbucket.org/stoneleaf/enum34. Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: BSD License Classifier: Programming Language :: Python Classifier: Topic :: Software Development Classifier: Programming Language :: Python :: 2.4 Classifier: Programming Language :: Python :: 2.5 Classifier: Programming Language :: Python :: 2.6 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3.3 Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: 3.5 Provides: enum enum34-1.1.6/enum34.egg-info/SOURCES.txt0000664000175000017500000000035612716237137017562 0ustar ethanethan00000000000000MANIFEST.in README setup.py enum/LICENSE enum/README enum/__init__.py enum/test.py enum/doc/enum.pdf enum/doc/enum.rst enum34.egg-info/PKG-INFO enum34.egg-info/SOURCES.txt enum34.egg-info/dependency_links.txt enum34.egg-info/top_level.txtenum34-1.1.6/enum34.egg-info/top_level.txt0000664000175000017500000000000512716237137020417 0ustar ethanethan00000000000000enum enum34-1.1.6/PKG-INFO0000664000175000017500000000373412716237137014171 0ustar ethanethan00000000000000Metadata-Version: 1.1 Name: enum34 Version: 1.1.6 Summary: Python 3.4 Enum backported to 3.3, 3.2, 3.1, 2.7, 2.6, 2.5, and 2.4 Home-page: https://bitbucket.org/stoneleaf/enum34 Author: Ethan Furman Author-email: ethan@stoneleaf.us License: BSD License Description: enum --- support for enumerations ======================================== An enumeration is a set of symbolic names (members) bound to unique, constant values. Within an enumeration, the members can be compared by identity, and the enumeration itself can be iterated over. from enum import Enum class Fruit(Enum): apple = 1 banana = 2 orange = 3 list(Fruit) # [, , ] len(Fruit) # 3 Fruit.banana # Fruit['banana'] # Fruit(2) # Fruit.banana is Fruit['banana'] is Fruit(2) # True Fruit.banana.name # 'banana' Fruit.banana.value # 2 Repository and Issue Tracker at https://bitbucket.org/stoneleaf/enum34. Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: BSD License Classifier: Programming Language :: Python Classifier: Topic :: Software Development Classifier: Programming Language :: Python :: 2.4 Classifier: Programming Language :: Python :: 2.5 Classifier: Programming Language :: Python :: 2.6 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3.3 Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: 3.5 Provides: enum enum34-1.1.6/README0000664000175000017500000000023512716237133013741 0ustar ethanethan00000000000000enum34 is the new Python stdlib enum module available in Python 3.4 backported for previous versions of Python from 2.4 to 3.3. tested on 2.6, 2.7, and 3.3+ enum34-1.1.6/setup.py0000664000175000017500000000503312716237133014574 0ustar ethanethan00000000000000import os import sys import setuptools from distutils.core import setup if sys.version_info[:2] < (2, 7): required = ['ordereddict'] else: required = [] long_desc = '''\ enum --- support for enumerations ======================================== An enumeration is a set of symbolic names (members) bound to unique, constant values. Within an enumeration, the members can be compared by identity, and the enumeration itself can be iterated over. from enum import Enum class Fruit(Enum): apple = 1 banana = 2 orange = 3 list(Fruit) # [, , ] len(Fruit) # 3 Fruit.banana # Fruit['banana'] # Fruit(2) # Fruit.banana is Fruit['banana'] is Fruit(2) # True Fruit.banana.name # 'banana' Fruit.banana.value # 2 Repository and Issue Tracker at https://bitbucket.org/stoneleaf/enum34. ''' py2_only = () py3_only = () make = [ 'rst2pdf enum/doc/enum.rst --output=enum/doc/enum.pdf', ] data = dict( name='enum34', version='1.1.6', url='https://bitbucket.org/stoneleaf/enum34', packages=['enum'], package_data={ 'enum' : [ 'LICENSE', 'README', 'doc/enum.rst', 'doc/enum.pdf', 'test.py', ] }, license='BSD License', description='Python 3.4 Enum backported to 3.3, 3.2, 3.1, 2.7, 2.6, 2.5, and 2.4', long_description=long_desc, provides=['enum'], install_requires=required, author='Ethan Furman', author_email='ethan@stoneleaf.us', classifiers=[ 'Development Status :: 5 - Production/Stable', 'Intended Audience :: Developers', 'License :: OSI Approved :: BSD License', 'Programming Language :: Python', 'Topic :: Software Development', 'Programming Language :: Python :: 2.4', 'Programming Language :: Python :: 2.5', 'Programming Language :: Python :: 2.6', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3.3', 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', ], ) if __name__ == '__main__': setup(**data)