Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Replace run_cell method, and fix up caching compiler so we can cache …

…a string, then compile AST nodes.
  • Loading branch information...
commit 7117b70562cc92ea7954e5e5601862e0de6bd237 1 parent 8f249fb
Thomas Kluyver authored

Showing 2 changed files with 30 additions and 140 deletions. Show diff stats Hide diff stats

  1. +16 21 IPython/core/compilerop.py
  2. +14 119 IPython/core/interactiveshell.py
37 IPython/core/compilerop.py
@@ -51,12 +51,12 @@ def code_name(code, number=0):
51 51 # Classes and functions
52 52 #-----------------------------------------------------------------------------
53 53
54   -class CachingCompiler(object):
  54 +class CachingCompiler(codeop.Compile):
55 55 """A compiler that caches code compiled from interactive statements.
56 56 """
57 57
58 58 def __init__(self):
59   - self._compiler = codeop.CommandCompiler()
  59 + codeop.Compile.__init__(self)
60 60
61 61 # This is ugly, but it must be done this way to allow multiple
62 62 # simultaneous ipython instances to coexist. Since Python itself
@@ -81,35 +81,30 @@ def __init__(self):
81 81 def compiler_flags(self):
82 82 """Flags currently active in the compilation process.
83 83 """
84   - return self._compiler.compiler.flags
  84 + return self.flags
  85 +
  86 + def cache(self, code, number=0):
  87 + """Make a name for a block of code, and cache the code.
85 88
86   - def __call__(self, code, symbol, number=0):
87   - """Compile some code while caching its contents such that the inspect
88   - module can find it later.
89   -
90 89 Parameters
91 90 ----------
92 91 code : str
93   - Source code to be compiled, one or more lines.
94   -
95   - symbol : str
96   - One of 'single', 'exec' or 'eval' (see the builtin ``compile``
97   - documentation for further details on these fields).
98   -
99   - number : int, optional
100   - An integer argument identifying the code, useful for informational
101   - purposes in tracebacks (typically it will be the IPython prompt
102   - number).
  92 + The Python source code to cache.
  93 + number : int
  94 + A number which forms part of the code's name. Used for the execution
  95 + counter.
  96 +
  97 + Returns
  98 + -------
  99 + The name of the cached code (as a string). Pass this as the filename
  100 + argument to compilation, so that tracebacks are correctly hooked up.
103 101 """
104 102 name = code_name(code, number)
105   - code_obj = self._compiler(code, name, symbol)
106 103 entry = (len(code), time.time(),
107 104 [line+'\n' for line in code.splitlines()], name)
108   - # Cache the info both in the linecache (a global cache used internally
109   - # by most of Python's inspect/traceback machinery), and in our cache
110 105 linecache.cache[name] = entry
111 106 linecache._ipython_cache[name] = entry
112   - return code_obj
  107 + return name
113 108
114 109 def check_cache(self, *args):
115 110 """Call linecache.checkcache() safely protecting our cached values.
133 IPython/core/interactiveshell.py
@@ -2100,7 +2100,7 @@ def safe_execfile_ipy(self, fname):
2100 2100 self.showtraceback()
2101 2101 warn('Unknown failure executing file: <%s>' % fname)
2102 2102
2103   - def run_cell_NODE(self, cell, store_history=True):
  2103 + def run_cell(self, cell, store_history=True):
2104 2104 """Run a complete IPython cell.
2105 2105
2106 2106 Parameters
@@ -2123,19 +2123,22 @@ def run_cell_NODE(self, cell, store_history=True):
2123 2123
2124 2124 self.logger.log(cell, raw_cell)
2125 2125
  2126 + cell_name = self.compile.cache(cell, self.execution_count)
  2127 +
2126 2128 with self.display_trap:
2127 2129 try:
2128 2130 code_ast = ast.parse(cell)
2129 2131 except (OverflowError, SyntaxError, ValueError, TypeError, MemoryError):
2130 2132 # Case 1
2131   - self.showsyntaxerror(filename)
  2133 + self.showsyntaxerror()
  2134 + self.execution_count += 1
2132 2135 return None
2133 2136
2134 2137 interactivity = 1 # Last node to be run interactive
2135 2138 if len(cell.splitlines()) == 1:
2136 2139 interactivity = 2 # Single line; run fully interactive
2137 2140
2138   - self.run_ast_nodes(code_ast.body, interactivity)
  2141 + self.run_ast_nodes(code_ast.body, cell_name, interactivity)
2139 2142
2140 2143 if store_history:
2141 2144 # Write output to the database. Does nothing unless
@@ -2144,7 +2147,7 @@ def run_cell_NODE(self, cell, store_history=True):
2144 2147 # Each cell is a *single* input, regardless of how many lines it has
2145 2148 self.execution_count += 1
2146 2149
2147   - def run_ast_nodes(self, nodelist, interactivity=1):
  2150 + def run_ast_nodes(self, nodelist, cell_name, interactivity=1):
2148 2151 """Run a sequence of AST nodes. The execution mode depends on the
2149 2152 interactivity parameter.
2150 2153
@@ -2167,128 +2170,19 @@ def run_ast_nodes(self, nodelist, interactivity=1):
2167 2170 else:
2168 2171 to_run_exec, to_run_interactive = [], nodelist
2169 2172
  2173 + exec_count = self.execution_count
2170 2174 if to_run_exec:
2171 2175 mod = ast.Module(to_run_exec)
2172   - name = "<ipython-prompt-%d-exec>" % self.execution_count
2173   - self.code_to_run = code = compile(mod, name, "exec")
  2176 + self.code_to_run = code = self.compile(mod, cell_name, "exec")
