Issue #7042: Use a better mechanism for testing timers in test_signal.
[python.git] / Demo / newmetaclasses / Enum.py
blob2a5823b563367878da4aa526e45906d7fe1ff501
1 """Enumeration metaclass."""
3 class EnumMetaclass(type):
4 """Metaclass for enumeration.
6 To define your own enumeration, do something like
8 class Color(Enum):
9 red = 1
10 green = 2
11 blue = 3
13 Now, Color.red, Color.green and Color.blue behave totally
14 different: they are enumerated values, not integers.
16 Enumerations cannot be instantiated; however they can be
17 subclassed.
18 """
20 def __init__(cls, name, bases, dict):
21 super(EnumMetaclass, cls).__init__(name, bases, dict)
22 cls._members = []
23 for attr in dict.keys():
24 if not (attr.startswith('__') and attr.endswith('__')):
25 enumval = EnumInstance(name, attr, dict[attr])
26 setattr(cls, attr, enumval)
27 cls._members.append(attr)
29 def __getattr__(cls, name):
30 if name == "__members__":
31 return cls._members
32 raise AttributeError, name
34 def __repr__(cls):
35 s1 = s2 = ""
36 enumbases = [base.__name__ for base in cls.__bases__
37 if isinstance(base, EnumMetaclass) and not base is Enum]
38 if enumbases:
39 s1 = "(%s)" % ", ".join(enumbases)
40 enumvalues = ["%s: %d" % (val, getattr(cls, val))
41 for val in cls._members]
42 if enumvalues:
43 s2 = ": {%s}" % ", ".join(enumvalues)
44 return "%s%s%s" % (cls.__name__, s1, s2)
46 class FullEnumMetaclass(EnumMetaclass):
47 """Metaclass for full enumerations.
49 A full enumeration displays all the values defined in base classes.
50 """
52 def __init__(cls, name, bases, dict):
53 super(FullEnumMetaclass, cls).__init__(name, bases, dict)
54 for obj in cls.__mro__:
55 if isinstance(obj, EnumMetaclass):
56 for attr in obj._members:
57 # XXX inefficient
58 if not attr in cls._members:
59 cls._members.append(attr)
61 class EnumInstance(int):
62 """Class to represent an enumeration value.
64 EnumInstance('Color', 'red', 12) prints as 'Color.red' and behaves
65 like the integer 12 when compared, but doesn't support arithmetic.
67 XXX Should it record the actual enumeration rather than just its
68 name?
69 """
71 def __new__(cls, classname, enumname, value):
72 return int.__new__(cls, value)
74 def __init__(self, classname, enumname, value):
75 self.__classname = classname
76 self.__enumname = enumname
78 def __repr__(self):
79 return "EnumInstance(%s, %s, %d)" % (self.__classname, self.__enumname,
80 self)
82 def __str__(self):
83 return "%s.%s" % (self.__classname, self.__enumname)
85 class Enum:
86 __metaclass__ = EnumMetaclass
88 class FullEnum:
89 __metaclass__ = FullEnumMetaclass
91 def _test():
93 class Color(Enum):
94 red = 1
95 green = 2
96 blue = 3
98 print Color.red
100 print repr(Color.red)
101 print Color.red == Color.red
102 print Color.red == Color.blue
103 print Color.red == 1
104 print Color.red == 2
106 class ExtendedColor(Color):
107 white = 0
108 orange = 4
109 yellow = 5
110 purple = 6
111 black = 7
113 print ExtendedColor.orange
114 print ExtendedColor.red
116 print Color.red == ExtendedColor.red
118 class OtherColor(Enum):
119 white = 4
120 blue = 5
122 class MergedColor(Color, OtherColor):
123 pass
125 print MergedColor.red
126 print MergedColor.white
128 print Color
129 print ExtendedColor
130 print OtherColor
131 print MergedColor
133 def _test2():
135 class Color(FullEnum):
136 red = 1
137 green = 2
138 blue = 3
140 print Color.red
142 print repr(Color.red)
143 print Color.red == Color.red
144 print Color.red == Color.blue
145 print Color.red == 1
146 print Color.red == 2
148 class ExtendedColor(Color):
149 white = 0
150 orange = 4
151 yellow = 5
152 purple = 6
153 black = 7
155 print ExtendedColor.orange
156 print ExtendedColor.red
158 print Color.red == ExtendedColor.red
160 class OtherColor(FullEnum):
161 white = 4
162 blue = 5
164 class MergedColor(Color, OtherColor):
165 pass
167 print MergedColor.red
168 print MergedColor.white
170 print Color
171 print ExtendedColor
172 print OtherColor
173 print MergedColor
175 if __name__ == '__main__':
176 _test()
177 _test2()