Skip to content
This repository
Browse code

Document the code execution semantics much more carefully.

Also renamed user var/expression functions to match the fields in the
execute request.
  • Loading branch information...
commit 878faee604fc55bd988e7edf28985085ba81a83b 1 parent 4c7fc69
Fernando Perez authored September 17, 2010
33  IPython/core/interactiveshell.py
@@ -1964,10 +1964,17 @@ def _simple_error(self):
1964 1964
         etype, value = sys.exc_info()[:2]
1965 1965
         return u'[ERROR] {e.__name__}: {v}'.format(e=etype, v=value)
1966 1966
 
1967  
-    def get_user_variables(self, names):
  1967
+    def user_variables(self, names):
1968 1968
         """Get a list of variable names from the user's namespace.
1969 1969
 
1970  
-        The return value is a dict with the repr() of each value.
  1970
+        Parameters
  1971
+        ----------
  1972
+        names : list of strings
  1973
+          A list of names of variables to be read from the user namespace.
  1974
+
  1975
+        Returns
  1976
+        -------
  1977
+        A dict, keyed by the input names and with the repr() of each value.
1971 1978
         """
1972 1979
         out = {}
1973 1980
         user_ns = self.user_ns
@@ -1979,10 +1986,20 @@ def get_user_variables(self, names):
1979 1986
             out[varname] = value
1980 1987
         return out
1981 1988
         
1982  
-    def eval_expressions(self, expressions):
  1989
+    def user_expressions(self, expressions):
1983 1990
         """Evaluate a dict of expressions in the user's namespace.
1984 1991
 
1985  
-        The return value is a dict with the repr() of each value.
  1992
+        Parameters
  1993
+        ----------
  1994
+        expressions : dict
  1995
+          A dict with string keys and string values.  The expression values
  1996
+          should be valid Python expressions, each of which will be evaluated
  1997
+          in the user namespace.
  1998
+        
  1999
+        Returns
  2000
+        -------
  2001
+        A dict, keyed like the input expressions dict, with the repr() of each
  2002
+        value.
1986 2003
         """
1987 2004
         out = {}
1988 2005
         user_ns = self.user_ns
@@ -2121,10 +2138,10 @@ def run_cell(self, cell):
2121 2138
 
2122 2139
         If there's more than one block, it depends:
2123 2140
 
2124  
-        - if the last one is a single line long, run all but the last in
2125  
-        'exec' mode and the very last one in 'single' mode.  This makes it
2126  
-        easy to type simple expressions at the end to see computed values.
2127  
-        - otherwise (last one is also multiline), run all in 'exec' mode
  2141
+        - if the last one is no more than two lines long, run all but the last
  2142
+        in 'exec' mode and the very last one in 'single' mode.  This makes it
  2143
+        easy to type simple expressions at the end to see computed values.  -
  2144
+        otherwise (last one is also multiline), run all in 'exec' mode
2128 2145
 
2129 2146
         When code is executed in 'single' mode, :func:`sys.displayhook` fires,
2130 2147
         results are displayed and output prompts are computed.  In 'exec' mode,
4  IPython/zmq/ipkernel.py
@@ -250,9 +250,9 @@ def execute_request(self, ident, parent):
250 250
         # or not.  If it did, we proceed to evaluate user_variables/expressions
251 251
         if reply_content['status'] == 'ok':
252 252
             reply_content[u'user_variables'] = \
253  
-                         shell.get_user_variables(content[u'user_variables'])
  253
+                         shell.user_variables(content[u'user_variables'])
254 254
             reply_content[u'user_expressions'] = \
255  
-                         shell.eval_expressions(content[u'user_expressions'])
  255
+                         shell.user_expressions(content[u'user_expressions'])
256 256
         else:
257 257
             # If there was an error, don't even try to compute variables or
258 258
             # expressions
145  docs/source/development/messaging.txt
@@ -160,30 +160,23 @@ Message type: ``execute_request``::
160 160
     'user_expressions' : dict,
161 161
     }
162 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.
  163
+The ``code`` field contains a single string (possibly multiline).  The kernel
  164
+is responsible for splitting this into one or more independent execution blocks
  165
+and deciding whether to compile these in 'single' or 'exec' mode (see below for
  166
+detailed execution semantics).
172 167
 
173 168
 The ``user_`` fields deserve a detailed explanation.  In the past, IPython had
174 169
 the notion of a prompt string that allowed arbitrary code to be evaluated, and
175 170
 this was put to good use by many in creating prompts that displayed system
176 171
 status, path information, and even more esoteric uses like remote instrument
177 172
 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.
  173
+between the kernel and the clients, the kernel has no prompt knowledge; prompts
  174
+are a frontend-side feature, and it should be even possible for different
  175
+frontends to display different prompts while interacting with the same kernel.
182 176
 
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:
  177
+The kernel now provides the ability to retrieve data from the user's namespace
  178
+after the execution of the main ``code``, thanks to two fields in the
  179
+``execute_request`` message:
187 180
 
188 181
 - ``user_variables``: If only variables from the user's namespace are needed, a
189 182
   list of variable names can be passed and a dict with these names as keys and
@@ -205,32 +198,106 @@ terminal, etc).
205 198
    empty code string and ``silent=True``.
206 199
 
207 200
 Execution semantics
208  
-    Upon completion of the execution request, the kernel *always* sends a
209  
-    reply, with a status code indicating what happened and additional data
210  
-    depending on the outcome.
  201
+~~~~~~~~~~~~~~~~~~~
211 202
 
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.
  203
+When the silent flag is false, the execution of use code consists of the
  204
+following phases (in silent mode, only the ``code`` field is executed):
215 205
 
