##// END OF EJS Templates
update Session object per review...
MinRK -
Show More
@@ -1,5 +1,12 b''
1 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 12 # Copyright (C) 2010-2011 The IPython Development Team
@@ -31,8 +38,7 b' from zmq.utils import jsonapi'
31 38 from zmq.eventloop.ioloop import IOLoop
32 39 from zmq.eventloop.zmqstream import ZMQStream
33 40
34 from IPython.config.application import Application
35 from IPython.config.configurable import Configurable
41 from IPython.config.configurable import Configurable, LoggingConfigurable
36 42 from IPython.utils.importstring import import_item
37 43 from IPython.utils.jsonutil import extract_dates, squash_dates, date_default
38 44 from IPython.utils.traitlets import CStr, Unicode, Bool, Any, Instance, Set
@@ -75,15 +81,11 b' DELIM="<IDS|MSG>"'
75 81 # Classes
76 82 #-----------------------------------------------------------------------------
77 83
78 class SessionFactory(Configurable):
84 class SessionFactory(LoggingConfigurable):
79 85 """The Base class for configurables that have a Session, Context, logger,
80 86 and IOLoop.
81 87 """
82 88
83 log = Instance('logging.Logger')
84 def _log_default(self):
85 return Application.instance().log
86
87 89 logname = Unicode('')
88 90 def _logname_changed(self, name, old, new):
89 91 self.log = logging.getLogger(new)
@@ -161,8 +163,48 b' def extract_header(msg_or_header):'
161 163 return h
162 164
163 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 206 debug=Bool(False, config=True, help="""Debug output in the Session""")
207
166 208 packer = Unicode('json',config=True,
167 209 help="""The name of the packer for serializing messages.
168 210 Should be one of 'json', 'pickle', or an import name
@@ -194,6 +236,7 b' class Session(Configurable):'
194 236 help="""The UUID identifying this session.""")
195 237 def _session_default(self):
196 238 return bytes(uuid.uuid4())
239
197 240 username = Unicode(os.environ.get('USER','username'), config=True,
198 241 help="""Username for the Session. Default is your system username.""")
199 242
@@ -206,7 +249,6 b' class Session(Configurable):'
206 249 else:
207 250 self.auth = None
208 251 auth = Instance(hmac.HMAC)
209 counters = Instance('collections.defaultdict', (int,))
210 252 digest_history = Set()
211 253
212 254 keyfile = Unicode('', config=True,
@@ -227,6 +269,38 b' class Session(Configurable):'
227 269 raise TypeError("unpacker must be callable, not %s"%type(new))
228 270
229 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 304 super(Session, self).__init__(**kwargs)
231 305 self._check_packers()
232 306 self.none = self.pack({})
@@ -290,6 +364,14 b' class Session(Configurable):'
290 364 return h.hexdigest()
291 365
292 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 375 content = msg.get('content', {})
294 376 if content is None:
295 377 content = self.none
@@ -335,8 +417,8 b' class Session(Configurable):'
335 417 stream : zmq.Socket or ZMQStream
336 418 the socket-like object used to send the data
337 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
339 than once.
420 Normally, msg_or_type will be a msg_type unless a message is being
421 sent more than once.
340 422
341 423 content : dict or None
342 424 the content of the message (ignored if msg_or_type is a message)
@@ -436,9 +518,8 b' class Session(Configurable):'
436 518 return None,None
437 519 else:
438 520 raise
439 # return an actual Message object
440 # determine the number of idents by trying to unpack them.
441 # this is terrible:
521 # split multipart message into identity list and message dict
522 # invalid large messages can cause very expensive string comparisons
442 523 idents, msg = self.feed_identities(msg, copy)
443 524 try:
444 525 return idents, self.unpack_message(msg, content=content, copy=copy)
@@ -448,8 +529,9 b' class Session(Configurable):'
448 529 raise e
449 530
450 531 def feed_identities(self, msg, copy=True):
451 """feed until DELIM is reached, then return the prefix as idents and remainder as
452 msg. This is easily broken by setting an IDENT to DELIM, but that would be silly.
532 """feed until DELIM is reached, then return the prefix as idents and
533 remainder as msg. This is easily broken by setting an IDENT to DELIM,
534 but that would be silly.
453 535
454 536 Parameters
455 537 ----------
@@ -536,3 +618,4 b' def test_msg2obj():'
536 618 am2 = dict(ao)
537 619 assert am['x'] == am2['x']
538 620 assert am['y']['z'] == am2['y']['z']
621
General Comments 0
You need to be logged in to leave comments. Login now