##// END OF EJS Templates
Improvements to exception handling to transport structured tracebacks....
Improvements to exception handling to transport structured tracebacks. This code is still fairly hackish, but we're starting to get there. We still need to improve the api, because right now runlines() does way too much, and I had to set the exception state in a temporary private variable. But client-side things are working better, so we can continue fixing the kernel without bottlenecking Evan.

File last commit:

r2606:f0587bad
r2838:cbe60016
Show More
session.py
122 lines | 3.2 KiB | text/x-python | PythonLexer
import os
import uuid
import pprint
import zmq
class Message(object):
"""A simple message object that maps dict keys to attributes.
A Message can be created from a dict and a dict from a Message instance
simply by calling dict(msg_obj)."""
def __init__(self, msg_dict):
dct = self.__dict__
for k, v in msg_dict.iteritems():
if isinstance(v, dict):
v = Message(v)
dct[k] = v
# Having this iterator lets dict(msg_obj) work out of the box.
def __iter__(self):
return iter(self.__dict__.iteritems())
def __repr__(self):
return repr(self.__dict__)
def __str__(self):
return pprint.pformat(self.__dict__)
def __contains__(self, k):
return k in self.__dict__
def __getitem__(self, k):
return self.__dict__[k]
def msg_header(msg_id, username, session):
return {
'msg_id' : msg_id,
'username' : username,
'session' : session
}
def extract_header(msg_or_header):
"""Given a message or header, return the header."""
if not msg_or_header:
return {}
try:
# See if msg_or_header is the entire message.
h = msg_or_header['header']
except KeyError:
try:
# See if msg_or_header is just the header
h = msg_or_header['msg_id']
except KeyError:
raise
else:
h = msg_or_header
if not isinstance(h, dict):
h = dict(h)
return h
class Session(object):
def __init__(self, username=os.environ.get('USER','username'), session=None):
self.username = username
if session is None:
self.session = str(uuid.uuid4())
else:
self.session = session
self.msg_id = 0
def msg_header(self):
h = msg_header(self.msg_id, self.username, self.session)
self.msg_id += 1
return h
def msg(self, msg_type, content=None, parent=None):
msg = {}
msg['header'] = self.msg_header()
msg['parent_header'] = {} if parent is None else extract_header(parent)
msg['msg_type'] = msg_type
msg['content'] = {} if content is None else content
return msg
def send(self, socket, msg_type, content=None, parent=None, ident=None):
msg = self.msg(msg_type, content, parent)
if ident is not None:
socket.send(ident, zmq.SNDMORE)
socket.send_json(msg)
omsg = Message(msg)
return omsg
def recv(self, socket, mode=zmq.NOBLOCK):
try:
msg = socket.recv_json(mode)
except zmq.ZMQError, e:
if e.errno == zmq.EAGAIN:
# We can convert EAGAIN to None as we know in this case
# recv_json won't return None.
return None
else:
raise
return Message(msg)
def test_msg2obj():
am = dict(x=1)
ao = Message(am)
assert ao.x == am['x']
am['y'] = dict(z=1)
ao = Message(am)
assert ao.y.z == am['y']['z']
k1, k2 = 'y', 'z'
assert ao[k1][k2] == am[k1][k2]
am2 = dict(ao)
assert am['x'] == am2['x']
assert am['y']['z'] == am2['y']['z']