""" @file helpers.py @date 2009-02-05 Contributors can be viewed at: http://svn.secondlife.com/svn/linden/projects/2008/pyogp/CONTRIBUTORS.txt $LicenseInfo:firstyear=2008&license=apachev2$ Copyright 2008, Linden Research, Inc. Licensed under the Apache License, Version 2.0 (the "License"). You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 or in http://svn.secondlife.com/svn/linden/projects/2008/pyogp/LICENSE.txt $/LicenseInfo$ """ # standard python libs from logging import getLogger, CRITICAL, ERROR, WARNING, INFO, DEBUG # related from indra.base import llsd # pyogp from pyogp.lib.base.exc import DataParsingError, DeserializationFailed # initialize loggin logger = getLogger('...utilities.helpers') log = logger.log class Helpers(object): """ contains useful helper functions """ def bytes_to_hex(self, data): """ converts bytes to hex format """ #from binascii import hexlify #return hex_string #hex_string = hexlify(data) return ''.join(["%02X " % ord(x) for x in data]).strip() def bytes_to_ascii(self, data): " converts bytes to ascii format " from binascii import b2a_uu ascii_string = b2a_uu(data) return ascii_string def hex_to_ascii(self, data): " converts bytes to ascii format " from binascii import unhexlify try: ascii_string = unhexlify(data) except TypeError, error: raise DataParsingError('hex_to_ascii failure: \'%s\': processing data: \'%s\'' % (error, data)) return ascii_string def bytes_to_base64(self, data): " converts bytes to ascii format " from binascii import b2a_base64 base64_string = b2a_base64(data) return base64_string # ~~~~~~~~~ # Callbacks # ~~~~~~~~~ def log_packet(self, packet, _object): """ default logging function for packets """ log(INFO, "Object %s is monitoring packet type %s: \n%s" % (type(_object), packet.name, packet.data())) def log_event_queue_data(self, data, _object): """ default logging function for event queue data events """ log(INFO, "Object %s is monitoring event queue data event %s: \n%s" % (type(_object), data.name, data.__dict__)) def null_packet_handler(self, packet, _object): """ just a null event handler for watching aka fully parsing specific packets """ pass class ListLLSDSerializer(object): """adapter for serializing a list to LLSD An example: >>> d=['ChatSessionRequest', 'CopyInventoryFromNotecard'] >>> serializer = ListLLSDSerializer(d) >>> serializer.serialize() 'ChatSessionRequestCopyInventoryFromNotecard' >>> serializer.content_type 'application/llsd+xml' """ def __init__(self, context): self.context = context def serialize(self): """convert the payload to LLSD""" return llsd.format_xml(self.context) @property def content_type(self): """return the content type of this serializer""" return "application/llsd+xml" class DictLLSDSerializer(object): """adapter for serializing a dictionary to LLSD An example: >>> d={'foo':'bar', 'test':1234} >>> serializer = DictLLSDSerializer(d) >>> serializer.serialize() 'test1234foobar' >>> serializer.content_type 'application/llsd+xml' """ def __init__(self, context): self.context = context def serialize(self): """convert the payload to LLSD""" return llsd.format_xml(self.context) @property def content_type(self): """return the content type of this serializer""" return "application/llsd+xml" class LLSDDeserializer(object): """utility for deserializing LLSD data The deserialization component is defined as a utility because the input data can be a string or a file. It might be possible to define this as an adapter on a string but a string is too generic for this. So that's why it is a utility. You can use it like this: >>> s='test1234foobar' We use queryUtility because this returns None instead of an exception when a utility is not registered. We use the content type we received as the name of the utility. Another option would of course be to subclas string to some LLSDString class and use an adapter. We then would need some factory for generating the LLSDString class from whatever came back from the HTTP call. So here is how you use that utility: >>> deserializer = LLSDDeserializer() >>> llsd = deserializer.deserialize(s) >>> llsd {'test': 1234, 'foo': 'bar'} We can also test this with some non-LLSD string: >>> llsd = deserializer.deserialize_string('mumpitz') # this is not LLSD Traceback (most recent call last): ... DeserializationFailed: deserialization failed for 'mumpitz', reason: 'invalid token at index 0: 109' >>> llsd = deserializer.deserialize_string('barfoo') Traceback (most recent call last): ... DeserializationFailed: deserialization failed for 'barfoo', reason: 'binary notation not yet supported' """ def deserialize(self, data): """ convenience class to handle a variety of inputs """ if type(data) == str: return self.deserialize_string(data) # won't handle another case until we need to def deserialize_string(self, data): """ deserialize a string """ try: r = llsd.parse(data) except llsd.LLSDParseError, e: raise DeserializationFailed(data, str(e)) if r==False: raise DeserializationFailed(data, 'result was False') return r def deserialize_file(self, fp): """ deserialize a file """ data = fp.read() return self.deserialize_string(data)