1 2class EnumValue(object): 3 def __init__(self, value, name=None): 4 self.value = value 5 self.name = name 6 7 def __hash__(self): 8 return self.value 9 10 def __cmp__(self, other): 11 if isinstance(other, EnumValue): 12 return self.value.__cmp__(other.value) 13 else: 14 return self.value.__cmp__(other) 15 16 def __unicode__(self): 17 return self.name 18 19 def __str__(self): 20 return self.name 21 22 def __repr__(self): 23 return self.name 24 25 26class EnumMeta(type): 27 def __init__(self, name, bases, dict_): 28 self.registry = self.registry.copy() 29 self.name_registry = self.name_registry.copy() 30 for k, v in dict_.iteritems(): 31 if isinstance(v, EnumValue) and v not in self.registry: 32 if v.name is None: 33 v.name = k 34 self.registry[v.value] = v 35 self.name_registry[v.name] = v 36 return super(EnumMeta, self).__init__(name, bases, dict_) 37 38 def __iter__(self): 39 return self.registry.itervalues() 40 41 def __getitem__(self, key): 42 return self.registry[key] 43 44 45class Enum(object): 46 __metaclass__ = EnumMeta 47 registry = {} 48 name_registry = {} 49 50 @classmethod 51 def from_id(cls, value): 52 try: 53 return cls.registry[value] 54 except KeyError: 55 raise ValueError('Invalid value for {}: {}'.format(cls.__name__, value)) 56 57 @classmethod 58 def from_string(cls, name): 59 try: 60 return cls.name_registry[name] 61 except KeyError: 62 raise ValueError('Invalid name for {}: {}'.format(cls.__name__, name)) 63