Show More
@@ -0,0 +1,43 b'' | |||||
|
1 | """ Defines a dummy socket implementing (part of) the zmq.Socket interface. """ | |||
|
2 | ||||
|
3 | #----------------------------------------------------------------------------- | |||
|
4 | # Copyright (C) 2012 The IPython Development Team | |||
|
5 | # | |||
|
6 | # Distributed under the terms of the BSD License. The full license is in | |||
|
7 | # the file COPYING, distributed as part of this software. | |||
|
8 | #----------------------------------------------------------------------------- | |||
|
9 | ||||
|
10 | #----------------------------------------------------------------------------- | |||
|
11 | # Imports | |||
|
12 | #----------------------------------------------------------------------------- | |||
|
13 | ||||
|
14 | # Standard library imports. | |||
|
15 | import Queue | |||
|
16 | ||||
|
17 | # System library imports. | |||
|
18 | import zmq | |||
|
19 | ||||
|
20 | # Local imports. | |||
|
21 | from IPython.utils.traitlets import HasTraits, Instance, Int | |||
|
22 | ||||
|
23 | #----------------------------------------------------------------------------- | |||
|
24 | # Dummy socket class | |||
|
25 | #----------------------------------------------------------------------------- | |||
|
26 | ||||
|
27 | class DummySocket(HasTraits): | |||
|
28 | """ A dummy socket implementing (part of) the zmq.Socket interface. """ | |||
|
29 | ||||
|
30 | queue = Instance(Queue.Queue, ()) | |||
|
31 | message_sent = Int(0) # Should be an Event | |||
|
32 | ||||
|
33 | #------------------------------------------------------------------------- | |||
|
34 | # zmq.Socket interface | |||
|
35 | #------------------------------------------------------------------------- | |||
|
36 | ||||
|
37 | def recv_multipart(self, flags=0, copy=True, track=False): | |||
|
38 | return self.queue.get_nowait() | |||
|
39 | ||||
|
40 | def send_multipart(self, msg_parts, flags=0, copy=True, track=False): | |||
|
41 | msg_parts = map(zmq.Message, msg_parts) | |||
|
42 | self.queue.put_nowait(msg_parts) | |||
|
43 | self.message_sent += 1 |
@@ -11,7 +11,15 b'' | |||||
11 | # Imports |
|
11 | # Imports | |
12 | #----------------------------------------------------------------------------- |
|
12 | #----------------------------------------------------------------------------- | |
13 |
|
13 | |||
|
14 | # Standard library imports | |||
|
15 | from contextlib import contextmanager | |||
|
16 | import logging | |||
|
17 | import sys | |||
|
18 | ||||
14 | # Local imports. |
|
19 | # Local imports. | |
|
20 | from IPython.embedded.socket import DummySocket | |||
|
21 | from IPython.utils.jsonutil import json_clean | |||
|
22 | from IPython.utils.traitlets import Any, Instance, List | |||
15 | from IPython.zmq.ipkernel import Kernel |
|
23 | from IPython.zmq.ipkernel import Kernel | |
16 |
|
24 | |||
17 | #----------------------------------------------------------------------------- |
|
25 | #----------------------------------------------------------------------------- | |
@@ -19,4 +27,105 b' from IPython.zmq.ipkernel import Kernel' | |||||
19 | #----------------------------------------------------------------------------- |
|
27 | #----------------------------------------------------------------------------- | |
20 |
|
28 | |||
21 | class EmbeddedKernel(Kernel): |
|
29 | class EmbeddedKernel(Kernel): | |
22 | pass |
|
30 | ||
|
31 | #------------------------------------------------------------------------- | |||
|
32 | # EmbeddedKernel interface | |||
|
33 | #------------------------------------------------------------------------- | |||
|
34 | ||||
|
35 | frontends = List( | |||
|
36 | Instance('IPython.embedded.kernelmanager.EmbeddedKernelManager')) | |||
|
37 | ||||
|
38 | raw_input_str = Any() | |||
|
39 | stdout = Any() | |||
|
40 | stderr = Any() | |||
|
41 | ||||
|
42 | #------------------------------------------------------------------------- | |||
|
43 | # Kernel interface | |||
|
44 | #------------------------------------------------------------------------- | |||
|
45 | ||||
|
46 | shell_streams = List() | |||
|
47 | control_stream = Any() | |||
|
48 | iopub_socket = Instance(DummySocket, ()) | |||
|
49 | stdin_socket = Instance(DummySocket, ()) | |||
|
50 | ||||
|
51 | def __init__(self, **traits): | |||
|
52 | # When an InteractiveShell is instantiated by our base class, it binds | |||
|
53 | # the current values of sys.stdout and sys.stderr. | |||
|
54 | with self._redirected_io(): | |||
|
55 | super(EmbeddedKernel, self).__init__(**traits) | |||
|
56 | ||||
|
57 | self.iopub_socket.on_trait_change(self._io_dispatch, 'message_sent') | |||
|
58 | ||||
|
59 | def execute_request(self, stream, ident, parent): | |||
|
60 | """ Override for temporary IO redirection. """ | |||
|
61 | with self._redirected_io(): | |||
|
62 | super(EmbeddedKernel, self).execute_request(stream, ident, parent) | |||
|
63 | ||||
|
64 | def start(self): | |||
|
65 | """ Override registration of dispatchers for streams. """ | |||
|
66 | self.shell.exit_now = False | |||
|
67 | ||||
|
68 | def _abort_queue(self, stream): | |||
|
69 | """ The embedded kernel don't abort requests. """ | |||
|
70 | pass | |||
|
71 | ||||
|
72 | def _raw_input(self, prompt, ident, parent): | |||
|
73 | # Flush output before making the request. | |||
|
74 | self.raw_input_str = None | |||
|
75 | sys.stderr.flush() | |||
|
76 | sys.stdout.flush() | |||
|
77 | ||||
|
78 | # Send the input request. | |||
|
79 | content = json_clean(dict(prompt=prompt)) | |||
|
80 | msg = self.session.msg(u'input_request', content, parent) | |||
|
81 | for frontend in self.frontends: | |||
|
82 | if frontend.session.session == parent['header']['session']: | |||
|
83 | frontend.stdin_channel.call_handlers(msg) | |||
|
84 | break | |||
|
85 | else: | |||
|
86 | log.error('No frontend found for raw_input request') | |||
|
87 | return str() | |||
|
88 | ||||
|
89 | # Await a response. | |||
|
90 | while self.raw_input_str is None: | |||
|
91 | frontend.stdin_channel.process_events() | |||
|
92 | return self.raw_input_str | |||
|
93 | ||||
|
94 | #------------------------------------------------------------------------- | |||
|
95 | # Protected interface | |||
|
96 | #------------------------------------------------------------------------- | |||
|
97 | ||||
|
98 | @contextmanager | |||
|
99 | def _redirected_io(self): | |||
|
100 | """ Temporarily redirect IO to the kernel. | |||
|
101 | """ | |||
|
102 | sys_stdout, sys_stderr = sys.stdout, sys.stderr | |||
|
103 | sys.stdout, sys.stderr = self.stdout, self.stderr | |||
|
104 | yield | |||
|
105 | sys.stdout, sys.stderr = sys_stdout, sys_stderr | |||
|
106 | ||||
|
107 | #------ Trait change handlers -------------------------------------------- | |||
|
108 | ||||
|
109 | def _io_dispatch(self): | |||
|
110 | """ Called when a message is sent to the IO socket. | |||
|
111 | """ | |||
|
112 | ident, msg = self.session.recv(self.iopub_socket, copy=False) | |||
|
113 | for frontend in self.frontends: | |||
|
114 | frontend.sub_channel.call_handlers(msg) | |||
|
115 | ||||
|
116 | #------ Trait initializers ----------------------------------------------- | |||
|
117 | ||||
|
118 | def _log_default(self): | |||
|
119 | return logging.getLogger(__name__) | |||
|
120 | ||||
|
121 | def _session_default(self): | |||
|
122 | from IPython.zmq.session import Session | |||
|
123 | return Session(config=self.config) | |||
|
124 | ||||
|
125 | def _stdout_default(self): | |||
|
126 | from IPython.zmq.iostream import OutStream | |||
|
127 | return OutStream(self.session, self.iopub_socket, u'stdout') | |||
|
128 | ||||
|
129 | def _stderr_default(self): | |||
|
130 | from IPython.zmq.iostream import OutStream | |||
|
131 | return OutStream(self.session, self.iopub_socket, u'stderr') |
@@ -13,6 +13,7 b'' | |||||
13 |
|
13 | |||
14 | # Local imports. |
|
14 | # Local imports. | |
15 | from IPython.config.loader import Config |
|
15 | from IPython.config.loader import Config | |
|
16 | from IPython.embedded.socket import DummySocket | |||
16 | from IPython.utils.traitlets import HasTraits, Any, Instance, Type |
|
17 | from IPython.utils.traitlets import HasTraits, Any, Instance, Type | |
17 |
|
18 | |||
18 | #----------------------------------------------------------------------------- |
|
19 | #----------------------------------------------------------------------------- | |
@@ -77,6 +78,10 b' class ShellEmbeddedChannel(EmbeddedChannel):' | |||||
77 | # flag for whether execute requests should be allowed to call raw_input |
|
78 | # flag for whether execute requests should be allowed to call raw_input | |
78 | allow_stdin = True |
|
79 | allow_stdin = True | |
79 |
|
80 | |||
|
81 | #-------------------------------------------------------------------------- | |||
|
82 | # ShellChannel interface | |||
|
83 | #-------------------------------------------------------------------------- | |||
|
84 | ||||
80 | def execute(self, code, silent=False, store_history=True, |
|
85 | def execute(self, code, silent=False, store_history=True, | |
81 | user_variables=[], user_expressions={}, allow_stdin=None): |
|
86 | user_variables=[], user_expressions={}, allow_stdin=None): | |
82 | """Execute code in the kernel. |
|
87 | """Execute code in the kernel. | |
@@ -115,7 +120,15 b' class ShellEmbeddedChannel(EmbeddedChannel):' | |||||
115 | ------- |
|
120 | ------- | |
116 | The msg_id of the message sent. |
|
121 | The msg_id of the message sent. | |
117 | """ |
|
122 | """ | |
118 | raise NotImplementedError |
|
123 | if allow_stdin is None: | |
|
124 | allow_stdin = self.allow_stdin | |||
|
125 | content = dict(code=code, silent=silent, store_history=store_history, | |||
|
126 | user_variables=user_variables, | |||
|
127 | user_expressions=user_expressions, | |||
|
128 | allow_stdin=allow_stdin) | |||
|
129 | msg = self.manager.session.msg('execute_request', content) | |||
|
130 | self._dispatch_to_kernel(msg) | |||
|
131 | return msg['header']['msg_id'] | |||
119 |
|
132 | |||
120 | def complete(self, text, line, cursor_pos, block=None): |
|
133 | def complete(self, text, line, cursor_pos, block=None): | |
121 | """Tab complete text in the kernel's namespace. |
|
134 | """Tab complete text in the kernel's namespace. | |
@@ -137,7 +150,10 b' class ShellEmbeddedChannel(EmbeddedChannel):' | |||||
137 | ------- |
|
150 | ------- | |
138 | The msg_id of the message sent. |
|
151 | The msg_id of the message sent. | |
139 | """ |
|
152 | """ | |
140 | raise NotImplementedError |
|
153 | content = dict(text=text, line=line, block=block, cursor_pos=cursor_pos) | |
|
154 | msg = self.manager.session.msg('complete_request', content) | |||
|
155 | self._dispatch_to_kernel(msg) | |||
|
156 | return msg['header']['msg_id'] | |||
141 |
|
157 | |||
142 | def object_info(self, oname, detail_level=0): |
|
158 | def object_info(self, oname, detail_level=0): | |
143 | """Get metadata information about an object. |
|
159 | """Get metadata information about an object. | |
@@ -153,7 +169,10 b' class ShellEmbeddedChannel(EmbeddedChannel):' | |||||
153 | ------- |
|
169 | ------- | |
154 | The msg_id of the message sent. |
|
170 | The msg_id of the message sent. | |
155 | """ |
|
171 | """ | |
156 | raise NotImplementedError |
|
172 | content = dict(oname=oname, detail_level=detail_level) | |
|
173 | msg = self.manager.session.msg('object_info_request', content) | |||
|
174 | self._dispatch_to_kernel(msg) | |||
|
175 | return msg['header']['msg_id'] | |||
157 |
|
176 | |||
158 | def history(self, raw=True, output=False, hist_access_type='range', **kwds): |
|
177 | def history(self, raw=True, output=False, hist_access_type='range', **kwds): | |
159 | """Get entries from the history list. |
|
178 | """Get entries from the history list. | |
@@ -187,7 +206,11 b' class ShellEmbeddedChannel(EmbeddedChannel):' | |||||
187 | ------- |
|
206 | ------- | |
188 | The msg_id of the message sent. |
|
207 | The msg_id of the message sent. | |
189 | """ |
|
208 | """ | |
190 | raise NotImplementedError |
|
209 | content = dict(raw=raw, output=output, | |
|
210 | hist_access_type=hist_access_type, **kwds) | |||
|
211 | msg = self.manager.session.msg('history_request', content) | |||
|
212 | self._dispatch_to_kernel(msg) | |||
|
213 | return msg['header']['msg_id'] | |||
191 |
|
214 | |||
192 | def shutdown(self, restart=False): |
|
215 | def shutdown(self, restart=False): | |
193 | """ Request an immediate kernel shutdown. |
|
216 | """ Request an immediate kernel shutdown. | |
@@ -197,6 +220,25 b' class ShellEmbeddedChannel(EmbeddedChannel):' | |||||
197 | # FIXME: What to do here? |
|
220 | # FIXME: What to do here? | |
198 | raise NotImplementedError('Shutdown not supported for embedded kernel') |
|
221 | raise NotImplementedError('Shutdown not supported for embedded kernel') | |
199 |
|
222 | |||
|
223 | #-------------------------------------------------------------------------- | |||
|
224 | # Protected interface | |||
|
225 | #-------------------------------------------------------------------------- | |||
|
226 | ||||
|
227 | def _dispatch_to_kernel(self, msg): | |||
|
228 | """ Send a message to the kernel and handle a reply. | |||
|
229 | """ | |||
|
230 | kernel = self.manager.kernel | |||
|
231 | if kernel is None: | |||
|
232 | raise RuntimeError('Cannot send request. No kernel exists.') | |||
|
233 | ||||
|
234 | stream = DummySocket() | |||
|
235 | self.manager.session.send(stream, msg) | |||
|
236 | msg_parts = stream.recv_multipart() | |||
|
237 | kernel.dispatch_shell(stream, msg_parts) | |||
|
238 | ||||
|
239 | idents, reply_msg = self.manager.session.recv(stream, copy=False) | |||
|
240 | self.call_handlers_later(reply_msg) | |||
|
241 | ||||
200 |
|
242 | |||
201 | class SubEmbeddedChannel(EmbeddedChannel): |
|
243 | class SubEmbeddedChannel(EmbeddedChannel): | |
202 | """The SUB channel which listens for messages that the kernel publishes. |
|
244 | """The SUB channel which listens for messages that the kernel publishes. | |
@@ -216,7 +258,10 b' class StdInEmbeddedChannel(EmbeddedChannel):' | |||||
216 | def input(self, string): |
|
258 | def input(self, string): | |
217 | """ Send a string of raw input to the kernel. |
|
259 | """ Send a string of raw input to the kernel. | |
218 | """ |
|
260 | """ | |
219 | raise NotImplementedError |
|
261 | kernel = self.manager.kernel | |
|
262 | if kernel is None: | |||
|
263 | raise RuntimeError('Cannot send input reply. No kernel exists.') | |||
|
264 | kernel.raw_input_str = string | |||
220 |
|
265 | |||
221 |
|
266 | |||
222 | class HBEmbeddedChannel(EmbeddedChannel): |
|
267 | class HBEmbeddedChannel(EmbeddedChannel): |
@@ -15,7 +15,7 b'' | |||||
15 | from IPython.config import Configurable |
|
15 | from IPython.config import Configurable | |
16 |
|
16 | |||
17 | from IPython.utils.jsonutil import json_clean |
|
17 | from IPython.utils.jsonutil import json_clean | |
18 | from IPython.utils.traitlets import Instance, Dict, CBytes |
|
18 | from IPython.utils.traitlets import Any, Instance, Dict, CBytes | |
19 |
|
19 | |||
20 | from IPython.zmq.serialize import serialize_object |
|
20 | from IPython.zmq.serialize import serialize_object | |
21 | from IPython.zmq.session import Session, extract_header |
|
21 | from IPython.zmq.session import Session, extract_header | |
@@ -29,7 +29,7 b' class ZMQDataPublisher(Configurable):' | |||||
29 |
|
29 | |||
30 | topic = topic = CBytes(b'datapub') |
|
30 | topic = topic = CBytes(b'datapub') | |
31 | session = Instance(Session) |
|
31 | session = Instance(Session) | |
32 |
pub_socket = |
|
32 | pub_socket = Any() | |
33 | parent_header = Dict({}) |
|
33 | parent_header = Dict({}) | |
34 |
|
34 | |||
35 | def set_parent(self, parent): |
|
35 | def set_parent(self, parent): |
@@ -3,7 +3,7 b' import sys' | |||||
3 |
|
3 | |||
4 | from IPython.core.displayhook import DisplayHook |
|
4 | from IPython.core.displayhook import DisplayHook | |
5 | from IPython.utils.jsonutil import encode_images |
|
5 | from IPython.utils.jsonutil import encode_images | |
6 | from IPython.utils.traitlets import Instance, Dict |
|
6 | from IPython.utils.traitlets import Any, Instance, Dict | |
7 | from session import extract_header, Session |
|
7 | from session import extract_header, Session | |
8 |
|
8 | |||
9 | class ZMQDisplayHook(object): |
|
9 | class ZMQDisplayHook(object): | |
@@ -37,7 +37,7 b' class ZMQShellDisplayHook(DisplayHook):' | |||||
37 | topic=None |
|
37 | topic=None | |
38 |
|
38 | |||
39 | session = Instance(Session) |
|
39 | session = Instance(Session) | |
40 |
pub_socket = |
|
40 | pub_socket = Any() | |
41 | parent_header = Dict({}) |
|
41 | parent_header = Dict({}) | |
42 |
|
42 | |||
43 | def set_parent(self, parent): |
|
43 | def set_parent(self, parent): |
@@ -644,7 +644,6 b' class Kernel(Configurable):' | |||||
644 | # Protected interface |
|
644 | # Protected interface | |
645 | #--------------------------------------------------------------------------- |
|
645 | #--------------------------------------------------------------------------- | |
646 |
|
646 | |||
647 |
|
||||
648 | def _wrap_exception(self, method=None): |
|
647 | def _wrap_exception(self, method=None): | |
649 | # import here, because _wrap_exception is only used in parallel, |
|
648 | # import here, because _wrap_exception is only used in parallel, | |
650 | # and parallel has higher min pyzmq version |
|
649 | # and parallel has higher min pyzmq version | |
@@ -739,36 +738,6 b' class Kernel(Configurable):' | |||||
739 | cpos = len(c['line']) |
|
738 | cpos = len(c['line']) | |
740 | return self.shell.complete(c['text'], c['line'], cpos) |
|
739 | return self.shell.complete(c['text'], c['line'], cpos) | |
741 |
|
740 | |||
742 | def _object_info(self, context): |
|
|||
743 | symbol, leftover = self._symbol_from_context(context) |
|
|||
744 | if symbol is not None and not leftover: |
|
|||
745 | doc = getattr(symbol, '__doc__', '') |
|
|||
746 | else: |
|
|||
747 | doc = '' |
|
|||
748 | object_info = dict(docstring = doc) |
|
|||
749 | return object_info |
|
|||
750 |
|
||||
751 | def _symbol_from_context(self, context): |
|
|||
752 | if not context: |
|
|||
753 | return None, context |
|
|||
754 |
|
||||
755 | base_symbol_string = context[0] |
|
|||
756 | symbol = self.shell.user_ns.get(base_symbol_string, None) |
|
|||
757 | if symbol is None: |
|
|||
758 | symbol = __builtin__.__dict__.get(base_symbol_string, None) |
|
|||
759 | if symbol is None: |
|
|||
760 | return None, context |
|
|||
761 |
|
||||
762 | context = context[1:] |
|
|||
763 | for i, name in enumerate(context): |
|
|||
764 | new_symbol = getattr(symbol, name, None) |
|
|||
765 | if new_symbol is None: |
|
|||
766 | return symbol, context[i:] |
|
|||
767 | else: |
|
|||
768 | symbol = new_symbol |
|
|||
769 |
|
||||
770 | return symbol, [] |
|
|||
771 |
|
||||
772 | def _at_shutdown(self): |
|
741 | def _at_shutdown(self): | |
773 | """Actions taken at shutdown by the kernel, called by python's atexit. |
|
742 | """Actions taken at shutdown by the kernel, called by python's atexit. | |
774 | """ |
|
743 | """ |
@@ -558,11 +558,9 b' class Session(Configurable):' | |||||
558 | msg : dict |
|
558 | msg : dict | |
559 | The constructed message. |
|
559 | The constructed message. | |
560 | """ |
|
560 | """ | |
561 |
|
561 | if not isinstance(stream, zmq.Socket): | ||
562 | if not isinstance(stream, (zmq.Socket, ZMQStream)): |
|
562 | # ZMQStreams and dummy sockets do not support tracking. | |
563 | raise TypeError("stream must be Socket or ZMQStream, not %r"%type(stream)) |
|
563 | track = False | |
564 | elif track and isinstance(stream, ZMQStream): |
|
|||
565 | raise TypeError("ZMQStream cannot track messages") |
|
|||
566 |
|
564 | |||
567 | if isinstance(msg_or_type, (Message, dict)): |
|
565 | if isinstance(msg_or_type, (Message, dict)): | |
568 | # We got a Message or message dict, not a msg_type so don't |
|
566 | # We got a Message or message dict, not a msg_type so don't |
@@ -42,7 +42,7 b' from IPython.utils import io, openpy' | |||||
42 | from IPython.utils.jsonutil import json_clean, encode_images |
|
42 | from IPython.utils.jsonutil import json_clean, encode_images | |
43 | from IPython.utils.process import arg_split |
|
43 | from IPython.utils.process import arg_split | |
44 | from IPython.utils import py3compat |
|
44 | from IPython.utils import py3compat | |
45 | from IPython.utils.traitlets import Instance, Type, Dict, CBool, CBytes |
|
45 | from IPython.utils.traitlets import Any, Instance, Type, Dict, CBool, CBytes | |
46 | from IPython.utils.warn import warn, error |
|
46 | from IPython.utils.warn import warn, error | |
47 | from IPython.zmq.displayhook import ZMQShellDisplayHook |
|
47 | from IPython.zmq.displayhook import ZMQShellDisplayHook | |
48 | from IPython.zmq.datapub import ZMQDataPublisher |
|
48 | from IPython.zmq.datapub import ZMQDataPublisher | |
@@ -57,7 +57,7 b' class ZMQDisplayPublisher(DisplayPublisher):' | |||||
57 | """A display publisher that publishes data using a ZeroMQ PUB socket.""" |
|
57 | """A display publisher that publishes data using a ZeroMQ PUB socket.""" | |
58 |
|
58 | |||
59 | session = Instance(Session) |
|
59 | session = Instance(Session) | |
60 |
pub_socket = |
|
60 | pub_socket = Any() | |
61 | parent_header = Dict({}) |
|
61 | parent_header = Dict({}) | |
62 | topic = CBytes(b'displaypub') |
|
62 | topic = CBytes(b'displaypub') | |
63 |
|
63 |
General Comments 0
You need to be logged in to leave comments.
Login now