+++ /dev/null
-"""Enumeration metaclass."""\r
-\r
-class EnumMetaclass(type):\r
- """Metaclass for enumeration.\r
-\r
- To define your own enumeration, do something like\r
-\r
- class Color(Enum):\r
- red = 1\r
- green = 2\r
- blue = 3\r
-\r
- Now, Color.red, Color.green and Color.blue behave totally\r
- different: they are enumerated values, not integers.\r
-\r
- Enumerations cannot be instantiated; however they can be\r
- subclassed.\r
- """\r
-\r
- def __init__(cls, name, bases, dict):\r
- super(EnumMetaclass, cls).__init__(name, bases, dict)\r
- cls._members = []\r
- for attr in dict.keys():\r
- if not (attr.startswith('__') and attr.endswith('__')):\r
- enumval = EnumInstance(name, attr, dict[attr])\r
- setattr(cls, attr, enumval)\r
- cls._members.append(attr)\r
-\r
- def __getattr__(cls, name):\r
- if name == "__members__":\r
- return cls._members\r
- raise AttributeError, name\r
-\r
- def __repr__(cls):\r
- s1 = s2 = ""\r
- enumbases = [base.__name__ for base in cls.__bases__\r
- if isinstance(base, EnumMetaclass) and not base is Enum]\r
- if enumbases:\r
- s1 = "(%s)" % ", ".join(enumbases)\r
- enumvalues = ["%s: %d" % (val, getattr(cls, val))\r
- for val in cls._members]\r
- if enumvalues:\r
- s2 = ": {%s}" % ", ".join(enumvalues)\r
- return "%s%s%s" % (cls.__name__, s1, s2)\r
-\r
-class FullEnumMetaclass(EnumMetaclass):\r
- """Metaclass for full enumerations.\r
-\r
- A full enumeration displays all the values defined in base classes.\r
- """\r
-\r
- def __init__(cls, name, bases, dict):\r
- super(FullEnumMetaclass, cls).__init__(name, bases, dict)\r
- for obj in cls.__mro__:\r
- if isinstance(obj, EnumMetaclass):\r
- for attr in obj._members:\r
- # XXX inefficient\r
- if not attr in cls._members:\r
- cls._members.append(attr)\r
-\r
-class EnumInstance(int):\r
- """Class to represent an enumeration value.\r
-\r
- EnumInstance('Color', 'red', 12) prints as 'Color.red' and behaves\r
- like the integer 12 when compared, but doesn't support arithmetic.\r
-\r
- XXX Should it record the actual enumeration rather than just its\r
- name?\r
- """\r
-\r
- def __new__(cls, classname, enumname, value):\r
- return int.__new__(cls, value)\r
-\r
- def __init__(self, classname, enumname, value):\r
- self.__classname = classname\r
- self.__enumname = enumname\r
-\r
- def __repr__(self):\r
- return "EnumInstance(%s, %s, %d)" % (self.__classname, self.__enumname,\r
- self)\r
-\r
- def __str__(self):\r
- return "%s.%s" % (self.__classname, self.__enumname)\r
-\r
-class Enum:\r
- __metaclass__ = EnumMetaclass\r
-\r
-class FullEnum:\r
- __metaclass__ = FullEnumMetaclass\r
-\r
-def _test():\r
-\r
- class Color(Enum):\r
- red = 1\r
- green = 2\r
- blue = 3\r
-\r
- print Color.red\r
-\r
- print repr(Color.red)\r
- print Color.red == Color.red\r
- print Color.red == Color.blue\r
- print Color.red == 1\r
- print Color.red == 2\r
-\r
- class ExtendedColor(Color):\r
- white = 0\r
- orange = 4\r
- yellow = 5\r
- purple = 6\r
- black = 7\r
-\r
- print ExtendedColor.orange\r
- print ExtendedColor.red\r
-\r
- print Color.red == ExtendedColor.red\r
-\r
- class OtherColor(Enum):\r
- white = 4\r
- blue = 5\r
-\r
- class MergedColor(Color, OtherColor):\r
- pass\r
-\r
- print MergedColor.red\r
- print MergedColor.white\r
-\r
- print Color\r
- print ExtendedColor\r
- print OtherColor\r
- print MergedColor\r
-\r
-def _test2():\r
-\r
- class Color(FullEnum):\r
- red = 1\r
- green = 2\r
- blue = 3\r
-\r
- print Color.red\r
-\r
- print repr(Color.red)\r
- print Color.red == Color.red\r
- print Color.red == Color.blue\r
- print Color.red == 1\r
- print Color.red == 2\r
-\r
- class ExtendedColor(Color):\r
- white = 0\r
- orange = 4\r
- yellow = 5\r
- purple = 6\r
- black = 7\r
-\r
- print ExtendedColor.orange\r
- print ExtendedColor.red\r
-\r
- print Color.red == ExtendedColor.red\r
-\r
- class OtherColor(FullEnum):\r
- white = 4\r
- blue = 5\r
-\r
- class MergedColor(Color, OtherColor):\r
- pass\r
-\r
- print MergedColor.red\r
- print MergedColor.white\r
-\r
- print Color\r
- print ExtendedColor\r
- print OtherColor\r
- print MergedColor\r
-\r
-if __name__ == '__main__':\r
- _test()\r
- _test2()\r