##// END OF EJS Templates
add unregister_target to CommManagers
MinRK -
Show More
@@ -1,164 +1,169 b''
1 1 //----------------------------------------------------------------------------
2 2 // Copyright (C) 2013 The IPython Development Team
3 3 //
4 4 // Distributed under the terms of the BSD License. The full license is in
5 5 // the file COPYING, distributed as part of this software.
6 6 //----------------------------------------------------------------------------
7 7
8 8 //============================================================================
9 9 // Comm and CommManager bases
10 10 //============================================================================
11 11 /**
12 12 * Base Comm classes
13 13 * @module IPython
14 14 * @namespace IPython
15 15 * @submodule comm
16 16 */
17 17
18 18 var IPython = (function (IPython) {
19 19 "use strict";
20 20
21 21 //-----------------------------------------------------------------------
22 22 // CommManager class
23 23 //-----------------------------------------------------------------------
24 24
25 25 var CommManager = function (kernel) {
26 26 this.comms = {};
27 27 this.targets = {};
28 28 if (kernel !== undefined) {
29 29 this.init_kernel(kernel);
30 30 }
31 31 };
32 32
33 33 CommManager.prototype.init_kernel = function (kernel) {
34 34 // connect the kernel, and register message handlers
35 35 this.kernel = kernel;
36 36 var msg_types = ['comm_open', 'comm_msg', 'comm_close'];
37 37 for (var i = 0; i < msg_types.length; i++) {
38 38 var msg_type = msg_types[i];
39 39 kernel.register_iopub_handler(msg_type, $.proxy(this[msg_type], this));
40 40 }
41 41 };
42 42
43 43 CommManager.prototype.register_target = function (target_name, f) {
44 44 // Register a target function for a given target name
45 45 this.targets[target_name] = f;
46 46 };
47 47
48 CommManager.prototype.unregister_target = function (target_name, f) {
49 // Unregister a target function for a given target name
50 delete this.targets[target_name];
51 };
52
48 53 CommManager.prototype.register_comm = function (comm) {
49 54 // Register a comm in the mapping
50 55 this.comms[comm.comm_id] = comm;
51 56 comm.kernel = this.kernel;
52 57 return comm.comm_id;
53 58 };
54 59
55 60 CommManager.prototype.unregister_comm = function (comm_id) {
56 61 // Remove a comm from the mapping
57 62 delete this.comms[comm_id];
58 63 };
59 64
60 65 // comm message handlers
61 66
62 67 CommManager.prototype.comm_open = function (msg) {
63 68 var content = msg.content;
64 69 var f = this.targets[content.target_name];
65 70 if (f === undefined) {
66 71 console.log("No such target registered: ", content.target_name);
67 72 console.log("Available targets are: ", this.targets);
68 73 return;
69 74 }
70 75 var comm = new Comm(content.comm_id);
71 76 this.register_comm(comm);
72 77 f(comm, msg);
73 78 };
74 79
75 80 CommManager.prototype.comm_close = function (msg) {
76 81 var content = msg.content;
77 82 var comm = this.comms[content.comm_id];
78 83 if (comm === undefined) {
79 84 return;
80 85 }
81 86 delete this.comms[content.comm_id];
82 87 comm.handle_close(msg);
83 88 };
84 89
85 90 CommManager.prototype.comm_msg = function (msg) {
86 91 var content = msg.content;
87 92 var comm = this.comms[content.comm_id];
88 93 if (comm === undefined) {
89 94 return;
90 95 }
91 96 comm.handle_msg(msg);
92 97 };
93 98
94 99 //-----------------------------------------------------------------------
95 100 // Comm base class
96 101 //-----------------------------------------------------------------------
97 102
98 103 var Comm = function (comm_id, target_name) {
99 104 this.comm_id = comm_id || new IPython.utils.uuid();
100 105 this.target_name = target_name;
101 106 this._msg_callback = this._close_callback = null;
102 107 };
103 108
104 109 // methods for sending messages
105 110 Comm.prototype.open = function (data, callbacks, metadata) {
106 111 var content = {
107 112 comm_id : this.comm_id,
108 113 target_name : this.target_name,
109 114 data : data || {},
110 115 };
111 116 return this.kernel.send_shell_message("comm_open", content, callbacks, metadata);
112 117 };
113 118
114 119 Comm.prototype.send = function (data, callbacks, metadata) {
115 120 var content = {
116 121 comm_id : this.comm_id,
117 122 data : data || {},
118 123 };
119 124 return this.kernel.send_shell_message("comm_msg", content, callbacks, metadata);
120 125 };
121 126
122 127 Comm.prototype.close = function (data, callbacks, metadata) {
123 128 var content = {
124 129 comm_id : this.comm_id,
125 130 data : data || {},
126 131 };
127 132 return this.kernel.send_shell_message("comm_close", content, callbacks, metadata);
128 133 };
129 134
130 135 // methods for registering callbacks for incoming messages
131 136 Comm.prototype._register_callback = function (key, callback) {
132 137 this['_' + key + '_callback'] = callback;
133 138 };
134 139
135 140 Comm.prototype.on_msg = function (callback) {
136 141 this._register_callback('msg', callback);
137 142 };
138 143
139 144 Comm.prototype.on_close = function (callback) {
140 145 this._register_callback('close', callback);
141 146 };
142 147
143 148 // methods for handling incoming messages
144 149
145 150 Comm.prototype._maybe_callback = function (key, msg) {
146 151 var callback = this['_' + key + '_callback'];
147 152 if (callback) callback(msg);
148 153 };
149 154
150 155 Comm.prototype.handle_msg = function (msg) {
151 156 this._maybe_callback('msg', msg);
152 157 };
153 158
154 159 Comm.prototype.handle_close = function (msg) {
155 160 this._maybe_callback('close', msg);
156 161 };
157 162
158 163 IPython.CommManager = CommManager;
159 164 IPython.Comm = Comm;
160 165
161 166 return IPython;
162 167
163 168 }(IPython));
164 169
@@ -1,166 +1,170 b''
1 1 """Base class to manage comms"""
2 2
3 3 #-----------------------------------------------------------------------------
4 4 # Copyright (C) 2013 The IPython Development Team
5 5 #
6 6 # Distributed under the terms of the BSD License. The full license is in
7 7 # the file COPYING, distributed as part of this software.
8 8 #-----------------------------------------------------------------------------
9 9
10 10 #-----------------------------------------------------------------------------
11 11 # Imports
12 12 #-----------------------------------------------------------------------------
13 13
14 14 import sys
15 15
16 16 from IPython.config import LoggingConfigurable
17 17 from IPython.core.prompts import LazyEvaluate
18 18 from IPython.core.getipython import get_ipython
19 19
20 20 from IPython.utils.importstring import import_item
21 21 from IPython.utils.traitlets import Instance, Unicode, Dict, Any
22 22
23 23 from .comm import Comm
24 24
25 25 #-----------------------------------------------------------------------------
26 26 # Code
27 27 #-----------------------------------------------------------------------------
28 28
29 29 def lazy_keys(dikt):
30 30 """Return lazy-evaluated string representation of a dictionary's keys
31 31
32 32 Key list is only constructed if it will actually be used.
33 33 Used for debug-logging.
34 34 """
35 35 return LazyEvaluate(lambda d: list(d.keys()))
36 36
37 37
38 38 def with_output(method):
39 39 """method decorator for ensuring output is handled properly in a message handler
40 40
41 41 - sets parent header before entering the method
42 42 - publishes busy/idle
43 43 - flushes stdout/stderr after
44 44 """
45 45 def method_with_output(self, stream, ident, msg):
46 46 parent = msg['header']
47 47 self.shell.set_parent(parent)
48 48 self.shell.kernel._publish_status('busy')
49 49 try:
50 50 return method(self, stream, ident, msg)
51 51 finally:
52 52 sys.stdout.flush()
53 53 sys.stderr.flush()
54 54 self.shell.kernel._publish_status('idle')
55 55
56 56 return method_with_output
57 57
58 58
59 59 class CommManager(LoggingConfigurable):
60 60 """Manager for Comms in the Kernel"""
61 61
62 62 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
63 63 def _shell_default(self):
64 64 return get_ipython()
65 65 iopub_socket = Any()
66 66 def _iopub_socket_default(self):
67 67 return self.shell.kernel.iopub_socket
68 68 session = Instance('IPython.kernel.zmq.session.Session')
69 69 def _session_default(self):
70 70 if self.shell is None:
71 71 return
72 72 return self.shell.kernel.session
73 73
74 74 comms = Dict()
75 75 targets = Dict()
76 76
77 77 # Public APIs
78 78
79 79 def register_target(self, target_name, f):
80 80 """Register a callable f for a given target name
81 81
82 82 f will be called with a Comm object as its only argument
83 83 when a comm_open message is received with `target`.
84 84
85 85 f can be a Python callable or an import string for one.
86 86 """
87 87 if isinstance(f, basestring):
88 88 f = import_item(f)
89 89
90 90 self.targets[target_name] = f
91 91
92 def unregister_target(self, target_name, f):
93 """Unregister a callable registered with register_target"""
94 return self.targets.pop(target_name);
95
92 96 def register_comm(self, comm):
93 97 """Register a new comm"""
94 98 comm_id = comm.comm_id
95 99 comm.shell = self.shell
96 100 comm.iopub_socket = self.iopub_socket
97 101 self.comms[comm_id] = comm
98 102 return comm_id
99 103
100 104 def unregister_comm(self, comm_id):
101 105 """Unregister a comm, and close its counterpart"""
102 106 # unlike get_comm, this should raise a KeyError
103 107 comm = self.comms.pop(comm_id)
104 108 comm.close()
105 109
106 110 def get_comm(self, comm_id):
107 111 """Get a comm with a particular id
108 112
109 113 Returns the comm if found, otherwise None.
110 114
111 115 This will not raise an error,
112 116 it will log messages if the comm cannot be found.
113 117 """
114 118 if comm_id not in self.comms:
115 119 self.log.error("No such comm: %s", comm_id)
116 120 self.log.debug("Current comms: %s", lazy_keys(self.comms))
117 121 return
118 122 # call, because we store weakrefs
119 123 comm = self.comms[comm_id]
120 124 return comm
121 125
122 126 # Message handlers
123 127 @with_output
124 128 def comm_open(self, stream, ident, msg):
125 129 """Handler for comm_open messages"""
126 130 content = msg['content']
127 131 comm_id = content['comm_id']
128 132 target_name = content['target_name']
129 133 f = self.targets.get(target_name, None)
130 134 comm = Comm(comm_id=comm_id,
131 135 shell=self.shell,
132 136 iopub_socket=self.iopub_socket,
133 137 primary=False,
134 138 )
135 139 if f is None:
136 140 self.log.error("No such comm target registered: %s", target_name)
137 141 comm.close()
138 142 return
139 143 self.register_comm(comm)
140 144 f(comm, msg)
141 145
142 146 @with_output
143 147 def comm_msg(self, stream, ident, msg):
144 148 """Handler for comm_msg messages"""
145 149 content = msg['content']
146 150 comm_id = content['comm_id']
147 151 comm = self.get_comm(comm_id)
148 152 if comm is None:
149 153 # no such comm
150 154 return
151 155 comm.handle_msg(msg)
152 156
153 157 @with_output
154 158 def comm_close(self, stream, ident, msg):
155 159 """Handler for comm_close messages"""
156 160 content = msg['content']
157 161 comm_id = content['comm_id']
158 162 comm = self.get_comm(comm_id)
159 163 if comm is None:
160 164 # no such comm
161 165 return
162 166 del self.comms[comm_id]
163 167 comm.handle_close(msg)
164 168
165 169
166 170 __all__ = ['CommManager']
General Comments 0
You need to be logged in to leave comments. Login now