##// END OF EJS Templates
update Session object per review...
MinRK -
Show More
@@ -1,5 +1,12 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 """edited session.py to work with streams, and move msg_type to the header
2 """Session object for building, serializing, sending, and receiving messages in
3 IPython. The Session object supports serialization, HMAC signatures, and
4 metadata on messages.
5
6 Also defined here are utilities for working with Sessions:
7 * A SessionFactory to be used as a base class for configurables that work with
8 Sessions.
9 * A Message object for convenience that allows attribute-access to the msg dict.
3 """
10 """
4 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
5 # Copyright (C) 2010-2011 The IPython Development Team
12 # Copyright (C) 2010-2011 The IPython Development Team
@@ -31,8 +38,7 b' from zmq.utils import jsonapi'
31 from zmq.eventloop.ioloop import IOLoop
38 from zmq.eventloop.ioloop import IOLoop
32 from zmq.eventloop.zmqstream import ZMQStream
39 from zmq.eventloop.zmqstream import ZMQStream
33
40
34 from IPython.config.application import Application
41 from IPython.config.configurable import Configurable, LoggingConfigurable
35 from IPython.config.configurable import Configurable
36 from IPython.utils.importstring import import_item
42 from IPython.utils.importstring import import_item
37 from IPython.utils.jsonutil import extract_dates, squash_dates, date_default
43 from IPython.utils.jsonutil import extract_dates, squash_dates, date_default
38 from IPython.utils.traitlets import CStr, Unicode, Bool, Any, Instance, Set
44 from IPython.utils.traitlets import CStr, Unicode, Bool, Any, Instance, Set
@@ -75,15 +81,11 b' DELIM="<IDS|MSG>"'
75 # Classes
81 # Classes
76 #-----------------------------------------------------------------------------
82 #-----------------------------------------------------------------------------
77
83
78 class SessionFactory(Configurable):
84 class SessionFactory(LoggingConfigurable):
79 """The Base class for configurables that have a Session, Context, logger,
85 """The Base class for configurables that have a Session, Context, logger,
80 and IOLoop.
86 and IOLoop.
81 """
87 """
82
88
83 log = Instance('logging.Logger')
84 def _log_default(self):
85 return Application.instance().log
86
87 logname = Unicode('')
89 logname = Unicode('')
88 def _logname_changed(self, name, old, new):
90 def _logname_changed(self, name, old, new):
89 self.log = logging.getLogger(new)
91 self.log = logging.getLogger(new)
@@ -161,8 +163,48 b' def extract_header(msg_or_header):'
161 return h
163 return h
162
164
163 class Session(Configurable):
165 class Session(Configurable):
164 """tweaked version of IPython.zmq.session.Session, for development in Parallel"""
166 """Object for handling serialization and sending of messages.
167
168 The Session object handles building messages and sending them
169 with ZMQ sockets or ZMQStream objects. Objects can communicate with each
170 other over the network via Session objects, and only need to work with the
171 dict-based IPython message spec. The Session will handle
172 serialization/deserialization, security, and metadata.
173
174 Sessions support configurable serialiization via packer/unpacker traits,
175 and signing with HMAC digests via the key/keyfile traits.
176
177 Parameters
178 ----------
179
180 debug : bool
181 whether to trigger extra debugging statements
182 packer/unpacker : str : 'json', 'pickle' or import_string
183 importstrings for methods to serialize message parts. If just
184 'json' or 'pickle', predefined JSON and pickle packers will be used.
185 Otherwise, the entire importstring must be used.
186
187 The functions must accept at least valid JSON input, and output *bytes*.
188
189 For example, to use msgpack:
190 packer = 'msgpack.packb', unpacker='msgpack.unpackb'
191 pack/unpack : callables
192 You can also set the pack/unpack callables for serialization directly.
193 session : bytes
194 the ID of this Session object. The default is to generate a new UUID.
195 username : unicode
196 username added to message headers. The default is to ask the OS.
197 key : bytes
198 The key used to initialize an HMAC signature. If unset, messages
199 will not be signed or checked.
200 keyfile : filepath
201 The file containing a key. If this is set, `key` will be initialized
202 to the contents of the file.
203
204 """
205
165 debug=Bool(False, config=True, help="""Debug output in the Session""")
206 debug=Bool(False, config=True, help="""Debug output in the Session""")
207
166 packer = Unicode('json',config=True,
208 packer = Unicode('json',config=True,
167 help="""The name of the packer for serializing messages.
209 help="""The name of the packer for serializing messages.
168 Should be one of 'json', 'pickle', or an import name
210 Should be one of 'json', 'pickle', or an import name
@@ -194,6 +236,7 b' class Session(Configurable):'
194 help="""The UUID identifying this session.""")
236 help="""The UUID identifying this session.""")
195 def _session_default(self):
237 def _session_default(self):
196 return bytes(uuid.uuid4())
238 return bytes(uuid.uuid4())
239
197 username = Unicode(os.environ.get('USER','username'), config=True,
240 username = Unicode(os.environ.get('USER','username'), config=True,
198 help="""Username for the Session. Default is your system username.""")
241 help="""Username for the Session. Default is your system username.""")
199
242
@@ -206,7 +249,6 b' class Session(Configurable):'
206 else:
249 else:
207 self.auth = None
250 self.auth = None
208 auth = Instance(hmac.HMAC)
251 auth = Instance(hmac.HMAC)
209 counters = Instance('collections.defaultdict', (int,))
210 digest_history = Set()
252 digest_history = Set()
211
253
212 keyfile = Unicode('', config=True,
254 keyfile = Unicode('', config=True,
@@ -227,6 +269,38 b' class Session(Configurable):'
227 raise TypeError("unpacker must be callable, not %s"%type(new))
269 raise TypeError("unpacker must be callable, not %s"%type(new))
228
270
229 def __init__(self, **kwargs):
271 def __init__(self, **kwargs):
272 """create a Session object
273
274 Parameters
275 ----------
276
277 debug : bool
278 whether to trigger extra debugging statements
279 packer/unpacker : str : 'json', 'pickle' or import_string
280 importstrings for methods to serialize message parts. If just
281 'json' or 'pickle', predefined JSON and pickle packers will be used.
282 Otherwise, the entire importstring must be used.
283
284 The functions must accept at least valid JSON input, and output
285 *bytes*.
286
287 For example, to use msgpack:
288 packer = 'msgpack.packb', unpacker='msgpack.unpackb'
289 pack/unpack : callables
290 You can also set the pack/unpack callables for serialization
291 directly.
292 session : bytes
293 the ID of this Session object. The default is to generate a new
294 UUID.
295 username : unicode
296 username added to message headers. The default is to ask the OS.
297 key : bytes
298 The key used to initialize an HMAC signature. If unset, messages
299 will not be signed or checked.
300 keyfile : filepath
301 The file containing a key. If this is set, `key` will be
302 initialized to the contents of the file.
303 """
230 super(Session, self).__init__(**kwargs)
304 super(Session, self).__init__(**kwargs)
231 self._check_packers()
305 self._check_packers()
232 self.none = self.pack({})
306 self.none = self.pack({})
@@ -290,6 +364,14 b' class Session(Configurable):'
290 return h.hexdigest()
364 return h.hexdigest()
291
365
292 def serialize(self, msg, ident=None):
366 def serialize(self, msg, ident=None):
367 """Serialize the message components to bytes.
368
369 Returns
370 -------
371
372 list of bytes objects
373
374 """
293 content = msg.get('content', {})
375 content = msg.get('content', {})
294 if content is None:
376 if content is None:
295 content = self.none
377 content = self.none
@@ -335,8 +417,8 b' class Session(Configurable):'
335 stream : zmq.Socket or ZMQStream
417 stream : zmq.Socket or ZMQStream
336 the socket-like object used to send the data
418 the socket-like object used to send the data
337 msg_or_type : str or Message/dict
419 msg_or_type : str or Message/dict
338 Normally, msg_or_type will be a msg_type unless a message is being sent more
420 Normally, msg_or_type will be a msg_type unless a message is being
339 than once.
421 sent more than once.
340
422
341 content : dict or None
423 content : dict or None
342 the content of the message (ignored if msg_or_type is a message)
424 the content of the message (ignored if msg_or_type is a message)
@@ -436,9 +518,8 b' class Session(Configurable):'
436 return None,None
518 return None,None
437 else:
519 else:
438 raise
520 raise
439 # return an actual Message object
521 # split multipart message into identity list and message dict
440 # determine the number of idents by trying to unpack them.
522 # invalid large messages can cause very expensive string comparisons
441 # this is terrible:
442 idents, msg = self.feed_identities(msg, copy)
523 idents, msg = self.feed_identities(msg, copy)
443 try:
524 try:
444 return idents, self.unpack_message(msg, content=content, copy=copy)
525 return idents, self.unpack_message(msg, content=content, copy=copy)
@@ -448,8 +529,9 b' class Session(Configurable):'
448 raise e
529 raise e
449
530
450 def feed_identities(self, msg, copy=True):
531 def feed_identities(self, msg, copy=True):
451 """feed until DELIM is reached, then return the prefix as idents and remainder as
532 """feed until DELIM is reached, then return the prefix as idents and
452 msg. This is easily broken by setting an IDENT to DELIM, but that would be silly.
533 remainder as msg. This is easily broken by setting an IDENT to DELIM,
534 but that would be silly.
453
535
454 Parameters
536 Parameters
455 ----------
537 ----------
@@ -536,3 +618,4 b' def test_msg2obj():'
536 am2 = dict(ao)
618 am2 = dict(ao)
537 assert am['x'] == am2['x']
619 assert am['x'] == am2['x']
538 assert am['y']['z'] == am2['y']['z']
620 assert am['y']['z'] == am2['y']['z']
621
General Comments 0
You need to be logged in to leave comments. Login now