Source code for pas.parser.types

import __builtin__
from pas.parser import registry, errors
import xdrlib
from collections import namedtuple
from lxml import etree

# pylint: disable-msg=C0103,C0111

[docs]class cls(object): """ Allows to define and automatically register a new POP class. :param id: The classid to which this class will be mapped. :param name: The name to use as string representation of this class. Normally its the original class name. :param methods: The list of methods bound to an instance of this class. :type id: int :type name: ``str`` or ``unicode`` compatible object :type methods: list of :func:`pas.parser.types.func` objects """ def __init__(self, id, name, methods): self.id = id self.name = name self.methods = __builtin__.dict([(m.id, m) for m in methods]) registry.current_registry.register_class(self) def __str__(self): return self.name def getmethod(self, methodid): try: return self.methods[methodid] except KeyError: raise errors.UnknownMethod(self, methodid)
[docs]class exc(cls): """ Allows to define and automatically register a new POP exception type. :param id: The exception ID to which this exception will be mapped. :param name: The name to use as string representation of this exception. Normally its always the original exception name. :param properties: The list of properties bound to an instance of this exception. :type id: int :type name: ``str`` or ``unicode`` compatible object :type properties: list of POP Parser DSL types """ def __init__(self, id, name, properties): self.id = id self.name = name self.properties = properties registry.current_registry.register_exception(self) def arguments(self, decoder): return [p(decoder) for p in self.properties]
[docs]class func(object): """ Allows to define a new POP method bound to a specific class instance. The method itself will never know to which class it belongs; to bind a method to a class insert it in the ``methods`` argument at class declaration time. :param id: The method ID to which this method will be mapped. :param name: The name to use as string representation of this method. Normally its always the original method name. :param args: A list of arguments taken by this method. The provided types will be directly used to decode the payload. Any built-in or custom defined scalar or complex type is accepted. :param retypes: A list of types of the values returned by this method. The provided types will be directly used to decode the payload. Any built-in or custom defined scalar or complex type is accepted. Note that an ``[out]`` argument will be present in the POP response and shall thus be inserted into the ``retypes`` list. :type id: int :type name: ``str`` or ``unicode`` compatible object :type args: list of POP Parser DSL types :type retypes: list of POP Parser DSL types """ def __init__(self, id, name, args, retypes): self.id = id self.name = name self.retypes = retypes self.args = args def toxml(self): el = etree.Element('method') attrs = el.attrib attrs['id'] = str(self.id) attrs['name'] = self.name return el def __str__(self): return self.name def arguments(self, decoder): return [a(decoder) for a in self.args] def result(self, decoder): return [r(decoder) for r in self.retypes]
def string(stream): return stream.unpack_string()[:-1] def uint(stream): return stream.unpack_uint() def int(stream): return stream.unpack_int() def popbool(stream): """ The POP-C++ implementation doesn't encode booleans as defined by the RFC. This alternate implementation provides a workaround. """ return __builtin__.bool(stream.unpack_int() & 0xff000000) def bool(stream): return stream.unpack_bool() def float(stream): return stream.unpack_float()
[docs]def compound(name, *parts): """ Creates a new compound type consisting of different parts. The parts are specified by the ``parts`` argument and read one adter the other from the POP payload. :param name: The name to give to the new type, used when pretty printing the value. :param parts: The actual definition of the compound type. :type parts: list of ``(name, type)`` tuples Use it like this:: NewType = compound('NewTypeName', ('member_1', string), ('member_2', int), ('member_3', float) # ... ) """ model = namedtuple(name, ' '.join(p[0] for p in parts)) def decoder(stream): return model(**__builtin__.dict([(name, type(stream)) for name, type in parts])) return decoder
[docs]def dict(key, value): """ Creates a new complex type mapping keys to values. All keys will share the same value type and so will all values. :param key: The type to use to decode the key. :param value: The type to use to decode the value. Use it like this:: # SomeCompoundType.dict_member will hold a mapping of strings to integers SomeCompoundType = compound('SomeCompountTypeName', # ...other members... ('dict_member', dict(string, float)), ) """ def decoder(stream): return __builtin__.dict([(key(stream), value(stream)) for i in range(int(stream))]) return decoder
[docs]def array(type): """ Creates a new complex type representing a length prefixed array of homogeneous items. :param type: The type of each item in the array. Use it like this:: # SomeCompoundType.array_member will hold a variable length array of ints SomeCompoundType = compound('SomeCompountTypeName', # ...other members... ('array_member', array(int)), ) """ # Work around to the standard xdrlib to provide the argument to the type # function as it is not passed by the unpack_farray method of the Unpacker # class. @see xdrlib.py:224 # @todo: Discuss on py-dev about a possible improvement. def unpack(stream): def unpacker(): return type(stream) return stream.unpack_array(unpack_item=unpacker) return unpack
[docs]def optional(type, unpack_bool=popbool): """ Special composer type which allows to declare a structure member as optional. An optional member is member prefixed by a ``bool`` flag; the flag is first read, if it yields ``true``, it means that the value was encoded and it can be read, if it yields ``false``, it means that no value was encoded and the member is skipped. :param type: The type of the optional value. :param unpack_bool: The type to use to decode the boolean flag. Defaults to :c:type:`popbool`, but can be changed to ``bool`` if the encoding is done in an RPC compliant way. :type unpack_bool: callable Use it like this:: # SomeCompoundType.optional_member will hold a string if it was encoded # or None if it was not encoded SomeCompoundType = compound('SomeCompountTypeName', # ...other members... ('optional_member', string), ) """ def unpack(stream): if unpack_bool(stream): return type(stream) else: return None return unpack
accesspoint = compound('AccessPoint', ('endpoint', string) ) NodeInfo = compound('NodeInfo', ('nodeId', string), ('operatingSystem', string), ('power', float), ('cpuSpeed', int), ('memorySize', float), ('networkBandwidth', int), ('diskSpace', int), ('protocol', string), ('encoding', string) ) ExplorationList = array( compound('ListNode', ('nodeId', string), ('visited', array(string)) ) ) ObjectDescription = compound('ObjectDescription', ('power0', float), ('power1', float), ('memory0', float), ('memory1', float), ('bandwidth0', float), ('bandwidth1', float), ('walltime', float), ('manual', int), ('cwd', string), ('search0', int), ('search1', int), ('search2', int), ('url', string), ('user', string), ('core', string), ('arch', string), ('batch', string), ('joburl', string), ('executable', string), ('platforms', string), ('protocol', string), ('encoding', string), ('attributes', dict(string, string)) ) Request = compound('Request', ('uid', string), ('maxHops', int), ('nodeId', optional(string)), ('operatingSystem', optional(string)), ('minCpuSpeed', optional(int)), ('hasExpectedCpuSpeedSet', optional(int)), ('minMemorySize', optional(float)), ('expectedMemorySize', optional(float)), ('minNetworkBandwidth', optional(int)), ('expectedNetworkBandwidth', optional(int)), ('minDiskSpace', optional(int)), ('expectedDiskSpace', optional(int)), ('minPower', optional(float)), ('expectedPower', optional(float)), ('protocol', optional(string)), ('encoding', optional(string)), ('explorationList', ExplorationList) ) Response = compound('Response', ('uid', string), ('nodeInfo', NodeInfo), ('explorationList', ExplorationList) ) POPCSearchNode = compound('POPCSearchNode_UnknownSerializationFormat', ('od', ObjectDescription), ('accesspoint', accesspoint), ('refcount', int) ) POPCSearchNodeInfo = compound('POPCSearchNodeInfo', ('nodeId', string), ('operatingSystem', string), ('power', float), ('cpuSpeed', int), ('memorySize', float), ('networkBandwidth', int), ('diskSpace', int), ('protocol', string), ('encoding', string) )