##// END OF EJS Templates
Cleaned up KernelManager interface and clarified documentation.
epatters -
Show More
@@ -1,83 +1,82 b''
1 # System library imports
1 # System library imports
2 from PyQt4 import QtCore, QtGui
2 from PyQt4 import QtCore, QtGui
3
3
4 # Local imports
4 # Local imports
5 from frontend_widget import FrontendWidget
5 from frontend_widget import FrontendWidget
6
6
7
7
8 class IPythonWidget(FrontendWidget):
8 class IPythonWidget(FrontendWidget):
9 """ A FrontendWidget for an IPython kernel.
9 """ A FrontendWidget for an IPython kernel.
10 """
10 """
11
11
12 #---------------------------------------------------------------------------
12 #---------------------------------------------------------------------------
13 # 'FrontendWidget' interface
13 # 'FrontendWidget' interface
14 #---------------------------------------------------------------------------
14 #---------------------------------------------------------------------------
15
15
16 def __init__(self, kernel_manager, parent=None):
16 def __init__(self, kernel_manager, parent=None):
17 super(IPythonWidget, self).__init__(kernel_manager, parent)
17 super(IPythonWidget, self).__init__(kernel_manager, parent)
18
18
19 self._magic_overrides = {}
19 self._magic_overrides = {}
20
20
21 def execute_source(self, source, hidden=False, interactive=False):
21 def execute_source(self, source, hidden=False, interactive=False):
22 """ Reimplemented to override magic commands.
22 """ Reimplemented to override magic commands.
23 """
23 """
24 magic_source = source.strip()
24 magic_source = source.strip()
25 if magic_source.startswith('%'):
25 if magic_source.startswith('%'):
26 magic_source = magic_source[1:]
26 magic_source = magic_source[1:]
27 magic, sep, arguments = magic_source.partition(' ')
27 magic, sep, arguments = magic_source.partition(' ')
28 if not magic:
28 if not magic:
29 magic = magic_source
29 magic = magic_source
30
30
31 callback = self._magic_overrides.get(magic)
31 callback = self._magic_overrides.get(magic)
32 if callback:
32 if callback:
33 output = callback(arguments)
33 output = callback(arguments)
34 if output:
34 if output:
35 self.appendPlainText(output)
35 self.appendPlainText(output)
36 self._show_prompt('>>> ')
36 self._show_prompt('>>> ')
37 return True
37 return True
38 else:
38 else:
39 return super(IPythonWidget, self).execute_source(source, hidden,
39 return super(IPythonWidget, self).execute_source(source, hidden,
40 interactive)
40 interactive)
41
41
42 #---------------------------------------------------------------------------
42 #---------------------------------------------------------------------------
43 # 'IPythonWidget' interface
43 # 'IPythonWidget' interface
44 #---------------------------------------------------------------------------
44 #---------------------------------------------------------------------------
45
45
46 def set_magic_override(self, magic, callback):
46 def set_magic_override(self, magic, callback):
47 """ Overrides an IPython magic command. This magic will be intercepted
47 """ Overrides an IPython magic command. This magic will be intercepted
48 by the frontend rather than passed on to the kernel and 'callback'
48 by the frontend rather than passed on to the kernel and 'callback'
49 will be called with a single argument: a string of argument(s) for
49 will be called with a single argument: a string of argument(s) for
50 the magic. The callback can (optionally) return text to print to the
50 the magic. The callback can (optionally) return text to print to the
51 console.
51 console.
52 """
52 """
53 self._magic_overrides[magic] = callback
53 self._magic_overrides[magic] = callback
54
54
55 def remove_magic_override(self, magic):
55 def remove_magic_override(self, magic):
56 """ Removes the override for the specified magic, if there is one.
56 """ Removes the override for the specified magic, if there is one.
57 """
57 """
58 try:
58 try:
59 del self._magic_overrides[magic]
59 del self._magic_overrides[magic]
60 except KeyError:
60 except KeyError:
61 pass
61 pass
62
62
63
63
64 if __name__ == '__main__':
64 if __name__ == '__main__':
65 import sys
65 import sys
66 from IPython.frontend.qt.kernelmanager import QtKernelManager
66 from IPython.frontend.qt.kernelmanager import QtKernelManager
67
67
68 # Create KernelManager
68 # Create KernelManager
69 xreq_addr = ('127.0.0.1', 5575)
69 kernel_manager = QtKernelManager(xreq_address = ('127.0.0.1', 5575),
70 sub_addr = ('127.0.0.1', 5576)
70 sub_address = ('127.0.0.1', 5576),
71 rep_addr = ('127.0.0.1', 5577)
71 rep_address = ('127.0.0.1', 5577))
72 kernel_manager = QtKernelManager(xreq_addr, sub_addr, rep_addr)
73 kernel_manager.sub_channel.start()
72 kernel_manager.sub_channel.start()
74 kernel_manager.xreq_channel.start()
73 kernel_manager.xreq_channel.start()
75
74
76 # Launch application
75 # Launch application
77 app = QtGui.QApplication(sys.argv)
76 app = QtGui.QApplication(sys.argv)
78 widget = IPythonWidget(kernel_manager)
77 widget = IPythonWidget(kernel_manager)
79 widget.setWindowTitle('Python')
78 widget.setWindowTitle('Python')
80 widget.resize(640, 480)
79 widget.resize(640, 480)
81 widget.show()
80 widget.show()
82 sys.exit(app.exec_())
81 sys.exit(app.exec_())
83
82
@@ -1,335 +1,359 b''
1 """Kernel frontend classes.
1 """Kernel frontend classes.
2
2
3 TODO: Create logger to handle debugging and console messages.
3 TODO: Create logger to handle debugging and console messages.
4
4
5 """
5 """
6
6
7 # Standard library imports.
7 # Standard library imports.
8 from Queue import Queue, Empty
8 from Queue import Queue, Empty
9 from threading import Thread
9 from threading import Thread
10 import time
10 import time
11 import traceback
11 import traceback
12
12
13 # System library imports.
13 # System library imports.
14 import zmq
14 import zmq
15 from zmq import POLLIN, POLLOUT, POLLERR
15 from zmq import POLLIN, POLLOUT, POLLERR
16 from zmq.eventloop import ioloop
16 from zmq.eventloop import ioloop
17
17
18 # Local imports.
18 # Local imports.
19 from IPython.utils.traitlets import HasTraits, Any, Int, Instance, Str, Type
19 from IPython.utils.traitlets import HasTraits, Any, Int, Instance, Str, Type
20 from session import Session
20 from session import Session
21
21
22
22
23 class MissingHandlerError(Exception):
23 class MissingHandlerError(Exception):
24 pass
24 pass
25
25
26
26
27 class ZmqSocketChannel(Thread):
27 class ZmqSocketChannel(Thread):
28 """ The base class for the channels that use ZMQ sockets.
29 """
28
30
29 socket = None
31 def __init__(self, context, session, addr=None):
30
31 def __init__(self, context, session, addr):
32 self.context = context
32 self.context = context
33 self.session = session
33 self.session = session
34 self.addr = addr
34 self.addr = addr
35 self.socket = None
36
35 super(ZmqSocketChannel, self).__init__()
37 super(ZmqSocketChannel, self).__init__()
36 self.daemon = True
38 self.daemon = True
37
39
38
40
39 class SubSocketChannel(ZmqSocketChannel):
41 class SubSocketChannel(ZmqSocketChannel):
40
42
41 handlers = None
43 handlers = None
42 _overriden_call_handler = None
44 _overriden_call_handler = None
43
45
44 def __init__(self, context, session, addr):
46 def __init__(self, context, session, addr=None):
45 self.handlers = {}
47 self.handlers = {}
46 super(SubSocketChannel, self).__init__(context, session, addr)
48 super(SubSocketChannel, self).__init__(context, session, addr)
47
49
48 def run(self):
50 def run(self):
49 self.socket = self.context.socket(zmq.SUB)
51 self.socket = self.context.socket(zmq.SUB)
50 self.socket.setsockopt(zmq.SUBSCRIBE,'')
52 self.socket.setsockopt(zmq.SUBSCRIBE,'')
51 self.socket.setsockopt(zmq.IDENTITY, self.session.session)
53 self.socket.setsockopt(zmq.IDENTITY, self.session.session)
52 self.socket.connect('tcp://%s:%i' % self.addr)
54 self.socket.connect('tcp://%s:%i' % self.addr)
53 self.ioloop = ioloop.IOLoop()
55 self.ioloop = ioloop.IOLoop()
54 self.ioloop.add_handler(self.socket, self._handle_events,
56 self.ioloop.add_handler(self.socket, self._handle_events,
55 POLLIN|POLLERR)
57 POLLIN|POLLERR)
56 self.ioloop.start()
58 self.ioloop.start()
57
59
58 def _handle_events(self, socket, events):
60 def _handle_events(self, socket, events):
59 # Turn on and off POLLOUT depending on if we have made a request
61 # Turn on and off POLLOUT depending on if we have made a request
60 if events & POLLERR:
62 if events & POLLERR:
61 self._handle_err()
63 self._handle_err()
62 if events & POLLIN:
64 if events & POLLIN:
63 self._handle_recv()
65 self._handle_recv()
64
66
65 def _handle_err(self):
67 def _handle_err(self):
66 raise zmq.ZmqError()
68 raise zmq.ZmqError()
67
69
68 def _handle_recv(self):
70 def _handle_recv(self):
69 msg = self.socket.recv_json()
71 msg = self.socket.recv_json()
70 self.call_handlers(msg)
72 self.call_handlers(msg)
71
73
72 def override_call_handler(self, func):
74 def override_call_handler(self, func):
73 """Permanently override the call_handler.
75 """Permanently override the call_handler.
74
76
75 The function func will be called as::
77 The function func will be called as::
76
78
77 func(handler, msg)
79 func(handler, msg)
78
80
79 And must call::
81 And must call::
80
82
81 handler(msg)
83 handler(msg)
82
84
83 in the main thread.
85 in the main thread.
84 """
86 """
85 assert callable(func), "not a callable: %r" % func
87 assert callable(func), "not a callable: %r" % func
86 self._overriden_call_handler = func
88 self._overriden_call_handler = func
87
89
88 def call_handlers(self, msg):
90 def call_handlers(self, msg):
89 handler = self.handlers.get(msg['msg_type'], None)
91 handler = self.handlers.get(msg['msg_type'], None)
90 if handler is not None:
92 if handler is not None:
91 try:
93 try:
92 self.call_handler(handler, msg)
94 self.call_handler(handler, msg)
93 except:
95 except:
94 # XXX: This should be logged at least
96 # XXX: This should be logged at least
95 traceback.print_last()
97 traceback.print_last()
96
98
97 def call_handler(self, handler, msg):
99 def call_handler(self, handler, msg):
98 if self._overriden_call_handler is not None:
100 if self._overriden_call_handler is not None:
99 self._overriden_call_handler(handler, msg)
101 self._overriden_call_handler(handler, msg)
100 elif hasattr(self, '_call_handler'):
102 elif hasattr(self, '_call_handler'):
101 call_handler = getattr(self, '_call_handler')
103 call_handler = getattr(self, '_call_handler')
102 call_handler(handler, msg)
104 call_handler(handler, msg)
103 else:
105 else:
104 raise RuntimeError('no handler!')
106 raise RuntimeError('no handler!')
105
107
106 def add_handler(self, callback, msg_type):
108 def add_handler(self, callback, msg_type):
107 """Register a callback for msg type."""
109 """Register a callback for msg type."""
108 self.handlers[msg_type] = callback
110 self.handlers[msg_type] = callback
109
111
110 def remove_handler(self, msg_type):
112 def remove_handler(self, msg_type):
111 """Remove the callback for msg type."""
113 """Remove the callback for msg type."""
112 self.handlers.pop(msg_type, None)
114 self.handlers.pop(msg_type, None)
113
115
114 def flush(self):
116 def flush(self):
115 """Immediately processes all pending messages on the SUB channel. This
117 """Immediately processes all pending messages on the SUB channel. This
116 method is thread safe.
118 method is thread safe.
117 """
119 """
118 self._flushed = False
120 self._flushed = False
119 self.ioloop.add_callback(self._flush)
121 self.ioloop.add_callback(self._flush)
120 while not self._flushed:
122 while not self._flushed:
121 time.sleep(0.01)
123 time.sleep(0.01)
122
124
123 def _flush(self):
125 def _flush(self):
124 """Called in this thread by the IOLoop to indicate that all events have
126 """Called in this thread by the IOLoop to indicate that all events have
125 been processed.
127 been processed.
126 """
128 """
127 self._flushed = True
129 self._flushed = True
128
130
129
131
130 class XReqSocketChannel(ZmqSocketChannel):
132 class XReqSocketChannel(ZmqSocketChannel):
131
133
132 handler_queue = None
134 handler_queue = None
133 command_queue = None
135 command_queue = None
134 handlers = None
136 handlers = None
135 _overriden_call_handler = None
137 _overriden_call_handler = None
136
138
137 def __init__(self, context, session, addr):
139 def __init__(self, context, session, addr=None):
138 self.handlers = {}
140 self.handlers = {}
139 self.handler_queue = Queue()
141 self.handler_queue = Queue()
140 self.command_queue = Queue()
142 self.command_queue = Queue()
141 super(XReqSocketChannel, self).__init__(context, session, addr)
143 super(XReqSocketChannel, self).__init__(context, session, addr)
142
144
143 def run(self):
145 def run(self):
144 self.socket = self.context.socket(zmq.XREQ)
146 self.socket = self.context.socket(zmq.XREQ)
145 self.socket.setsockopt(zmq.IDENTITY, self.session.session)
147 self.socket.setsockopt(zmq.IDENTITY, self.session.session)
146 self.socket.connect('tcp://%s:%i' % self.addr)
148 self.socket.connect('tcp://%s:%i' % self.addr)
147 self.ioloop = ioloop.IOLoop()
149 self.ioloop = ioloop.IOLoop()
148 self.ioloop.add_handler(self.socket, self._handle_events,
150 self.ioloop.add_handler(self.socket, self._handle_events,
149 POLLIN|POLLOUT|POLLERR)
151 POLLIN|POLLOUT|POLLERR)
150 self.ioloop.start()
152 self.ioloop.start()
151
153
152 def _handle_events(self, socket, events):
154 def _handle_events(self, socket, events):
153 # Turn on and off POLLOUT depending on if we have made a request
155 # Turn on and off POLLOUT depending on if we have made a request
154 if events & POLLERR:
156 if events & POLLERR:
155 self._handle_err()
157 self._handle_err()
156 if events & POLLOUT:
158 if events & POLLOUT:
157 self._handle_send()
159 self._handle_send()
158 if events & POLLIN:
160 if events & POLLIN:
159 self._handle_recv()
161 self._handle_recv()
160
162
161 def _handle_recv(self):
163 def _handle_recv(self):
162 msg = self.socket.recv_json()
164 msg = self.socket.recv_json()
163 self.call_handlers(msg)
165 self.call_handlers(msg)
164
166
165 def _handle_send(self):
167 def _handle_send(self):
166 try:
168 try:
167 msg = self.command_queue.get(False)
169 msg = self.command_queue.get(False)
168 except Empty:
170 except Empty:
169 pass
171 pass
170 else:
172 else:
171 self.socket.send_json(msg)
173 self.socket.send_json(msg)
172
174
173 def _handle_err(self):
175 def _handle_err(self):
174 raise zmq.ZmqError()
176 raise zmq.ZmqError()
175
177
176 def _queue_request(self, msg, callback):
178 def _queue_request(self, msg, callback):
177 handler = self._find_handler(msg['msg_type'], callback)
179 handler = self._find_handler(msg['msg_type'], callback)
178 self.handler_queue.put(handler)
180 self.handler_queue.put(handler)
179 self.command_queue.put(msg)
181 self.command_queue.put(msg)
180
182
181 def execute(self, code, callback=None):
183 def execute(self, code, callback=None):
182 # Create class for content/msg creation. Related to, but possibly
184 # Create class for content/msg creation. Related to, but possibly
183 # not in Session.
185 # not in Session.
184 content = dict(code=code)
186 content = dict(code=code)
185 msg = self.session.msg('execute_request', content)
187 msg = self.session.msg('execute_request', content)
186 self._queue_request(msg, callback)
188 self._queue_request(msg, callback)
187 return msg['header']['msg_id']
189 return msg['header']['msg_id']
188
190
189 def complete(self, text, line, block=None, callback=None):
191 def complete(self, text, line, block=None, callback=None):
190 content = dict(text=text, line=line)
192 content = dict(text=text, line=line)
191 msg = self.session.msg('complete_request', content)
193 msg = self.session.msg('complete_request', content)
192 self._queue_request(msg, callback)
194 self._queue_request(msg, callback)
193 return msg['header']['msg_id']
195 return msg['header']['msg_id']
194
196
195 def object_info(self, oname, callback=None):
197 def object_info(self, oname, callback=None):
196 content = dict(oname=oname)
198 content = dict(oname=oname)
197 msg = self.session.msg('object_info_request', content)
199 msg = self.session.msg('object_info_request', content)
198 self._queue_request(msg, callback)
200 self._queue_request(msg, callback)
199 return msg['header']['msg_id']
201 return msg['header']['msg_id']
200
202
201 def _find_handler(self, name, callback):
203 def _find_handler(self, name, callback):
202 if callback is not None:
204 if callback is not None:
203 return callback
205 return callback
204 handler = self.handlers.get(name)
206 handler = self.handlers.get(name)
205 if handler is None:
207 if handler is None:
206 raise MissingHandlerError(
208 raise MissingHandlerError(
207 'No handler defined for method: %s' % name)
209 'No handler defined for method: %s' % name)
208 return handler
210 return handler
209
211
210 def override_call_handler(self, func):
212 def override_call_handler(self, func):
211 """Permanently override the call_handler.
213 """Permanently override the call_handler.
212
214
213 The function func will be called as::
215 The function func will be called as::
214
216
215 func(handler, msg)
217 func(handler, msg)
216
218
217 And must call::
219 And must call::
218
220
219 handler(msg)
221 handler(msg)
220
222
221 in the main thread.
223 in the main thread.
222 """
224 """
223 assert callable(func), "not a callable: %r" % func
225 assert callable(func), "not a callable: %r" % func
224 self._overriden_call_handler = func
226 self._overriden_call_handler = func
225
227
226 def call_handlers(self, msg):
228 def call_handlers(self, msg):
227 try:
229 try:
228 handler = self.handler_queue.get(False)
230 handler = self.handler_queue.get(False)
229 except Empty:
231 except Empty:
230 print "Message received with no handler!!!"
232 print "Message received with no handler!!!"
231 print msg
233 print msg
232 else:
234 else:
233 self.call_handler(handler, msg)
235 self.call_handler(handler, msg)
234
236
235 def call_handler(self, handler, msg):
237 def call_handler(self, handler, msg):
236 if self._overriden_call_handler is not None:
238 if self._overriden_call_handler is not None:
237 self._overriden_call_handler(handler, msg)
239 self._overriden_call_handler(handler, msg)
238 elif hasattr(self, '_call_handler'):
240 elif hasattr(self, '_call_handler'):
239 call_handler = getattr(self, '_call_handler')
241 call_handler = getattr(self, '_call_handler')
240 call_handler(handler, msg)
242 call_handler(handler, msg)
241 else:
243 else:
242 raise RuntimeError('no handler!')
244 raise RuntimeError('no handler!')
243
245
244
246
245 class RepSocketChannel(ZmqSocketChannel):
247 class RepSocketChannel(ZmqSocketChannel):
246
248
247 def on_raw_input():
249 def on_raw_input():
248 pass
250 pass
249
251
250
252
251 class KernelManager(HasTraits):
253 class KernelManager(HasTraits):
254 """ Manages a kernel for a frontend.
252
255
253 # The addresses to use for the various channels. Should be tuples of form
256 The SUB channel is for the frontend to receive messages published by the
254 # (ip_address, port).
257 kernel.
255 sub_address = Any
258
256 xreq_address = Any
259 The REQ channel is for the frontend to make requests of the kernel.
257 rep_address = Any
260
258 # FIXME: Add Tuple to Traitlets.
261 The REP channel is for the kernel to request stdin (raw_input) from the
259 #sub_address = Tuple(Str, Int)
262 frontend.
260 #xreq_address = Tuple(Str, Int)
263 """
261 #rep_address = Tuple(Str, Int)
262
264
263 # The PyZMQ Context to use for communication with the kernel.
265 # The PyZMQ Context to use for communication with the kernel.
264 context = Instance(zmq.Context, ())
266 context = Instance(zmq.Context, ())
265
267
266 # The Session to use for communication with the kernel.
268 # The Session to use for communication with the kernel.
267 session = Instance(Session, ())
269 session = Instance(Session, ())
268
270
271 # The channels objects used for communication with the kernel.
272 # FIXME: Add '_traitname_default' instantiation method to Traitlets.
273 #sub_channel = Instance(SubSocketChannel)
274 #xreq_channel = Instance(XReqSocketChannel)
275 #rep_channel = Instance(RepSocketChannel)
276
269 # The classes to use for the various channels.
277 # The classes to use for the various channels.
270 sub_channel_class = Type(SubSocketChannel)
278 sub_channel_class = Type(SubSocketChannel)
271 xreq_channel_class = Type(XReqSocketChannel)
279 xreq_channel_class = Type(XReqSocketChannel)
272 rep_channel_class = Type(RepSocketChannel)
280 rep_channel_class = Type(RepSocketChannel)
273
281
282 # The addresses to use for the various channels. Should be tuples of form
283 # (ip_address, port).
284 #sub_address = DelegatesTo('sub_channel')
285 #xreq_address = DelegatesTo('xreq_channel')
286 #rep_address = DelegatesTo('rep_channel')
287
274 # Protected traits.
288 # Protected traits.
275 _sub_channel = Any
289 _sub_channel = Any
276 _xreq_channel = Any
290 _xreq_channel = Any
277 _rep_channel = Any
291 _rep_channel = Any
278
292
279 def __init__(self, xreq_address, sub_address, rep_address, **traits):
293 def __init__(self, **traits):
280 super(KernelManager, self).__init__()
294 super(KernelManager, self).__init__()
281
295
282 self.xreq_address = xreq_address
283 self.sub_address = sub_address
284 self.rep_address = rep_address
285
286 # FIXME: This should be the business of HasTraits. The convention is:
296 # FIXME: This should be the business of HasTraits. The convention is:
287 # HasTraits.__init__(self, **traits_to_be_initialized.)
297 # HasTraits.__init__(self, **traits_to_be_initialized.)
288 for trait in traits:
298 for trait in traits:
289 setattr(self, trait, traits[trait])
299 setattr(self, trait, traits[trait])
290
300
291 def start_kernel(self):
301 def start_kernel(self):
292 """Start a localhost kernel on ip and port.
302 """Start a localhost kernel. If ports have been specified, use
293
303 them. Otherwise, choose an open port at random.
294 The SUB channel is for the frontend to receive messages published by
295 the kernel.
296
297 The REQ channel is for the frontend to make requests of the kernel.
298
299 The REP channel is for the kernel to request stdin (raw_input) from
300 the frontend.
301 """
304 """
302
305
303 def kill_kernel(self):
306 def kill_kernel(self):
304 """Kill the running kernel"""
307 """Kill the running kernel"""
305
308
306 def is_alive(self):
309 def is_alive(self):
307 """Is the kernel alive?"""
310 """Is the kernel alive?"""
308 return True
311 return True
309
312
310 def signal_kernel(self, signum):
313 def signal_kernel(self, signum):
311 """Send signum to the kernel."""
314 """Send signum to the kernel."""
312
315
313 @property
316 @property
314 def sub_channel(self):
317 def sub_channel(self):
315 """Get the SUB socket channel object."""
318 """Get the SUB socket channel object."""
316 if self._sub_channel is None:
319 if self._sub_channel is None:
317 self._sub_channel = self.sub_channel_class(
320 self._sub_channel = self.sub_channel_class(self.context,
318 self.context, self.session, self.sub_address)
321 self.session)
319 return self._sub_channel
322 return self._sub_channel
320
323
321 @property
324 @property
322 def xreq_channel(self):
325 def xreq_channel(self):
323 """Get the REQ socket channel object to make requests of the kernel."""
326 """Get the REQ socket channel object to make requests of the kernel."""
324 if self._xreq_channel is None:
327 if self._xreq_channel is None:
325 self._xreq_channel = self.xreq_channel_class(
328 self._xreq_channel = self.xreq_channel_class(self.context,
326 self.context, self.session, self.xreq_address)
329 self.session)
327 return self._xreq_channel
330 return self._xreq_channel
328
331
329 @property
332 @property
330 def rep_channel(self):
333 def rep_channel(self):
331 """Get the REP socket channel object to handle stdin (raw_input)."""
334 """Get the REP socket channel object to handle stdin (raw_input)."""
332 if self._rep_channel is None:
335 if self._rep_channel is None:
333 self._rep_channel = self.rep_channel_class(
336 self._rep_channel = self.rep_channel_class(self.context,
334 self.context, self.session, self.rep_address)
337 self.session)
335 return self._rep_channel
338 return self._rep_channel
339
340 def get_sub_address(self):
341 return self.sub_channel.addr
342 def set_sub_address(self, addr):
343 self.sub_channel.addr = addr
344 sub_address = property(get_sub_address, set_sub_address,
345 doc="The address used by SUB socket channel.")
346
347 def get_xreq_address(self):
348 return self.xreq_channel.addr
349 def set_xreq_address(self, addr):
350 self.xreq_channel.addr = addr
351 xreq_address = property(get_xreq_address, set_xreq_address,
352 doc="The address used by XREQ socket channel.")
353
354 def get_rep_address(self):
355 return self.rep_channel.addr
356 def set_rep_address(self, addr):
357 self.rep_channel.addr = addr
358 rep_address = property(get_rep_address, set_rep_address,
359 doc="The address used by REP socket channel.")
General Comments 0
You need to be logged in to leave comments. Login now