simples e flexivel
1 class Enum(object):
2 class EnumError(TypeError):
3 pass
4
5 def __init__(self):
6 self.__dict__['__rdict__'] = {} # reverse dict, value => key
7 self.__dict__['__ldict__'] = {} # labels dict, value => label
8
9 def __setattr__(self, name, value):
10 if name in self.__dict__:
11 raise self.EnumError, "%s is a constant value" % name
12 if not name.isupper():
13 raise NameError, 'enumeration constant %r not in uppercase' % name
14 self.__dict__[name] = value
15 self.__rdict__[value] = name
16
17 def __delattr__(self, name):
18 if name in self.__dict__:
19 raise self.EnumError, "Cannot unbind constant %s" % name
20 raise NameError, name
21
22 def validate(self, value):
23 if value not in self.__rdict__:
24 raise ValueError('%s is not a valid enumeration constant value' % value)
25 return True
26
27 def key(self, value):
28 if value not in self.__rdict__:
29 raise ValueError('%s is not a valid enumeration constant value' % value)
30 return self.__rdict__[value]
31
32 def label(self, value):
33 if value not in self.__rdict__:
34 raise ValueError('%s is not a valid enumeration constant value' % value)
35 return self.__ldict__.get(value) or self.__rdict__.get(value)
36
37 def setlabel(self, value, label):
38 if value not in self.__rdict__:
39 raise ValueError('%s is not a valid enumeration constant value' % value)
40 self.__ldict__[value] = label
41
42 def simpletest():
43 Zakarias = Enum()
44 Zakarias.ANNA = 1
45 Zakarias.BERNHARD = 2
46 Zakarias.CAESAR = 3
47
48 Zakarias.validate(Zakarias.ANNA)
49 Zakarias.validate(Zakarias.BERNHARD)
50 Zakarias.validate(Zakarias.CAESAR)
51
52 assert Zakarias.key(Zakarias.ANNA) == 'ANNA'
53 assert Zakarias.label(Zakarias.BERNHARD) == 'BERNHARD'
54 Zakarias.setlabel(Zakarias.CAESAR, 'Caesar Constant')
55 assert Zakarias.label(Zakarias.CAESAR) == 'Caesar Constant'
56
57 def simpletest2():
58 FoneType = Enum()
59 FoneType.PERSONAL = 1
60 FoneType.HOME = 2
61 FoneType.WORK = 3
62 FoneType.FAX = 4
63
64 class Internationalized(object):
65 defaultlang = 'pt-br'
66 def __str__(self, **args):
67 return super(Internationalized, self).__str__()
68
69 class EnumLabel(Internationalized):
70 def __init__(self, labels):
71 '''labels = {'lang': 'label', ...}'''
72 self.labels = labels
73 def __str__(self, lang=None):
74 return self.labels[lang or self.defaultlang]
75
76 FoneType.setlabel(FoneType.PERSONAL, EnumLabel({'en-us': 'personal', 'pt-br': 'pessoal'}))
77 FoneType.setlabel(FoneType.HOME, EnumLabel({'en-us': 'home', 'pt-br': 'casa'}))
78 FoneType.setlabel(FoneType.WORK, EnumLabel({'en-us': 'work', 'pt-br': 'trabalho'}))
79 FoneType.setlabel(FoneType.FAX, EnumLabel({'en-us': 'fax', 'pt-br': 'fax'}))
80
81 assert str(FoneType.label(FoneType.PERSONAL)) == 'pessoal'
82 assert FoneType.label(FoneType.PERSONAL).__str__(lang='en-us') == 'personal'
83
84 if __name__ == '__main__':
85 simpletest()
86 simpletest2()
Observações
A PEP 354 já define Enumerators.
Uma implementação dessa PEP pode ser vista no Cheeseshop