216  
-    Any error in retrieving the ``user_variables`` or evaluating the
217  
-    ``user_expressions`` will result in a simple error message in the return
218  
-    fields of the form::
  206
+1. Run the ``pre_runcode_hook``.
219 207
 
220  
-       [ERROR] ExceptionType: Exception message
  208
+2. Execute the ``code`` field, see below for details.
  209
+
  210
+3. If #2 succeeds, compute ``user_variables`` and ``user_expressions`` are
  211
+   computed.  This ensures that any error in the latter don't harm the main
  212
+   code execution.
  213
+
  214
+4. Call any method registered with :meth:`register_post_execute`.
  215
+
  216
+.. warning::
  217
+
  218
+   The API for running code before/after the main code block is likely to
  219
+   change soon.  Both the ``pre_runcode_hook`` and the
  220
+   :meth:`register_post_execute` are susceptible to modification, as we find a
  221
+   consistent model for both.
  222
+
  223
+To understand how the ``code`` field is executed, one must know that Python
  224
+code can be compiled in one of three modes (controlled by the ``mode`` argument
  225
+to the :func:`compile` builtin):
  226
+
  227
+*single*
  228
+  Valid for a single interactive statement (though the source can contain
  229
+  multiple lines, such as a for loop).  When compiled in this mode, the
  230
+  generated bytecode contains special instructions that trigger the calling of
  231
+  :func:`sys.displayhook` for any expression in the block that returns a value.
  232
+  This means that a single statement can actually produce multiple calls to
  233
+  :func:`sys.displayhook`, if for example it contains a loop where each
  234
+  iteration computes an unassigned expression would generate 10 calls::
  235
+
  236
+      for i in range(10):
  237
+          i**2
  238
+
  239
+*exec*
  240
+  An arbitrary amount of source code, this is how modules are compiled.
  241
+  :func:`sys.displayhook` is *never* implicitly called.
  242
+
  243
+*eval*
  244
+  A single expression that returns a value.  :func:`sys.displayhook` is *never*
  245
+  implicitly called.
  246
+
  247
+
  248
+The ``code`` field is split into individual blocks each of which is valid for
  249
+execution in 'single' mode, and then:
  250
+
  251
+- If there is only a single block: it is executed in 'single' mode.
  252
+
  253
+- If there is more than one block:
  254
+
  255
+  * if the last one is a single line long, run all but the last in 'exec' mode
  256
+    and the very last one in 'single' mode.  This makes it easy to type simple
  257
+    expressions at the end to see computed values.
  258
+
  259
+  * if the last one is no more than two lines long, run all but the last in
  260
+    'exec' mode and the very last one in 'single' mode.  This makes it easy to
  261
+    type simple expressions at the end to see computed values.  - otherwise
  262
+    (last one is also multiline), run all in 'exec' mode
  263
+
  264
+  * otherwise (last one is also multiline), run all in 'exec' mode as a single
  265
+    unit.
  266
+
  267
+Any error in retrieving the ``user_variables`` or evaluating the
  268
+``user_expressions`` will result in a simple error message in the return fields
  269
+of the form::
  270
+
  271
+   [ERROR] ExceptionType: Exception message
  272
+
  273
+The user can simply send the same variable name or expression for evaluation to
  274
+see a regular traceback.
  275
+
  276
+Errors in any registered post_execute functions are also reported similarly,
  277
+and the failing function is removed from the post_execution set so that it does
  278
+not continue triggering failures.
  279
+
  280
+Upon completion of the execution request, the kernel *always* sends a reply,
  281
+with a status code indicating what happened and additional data depending on
  282
+the outcome.  See :ref:`below <execution_results>` for the possible return
  283
+codes and associated data.
221 284
 
222  
-    The user can simply send the same variable name or expression for
223  
-    evaluation to see a regular traceback.
224 285
 
225 286
 Execution counter (old prompt number)
226  
-    The kernel has a single, monotonically increasing counter of all execution
227  
-    requests that are made with ``silent=False``.  This counter is used to
228  
-    populate the ``In[n]``, ``Out[n]`` and ``_n`` variables, so clients will
229  
-    likely want to display it in some form to the user, which will typically
230  
-    (but not necessarily) be done in the prompts.  The value of this counter
231  
-    will be returned as the ``execution_count`` field of all ``execute_reply```
232  
-    messages.
  287
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  288
+
  289
+The kernel has a single, monotonically increasing counter of all execution
  290
+requests that are made with ``silent=False``.  This counter is used to populate
  291
+the ``In[n]``, ``Out[n]`` and ``_n`` variables, so clients will likely want to
  292
+display it in some form to the user, which will typically (but not necessarily)
  293
+be done in the prompts.  The value of this counter will be returned as the
  294
+``execution_count`` field of all ``execute_reply`` messages.
  295
+
  296
+.. _execution_results:
233 297
 
  298
+Execution results
  299
+~~~~~~~~~~~~~~~~~
  300
+    
234 301
 Message type: ``execute_reply``::
235 302
 
236 303
     content = {
@@ -303,6 +370,11 @@ happens when the kernel was interrupted by a signal.
303 370
 Kernel attribute access
304 371
 -----------------------
305 372
 
  373
+.. warning::
  374
+
  375
+   This part of the messaging spec is not actually implemented in the kernel
  376
+   yet.
  377
+ 
306 378
 While this protocol does not specify full RPC access to arbitrary methods of
307 379
 the kernel object, the kernel does allow read (and in some cases write) access
308 380
 to certain attributes.
@@ -361,6 +433,7 @@ Message type: ``setattr_reply``::
361 433
     }
362 434
 
363 435
 
  436
+    
364 437
 Object information
365 438
 ------------------
366 439
 

0 notes on commit 878faee

Please sign in to comment.
Something went wrong with that request. Please try again.