2174 2177 if self.run_code(code) == 1:
2175 2178 return
2176 2179
2177 2180 if to_run_interactive:
2178 2181 mod = ast.Interactive(to_run_interactive)
2179   - name = "<ipython-prompt-%d-interactive>" % self.execution_count
2180   - self.code_to_run = code = compile(mod, name, "single")
  2182 + self.code_to_run = code = self.compile(mod, cell_name, "single")
2181 2183 return self.run_code(code)
2182   -
2183   -
2184   - def run_cell(self, cell, store_history=True):
2185   - """Run the contents of an entire multiline 'cell' of code, and store it
2186   - in the history.
2187   -
2188   - The cell is split into separate blocks which can be executed
2189   - individually. Then, based on how many blocks there are, they are
2190   - executed as follows:
2191   -
2192   - - A single block: 'single' mode. If it is also a single line, dynamic
2193   - transformations, including automagic and macros, will be applied.
2194   -
2195   - If there's more than one block, it depends:
2196   -
2197   - - if the last one is no more than two lines long, run all but the last
2198   - in 'exec' mode and the very last one in 'single' mode. This makes it
2199   - easy to type simple expressions at the end to see computed values. -
2200   - otherwise (last one is also multiline), run all in 'exec' mode
2201   -
2202   - When code is executed in 'single' mode, :func:`sys.displayhook` fires,
2203   - results are displayed and output prompts are computed. In 'exec' mode,
2204   - no results are displayed unless :func:`print` is called explicitly;
2205   - this mode is more akin to running a script.
2206   -
2207   - Parameters
2208   - ----------
2209   - cell : str
2210   - A single or multiline string.
2211   - """
2212   - # Store the untransformed code
2213   - raw_cell = cell
2214   -
2215   - # Code transformation and execution must take place with our
2216   - # modifications to builtins.
2217   - with self.builtin_trap:
2218   -
2219   - # We need to break up the input into executable blocks that can
2220   - # be runin 'single' mode, to provide comfortable user behavior.
2221   - blocks = self.input_splitter.split_blocks(cell)
2222   -
2223   - if not blocks: # Blank cell
2224   - return
2225   -
2226   - # We only do dynamic transforms on a single line. But a macro
2227   - # can be expanded to several lines, so we need to split it
2228   - # into input blocks again.
2229   - if len(cell.splitlines()) <= 1:
2230   - cell = self.prefilter_manager.prefilter_line(blocks[0])
2231   - blocks = self.input_splitter.split_blocks(cell)
2232   -
2233   - # Store the 'ipython' version of the cell as well, since
2234   - # that's what needs to go into the translated history and get
2235   - # executed (the original cell may contain non-python syntax).
2236   - cell = ''.join(blocks)
2237   -
2238   - # Store raw and processed history
2239   - if store_history:
2240   - self.history_manager.store_inputs(self.execution_count,
2241   - cell, raw_cell)
2242   -
2243   - self.logger.log(cell, raw_cell)
2244   -
2245   - # All user code execution should take place with our
2246   - # modified displayhook.
2247   - with self.display_trap:
2248   - # Single-block input should behave like an interactive prompt
2249   - if len(blocks) == 1:
2250   - out = self.run_source(blocks[0])
2251   - # Write output to the database. Does nothing unless
2252   - # history output logging is enabled.
2253   - if store_history:
2254   - self.history_manager.store_output(self.execution_count)
2255   - # Since we return here, we need to update the
2256   - # execution count
2257   - self.execution_count += 1
2258   - return out
2259   -
2260   - # In multi-block input, if the last block is a simple (one-two
2261   - # lines) expression, run it in single mode so it produces output.
2262   - # Otherwise just run it all in 'exec' mode. This seems like a
2263   - # reasonable usability design.
2264   - last = blocks[-1]
2265   - last_nlines = len(last.splitlines())
2266   -
2267   - if last_nlines < 2:
2268   - # Here we consider the cell split between 'body' and 'last',
2269   - # store all history and execute 'body', and if successful, then
2270   - # proceed to execute 'last'.
2271   -
2272   - # Get the main body to run as a cell
2273   - ipy_body = ''.join(blocks[:-1])
2274   - retcode = self.run_source(ipy_body, symbol='exec',
2275   - post_execute=False)
2276   - if retcode==0:
2277   - # Last expression compiled as 'single' so it
2278   - # produces output
2279   - self.run_source(last)
2280   - else:
2281   - # Run the whole cell as one entity, storing both raw and
2282   - # processed input in history
2283   - self.run_source(cell, symbol='exec')
2284   -
2285   - # Write output to the database. Does nothing unless
2286   - # history output logging is enabled.
2287   - if store_history:
2288   - self.history_manager.store_output(self.execution_count)
2289   - # Each cell is a *single* input, regardless of how many lines it has
2290   - self.execution_count += 1
2291   -
  2184 +
  2185 +
2292 2186 # PENDING REMOVAL: this method is slated for deletion, once our new
2293 2187 # input logic has been 100% moved to frontends and is stable.
2294 2188 def runlines(self, lines, clean=False):
@@ -2378,7 +2272,8 @@ def run_source(self, source, filename=None,
2378 2272 print 'encoding', self.stdin_encoding # dbg
2379 2273
2380 2274 try:
2381   - code = self.compile(usource, symbol, self.execution_count)
  2275 + code_name = self.compile.cache(usource, self.execution_count)
  2276 + code = self.compile(usource, code_name, symbol)
2382 2277 except (OverflowError, SyntaxError, ValueError, TypeError, MemoryError):
2383 2278 # Case 1
2384 2279 self.showsyntaxerror(filename)

0 comments on commit 7117b70

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