Package flumotion :: Package common :: Module enum
[hide private]

Source Code for Module flumotion.common.enum

  1  # -*- Mode: Python; test-case-name: flumotion.test.test_enum -*- 
  2  # vi:si:et:sw=4:sts=4:ts=4 
  3   
  4  # Flumotion - a streaming media server 
  5  # Copyright (C) 2004,2005,2006,2007,2008,2009 Fluendo, S.L. 
  6  # Copyright (C) 2010,2011 Flumotion Services, S.A. 
  7  # All rights reserved. 
  8  # 
  9  # This file may be distributed and/or modified under the terms of 
 10  # the GNU Lesser General Public License version 2.1 as published by 
 11  # the Free Software Foundation. 
 12  # This file is distributed without any warranty; without even the implied 
 13  # warranty of merchantability or fitness for a particular purpose. 
 14  # See "LICENSE.LGPL" in the source distribution for more information. 
 15  # 
 16  # Headers in this file shall remain intact. 
 17   
 18  """simple enum and implementation 
 19  """ 
 20   
 21  from twisted.python.reflect import qual 
 22  from twisted.spread import jelly 
 23   
 24  __version__ = "$Rev$" 
 25  _enumClassRegistry = {} 
 26   
 27   
28 -class EnumMetaClass(type):
29 # pychecker likes this attribute to be there since we use it in this class 30 __enums__ = {} 31
32 - def __len__(self):
33 return len(self.__enums__)
34
35 - def __getitem__(self, value):
36 try: 37 return self.__enums__[value] 38 except KeyError: 39 raise StopIteration
40
41 - def __setitem__(self, value, enum):
42 self.__enums__[value] = enum 43 setattr(self, enum.name, enum)
44 45
46 -class Enum(object, jelly.Jellyable):
47 48 __metaclass__ = EnumMetaClass 49
50 - def __init__(self, value, name, nick=None):
51 self.value = value 52 self.name = name 53 54 if nick == None: 55 nick = name 56 57 self.nick = nick 58 self._enumClassName = self.__class__.__name__
59
60 - def __repr__(self):
61 return '<enum %s of type %s>' % (self.name, 62 self.__class__.__name__)
63
64 - def get(klass, value):
65 return klass.__enums__[value]
66 get = classmethod(get) 67
68 - def set(klass, value, item):
69 klass[value] = item
70 set = classmethod(set) 71
72 - def jellyFor(self, jellier):
73 sxp = jellier.prepare(self) 74 sxp.extend([ 75 qual(Enum), 76 self._enumClassName, 77 self.value, self.name, self.nick]) 78 return jellier.preserve(self, sxp)
79 80
81 -class EnumClass(object):
82
83 - def __new__(klass, type_name, names=(), nicks=(), **extras):
84 if nicks: 85 if len(names) != len(nicks): 86 raise TypeError("nicks must have the same length as names") 87 else: 88 nicks = names 89 90 for extra in extras.values(): 91 if not isinstance(extra, (tuple, list)): 92 raise TypeError( 93 'extra must be a sequence, not %s' % type(extra)) 94 95 if len(extra) != len(names): 96 raise TypeError("extra items must have a length of %d" % 97 len(names)) 98 99 # we reset __enums__ to {} otherwise it retains the other registered 100 # ones 101 etype = EnumMetaClass(type_name, (Enum, ), {'__enums__': {}}) 102 for value, name in enumerate(names): 103 enum = etype(value, name, nicks[value]) 104 for extra_key, extra_values in extras.items(): 105 assert not hasattr(enum, extra_key) 106 setattr(enum, extra_key, extra_values[value]) 107 etype[value] = enum 108 109 _enumClassRegistry[type_name] = etype 110 return etype
111 112 113 # Enum unjellyer should not be a new style class, 114 # otherwise Twsited 2.0.1 will not recognise it. 115 116
117 -class EnumUnjellyer(jelly.Unjellyable):
118
119 - def unjellyFor(self, unjellier, jellyList):
120 enumClassName, value, name, nick = jellyList[1:] 121 enumClass = _enumClassRegistry.get(enumClassName, None) 122 if enumClass: 123 # Retrieve the enum singleton 124 enum = enumClass.get(value) 125 assert enum.name == name, "Inconsistent Enum Name" 126 else: 127 # Create a generic Enum container 128 enum = Enum(value, name, nick) 129 enum._enumClassName = enumClassName 130 return enum
131 132 133 jelly.setUnjellyableForClass(qual(Enum), EnumUnjellyer) 134