##// END OF EJS Templates
unregister and register both take comm as argument
Sylvain Corlay -
Show More
@@ -1,150 +1,150 b''
1 """Base class to manage comms"""
1 """Base class to manage comms"""
2
2
3 # Copyright (c) IPython Development Team.
3 # Copyright (c) IPython Development Team.
4 # Distributed under the terms of the Modified BSD License.
4 # Distributed under the terms of the Modified BSD License.
5
5
6 import sys
6 import sys
7
7
8 from IPython.config import LoggingConfigurable
8 from IPython.config import LoggingConfigurable
9 from IPython.core.prompts import LazyEvaluate
9 from IPython.core.prompts import LazyEvaluate
10 from IPython.core.getipython import get_ipython
10 from IPython.core.getipython import get_ipython
11
11
12 from IPython.utils.importstring import import_item
12 from IPython.utils.importstring import import_item
13 from IPython.utils.py3compat import string_types
13 from IPython.utils.py3compat import string_types
14 from IPython.utils.traitlets import Instance, Unicode, Dict, Any
14 from IPython.utils.traitlets import Instance, Unicode, Dict, Any
15
15
16 from .comm import Comm
16 from .comm import Comm
17
17
18
18
19 def lazy_keys(dikt):
19 def lazy_keys(dikt):
20 """Return lazy-evaluated string representation of a dictionary's keys
20 """Return lazy-evaluated string representation of a dictionary's keys
21
21
22 Key list is only constructed if it will actually be used.
22 Key list is only constructed if it will actually be used.
23 Used for debug-logging.
23 Used for debug-logging.
24 """
24 """
25 return LazyEvaluate(lambda d: list(d.keys()))
25 return LazyEvaluate(lambda d: list(d.keys()))
26
26
27
27
28 class CommManager(LoggingConfigurable):
28 class CommManager(LoggingConfigurable):
29 """Manager for Comms in the Kernel"""
29 """Manager for Comms in the Kernel"""
30
30
31 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
31 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
32 def _shell_default(self):
32 def _shell_default(self):
33 return get_ipython()
33 return get_ipython()
34 iopub_socket = Any()
34 iopub_socket = Any()
35 def _iopub_socket_default(self):
35 def _iopub_socket_default(self):
36 return self.shell.kernel.iopub_socket
36 return self.shell.kernel.iopub_socket
37 session = Instance('IPython.kernel.zmq.session.Session')
37 session = Instance('IPython.kernel.zmq.session.Session')
38 def _session_default(self):
38 def _session_default(self):
39 if self.shell is None:
39 if self.shell is None:
40 return
40 return
41 return self.shell.kernel.session
41 return self.shell.kernel.session
42
42
43 comms = Dict()
43 comms = Dict()
44 targets = Dict()
44 targets = Dict()
45
45
46 # Public APIs
46 # Public APIs
47
47
48 def register_target(self, target_name, f):
48 def register_target(self, target_name, f):
49 """Register a callable f for a given target name
49 """Register a callable f for a given target name
50
50
51 f will be called with two arguments when a comm_open message is received with `target`:
51 f will be called with two arguments when a comm_open message is received with `target`:
52
52
53 - the Comm instance
53 - the Comm instance
54 - the `comm_open` message itself.
54 - the `comm_open` message itself.
55
55
56 f can be a Python callable or an import string for one.
56 f can be a Python callable or an import string for one.
57 """
57 """
58 if isinstance(f, string_types):
58 if isinstance(f, string_types):
59 f = import_item(f)
59 f = import_item(f)
60
60
61 self.targets[target_name] = f
61 self.targets[target_name] = f
62
62
63 def unregister_target(self, target_name, f):
63 def unregister_target(self, target_name, f):
64 """Unregister a callable registered with register_target"""
64 """Unregister a callable registered with register_target"""
65 return self.targets.pop(target_name);
65 return self.targets.pop(target_name);
66
66
67 def register_comm(self, comm):
67 def register_comm(self, comm):
68 """Register a new comm"""
68 """Register a new comm"""
69 comm_id = comm.comm_id
69 comm_id = comm.comm_id
70 comm.shell = self.shell
70 comm.shell = self.shell
71 comm.iopub_socket = self.iopub_socket
71 comm.iopub_socket = self.iopub_socket
72 self.comms[comm_id] = comm
72 self.comms[comm_id] = comm
73 return comm_id
73 return comm_id
74
74
75 def unregister_comm(self, comm_id):
75 def unregister_comm(self, comm):
76 """Unregister a comm, and close its counterpart"""
76 """Unregister a comm, and close its counterpart"""
77 # unlike get_comm, this should raise a KeyError
77 # unlike get_comm, this should raise a KeyError
78 comm = self.comms.pop(comm_id)
78 comm = self.comms.pop(comm.comm_id)
79
79
80 def get_comm(self, comm_id):
80 def get_comm(self, comm_id):
81 """Get a comm with a particular id
81 """Get a comm with a particular id
82
82
83 Returns the comm if found, otherwise None.
83 Returns the comm if found, otherwise None.
84
84
85 This will not raise an error,
85 This will not raise an error,
86 it will log messages if the comm cannot be found.
86 it will log messages if the comm cannot be found.
87 """
87 """
88 if comm_id not in self.comms:
88 if comm_id not in self.comms:
89 self.log.error("No such comm: %s", comm_id)
89 self.log.error("No such comm: %s", comm_id)
90 self.log.debug("Current comms: %s", lazy_keys(self.comms))
90 self.log.debug("Current comms: %s", lazy_keys(self.comms))
91 return
91 return
92 # call, because we store weakrefs
92 # call, because we store weakrefs
93 comm = self.comms[comm_id]
93 comm = self.comms[comm_id]
94 return comm
94 return comm
95
95
96 # Message handlers
96 # Message handlers
97 def comm_open(self, stream, ident, msg):
97 def comm_open(self, stream, ident, msg):
98 """Handler for comm_open messages"""
98 """Handler for comm_open messages"""
99 content = msg['content']
99 content = msg['content']
100 comm_id = content['comm_id']
100 comm_id = content['comm_id']
101 target_name = content['target_name']
101 target_name = content['target_name']
102 f = self.targets.get(target_name, None)
102 f = self.targets.get(target_name, None)
103 comm = Comm(comm_id=comm_id,
103 comm = Comm(comm_id=comm_id,
104 shell=self.shell,
104 shell=self.shell,
105 iopub_socket=self.iopub_socket,
105 iopub_socket=self.iopub_socket,
106 primary=False,
106 primary=False,
107 )
107 )
108 if f is None:
108 if f is None:
109 self.log.error("No such comm target registered: %s", target_name)
109 self.log.error("No such comm target registered: %s", target_name)
110 comm.close()
110 comm.close()
111 return
111 return
112 self.register_comm(comm)
112 self.register_comm(comm)
113 try:
113 try:
114 f(comm, msg)
114 f(comm, msg)
115 except Exception:
115 except Exception:
116 self.log.error("Exception opening comm with target: %s", target_name, exc_info=True)
116 self.log.error("Exception opening comm with target: %s", target_name, exc_info=True)
117 comm.close()
117 comm.close()
118 self.unregister_comm(comm_id)
118 self.unregister_comm(comm)
119
119
120 def comm_msg(self, stream, ident, msg):
120 def comm_msg(self, stream, ident, msg):
121 """Handler for comm_msg messages"""
121 """Handler for comm_msg messages"""
122 content = msg['content']
122 content = msg['content']
123 comm_id = content['comm_id']
123 comm_id = content['comm_id']
124 comm = self.get_comm(comm_id)
124 comm = self.get_comm(comm_id)
125 if comm is None:
125 if comm is None:
126 # no such comm
126 # no such comm
127 return
127 return
128 try:
128 try:
129 comm.handle_msg(msg)
129 comm.handle_msg(msg)
130 except Exception:
130 except Exception:
131 self.log.error("Exception in comm_msg for %s", comm_id, exc_info=True)
131 self.log.error("Exception in comm_msg for %s", comm_id, exc_info=True)
132
132
133 def comm_close(self, stream, ident, msg):
133 def comm_close(self, stream, ident, msg):
134 """Handler for comm_close messages"""
134 """Handler for comm_close messages"""
135 content = msg['content']
135 content = msg['content']
136 comm_id = content['comm_id']
136 comm_id = content['comm_id']
137 comm = self.get_comm(comm_id)
137 comm = self.get_comm(comm_id)
138 if comm is None:
138 if comm is None:
139 # no such comm
139 # no such comm
140 self.log.debug("No such comm to close: %s", comm_id)
140 self.log.debug("No such comm to close: %s", comm_id)
141 return
141 return
142 del self.comms[comm_id]
142 del self.comms[comm_id]
143
143
144 try:
144 try:
145 comm.handle_close(msg)
145 comm.handle_close(msg)
146 except Exception:
146 except Exception:
147 self.log.error("Exception handling comm_close for %s", comm_id, exc_info=True)
147 self.log.error("Exception handling comm_close for %s", comm_id, exc_info=True)
148
148
149
149
150 __all__ = ['CommManager']
150 __all__ = ['CommManager']
General Comments 0
You need to be logged in to leave comments. Login now