##// END OF EJS Templates
Update messaging doc with refinements about user variables/expressions.
Fernando Perez -
Show More
@@ -1,104 +1,104 b''
1 # Makefile for Sphinx documentation
1 # Makefile for Sphinx documentation
2 #
2 #
3
3
4 # You can set these variables from the command line.
4 # You can set these variables from the command line.
5 SPHINXOPTS =
5 SPHINXOPTS =
6 SPHINXBUILD = sphinx-build
6 SPHINXBUILD = sphinx-build
7 PAPER =
7 PAPER =
8 SRCDIR = source
8 SRCDIR = source
9
9
10 # Internal variables.
10 # Internal variables.
11 PAPEROPT_a4 = -D latex_paper_size=a4
11 PAPEROPT_a4 = -D latex_paper_size=a4
12 PAPEROPT_letter = -D latex_paper_size=letter
12 PAPEROPT_letter = -D latex_paper_size=letter
13 ALLSPHINXOPTS = -d build/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) $(SRCDIR)
13 ALLSPHINXOPTS = -d build/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) $(SRCDIR)
14
14
15 .PHONY: help clean html web pickle htmlhelp latex changes linkcheck api
15 .PHONY: help clean html web pickle htmlhelp latex changes linkcheck api
16
16
17 default: html
17 default: html
18
18
19 help:
19 help:
20 @echo "Please use \`make <target>' where <target> is one of"
20 @echo "Please use \`make <target>' where <target> is one of"
21 @echo " html to make standalone HTML files"
21 @echo " html to make standalone HTML files"
22 @echo " pickle to make pickle files (usable by e.g. sphinx-web)"
22 @echo " pickle to make pickle files (usable by e.g. sphinx-web)"
23 @echo " htmlhelp to make HTML files and a HTML help project"
23 @echo " htmlhelp to make HTML files and a HTML help project"
24 @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
24 @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
25 @echo " changes to make an overview over all changed/added/deprecated items"
25 @echo " changes to make an overview over all changed/added/deprecated items"
26 @echo " linkcheck to check all external links for integrity"
26 @echo " linkcheck to check all external links for integrity"
27 @echo
27 @echo
28 @echo "Compound utility targets:"
28 @echo "Compound utility targets:"
29 @echo "pdf latex and then runs the PDF generation"
29 @echo "pdf latex and then runs the PDF generation"
30 @echo "all html and pdf"
30 @echo "all html and pdf"
31 @echo "dist all, and then puts the results in dist/"
31 @echo "dist all, and then puts the results in dist/"
32 @echo "gitwash-update update git workflow from source repo"
32 @echo "gitwash-update update git workflow from source repo"
33
33
34 clean:
34 clean:
35 -rm -rf build/* dist/* $(SRCDIR)/api/generated
35 -rm -rf build/* dist/* $(SRCDIR)/api/generated
36
36
37 pdf: latex
37 pdf: latex
38 cd build/latex && make all-pdf
38 cd build/latex && make all-pdf
39
39
40 all: html pdf
40 all: html pdf
41
41
42 dist: all
42 dist: all
43 mkdir -p dist
43 mkdir -p dist
44 rm -rf dist/*
44 rm -rf dist/*
45 ln build/latex/ipython.pdf dist/
45 ln build/latex/ipython.pdf dist/
46 cp -al build/html dist/
46 cp -al build/html dist/
47 @echo "Build finished. Final docs are in dist/"
47 @echo "Build finished. Final docs are in dist/"
48
48
49 html: api
49 html: api
50 mkdir -p build/html build/doctrees
50 mkdir -p build/html build/doctrees
51 $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) build/html
51 $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) build/html
52 @echo
52 @echo
53 @echo "Build finished. The HTML pages are in build/html."
53 @echo "Build finished. The HTML pages are in build/html."
54
54
55 api: source/api/generated/gen.txt
55 api: source/api/generated/gen.txt
56
56
57 source/api/generated/gen.txt:
57 source/api/generated/gen.txt:
58 python autogen_api.py
58 python autogen_api.py
59 @echo "Build API docs finished."
59 @echo "Build API docs finished."
60
60
61 pickle:
61 pickle:
62 mkdir -p build/pickle build/doctrees
62 mkdir -p build/pickle build/doctrees
63 $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) build/pickle
63 $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) build/pickle
64 @echo
64 @echo
65 @echo "Build finished; now you can process the pickle files or run"
65 @echo "Build finished; now you can process the pickle files or run"
66 @echo " sphinx-web build/pickle"
66 @echo " sphinx-web build/pickle"
67 @echo "to start the sphinx-web server."
67 @echo "to start the sphinx-web server."
68
68
69 web: pickle
69 web: pickle
70
70
71 htmlhelp:
71 htmlhelp:
72 mkdir -p build/htmlhelp build/doctrees
72 mkdir -p build/htmlhelp build/doctrees
73 $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) build/htmlhelp
73 $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) build/htmlhelp
74 @echo
74 @echo
75 @echo "Build finished; now you can run HTML Help Workshop with the" \
75 @echo "Build finished; now you can run HTML Help Workshop with the" \
76 ".hhp project file in build/htmlhelp."
76 ".hhp project file in build/htmlhelp."
77
77
78 latex: api
78 latex: api
79 mkdir -p build/latex build/doctrees
79 mkdir -p build/latex build/doctrees
80 $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) build/latex
80 $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) build/latex
81 @echo
81 @echo
82 @echo "Build finished; the LaTeX files are in build/latex."
82 @echo "Build finished; the LaTeX files are in build/latex."
83 @echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \
83 @echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \
84 "run these through (pdf)latex."
84 "run these through (pdf)latex."
85
85
86 changes:
86 changes:
87 mkdir -p build/changes build/doctrees
87 mkdir -p build/changes build/doctrees
88 $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) build/changes
88 $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) build/changes
89 @echo
89 @echo
90 @echo "The overview file is in build/changes."
90 @echo "The overview file is in build/changes."
91
91
92 linkcheck:
92 linkcheck:
93 mkdir -p build/linkcheck build/doctrees
93 mkdir -p build/linkcheck build/doctrees
94 $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) build/linkcheck
94 $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) build/linkcheck
95 @echo
95 @echo
96 @echo "Link check complete; look for any errors in the above output " \
96 @echo "Link check complete; look for any errors in the above output " \
97 "or in build/linkcheck/output.txt."
97 "or in build/linkcheck/output.txt."
98
98
99 gitwash-update:
99 gitwash-update:
100 python ../tools/gitwash_dumper.py source/development ipython
100 python ../tools/gitwash_dumper.py source/development ipython
101 cd source/development/gitwash && rename 's/.rst/.txt/' *.rst
101 cd source/development/gitwash && rename 's/.rst/.txt/' *.rst
102
102
103 nightly: dist
103 nightly: dist
104 rsync -avH --delete dist/ ipython:www/doc/nightly No newline at end of file
104 rsync -avH --delete dist/ ipython:www/doc/nightly
@@ -1,668 +1,708 b''
1 .. _messaging:
1 .. _messaging:
2
2
3 ======================
3 ======================
4 Messaging in IPython
4 Messaging in IPython
5 ======================
5 ======================
6
6
7
7
8 Introduction
8 Introduction
9 ============
9 ============
10
10
11 This document explains the basic communications design and messaging
11 This document explains the basic communications design and messaging
12 specification for how the various IPython objects interact over a network
12 specification for how the various IPython objects interact over a network
13 transport. The current implementation uses the ZeroMQ_ library for messaging
13 transport. The current implementation uses the ZeroMQ_ library for messaging
14 within and between hosts.
14 within and between hosts.
15
15
16 .. Note::
16 .. Note::
17
17
18 This document should be considered the authoritative description of the
18 This document should be considered the authoritative description of the
19 IPython messaging protocol, and all developers are strongly encouraged to
19 IPython messaging protocol, and all developers are strongly encouraged to
20 keep it updated as the implementation evolves, so that we have a single
20 keep it updated as the implementation evolves, so that we have a single
21 common reference for all protocol details.
21 common reference for all protocol details.
22
22
23 The basic design is explained in the following diagram:
23 The basic design is explained in the following diagram:
24
24
25 .. image:: frontend-kernel.png
25 .. image:: frontend-kernel.png
26 :width: 450px
26 :width: 450px
27 :alt: IPython kernel/frontend messaging architecture.
27 :alt: IPython kernel/frontend messaging architecture.
28 :align: center
28 :align: center
29 :target: ../_images/frontend-kernel.png
29 :target: ../_images/frontend-kernel.png
30
30
31 A single kernel can be simultaneously connected to one or more frontends. The
31 A single kernel can be simultaneously connected to one or more frontends. The
32 kernel has three sockets that serve the following functions:
32 kernel has three sockets that serve the following functions:
33
33
34 1. REQ: this socket is connected to a *single* frontend at a time, and it allows
34 1. REQ: this socket is connected to a *single* frontend at a time, and it allows
35 the kernel to request input from a frontend when :func:`raw_input` is called.
35 the kernel to request input from a frontend when :func:`raw_input` is called.
36 The frontend holding the matching REP socket acts as a 'virtual keyboard'
36 The frontend holding the matching REP socket acts as a 'virtual keyboard'
37 for the kernel while this communication is happening (illustrated in the
37 for the kernel while this communication is happening (illustrated in the
38 figure by the black outline around the central keyboard). In practice,
38 figure by the black outline around the central keyboard). In practice,
39 frontends may display such kernel requests using a special input widget or
39 frontends may display such kernel requests using a special input widget or
40 otherwise indicating that the user is to type input for the kernel instead
40 otherwise indicating that the user is to type input for the kernel instead
41 of normal commands in the frontend.
41 of normal commands in the frontend.
42
42
43 2. XREP: this single sockets allows multiple incoming connections from
43 2. XREP: this single sockets allows multiple incoming connections from
44 frontends, and this is the socket where requests for code execution, object
44 frontends, and this is the socket where requests for code execution, object
45 information, prompts, etc. are made to the kernel by any frontend. The
45 information, prompts, etc. are made to the kernel by any frontend. The
46 communication on this socket is a sequence of request/reply actions from
46 communication on this socket is a sequence of request/reply actions from
47 each frontend and the kernel.
47 each frontend and the kernel.
48
48
49 3. PUB: this socket is the 'broadcast channel' where the kernel publishes all
49 3. PUB: this socket is the 'broadcast channel' where the kernel publishes all
50 side effects (stdout, stderr, etc.) as well as the requests coming from any
50 side effects (stdout, stderr, etc.) as well as the requests coming from any
51 client over the XREP socket and its own requests on the REP socket. There
51 client over the XREP socket and its own requests on the REP socket. There
52 are a number of actions in Python which generate side effects: :func:`print`
52 are a number of actions in Python which generate side effects: :func:`print`
53 writes to ``sys.stdout``, errors generate tracebacks, etc. Additionally, in
53 writes to ``sys.stdout``, errors generate tracebacks, etc. Additionally, in
54 a multi-client scenario, we want all frontends to be able to know what each
54 a multi-client scenario, we want all frontends to be able to know what each
55 other has sent to the kernel (this can be useful in collaborative scenarios,
55 other has sent to the kernel (this can be useful in collaborative scenarios,
56 for example). This socket allows both side effects and the information
56 for example). This socket allows both side effects and the information
57 about communications taking place with one client over the XREQ/XREP channel
57 about communications taking place with one client over the XREQ/XREP channel
58 to be made available to all clients in a uniform manner.
58 to be made available to all clients in a uniform manner.
59
59
60 All messages are tagged with enough information (details below) for clients
60 All messages are tagged with enough information (details below) for clients
61 to know which messages come from their own interaction with the kernel and
61 to know which messages come from their own interaction with the kernel and
62 which ones are from other clients, so they can display each type
62 which ones are from other clients, so they can display each type
63 appropriately.
63 appropriately.
64
64
65 The actual format of the messages allowed on each of these channels is
65 The actual format of the messages allowed on each of these channels is
66 specified below. Messages are dicts of dicts with string keys and values that
66 specified below. Messages are dicts of dicts with string keys and values that
67 are reasonably representable in JSON. Our current implementation uses JSON
67 are reasonably representable in JSON. Our current implementation uses JSON
68 explicitly as its message format, but this shouldn't be considered a permanent
68 explicitly as its message format, but this shouldn't be considered a permanent
69 feature. As we've discovered that JSON has non-trivial performance issues due
69 feature. As we've discovered that JSON has non-trivial performance issues due
70 to excessive copying, we may in the future move to a pure pickle-based raw
70 to excessive copying, we may in the future move to a pure pickle-based raw
71 message format. However, it should be possible to easily convert from the raw
71 message format. However, it should be possible to easily convert from the raw
72 objects to JSON, since we may have non-python clients (e.g. a web frontend).
72 objects to JSON, since we may have non-python clients (e.g. a web frontend).
73 As long as it's easy to make a JSON version of the objects that is a faithful
73 As long as it's easy to make a JSON version of the objects that is a faithful
74 representation of all the data, we can communicate with such clients.
74 representation of all the data, we can communicate with such clients.
75
75
76 .. Note::
76 .. Note::
77
77
78 Not all of these have yet been fully fleshed out, but the key ones are, see
78 Not all of these have yet been fully fleshed out, but the key ones are, see
79 kernel and frontend files for actual implementation details.
79 kernel and frontend files for actual implementation details.
80
80
81
81
82 Python functional API
82 Python functional API
83 =====================
83 =====================
84
84
85 As messages are dicts, they map naturally to a ``func(**kw)`` call form. We
85 As messages are dicts, they map naturally to a ``func(**kw)`` call form. We
86 should develop, at a few key points, functional forms of all the requests that
86 should develop, at a few key points, functional forms of all the requests that
87 take arguments in this manner and automatically construct the necessary dict
87 take arguments in this manner and automatically construct the necessary dict
88 for sending.
88 for sending.
89
89
90
90
91 General Message Format
91 General Message Format
92 ======================
92 ======================
93
93
94 All messages send or received by any IPython process should have the following
94 All messages send or received by any IPython process should have the following
95 generic structure::
95 generic structure::
96
96
97 {
97 {
98 # The message header contains a pair of unique identifiers for the
98 # The message header contains a pair of unique identifiers for the
99 # originating session and the actual message id, in addition to the
99 # originating session and the actual message id, in addition to the
100 # username for the process that generated the message. This is useful in
100 # username for the process that generated the message. This is useful in
101 # collaborative settings where multiple users may be interacting with the
101 # collaborative settings where multiple users may be interacting with the
102 # same kernel simultaneously, so that frontends can label the various
102 # same kernel simultaneously, so that frontends can label the various
103 # messages in a meaningful way.
103 # messages in a meaningful way.
104 'header' : { 'msg_id' : uuid,
104 'header' : { 'msg_id' : uuid,
105 'username' : str,
105 'username' : str,
106 'session' : uuid
106 'session' : uuid
107 },
107 },
108
108
109 # In a chain of messages, the header from the parent is copied so that
109 # In a chain of messages, the header from the parent is copied so that
110 # clients can track where messages come from.
110 # clients can track where messages come from.
111 'parent_header' : dict,
111 'parent_header' : dict,
112
112
113 # All recognized message type strings are listed below.
113 # All recognized message type strings are listed below.
114 'msg_type' : str,
114 'msg_type' : str,
115
115
116 # The actual content of the message must be a dict, whose structure
116 # The actual content of the message must be a dict, whose structure
117 # depends on the message type.x
117 # depends on the message type.x
118 'content' : dict,
118 'content' : dict,
119 }
119 }
120
120
121 For each message type, the actual content will differ and all existing message
121 For each message type, the actual content will differ and all existing message
122 types are specified in what follows of this document.
122 types are specified in what follows of this document.
123
123
124
124
125 Messages on the XREP/XREQ socket
125 Messages on the XREP/XREQ socket
126 ================================
126 ================================
127
127
128 .. _execute:
128 .. _execute:
129
129
130 Execute
130 Execute
131 -------
131 -------
132
132
133 The execution request contains a single string, but this may be a multiline
133 This message type is used by frontends to ask the kernel to execute code on
134 string. The kernel is responsible for splitting this into possibly more than
134 behalf of the user, in a namespace reserved to the user's variables (and thus
135 one block and deciding whether to compile these in 'single' or 'exec' mode.
135 separate from the kernel's own internal code and variables).
136 We're still sorting out this policy. The current inputsplitter is capable of
137 splitting the input for blocks that can all be run as 'single', but in the long
138 run it may prove cleaner to only use 'single' mode for truly single-line
139 inputs, and run all multiline input in 'exec' mode. This would preserve the
140 natural behavior of single-line inputs while allowing long cells to behave more
141 likea a script. This design will be refined as we complete the implementation.
142
143 .. Note::
144
145 What today we call 'prompt requests' will be encoded in the
146 ``state_template`` field.
147
136
148 Message type: ``execute_request``::
137 Message type: ``execute_request``::
149
138
150 content = {
139 content = {
151 # Source code to be executed by the kernel, one or more lines.
140 # Source code to be executed by the kernel, one or more lines.
152 'code' : str,
141 'code' : str,
153
142
154 # A boolean flag which, if True, signals the kernel to execute this
143 # A boolean flag which, if True, signals the kernel to execute this
155 # code as quietly as possible. This means that the kernel will compile
144 # code as quietly as possible. This means that the kernel will compile
156 # the code witIPython/core/tests/h 'exec' instead of 'single' (so
145 # the code witIPython/core/tests/h 'exec' instead of 'single' (so
157 # sys.displayhook will not fire), and will *not*:
146 # sys.displayhook will not fire), and will *not*:
158 # - broadcast exceptions on the PUB socket
147 # - broadcast exceptions on the PUB socket
159 # - do any logging
148 # - do any logging
160 # - populate any history
149 # - populate any history
161 #
150 #
162 # The default is False.
151 # The default is False.
163 'silent' : bool,
152 'silent' : bool,
164
153
165 # An optional string to request arbitrary state information from the
154 # A list of variable names from the user's namespace to be retrieved. What
166 # kernel. This string is evaluated via the itpl module, and it can
155 # returns is a JSON string of the variable's repr(), not a python object.
167 # therefore contain arbitrary code for execution.
156 'user_variables' : list,
168
157
169 'state_template' : str,
158 # Similarly, a dict mapping names to expressions to be evaluated in the
159 # user's dict.
160 'user_expressions' : dict,
170 }
161 }
171
162
163 The ``code`` field contains a single string, but this may be a multiline
164 string. The kernel is responsible for splitting this into possibly more than
165 one block and deciding whether to compile these in 'single' or 'exec' mode.
166 We're still sorting out this policy. The current inputsplitter is capable of
167 splitting the input for blocks that can all be run as 'single', but in the long
168 run it may prove cleaner to only use 'single' mode for truly single-line
169 inputs, and run all multiline input in 'exec' mode. This would preserve the
170 natural behavior of single-line inputs while allowing long cells to behave more
171 likea a script. This design will be refined as we complete the implementation.
172
173 The ``user_`` fields deserve a detailed explanation. In the past, IPython had
174 the notion of a prompt string that allowed arbitrary code to be evaluated, and
175 this was put to good use by many in creating prompts that displayed system
176 status, path information, and even more esoteric uses like remote instrument
177 status aqcuired over the network. But now that IPython has a clean separation
178 between the kernel and the clients, the notion of embedding 'prompt'
179 maninpulations into the kernel itself feels awkward. Prompts should be a
180 frontend-side feature, and it should be even possible for different frontends
181 to display different prompts while interacting with the same kernel.
182
183 We have therefore abandoned the idea of a 'prompt string' to be evaluated by
184 the kernel, and instead provide the ability to retrieve from the user's
185 namespace information after the execution of the main ``code``, with two fields
186 of the execution request:
187
188 - ``user_variables``: If only variables from the user's namespace are needed, a
189 list of variable names can be passed and a dict with these names as keys and
190 their :func:`repr()` as values will be returned.
191
192 - ``user_expressions``: For more complex expressions that require function
193 evaluations, a dict can be provided with string keys and arbitrary python
194 expressions as values. The return message will contain also a dict with the
195 same keys and the :func:`repr()` of the evaluated expressions as value.
196
197 With this information, frontends can display any status information they wish
198 in the form that best suits each frontend (a status line, a popup, inline for a
199 terminal, etc).
200
201 .. Note::
202
203 In order to obtain the current execution counter for the purposes of
204 displaying input prompts, frontends simply make an execution request with an
205 empty code string and ``silent=True``.
206
172 Execution semantics
207 Execution semantics
173 Upon execution of the ``code`` field, the kernel *always* sends a reply,
208 Upon completion of the execution request, the kernel *always* sends a
174 with a status code indicating what happened and additional data depending
209 reply, with a status code indicating what happened and additional data
175 on the outcome.
210 depending on the outcome.
211
212 The ``code`` field is executed first, and then the ``user_variables`` and
213 ``user_expressions`` are computed. This ensures that any error in the
214 latter don't harm the main code execution.
176
215
177 Any code in the ``state_template`` string is evaluated, but full exceptions
216 Any error in retrieving the ``user_variables`` or evaluating the
178 that may occur are *not* propagated back. If any error occurs during the
217 ``user_expressions`` will result in a simple error message in the return
179 evaluation, the value of the string will simply be::
218 fields of the form::
180
219
181 [ERROR in <contents of template>: ExceptionType - Exception message]
220 [ERROR] ExceptionType: Exception message
182
221
183 The user can simply send the same code contained in the template for normal
222 The user can simply send the same variable name or expression for
184 evaluation to see a regular traceback.
223 evaluation to see a regular traceback.
185
224
186 Execution counter (old prompt number)
225 Execution counter (old prompt number)
187 The kernel has a single, monotonically increasing counter of all execution
226 The kernel has a single, monotonically increasing counter of all execution
188 requests that are made with ``silent=False``. This counter is used to
227 requests that are made with ``silent=False``. This counter is used to
189 populate the ``In[n]``, ``Out[n]`` and ``_n`` variables, so clients will
228 populate the ``In[n]``, ``Out[n]`` and ``_n`` variables, so clients will
190 likely want to display it in some form to the user, which will typically
229 likely want to display it in some form to the user, which will typically
191 (but not necessarily) be done in the prompts. The value of this counter
230 (but not necessarily) be done in the prompts. The value of this counter
192 will be returned as the ``execution_count`` field of all ``execute_reply```
231 will be returned as the ``execution_count`` field of all ``execute_reply```
193 messages.
232 messages.
194
233
195 Message type: ``execute_reply``::
234 Message type: ``execute_reply``::
196
235
197 content = {
236 content = {
198 # One of: 'ok' OR 'error' OR 'abort'
237 # One of: 'ok' OR 'error' OR 'abort'
199 'status' : str,
238 'status' : str,
200
239
201 # The global kernel counter that increases by one with each non-silent
240 # The global kernel counter that increases by one with each non-silent
202 # executed request. This will typically be used by clients to display
241 # executed request. This will typically be used by clients to display
203 # prompt numbers to the user. If the request was a silent one, this will
242 # prompt numbers to the user. If the request was a silent one, this will
204 # be the current value of the counter in the kernel.
243 # be the current value of the counter in the kernel.
205 'execution_count' : int,
244 'execution_count' : int,
206
245
207 # If the state_template was provided, this will contain the evaluated
246 # If the state_template was provided, this will contain the evaluated
208 # form of the template.
247 # form of the template.
209 'state' : str,
248 'state' : str,
210 }
249 }
211
250
212 When status is 'ok', the following extra fields are present::
251 When status is 'ok', the following extra fields are present::
213
252
214 {
253 {
215 # The kernel will often transform the input provided to it. If the
254 # The kernel will often transform the input provided to it. If the
216 # '---->' transform had been applied, this is filled, otherwise it's the
255 # '---->' transform had been applied, this is filled, otherwise it's the
217 # empty string. So transformations like magics don't appear here, only
256 # empty string. So transformations like magics don't appear here, only
218 # autocall ones.
257 # autocall ones.
219
258
220 'transformed_code' : str,
259 'transformed_code' : str,
221
260
222 # The execution payload is a dict with string keys that may have been
261 # The execution payload is a dict with string keys that may have been
223 # produced by the code being executed. It is retrieved by the kernel at
262 # produced by the code being executed. It is retrieved by the kernel at
224 # the end of the execution and sent back to the front end, which can take
263 # the end of the execution and sent back to the front end, which can take
225 # action on it as needed. See main text for further details.
264 # action on it as needed. See main text for further details.
226 'payload' : dict,
265 'payload' : dict,
227 }
266 }
228
267
229 .. admonition:: Execution payloads
268 .. admonition:: Execution payloads
230
269
231 The notion of an 'execution payload' is different from a return value of a
270 The notion of an 'execution payload' is different from a return value of a
232 given set of code, which normally is just displayed on the pyout stream
271 given set of code, which normally is just displayed on the pyout stream
233 through the PUB socket. The idea of a payload is to allow special types of
272 through the PUB socket. The idea of a payload is to allow special types of
234 code, typically magics, to populate a data container in the IPython kernel
273 code, typically magics, to populate a data container in the IPython kernel
235 that will be shipped back to the caller via this channel. The kernel will
274 that will be shipped back to the caller via this channel. The kernel will
236 have an API for this, probably something along the lines of::
275 have an API for this, probably something along the lines of::
237
276
238 ip.exec_payload_add(key, value)
277 ip.exec_payload_add(key, value)
239
278
240 though this API is still in the design stages. The data returned in this
279 though this API is still in the design stages. The data returned in this
241 payload will allow frontends to present special views of what just happened.
280 payload will allow frontends to present special views of what just happened.
242
281
243
282
244 When status is 'error', the following extra fields are present::
283 When status is 'error', the following extra fields are present::
245
284
246 {
285 {
247 'exc_name' : str, # Exception name, as a string
286 'exc_name' : str, # Exception name, as a string
248 'exc_value' : str, # Exception value, as a string
287 'exc_value' : str, # Exception value, as a string
249
288
250 # The traceback will contain a list of frames, represented each as a
289 # The traceback will contain a list of frames, represented each as a
251 # string. For now we'll stick to the existing design of ultraTB, which
290 # string. For now we'll stick to the existing design of ultraTB, which
252 # controls exception level of detail statefully. But eventually we'll
291 # controls exception level of detail statefully. But eventually we'll
253 # want to grow into a model where more information is collected and
292 # want to grow into a model where more information is collected and
254 # packed into the traceback object, with clients deciding how little or
293 # packed into the traceback object, with clients deciding how little or
255 # how much of it to unpack. But for now, let's start with a simple list
294 # how much of it to unpack. But for now, let's start with a simple list
256 # of strings, since that requires only minimal changes to ultratb as
295 # of strings, since that requires only minimal changes to ultratb as
257 # written.
296 # written.
258 'traceback' : list,
297 'traceback' : list,
259 }
298 }
260
299
261
300
262 When status is 'abort', there are for now no additional data fields. This
301 When status is 'abort', there are for now no additional data fields. This
263 happens when the kernel was interrupted by a signal.
302 happens when the kernel was interrupted by a signal.
264
303
265 Kernel attribute access
304 Kernel attribute access
266 -----------------------
305 -----------------------
267
306
268 While this protocol does not specify full RPC access to arbitrary methods of
307 While this protocol does not specify full RPC access to arbitrary methods of
269 the kernel object, the kernel does allow read (and in some cases write) access
308 the kernel object, the kernel does allow read (and in some cases write) access
270 to certain attributes.
309 to certain attributes.
271
310
272 The policy for which attributes can be read is: any attribute of the kernel, or
311 The policy for which attributes can be read is: any attribute of the kernel, or
273 its sub-objects, that belongs to a :class:`Configurable` object and has been
312 its sub-objects, that belongs to a :class:`Configurable` object and has been
274 declared at the class-level with Traits validation, is in principle accessible
313 declared at the class-level with Traits validation, is in principle accessible
275 as long as its name does not begin with a leading underscore. The attribute
314 as long as its name does not begin with a leading underscore. The attribute
276 itself will have metadata indicating whether it allows remote read and/or write
315 itself will have metadata indicating whether it allows remote read and/or write
277 access. The message spec follows for attribute read and write requests.
316 access. The message spec follows for attribute read and write requests.
278
317
279 Message type: ``getattr_request``::
318 Message type: ``getattr_request``::
280
319
281 content = {
320 content = {
282 # The (possibly dotted) name of the attribute
321 # The (possibly dotted) name of the attribute
283 'name' : str
322 'name' : str,
284 }
323 }
285
324
286 When a ``getattr_request`` fails, there are two possible error types:
325 When a ``getattr_request`` fails, there are two possible error types:
287
326
288 - AttributeError: this type of error was raised when trying to access the
327 - AttributeError: this type of error was raised when trying to access the
289 given name by the kernel itself. This means that the attribute likely
328 given name by the kernel itself. This means that the attribute likely
290 doesn't exist.
329 doesn't exist.
291
330
292 - AccessError: the attribute exists but its value is not readable remotely.
331 - AccessError: the attribute exists but its value is not readable remotely.
293
332
294
333
295 Message type: ``getattr_reply``::
334 Message type: ``getattr_reply``::
296
335
297 content = {
336 content = {
298 # One of ['ok', 'AttributeError', 'AccessError'].
337 # One of ['ok', 'AttributeError', 'AccessError'].
299 'status' : str
338 'status' : str,
300 # If status is 'ok', a JSON object.
339 # If status is 'ok', a JSON object.
301 'value' : object
340 'value' : object,
302 }
341 }
303
342
304 Message type: ``setattr_request``::
343 Message type: ``setattr_request``::
305
344
306 content = {
345 content = {
307 # The (possibly dotted) name of the attribute
346 # The (possibly dotted) name of the attribute
308 'name' : str
347 'name' : str,
309
348
310 # A JSON-encoded object, that will be validated by the Traits
349 # A JSON-encoded object, that will be validated by the Traits
311 # information in the kernel
350 # information in the kernel
312 'value' : object
351 'value' : object,
313 }
352 }
314
353
315 When a ``setattr_request`` fails, there are also two possible error types with
354 When a ``setattr_request`` fails, there are also two possible error types with
316 similar meanings as those of the ``getattr_request`` case, but for writing.
355 similar meanings as those of the ``getattr_request`` case, but for writing.
317
356
318 Message type: ``setattr_reply``::
357 Message type: ``setattr_reply``::
319
358
320 content = {
359 content = {
321 # One of ['ok', 'AttributeError', 'AccessError'].
360 # One of ['ok', 'AttributeError', 'AccessError'].
322 'status' : str
361 'status' : str,
323 }
362 }
324
363
325
364
326 Object information
365 Object information
327 ------------------
366 ------------------
328
367
329 One of IPython's most used capabilities is the introspection of Python objects
368 One of IPython's most used capabilities is the introspection of Python objects
330 in the user's namespace, typically invoked via the ``?`` and ``??`` characters
369 in the user's namespace, typically invoked via the ``?`` and ``??`` characters
331 (which in reality are shorthands for the ``%pinfo`` magic). This is used often
370 (which in reality are shorthands for the ``%pinfo`` magic). This is used often
332 enough that it warrants an explicit message type, especially because frontends
371 enough that it warrants an explicit message type, especially because frontends
333 may want to get object information in response to user keystrokes (like Tab or
372 may want to get object information in response to user keystrokes (like Tab or
334 F1) besides from the user explicitly typing code like ``x??``.
373 F1) besides from the user explicitly typing code like ``x??``.
335
374
336 Message type: ``object_info_request``::
375 Message type: ``object_info_request``::
337
376
338 content = {
377 content = {
339 # The (possibly dotted) name of the object to be searched in all
378 # The (possibly dotted) name of the object to be searched in all
340 # relevant namespaces
379 # relevant namespaces
341 'name' : str,
380 'name' : str,
342
381
343 # The level of detail desired. The default (0) is equivalent to typing
382 # The level of detail desired. The default (0) is equivalent to typing
344 # 'x?' at the prompt, 1 is equivalent to 'x??'.
383 # 'x?' at the prompt, 1 is equivalent to 'x??'.
345 'detail_level' : int,
384 'detail_level' : int,
346 }
385 }
347
386
348 The returned information will be a dictionary with keys very similar to the
387 The returned information will be a dictionary with keys very similar to the
349 field names that IPython prints at the terminal.
388 field names that IPython prints at the terminal.
350
389
351 Message type: ``object_info_reply``::
390 Message type: ``object_info_reply``::
352
391
353 content = {
392 content = {
354 # Flags for magics and system aliases
393 # Flags for magics and system aliases
355 'ismagic' : bool,
394 'ismagic' : bool,
356 'isalias' : bool,
395 'isalias' : bool,
357
396
358 # The name of the namespace where the object was found ('builtin',
397 # The name of the namespace where the object was found ('builtin',
359 # 'magics', 'alias', 'interactive', etc.)
398 # 'magics', 'alias', 'interactive', etc.)
360 'namespace' : str,
399 'namespace' : str,
361
400
362 # The type name will be type.__name__ for normal Python objects, but it
401 # The type name will be type.__name__ for normal Python objects, but it
363 # can also be a string like 'Magic function' or 'System alias'
402 # can also be a string like 'Magic function' or 'System alias'
364 'type_name' : str,
403 'type_name' : str,
365
404
366 'string_form' : str,
405 'string_form' : str,
367
406
368 # For objects with a __class__ attribute this will be set
407 # For objects with a __class__ attribute this will be set
369 'base_class' : str,
408 'base_class' : str,
370
409
371 # For objects with a __len__ attribute this will be set
410 # For objects with a __len__ attribute this will be set
372 'length' : int,
411 'length' : int,
373
412
374 # If the object is a function, class or method whose file we can find,
413 # If the object is a function, class or method whose file we can find,
375 # we give its full path
414 # we give its full path
376 'file' : str,
415 'file' : str,
377
416
378 # For pure Python callable objects, we can reconstruct the object
417 # For pure Python callable objects, we can reconstruct the object
379 # definition line which provides its call signature. For convenience this
418 # definition line which provides its call signature. For convenience this
380 # is returned as a single 'definition' field, but below the raw parts that
419 # is returned as a single 'definition' field, but below the raw parts that
381 # compose it are also returned as the argspec field.
420 # compose it are also returned as the argspec field.
382 'definition' : str,
421 'definition' : str,
383
422
384 # The individual parts that together form the definition string. Clients
423 # The individual parts that together form the definition string. Clients
385 # with rich display capabilities may use this to provide a richer and more
424 # with rich display capabilities may use this to provide a richer and more
386 # precise representation of the definition line (e.g. by highlighting
425 # precise representation of the definition line (e.g. by highlighting
387 # arguments based on the user's cursor position). For non-callable
426 # arguments based on the user's cursor position). For non-callable
388 # objects, this field is empty.
427 # objects, this field is empty.
389 'argspec' : { # The names of all the arguments
428 'argspec' : { # The names of all the arguments
390 args : list,
429 args : list,
391 # The name of the varargs (*args), if any
430 # The name of the varargs (*args), if any
392 varargs : str,
431 varargs : str,
393 # The name of the varkw (**kw), if any
432 # The name of the varkw (**kw), if any
394 varkw : str
433 varkw : str,
395 # The values (as strings) of all default arguments. Note
434 # The values (as strings) of all default arguments. Note
396 # that these must be matched *in reverse* with the 'args'
435 # that these must be matched *in reverse* with the 'args'
397 # list above, since the first positional args have no default
436 # list above, since the first positional args have no default
398 # value at all.
437 # value at all.
399 func_defaults : list
438 func_defaults : list,
400 }
439 },
401
440
402 # For instances, provide the constructor signature (the definition of
441 # For instances, provide the constructor signature (the definition of
403 # the __init__ method):
442 # the __init__ method):
404 'init_definition' : str,
443 'init_definition' : str,
405
444
406 # Docstrings: for any object (function, method, module, package) with a
445 # Docstrings: for any object (function, method, module, package) with a
407 # docstring, we show it. But in addition, we may provide additional
446 # docstring, we show it. But in addition, we may provide additional
408 # docstrings. For example, for instances we will show the constructor
447 # docstrings. For example, for instances we will show the constructor
409 # and class docstrings as well, if available.
448 # and class docstrings as well, if available.
410 'docstring' : str,
449 'docstring' : str,
411
450
412 # For instances, provide the constructor and class docstrings
451 # For instances, provide the constructor and class docstrings
413 'init_docstring' : str,
452 'init_docstring' : str,
414 'class_docstring' : str,
453 'class_docstring' : str,
415
454
416 # If detail_level was 1, we also try to find the source code that
455 # If detail_level was 1, we also try to find the source code that
417 # defines the object, if possible. The string 'None' will indicate
456 # defines the object, if possible. The string 'None' will indicate
418 # that no source was found.
457 # that no source was found.
419 'source' : str,
458 'source' : str,
420 }
459 }
421
460
422
461
423 Complete
462 Complete
424 --------
463 --------
425
464
426 Message type: ``complete_request``::
465 Message type: ``complete_request``::
427
466
428 content = {
467 content = {
429 # The text to be completed, such as 'a.is'
468 # The text to be completed, such as 'a.is'
430 'text' : str,
469 'text' : str,
431
470
432 # The full line, such as 'print a.is'. This allows completers to
471 # The full line, such as 'print a.is'. This allows completers to
433 # make decisions that may require information about more than just the
472 # make decisions that may require information about more than just the
434 # current word.
473 # current word.
435 'line' : str,
474 'line' : str,
436
475
437 # The entire block of text where the line is. This may be useful in the
476 # The entire block of text where the line is. This may be useful in the
438 # case of multiline completions where more context may be needed. Note: if
477 # case of multiline completions where more context may be needed. Note: if
439 # in practice this field proves unnecessary, remove it to lighten the
478 # in practice this field proves unnecessary, remove it to lighten the
440 # messages.
479 # messages.
441
480
442 'block' : str,
481 'block' : str,
443
482
444 # The position of the cursor where the user hit 'TAB' on the line.
483 # The position of the cursor where the user hit 'TAB' on the line.
445 'cursor_pos' : int,
484 'cursor_pos' : int,
446 }
485 }
447
486
448 Message type: ``complete_reply``::
487 Message type: ``complete_reply``::
449
488
450 content = {
489 content = {
451 # The list of all matches to the completion request, such as
490 # The list of all matches to the completion request, such as
452 # ['a.isalnum', 'a.isalpha'] for the above example.
491 # ['a.isalnum', 'a.isalpha'] for the above example.
453 'matches' : list
492 'matches' : list
454 }
493 }
455
494
456
495
457 History
496 History
458 -------
497 -------
459
498
460 For clients to explicitly request history from a kernel. The kernel has all
499 For clients to explicitly request history from a kernel. The kernel has all
461 the actual execution history stored in a single location, so clients can
500 the actual execution history stored in a single location, so clients can
462 request it from the kernel when needed.
501 request it from the kernel when needed.
463
502
464 Message type: ``history_request``::
503 Message type: ``history_request``::
465
504
466 content = {
505 content = {
467
506
468 # If True, also return output history in the resulting dict.
507 # If True, also return output history in the resulting dict.
469 'output' : bool,
508 'output' : bool,
470
509
471 # If True, return the raw input history, else the transformed input.
510 # If True, return the raw input history, else the transformed input.
472 'raw' : bool,
511 'raw' : bool,
473
512
474 # This parameter can be one of: A number, a pair of numbers, None
513 # This parameter can be one of: A number, a pair of numbers, None
475 # If not given, last 40 are returned.
514 # If not given, last 40 are returned.
476 # - number n: return the last n entries.
515 # - number n: return the last n entries.
477 # - pair n1, n2: return entries in the range(n1, n2).
516 # - pair n1, n2: return entries in the range(n1, n2).
478 # - None: return all history
517 # - None: return all history
479 'index' : n or (n1, n2) or None,
518 'index' : n or (n1, n2) or None,
480 }
519 }
481
520
482 Message type: ``history_reply``::
521 Message type: ``history_reply``::
483
522
484 content = {
523 content = {
485 # A dict with prompt numbers as keys and either (input, output) or input
524 # A dict with prompt numbers as keys and either (input, output) or input
486 # as the value depending on whether output was True or False,
525 # as the value depending on whether output was True or False,
487 # respectively.
526 # respectively.
488 'history' : dict,
527 'history' : dict,
489 }
528 }
529
490 Messages on the PUB/SUB socket
530 Messages on the PUB/SUB socket
491 ==============================
531 ==============================
492
532
493 Streams (stdout, stderr, etc)
533 Streams (stdout, stderr, etc)
494 ------------------------------
534 ------------------------------
495
535
496 Message type: ``stream``::
536 Message type: ``stream``::
497
537
498 content = {
538 content = {
499 # The name of the stream is one of 'stdin', 'stdout', 'stderr'
539 # The name of the stream is one of 'stdin', 'stdout', 'stderr'
500 'name' : str,
540 'name' : str,
501
541
502 # The data is an arbitrary string to be written to that stream
542 # The data is an arbitrary string to be written to that stream
503 'data' : str,
543 'data' : str,
504 }
544 }
505
545
506 When a kernel receives a raw_input call, it should also broadcast it on the pub
546 When a kernel receives a raw_input call, it should also broadcast it on the pub
507 socket with the names 'stdin' and 'stdin_reply'. This will allow other clients
547 socket with the names 'stdin' and 'stdin_reply'. This will allow other clients
508 to monitor/display kernel interactions and possibly replay them to their user
548 to monitor/display kernel interactions and possibly replay them to their user
509 or otherwise expose them.
549 or otherwise expose them.
510
550
511 Python inputs
551 Python inputs
512 -------------
552 -------------
513
553
514 These messages are the re-broadcast of the ``execute_request``.
554 These messages are the re-broadcast of the ``execute_request``.
515
555
516 Message type: ``pyin``::
556 Message type: ``pyin``::
517
557
518 content = {
558 content = {
519 # Source code to be executed, one or more lines
559 # Source code to be executed, one or more lines
520 'code' : str
560 'code' : str
521 }
561 }
522
562
523 Python outputs
563 Python outputs
524 --------------
564 --------------
525
565
526 When Python produces output from code that has been compiled in with the
566 When Python produces output from code that has been compiled in with the
527 'single' flag to :func:`compile`, any expression that produces a value (such as
567 'single' flag to :func:`compile`, any expression that produces a value (such as
528 ``1+1``) is passed to ``sys.displayhook``, which is a callable that can do with
568 ``1+1``) is passed to ``sys.displayhook``, which is a callable that can do with
529 this value whatever it wants. The default behavior of ``sys.displayhook`` in
569 this value whatever it wants. The default behavior of ``sys.displayhook`` in
530 the Python interactive prompt is to print to ``sys.stdout`` the :func:`repr` of
570 the Python interactive prompt is to print to ``sys.stdout`` the :func:`repr` of
531 the value as long as it is not ``None`` (which isn't printed at all). In our
571 the value as long as it is not ``None`` (which isn't printed at all). In our
532 case, the kernel instantiates as ``sys.displayhook`` an object which has
572 case, the kernel instantiates as ``sys.displayhook`` an object which has
533 similar behavior, but which instead of printing to stdout, broadcasts these
573 similar behavior, but which instead of printing to stdout, broadcasts these
534 values as ``pyout`` messages for clients to display appropriately.
574 values as ``pyout`` messages for clients to display appropriately.
535
575
536 Message type: ``pyout``::
576 Message type: ``pyout``::
537
577
538 content = {
578 content = {
539 # The data is typically the repr() of the object.
579 # The data is typically the repr() of the object.
540 'data' : str,
580 'data' : str,
541
581
542 # The prompt number for this execution is also provided so that clients
582 # The counter for this execution is also provided so that clients can
543 # can display it, since IPython automatically creates variables called
583 # display it, since IPython automatically creates variables called _N (for
544 # _N (for prompt N).
584 # prompt N).
545 'prompt_number' : int,
585 'execution_count' : int,
546 }
586 }
547
587
548 Python errors
588 Python errors
549 -------------
589 -------------
550
590
551 When an error occurs during code execution
591 When an error occurs during code execution
552
592
553 Message type: ``pyerr``::
593 Message type: ``pyerr``::
554
594
555 content = {
595 content = {
556 # Similar content to the execute_reply messages for the 'error' case,
596 # Similar content to the execute_reply messages for the 'error' case,
557 # except the 'status' field is omitted.
597 # except the 'status' field is omitted.
558 }
598 }
559
599
560 Kernel crashes
600 Kernel crashes
561 --------------
601 --------------
562
602
563 When the kernel has an unexpected exception, caught by the last-resort
603 When the kernel has an unexpected exception, caught by the last-resort
564 sys.excepthook, we should broadcast the crash handler's output before exiting.
604 sys.excepthook, we should broadcast the crash handler's output before exiting.
565 This will allow clients to notice that a kernel died, inform the user and
605 This will allow clients to notice that a kernel died, inform the user and
566 propose further actions.
606 propose further actions.
567
607
568 Message type: ``crash``::
608 Message type: ``crash``::
569
609
570 content = {
610 content = {
571 # Similarly to the 'error' case for execute_reply messages, this will
611 # Similarly to the 'error' case for execute_reply messages, this will
572 # contain exc_name, exc_type and traceback fields.
612 # contain exc_name, exc_type and traceback fields.
573
613
574 # An additional field with supplementary information such as where to
614 # An additional field with supplementary information such as where to
575 # send the crash message
615 # send the crash message
576 'info' : str,
616 'info' : str,
577 }
617 }
578
618
579
619
580 Future ideas
620 Future ideas
581 ------------
621 ------------
582
622
583 Other potential message types, currently unimplemented, listed below as ideas.
623 Other potential message types, currently unimplemented, listed below as ideas.
584
624
585 Message type: ``file``::
625 Message type: ``file``::
586
626
587 content = {
627 content = {
588 'path' : 'cool.jpg',
628 'path' : 'cool.jpg',
589 'mimetype' : str,
629 'mimetype' : str,
590 'data' : str,
630 'data' : str,
591 }
631 }
592
632
593
633
594 Messages on the REQ/REP socket
634 Messages on the REQ/REP socket
595 ==============================
635 ==============================
596
636
597 This is a socket that goes in the opposite direction: from the kernel to a
637 This is a socket that goes in the opposite direction: from the kernel to a
598 *single* frontend, and its purpose is to allow ``raw_input`` and similar
638 *single* frontend, and its purpose is to allow ``raw_input`` and similar
599 operations that read from ``sys.stdin`` on the kernel to be fulfilled by the
639 operations that read from ``sys.stdin`` on the kernel to be fulfilled by the
600 client. For now we will keep these messages as simple as possible, since they
640 client. For now we will keep these messages as simple as possible, since they
601 basically only mean to convey the ``raw_input(prompt)`` call.
641 basically only mean to convey the ``raw_input(prompt)`` call.
602
642
603 Message type: ``input_request``::
643 Message type: ``input_request``::
604
644
605 content = { 'prompt' : str }
645 content = { 'prompt' : str }
606
646
607 Message type: ``input_reply``::
647 Message type: ``input_reply``::
608
648
609 content = { 'value' : str }
649 content = { 'value' : str }
610
650
611 .. Note::
651 .. Note::
612
652
613 We do not explicitly try to forward the raw ``sys.stdin`` object, because in
653 We do not explicitly try to forward the raw ``sys.stdin`` object, because in
614 practice the kernel should behave like an interactive program. When a
654 practice the kernel should behave like an interactive program. When a
615 program is opened on the console, the keyboard effectively takes over the
655 program is opened on the console, the keyboard effectively takes over the
616 ``stdin`` file descriptor, and it can't be used for raw reading anymore.
656 ``stdin`` file descriptor, and it can't be used for raw reading anymore.
617 Since the IPython kernel effectively behaves like a console program (albeit
657 Since the IPython kernel effectively behaves like a console program (albeit
618 one whose "keyboard" is actually living in a separate process and
658 one whose "keyboard" is actually living in a separate process and
619 transported over the zmq connection), raw ``stdin`` isn't expected to be
659 transported over the zmq connection), raw ``stdin`` isn't expected to be
620 available.
660 available.
621
661
622
662
623 Heartbeat for kernels
663 Heartbeat for kernels
624 =====================
664 =====================
625
665
626 Initially we had considered using messages like those above over ZMQ for a
666 Initially we had considered using messages like those above over ZMQ for a
627 kernel 'heartbeat' (a way to detect quickly and reliably whether a kernel is
667 kernel 'heartbeat' (a way to detect quickly and reliably whether a kernel is
628 alive at all, even if it may be busy executing user code). But this has the
668 alive at all, even if it may be busy executing user code). But this has the
629 problem that if the kernel is locked inside extension code, it wouldn't execute
669 problem that if the kernel is locked inside extension code, it wouldn't execute
630 the python heartbeat code. But it turns out that we can implement a basic
670 the python heartbeat code. But it turns out that we can implement a basic
631 heartbeat with pure ZMQ, without using any Python messaging at all.
671 heartbeat with pure ZMQ, without using any Python messaging at all.
632
672
633 The monitor sends out a single zmq message (right now, it is a str of the
673 The monitor sends out a single zmq message (right now, it is a str of the
634 monitor's lifetime in seconds), and gets the same message right back, prefixed
674 monitor's lifetime in seconds), and gets the same message right back, prefixed
635 with the zmq identity of the XREQ socket in the heartbeat process. This can be
675 with the zmq identity of the XREQ socket in the heartbeat process. This can be
636 a uuid, or even a full message, but there doesn't seem to be a need for packing
676 a uuid, or even a full message, but there doesn't seem to be a need for packing
637 up a message when the sender and receiver are the exact same Python object.
677 up a message when the sender and receiver are the exact same Python object.
638
678
639 The model is this::
679 The model is this::
640
680
641 monitor.send(str(self.lifetime)) # '1.2345678910'
681 monitor.send(str(self.lifetime)) # '1.2345678910'
642
682
643 and the monitor receives some number of messages of the form::
683 and the monitor receives some number of messages of the form::
644
684
645 ['uuid-abcd-dead-beef', '1.2345678910']
685 ['uuid-abcd-dead-beef', '1.2345678910']
646
686
647 where the first part is the zmq.IDENTITY of the heart's XREQ on the engine, and
687 where the first part is the zmq.IDENTITY of the heart's XREQ on the engine, and
648 the rest is the message sent by the monitor. No Python code ever has any
688 the rest is the message sent by the monitor. No Python code ever has any
649 access to the message between the monitor's send, and the monitor's recv.
689 access to the message between the monitor's send, and the monitor's recv.
650
690
651
691
652 ToDo
692 ToDo
653 ====
693 ====
654
694
655 Missing things include:
695 Missing things include:
656
696
657 * Important: finish thinking through the payload concept and API.
697 * Important: finish thinking through the payload concept and API.
658
698
659 * Important: ensure that we have a good solution for magics like %edit. It's
699 * Important: ensure that we have a good solution for magics like %edit. It's
660 likely that with the payload concept we can build a full solution, but not
700 likely that with the payload concept we can build a full solution, but not
661 100% clear yet.
701 100% clear yet.
662
702
663 * Finishing the details of the heartbeat protocol.
703 * Finishing the details of the heartbeat protocol.
664
704
665 * Signal handling: specify what kind of information kernel should broadcast (or
705 * Signal handling: specify what kind of information kernel should broadcast (or
666 not) when it receives signals.
706 not) when it receives signals.
667
707
668 .. include:: ../links.rst
708 .. include:: ../links.rst
General Comments 0
You need to be logged in to leave comments. Login now