root/projects/2008/pyogp/pyogp.lib.base/trunk/pyogp/lib/base/utilities/helpers.py

Revision 2174, 6.7 kB (checked in by enus.linden, 7 months ago)

merging inventory-extension branch into trunk

Line 
1 # standard python libs
2 from logging import getLogger, CRITICAL, ERROR, WARNING, INFO, DEBUG
3 import time
4
5 # related
6 from indra.base import llsd
7 from eventlet import api
8
9 # pyogp
10 from pyogp.lib.base.exc import DataParsingError, DeserializationFailed
11
12 # initialize loggin
13 logger = getLogger('...utilities.helpers')
14 log = logger.log
15
16 class Helpers(object):
17     """ contains useful helper functions """
18
19     def bytes_to_hex(self, data):
20         """ converts bytes to hex format """
21
22         #from binascii import hexlify
23         #return hex_string
24         #hex_string = hexlify(data)
25         return ''.join(["%02X " % ord(x) for x in data]).strip()
26
27     def bytes_to_ascii(self, data):
28         " converts bytes to ascii format "
29
30         from binascii import b2a_uu
31
32         ascii_string = b2a_uu(data)
33
34         return ascii_string
35
36     def hex_to_ascii(self, data):
37         " converts bytes to ascii format "
38
39         from binascii import unhexlify
40
41         try:
42             ascii_string = unhexlify(data)
43         except TypeError, error:
44             raise DataParsingError('hex_to_ascii failure: \'%s\': processing data: \'%s\'' % (error, data))
45
46         return ascii_string
47
48     def bytes_to_base64(self, data):
49         " converts bytes to ascii format "
50
51         from binascii import b2a_base64
52
53         base64_string = b2a_base64(data)
54
55         return base64_string
56
57     # ~~~~~~~~~
58     # Callbacks
59     # ~~~~~~~~~
60
61     def log_packet(self, packet, _object):
62         """ default logging function for packets  """
63
64         log(INFO, "Object %s is monitoring packet type %s: \n%s" % (type(_object), packet.name, packet.data()))
65
66     def log_event_queue_data(self, data, _object):
67         """ default logging function for event queue data events  """
68
69         log(INFO, "Object %s is monitoring event queue data event %s: \n%s" % (type(_object), data.name, data.__dict__))
70
71     def null_packet_handler(self, packet, _object):
72         """ just a null event handler for watching aka fully parsing specific packets """
73
74         pass
75
76 class ListLLSDSerializer(object):
77     """adapter for serializing a list to LLSD
78
79     An example:
80     >>> d=['ChatSessionRequest', 'CopyInventoryFromNotecard']
81     >>> serializer = ListLLSDSerializer(d)
82     >>> serializer.serialize()
83     '<?xml version="1.0" ?><llsd><array><string>ChatSessionRequest</string><string>CopyInventoryFromNotecard</string></array></llsd>'
84     >>> serializer.content_type
85     'application/llsd+xml'
86
87     """
88
89     def __init__(self, context):
90         self.context = context
91
92     def serialize(self):
93         """convert the payload to LLSD"""
94         return llsd.format_xml(self.context)
95
96     @property
97     def content_type(self):
98         """return the content type of this serializer"""
99         return "application/llsd+xml"
100
101
102 class DictLLSDSerializer(object):
103     """adapter for serializing a dictionary to LLSD
104
105     An example:
106     >>> d={'foo':'bar', 'test':1234}
107     >>> serializer = DictLLSDSerializer(d)
108     >>> serializer.serialize()
109     '<?xml version="1.0" ?><llsd><map><key>test</key><integer>1234</integer><key>foo</key><string>bar</string></map></llsd>'
110     >>> serializer.content_type
111     'application/llsd+xml'
112
113     """
114
115     def __init__(self, context):
116         self.context = context
117
118     def serialize(self):
119         """convert the payload to LLSD"""
120         return llsd.format_xml(self.context)
121
122     @property
123     def content_type(self):
124         """return the content type of this serializer"""
125         return "application/llsd+xml"
126
127 class LLSDDeserializer(object):
128     """utility for deserializing LLSD data
129
130     The deserialization component is defined as a utility because the input
131     data can be a string or a file. It might be possible to define this as
132     an adapter on a string but a string is too generic for this. So that's
133     why it is a utility.
134
135     You can use it like this:
136
137     >>> s='<?xml version="1.0" ?><llsd><map><key>test</key><integer>1234</integer><key>foo</key><string>bar</string></map></llsd>'
138
139     We use queryUtility because this returns None instead of an exception
140     when a utility is not registered. We use the content type we received
141     as the name of the utility. Another option would of course be to subclas
142     string to some LLSDString class and use an adapter. We then would need some
143     factory for generating the LLSDString class from whatever came back from
144     the HTTP call.
145
146     So here is how you use that utility:
147     >>> deserializer = LLSDDeserializer()
148     >>> llsd = deserializer.deserialize(s)
149     >>> llsd
150     {'test': 1234, 'foo': 'bar'}
151
152     We can also test this with some non-LLSD string:
153
154     >>> llsd = deserializer.deserialize_string('mumpitz')   # this is not LLSD
155     Traceback (most recent call last):
156     ...
157     DeserializationFailed: deserialization failed for 'mumpitz', reason: 'invalid token at index 0: 109'
158
159     >>> llsd = deserializer.deserialize_string('barfoo')
160     Traceback (most recent call last):
161     ...
162     DeserializationFailed: deserialization failed for 'barfoo', reason: 'binary notation not yet supported'
163
164
165     """
166
167     def deserialize(self, data):
168         """ convenience class to handle a variety of inputs """
169
170         if type(data) == str:
171             return self.deserialize_string(data)
172         # won't handle another case until we need to
173
174     def deserialize_string(self, data):
175         """ deserialize a string """
176
177         try:
178             r = llsd.parse(data)
179         except llsd.LLSDParseError, e:
180             raise DeserializationFailed(data, str(e))
181         if r==False:
182             raise DeserializationFailed(data, 'result was False')
183         return r
184
185     def deserialize_file(self, fp):
186         """ deserialize a file """
187         data = fp.read()
188         return self.deserialize_string(data)
189
190 class Wait(object):
191     """ a simple timer that blocks a calling routine for the specified number of seconds
192
193     done since we were writing timing loops in test scripts repeatedly
194     returns True when it's done
195      """
196
197     def __init__(self, duration):
198
199         self.duration = int(duration)
200
201         # let's be nice and enabled a kill switch
202         self.enabled = False
203
204         self.run()
205
206     def run(self):
207
208         now = time.time()
209         start = now
210         self.enabled = True
211
212         while self.enabled and now - start < self.duration:
213
214             api.sleep()
215             now = time.time()
216
217         return True
218
219     def stop(self):
220
221         self.enabled = False
222
223 """
224 Contributors can be viewed at:
225 http://svn.secondlife.com/svn/linden/projects/2008/pyogp/CONTRIBUTORS.txt
226
227 $LicenseInfo:firstyear=2008&license=apachev2$
228
229 Copyright 2009, Linden Research, Inc.
230
231 Licensed under the Apache License, Version 2.0 (the "License").
232 You may obtain a copy of the License at:
233     http://www.apache.org/licenses/LICENSE-2.0
234 or in
235     http://svn.secondlife.com/svn/linden/projects/2008/pyogp/LICENSE.txt
236
237 $/LicenseInfo$
238 """
239
Note: See TracBrowser for help on using the browser.