| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239 |
- # -*- coding: utf-8 -*-
- # enum.py
- # Part of enum, a package providing enumerated types for Python.
- #
- # Copyright © 2007–2009 Ben Finney <ben+python@benfinney.id.au>
- # This is free software; you may copy, modify and/or distribute this work
- # under the terms of the GNU General Public License, version 2 or later
- # or, at your option, the terms of the Python license.
- """ Robust enumerated type support in Python.
- This package provides a module for robust enumerations in Python.
- An enumeration object is created with a sequence of string arguments
- to the Enum() constructor::
- >>> from enum import Enum
- >>> Colours = Enum('red', 'blue', 'green')
- >>> Weekdays = Enum('mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun')
- The return value is an immutable sequence object with a value for each
- of the string arguments. Each value is also available as an attribute
- named from the corresponding string argument::
- >>> pizza_night = Weekdays[4]
- >>> shirt_colour = Colours.green
- The values are constants that can be compared only with values from
- the same enumeration; comparison with other values will invoke
- Python's fallback comparisons::
- >>> pizza_night == Weekdays.fri
- True
- >>> shirt_colour > Colours.red
- True
- >>> shirt_colour == "green"
- False
- Each value from an enumeration exports its sequence index
- as an integer, and can be coerced to a simple string matching the
- original arguments used to create the enumeration::
- >>> str(pizza_night)
- 'fri'
- >>> shirt_colour.index
- 2
- """
- __author_name__ = "Ben Finney"
- __author_email__ = "ben+python@benfinney.id.au"
- __author__ = "%(__author_name__)s <%(__author_email__)s>" % vars()
- _copyright_year_begin = "2007"
- __date__ = "2009-08-26"
- _copyright_year_latest = __date__.split('-')[0]
- _copyright_year_range = _copyright_year_begin
- if _copyright_year_latest > _copyright_year_begin:
- _copyright_year_range += "–%(_copyright_year_latest)s" % vars()
- __copyright__ = (
- "Copyright © %(_copyright_year_range)s"
- " %(__author_name__)s") % vars()
- __license__ = "Choice of GPL or Python license"
- __url__ = "http://pypi.python.org/pypi/enum/"
- __version__ = "0.4.4"
- class EnumException(Exception):
- """ Base class for all exceptions in this module. """
- def __init__(self, *args, **kwargs):
- if self.__class__ is EnumException:
- class_name = self.__class__.__name__
- raise NotImplementedError(
- "%(class_name)s is an abstract base class" % vars())
- super(EnumException, self).__init__(*args, **kwargs)
- class EnumEmptyError(AssertionError, EnumException):
- """ Raised when attempting to create an empty enumeration. """
- def __str__(self):
- return "Enumerations cannot be empty"
- class EnumBadKeyError(TypeError, EnumException):
- """ Raised when creating an Enum with non-string keys. """
- def __init__(self, key):
- self.key = key
- def __str__(self):
- return "Enumeration keys must be strings: %(key)r" % vars(self)
- class EnumImmutableError(TypeError, EnumException):
- """ Raised when attempting to modify an Enum. """
- def __init__(self, *args):
- self.args = args
- def __str__(self):
- return "Enumeration does not allow modification"
- def _comparator(func):
- """ Decorator for EnumValue rich comparison methods. """
- def comparator_wrapper(self, other):
- try:
- assert self.enumtype == other.enumtype
- result = func(self.index, other.index)
- except (AssertionError, AttributeError):
- result = NotImplemented
- return result
- comparator_wrapper.__name__ = func.__name__
- comparator_wrapper.__doc__ = getattr(float, func.__name__).__doc__
- return comparator_wrapper
- class EnumValue(object):
- """ A specific value of an enumerated type. """
- def __init__(self, enumtype, index, key):
- """ Set up a new instance. """
- self._enumtype = enumtype
- self._index = index
- self._key = key
- @property
- def enumtype(self):
- return self._enumtype
- @property
- def key(self):
- return self._key
- def __str__(self):
- return str(self.key)
- @property
- def index(self):
- return self._index
- def __repr__(self):
- return "EnumValue(%(_enumtype)r, %(_index)r, %(_key)r)" % vars(self)
- def __hash__(self):
- return hash(self._index)
- @_comparator
- def __eq__(self, other):
- return (self == other)
- @_comparator
- def __ne__(self, other):
- return (self != other)
- @_comparator
- def __lt__(self, other):
- return (self < other)
- @_comparator
- def __le__(self, other):
- return (self <= other)
- @_comparator
- def __gt__(self, other):
- return (self > other)
- @_comparator
- def __ge__(self, other):
- return (self >= other)
- class Enum(object):
- """ Enumerated type. """
- def __init__(self, *keys, **kwargs):
- """ Create an enumeration instance. """
- value_type = kwargs.get('value_type', EnumValue)
- if not keys:
- raise EnumEmptyError()
- keys = tuple(keys)
- values = [None] * len(keys)
- for i, key in enumerate(keys):
- value = value_type(self, i, key)
- values[i] = value
- try:
- super(Enum, self).__setattr__(key, value)
- except TypeError:
- raise EnumBadKeyError(key)
- self.__dict__['_keys'] = keys
- self.__dict__['_values'] = values
- def __setattr__(self, name, value):
- raise EnumImmutableError(name)
- def __delattr__(self, name):
- raise EnumImmutableError(name)
- def __len__(self):
- return len(self._values)
- def __getitem__(self, index):
- return self._values[index]
- def __setitem__(self, index, value):
- raise EnumImmutableError(index)
- def __delitem__(self, index):
- raise EnumImmutableError(index)
- def __iter__(self):
- return iter(self._values)
- def __contains__(self, value):
- is_member = False
- if isinstance(value, basestring):
- is_member = (value in self._keys)
- else:
- is_member = (value in self._values)
- return is_member
- # Local variables:
- # mode: python
- # time-stamp-format: "%:y-%02m-%02d"
- # time-stamp-start: "__date__ = \""
- # time-stamp-end: "\"$"
- # time-stamp-line-limit: 200
- # End:
- # vim: filetype=python fileencoding=utf-8 :
|