SF.net SVN: fclient: [372] trunk/sandbox/fcp2/fcp_lib/pmstruct.py
Status: Pre-Alpha
Brought to you by:
jurner
|
From: <jU...@us...> - 2008-04-08 10:07:33
|
Revision: 372
http://fclient.svn.sourceforge.net/fclient/?rev=372&view=rev
Author: jUrner
Date: 2008-04-08 03:07:36 -0700 (Tue, 08 Apr 2008)
Log Message:
-----------
poor mans struct to handle persistent data
Added Paths:
-----------
trunk/sandbox/fcp2/fcp_lib/pmstruct.py
Added: trunk/sandbox/fcp2/fcp_lib/pmstruct.py
===================================================================
--- trunk/sandbox/fcp2/fcp_lib/pmstruct.py (rev 0)
+++ trunk/sandbox/fcp2/fcp_lib/pmstruct.py 2008-04-08 10:07:36 UTC (rev 372)
@@ -0,0 +1,140 @@
+"""Poor mans structure
+
+
+
+"""
+
+import base64
+#****************************************************************************
+#
+#****************************************************************************
+Str = (base64.b64decode, base64.b64encode, (str, unicode))
+Int = (int, str, int)
+Float = (float, float)
+
+
+
+class PoorMansStruct(object):
+ """Poor mans structure
+
+ Converts a maping to a string and vice versa
+
+
+ Subclasses must define a _fields_ attribute wich is a mapping from field name
+ to conversion methods (fieldName, (getter, setter, fieldType)). getter() should convert
+ the fields value to the desired python type, setter should convert the python
+ type to string. Both will be called with one argument: the value to convert
+ and should rasise if the value can not be converted. fieldType is the data type
+ expected on mappping conversion.
+
+ For convenience the module defines some standard types like Int, Float
+ and String.
+
+ >>> class S(PoorMansStruct):
+ ... _fields_ = [
+ ... ('Foo', (int, str, int)),
+ ... ('Bar', Str),
+ ... ]
+
+ To convert a mapping to a string, call toString() with the mapping to convert
+ >>> p = S.toString({'Foo': 123456, 'Bar': 'abcdefg'})
+ >>> p
+ '123456\\x01YWJjZGVmZw=='
+
+ To convert a string to a mapping call fromString() with the string to convert
+ >>> d = S.fromString(p)
+ >>> sorted(d.items())
+ [('Bar', 'abcdefg'), ('Foo', 123456)]
+
+
+ Field names must corrospond to mapping names
+ >>> p = S.toString({'IAmInvalid': 123456, 'Bar': 'abcdefg'})
+ Traceback (most recent call last):
+ ...
+ KeyError: 'Foo'
+
+
+ All field names must be present in the mapping passed
+ >>> p = S.toString({'Bar': 'abcdefg'})
+ Traceback (most recent call last):
+ ...
+ KeyError: 'Foo'
+
+ types of the mapping have to corrospond to field types
+ >>> p = S.toString({'Foo': 'invalid-int', 'Bar': 'abcdefg'})
+ Traceback (most recent call last):
+ ...
+ ValueError: Invalid type for field "Foo, expected: <type 'int'>"
+
+ invalid field types are detected on converting the string back to a mapping
+ >>> p = 'invalid-int\\x01YWJjZGVmZw=='
+ >>> S.fromString(p)
+ Traceback (most recent call last):
+ ...
+ ValueError: Invalid field #0: (invalid literal for int() with base 10: 'invalid-int')
+
+ too few fields in the input strig will be recognized
+ >>> p = 'YWJjZGVmZw=='
+ >>> S.fromString(p)
+ Traceback (most recent call last):
+ ...
+ ValueError: Too few fields in input string
+
+ ...aswell as too many
+ >>> p = '999\x01123456\x01YWJjZGVmZw=='
+ >>> S.fromString(p)
+ Traceback (most recent call last):
+ ...
+ ValueError: Too many fields in input string
+ """
+
+ _sep_ = '\x01'
+ _fields_ = []
+
+
+ @classmethod
+ def fromString(klass, string):
+ params = string.split(klass._sep_)
+ if len(params) > len(klass._fields_):
+ raise ValueError('Too many fields in input string')
+ if len(params) < len(klass._fields_):
+ raise ValueError('Too few fields in input string')
+ out = {}
+ for n, (fieldName, (getter, setter, fieldType)) in enumerate(klass._fields_):
+ try:
+ out[fieldName] = getter(params[n])
+ except Exception, details:
+ raise ValueError('Invalid field #%s: (%s)' % (n, details))
+ return out
+
+ @classmethod
+ def toString(klass, mapping):
+ out = []
+ for n, (fieldName, (getter, setter, fieldType)) in enumerate(klass._fields_):
+ value = mapping[fieldName]
+ if not isinstance(value, fieldType):
+ raise ValueError('Invalid type for field "%s, expected: %s"' % (fieldName, fieldType))
+ try:
+ value = setter(value)
+ assert isinstance(value, str)
+ out.append(value)
+ except Exception, details:
+ raise ValueError('Invalid field "%s": (%s)' % (fieldName, details))
+ return klass._sep_.join(out)
+
+
+"""
+class PersistentParams(PoorMansStruct):
+ _fields_ = [
+ ('Flags', PoorMansStruct.Int),
+ ('InitTime', PoorMansStruct.Float),
+ ('PerisitstentUserData', PoorMansStruct.Str),
+ ]
+"""
+#****************************************************************************
+#
+#****************************************************************************
+if __name__ == '__main__':
+ import doctest
+ print 'doctests failed: %s/%s' % doctest.testmod()
+
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|