SF.net SVN: fclient:[689] trunk/fclient/src/fclient/lib/fcp2/lib/pmstruct. py
Status: Pre-Alpha
Brought to you by:
jurner
From: <jU...@us...> - 2008-07-20 10:34:07
|
Revision: 689 http://fclient.svn.sourceforge.net/fclient/?rev=689&view=rev Author: jUrner Date: 2008-07-20 10:34:07 +0000 (Sun, 20 Jul 2008) Log Message: ----------- support for persistent params handling Added Paths: ----------- trunk/fclient/src/fclient/lib/fcp2/lib/pmstruct.py Added: trunk/fclient/src/fclient/lib/fcp2/lib/pmstruct.py =================================================================== --- trunk/fclient/src/fclient/lib/fcp2/lib/pmstruct.py (rev 0) +++ trunk/fclient/src/fclient/lib/fcp2/lib/pmstruct.py 2008-07-20 10:34:07 UTC (rev 689) @@ -0,0 +1,215 @@ +"""poor mans struct + +simple structure with (safe) serializing support + + +@requires: python >= 2.5 (L is never removed from str(nL) ) +""" + +import base64 +#******************************************************************* +# +#******************************************************************* +class PMStructError(Exception): pass + +SEP = '|' +HEADER = 'PMS' + +class BOOL(object): + _typecode_ = 'B' + @classmethod + def default(clss): + return False + @classmethod + def from_data(clss, data): + if data: + typecode, data = data[ :1], data [ 1: ] + if typecode == clss._typecode_: + try: + return data == '1' + except: pass + raise PMStructError('invalid bool') + @classmethod + def to_data(clss, value): + return clss._typecode_ + ('1' if value else '0') + @classmethod + def is_type(self, value): + return type(value) is bool + + +class FLOAT(object): + _typecode_ = 'F' + @classmethod + def default(clss): + return 0.0 + @classmethod + def from_data(clss, data): + if data: + typecode, data = data[ :1], data [ 1: ] + if typecode == clss._typecode_: + try: + return float(data) + except: pass + raise PMStructError('invalid int') + @classmethod + def to_data(clss, value): + return clss._typecode_ + str(value) + @classmethod + def is_type(self, value): + return type(value) is float + + +class INT(object): + _typecode_ = 'I' + @classmethod + def default(clss): + return 0 + @classmethod + def from_data(clss, data): + if data: + typecode, data = data[ :1], data [ 1: ] + if typecode == clss._typecode_: + try: + return int(data) + except: pass + raise PMStructError('invalid int') + @classmethod + def to_data(clss, value): + return clss._typecode_ + str(value) + @classmethod + def is_type(self, value): + return type(value) in (int, long) + + +class STRING(object): + _typecode_ = 'S' + @classmethod + def default(clss): + return '' + @classmethod + def from_data(clss, data): + if data: + typecode, data = data[ :1], data [ 1: ] + if typecode == clss._typecode_: + try: + return base64.b64decode(data) + except: pass + raise PMStructError('invalid string') + @classmethod + def to_data(clss, value): + return clss._typecode_ + base64.b64encode(value) + @classmethod + def is_type(self, value): + return type(value) in (str, unicode) + + +class PMStruct(object): + _fields_ = () + + def __init__(self, **kws): + self._fielddict_ = dict(self._fields_) + self.values = {} + for name, fieldtype in self._fields_: + value = kws.get(name, None) + if value is None: + value = fieldtype.default() + else: + if not fieldtype.is_type(value): + raise TypeError('invalid type for field: %r' % name) + del kws[name] + self.values[name] = value + if kws: + raise ValueError('no such field: %r' % kws.keys()[0]) + + + def __getitem__(self, name): + return self.values[name] + + def __setitem__(self, name, value): + fieldtype = self._fielddict_ [name] + if not fieldtype.is_type(value): + raise TypeError('invalid type for field: %r' % name) + self.values[name] = value + + + def __str__(self): + return self.__repr__() + + def __repr__(self): + return '<PMS' + repr(self.values) + '>' + + @classmethod + def load(clss, data): + data = data.split(SEP, 1) + if len(data) != 2: + raise PMStructError('invalid data') + header, data = data + if header != HEADER: + raise PMStructError('invalid data header') + #data = base64.b64decode(data) + data = data.split(SEP) + if len(data) != len(clss._fields_): + raise PMStructError('too few or too many fields') + kws = {} + for i, (name, fieldtype) in enumerate(clss._fields_): + kws[name] = fieldtype.from_data(data[i]) + return clss(**kws) + + def dump(self): + p = [] + for name, fieldtype in self._fields_: + value = fieldtype.to_data(self.values[name]) + p.append(value) + data = SEP.join(p) + #data = base64.b64encode(data) + return HEADER + SEP + data + + + +def foo(): + class PersistentParamsGet(PMStruct): + _fields_ = ( + ('Version', INT), + ('InitTime', FLOAT), + ('PersistentUserData', STRING), + ('HandleFilenameCollision', BOOL), + ('FilenameCollisionHandled', BOOL), + ('HandlePermanentRedirect', BOOL), + ('PermanentRedirectHandled', BOOL), + ) + + + p = PersistentParamsGet() + print p.dump() + print p + +#foo() +#print {1: 1, 2: 2} +#print repr({1: 1, 2: 2}) + +def test(): + + class MyStruct(PMStruct): + _fields_ = ( + ('Foo', INT), + ('Bar', BOOL), + ('Baz', STRING), + ('Muu', FLOAT) + ) + + + + p = MyStruct(Foo=100000000000L, Bar=True, Baz=u'abcdefg', Muu=1.2345678) + x = p.dump() + print x + print p.load(x) + print p['Foo'] + print p['Bar'] + print p['Baz'] + print p['Muu'] + + p['Muu'] = 123 + + + + This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |