##// END OF EJS Templates
Added mean + stdv to the %timeit magic - New tests pending - Corrected old ones
Pablo Galindo -
Show More
@@ -1,1365 +1,1375 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Implementation of execution-related magic functions."""
2 """Implementation of execution-related magic functions."""
3
3
4 # Copyright (c) IPython Development Team.
4 # Copyright (c) IPython Development Team.
5 # Distributed under the terms of the Modified BSD License.
5 # Distributed under the terms of the Modified BSD License.
6
6
7 from __future__ import print_function
7 from __future__ import print_function
8 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 import ast
10 import ast
11 import bdb
11 import bdb
12 import gc
12 import gc
13 import itertools
13 import itertools
14 import os
14 import os
15 import sys
15 import sys
16 import time
16 import time
17 import timeit
17 import timeit
18 import math
18 from pdb import Restart
19 from pdb import Restart
19
20
20 # cProfile was added in Python2.5
21 # cProfile was added in Python2.5
21 try:
22 try:
22 import cProfile as profile
23 import cProfile as profile
23 import pstats
24 import pstats
24 except ImportError:
25 except ImportError:
25 # profile isn't bundled by default in Debian for license reasons
26 # profile isn't bundled by default in Debian for license reasons
26 try:
27 try:
27 import profile, pstats
28 import profile, pstats
28 except ImportError:
29 except ImportError:
29 profile = pstats = None
30 profile = pstats = None
30
31
31 from IPython.core import oinspect
32 from IPython.core import oinspect
32 from IPython.core import magic_arguments
33 from IPython.core import magic_arguments
33 from IPython.core import page
34 from IPython.core import page
34 from IPython.core.error import UsageError
35 from IPython.core.error import UsageError
35 from IPython.core.macro import Macro
36 from IPython.core.macro import Macro
36 from IPython.core.magic import (Magics, magics_class, line_magic, cell_magic,
37 from IPython.core.magic import (Magics, magics_class, line_magic, cell_magic,
37 line_cell_magic, on_off, needs_local_scope)
38 line_cell_magic, on_off, needs_local_scope)
38 from IPython.testing.skipdoctest import skip_doctest
39 from IPython.testing.skipdoctest import skip_doctest
39 from IPython.utils import py3compat
40 from IPython.utils import py3compat
40 from IPython.utils.py3compat import builtin_mod, iteritems, PY3
41 from IPython.utils.py3compat import builtin_mod, iteritems, PY3
41 from IPython.utils.contexts import preserve_keys
42 from IPython.utils.contexts import preserve_keys
42 from IPython.utils.capture import capture_output
43 from IPython.utils.capture import capture_output
43 from IPython.utils.ipstruct import Struct
44 from IPython.utils.ipstruct import Struct
44 from IPython.utils.module_paths import find_mod
45 from IPython.utils.module_paths import find_mod
45 from IPython.utils.path import get_py_filename, shellglob
46 from IPython.utils.path import get_py_filename, shellglob
46 from IPython.utils.timing import clock, clock2
47 from IPython.utils.timing import clock, clock2
47 from warnings import warn
48 from warnings import warn
48 from logging import error
49 from logging import error
49
50
50 if PY3:
51 if PY3:
51 from io import StringIO
52 from io import StringIO
52 else:
53 else:
53 from StringIO import StringIO
54 from StringIO import StringIO
54
55
55 #-----------------------------------------------------------------------------
56 #-----------------------------------------------------------------------------
56 # Magic implementation classes
57 # Magic implementation classes
57 #-----------------------------------------------------------------------------
58 #-----------------------------------------------------------------------------
58
59
59
60
60 class TimeitResult(object):
61 class TimeitResult(object):
61 """
62 """
62 Object returned by the timeit magic with info about the run.
63 Object returned by the timeit magic with info about the run.
63
64
64 Contains the following attributes :
65 Contains the following attributes :
65
66
66 loops: (int) number of loops done per measurement
67 loops: (int) number of loops done per measurement
67 repeat: (int) number of times the measurement has been repeated
68 repeat: (int) number of times the measurement has been repeated
68 best: (float) best execution time / number
69 best: (float) best execution time / number
69 all_runs: (list of float) execution time of each run (in s)
70 all_runs: (list of float) execution time of each run (in s)
70 compile_time: (float) time of statement compilation (s)
71 compile_time: (float) time of statement compilation (s)
71
72
72 """
73 """
73
74
74 def __init__(self, loops, repeat, best, worst, all_runs, compile_time, precision):
75 def __init__(self, loops, repeat, average, stdev, all_runs, compile_time, precision):
75 self.loops = loops
76 self.loops = loops
76 self.repeat = repeat
77 self.repeat = repeat
77 self.best = best
78 self.average = average
78 self.worst = worst
79 self.stdev = stdev
79 self.all_runs = all_runs
80 self.all_runs = all_runs
80 self.compile_time = compile_time
81 self.compile_time = compile_time
81 self._precision = precision
82 self._precision = precision
82
83
83 def _repr_pretty_(self, p , cycle):
84 def _repr_pretty_(self, p , cycle):
84 if self.loops == 1: # No s at "loops" if only one loop
85 if self.loops == 1: # No s at "loops" if only one loop
85 unic = u"%d loop, best of %d: %s per loop" % (self.loops, self.repeat,
86 unic = (u"%s loop, average of %d: %s +- %s per loop (using standard deviation)"
86 _format_time(self.best, self._precision))
87 % (self.loops, self.repeat,
87 else:
88 _format_time(self.average, self._precision),
88 unic = u"%d loops, best of %d: %s per loop" % (self.loops, self.repeat,
89 _format_time(self.stdev, self._precision)))
89 _format_time(self.best, self._precision))
90 else:
90 p.text(u'<TimeitResult : '+unic+u'>')
91 unic = (u"%s loops, average of %d: %s +- %s per loop (using standard deviation)"
92 % (self.loops, self.repeat,
93 _format_time(self.average, self._precision),
94 _format_time(self.stdev, self._precision)))
95 p.text(u'<TimeitResult : '+unic+u'>')
91
96
92
97
93 class TimeitTemplateFiller(ast.NodeTransformer):
98 class TimeitTemplateFiller(ast.NodeTransformer):
94 """Fill in the AST template for timing execution.
99 """Fill in the AST template for timing execution.
95
100
96 This is quite closely tied to the template definition, which is in
101 This is quite closely tied to the template definition, which is in
97 :meth:`ExecutionMagics.timeit`.
102 :meth:`ExecutionMagics.timeit`.
98 """
103 """
99 def __init__(self, ast_setup, ast_stmt):
104 def __init__(self, ast_setup, ast_stmt):
100 self.ast_setup = ast_setup
105 self.ast_setup = ast_setup
101 self.ast_stmt = ast_stmt
106 self.ast_stmt = ast_stmt
102
107
103 def visit_FunctionDef(self, node):
108 def visit_FunctionDef(self, node):
104 "Fill in the setup statement"
109 "Fill in the setup statement"
105 self.generic_visit(node)
110 self.generic_visit(node)
106 if node.name == "inner":
111 if node.name == "inner":
107 node.body[:1] = self.ast_setup.body
112 node.body[:1] = self.ast_setup.body
108
113
109 return node
114 return node
110
115
111 def visit_For(self, node):
116 def visit_For(self, node):
112 "Fill in the statement to be timed"
117 "Fill in the statement to be timed"
113 if getattr(getattr(node.body[0], 'value', None), 'id', None) == 'stmt':
118 if getattr(getattr(node.body[0], 'value', None), 'id', None) == 'stmt':
114 node.body = self.ast_stmt.body
119 node.body = self.ast_stmt.body
115 return node
120 return node
116
121
117
122
118 class Timer(timeit.Timer):
123 class Timer(timeit.Timer):
119 """Timer class that explicitly uses self.inner
124 """Timer class that explicitly uses self.inner
120
125
121 which is an undocumented implementation detail of CPython,
126 which is an undocumented implementation detail of CPython,
122 not shared by PyPy.
127 not shared by PyPy.
123 """
128 """
124 # Timer.timeit copied from CPython 3.4.2
129 # Timer.timeit copied from CPython 3.4.2
125 def timeit(self, number=timeit.default_number):
130 def timeit(self, number=timeit.default_number):
126 """Time 'number' executions of the main statement.
131 """Time 'number' executions of the main statement.
127
132
128 To be precise, this executes the setup statement once, and
133 To be precise, this executes the setup statement once, and
129 then returns the time it takes to execute the main statement
134 then returns the time it takes to execute the main statement
130 a number of times, as a float measured in seconds. The
135 a number of times, as a float measured in seconds. The
131 argument is the number of times through the loop, defaulting
136 argument is the number of times through the loop, defaulting
132 to one million. The main statement, the setup statement and
137 to one million. The main statement, the setup statement and
133 the timer function to be used are passed to the constructor.
138 the timer function to be used are passed to the constructor.
134 """
139 """
135 it = itertools.repeat(None, number)
140 it = itertools.repeat(None, number)
136 gcold = gc.isenabled()
141 gcold = gc.isenabled()
137 gc.disable()
142 gc.disable()
138 try:
143 try:
139 timing = self.inner(it, self.timer)
144 timing = self.inner(it, self.timer)
140 finally:
145 finally:
141 if gcold:
146 if gcold:
142 gc.enable()
147 gc.enable()
143 return timing
148 return timing
144
149
145
150
146 @magics_class
151 @magics_class
147 class ExecutionMagics(Magics):
152 class ExecutionMagics(Magics):
148 """Magics related to code execution, debugging, profiling, etc.
153 """Magics related to code execution, debugging, profiling, etc.
149
154
150 """
155 """
151
156
152 def __init__(self, shell):
157 def __init__(self, shell):
153 super(ExecutionMagics, self).__init__(shell)
158 super(ExecutionMagics, self).__init__(shell)
154 if profile is None:
159 if profile is None:
155 self.prun = self.profile_missing_notice
160 self.prun = self.profile_missing_notice
156 # Default execution function used to actually run user code.
161 # Default execution function used to actually run user code.
157 self.default_runner = None
162 self.default_runner = None
158
163
159 def profile_missing_notice(self, *args, **kwargs):
164 def profile_missing_notice(self, *args, **kwargs):
160 error("""\
165 error("""\
161 The profile module could not be found. It has been removed from the standard
166 The profile module could not be found. It has been removed from the standard
162 python packages because of its non-free license. To use profiling, install the
167 python packages because of its non-free license. To use profiling, install the
163 python-profiler package from non-free.""")
168 python-profiler package from non-free.""")
164
169
165 @skip_doctest
170 @skip_doctest
166 @line_cell_magic
171 @line_cell_magic
167 def prun(self, parameter_s='', cell=None):
172 def prun(self, parameter_s='', cell=None):
168
173
169 """Run a statement through the python code profiler.
174 """Run a statement through the python code profiler.
170
175
171 Usage, in line mode:
176 Usage, in line mode:
172 %prun [options] statement
177 %prun [options] statement
173
178
174 Usage, in cell mode:
179 Usage, in cell mode:
175 %%prun [options] [statement]
180 %%prun [options] [statement]
176 code...
181 code...
177 code...
182 code...
178
183
179 In cell mode, the additional code lines are appended to the (possibly
184 In cell mode, the additional code lines are appended to the (possibly
180 empty) statement in the first line. Cell mode allows you to easily
185 empty) statement in the first line. Cell mode allows you to easily
181 profile multiline blocks without having to put them in a separate
186 profile multiline blocks without having to put them in a separate
182 function.
187 function.
183
188
184 The given statement (which doesn't require quote marks) is run via the
189 The given statement (which doesn't require quote marks) is run via the
185 python profiler in a manner similar to the profile.run() function.
190 python profiler in a manner similar to the profile.run() function.
186 Namespaces are internally managed to work correctly; profile.run
191 Namespaces are internally managed to work correctly; profile.run
187 cannot be used in IPython because it makes certain assumptions about
192 cannot be used in IPython because it makes certain assumptions about
188 namespaces which do not hold under IPython.
193 namespaces which do not hold under IPython.
189
194
190 Options:
195 Options:
191
196
192 -l <limit>
197 -l <limit>
193 you can place restrictions on what or how much of the
198 you can place restrictions on what or how much of the
194 profile gets printed. The limit value can be:
199 profile gets printed. The limit value can be:
195
200
196 * A string: only information for function names containing this string
201 * A string: only information for function names containing this string
197 is printed.
202 is printed.
198
203
199 * An integer: only these many lines are printed.
204 * An integer: only these many lines are printed.
200
205
201 * A float (between 0 and 1): this fraction of the report is printed
206 * A float (between 0 and 1): this fraction of the report is printed
202 (for example, use a limit of 0.4 to see the topmost 40% only).
207 (for example, use a limit of 0.4 to see the topmost 40% only).
203
208
204 You can combine several limits with repeated use of the option. For
209 You can combine several limits with repeated use of the option. For
205 example, ``-l __init__ -l 5`` will print only the topmost 5 lines of
210 example, ``-l __init__ -l 5`` will print only the topmost 5 lines of
206 information about class constructors.
211 information about class constructors.
207
212
208 -r
213 -r
209 return the pstats.Stats object generated by the profiling. This
214 return the pstats.Stats object generated by the profiling. This
210 object has all the information about the profile in it, and you can
215 object has all the information about the profile in it, and you can
211 later use it for further analysis or in other functions.
216 later use it for further analysis or in other functions.
212
217
213 -s <key>
218 -s <key>
214 sort profile by given key. You can provide more than one key
219 sort profile by given key. You can provide more than one key
215 by using the option several times: '-s key1 -s key2 -s key3...'. The
220 by using the option several times: '-s key1 -s key2 -s key3...'. The
216 default sorting key is 'time'.
221 default sorting key is 'time'.
217
222
218 The following is copied verbatim from the profile documentation
223 The following is copied verbatim from the profile documentation
219 referenced below:
224 referenced below:
220
225
221 When more than one key is provided, additional keys are used as
226 When more than one key is provided, additional keys are used as
222 secondary criteria when the there is equality in all keys selected
227 secondary criteria when the there is equality in all keys selected
223 before them.
228 before them.
224
229
225 Abbreviations can be used for any key names, as long as the
230 Abbreviations can be used for any key names, as long as the
226 abbreviation is unambiguous. The following are the keys currently
231 abbreviation is unambiguous. The following are the keys currently
227 defined:
232 defined:
228
233
229 ============ =====================
234 ============ =====================
230 Valid Arg Meaning
235 Valid Arg Meaning
231 ============ =====================
236 ============ =====================
232 "calls" call count
237 "calls" call count
233 "cumulative" cumulative time
238 "cumulative" cumulative time
234 "file" file name
239 "file" file name
235 "module" file name
240 "module" file name
236 "pcalls" primitive call count
241 "pcalls" primitive call count
237 "line" line number
242 "line" line number
238 "name" function name
243 "name" function name
239 "nfl" name/file/line
244 "nfl" name/file/line
240 "stdname" standard name
245 "stdname" standard name
241 "time" internal time
246 "time" internal time
242 ============ =====================
247 ============ =====================
243
248
244 Note that all sorts on statistics are in descending order (placing
249 Note that all sorts on statistics are in descending order (placing
245 most time consuming items first), where as name, file, and line number
250 most time consuming items first), where as name, file, and line number
246 searches are in ascending order (i.e., alphabetical). The subtle
251 searches are in ascending order (i.e., alphabetical). The subtle
247 distinction between "nfl" and "stdname" is that the standard name is a
252 distinction between "nfl" and "stdname" is that the standard name is a
248 sort of the name as printed, which means that the embedded line
253 sort of the name as printed, which means that the embedded line
249 numbers get compared in an odd way. For example, lines 3, 20, and 40
254 numbers get compared in an odd way. For example, lines 3, 20, and 40
250 would (if the file names were the same) appear in the string order
255 would (if the file names were the same) appear in the string order
251 "20" "3" and "40". In contrast, "nfl" does a numeric compare of the
256 "20" "3" and "40". In contrast, "nfl" does a numeric compare of the
252 line numbers. In fact, sort_stats("nfl") is the same as
257 line numbers. In fact, sort_stats("nfl") is the same as
253 sort_stats("name", "file", "line").
258 sort_stats("name", "file", "line").
254
259
255 -T <filename>
260 -T <filename>
256 save profile results as shown on screen to a text
261 save profile results as shown on screen to a text
257 file. The profile is still shown on screen.
262 file. The profile is still shown on screen.
258
263
259 -D <filename>
264 -D <filename>
260 save (via dump_stats) profile statistics to given
265 save (via dump_stats) profile statistics to given
261 filename. This data is in a format understood by the pstats module, and
266 filename. This data is in a format understood by the pstats module, and
262 is generated by a call to the dump_stats() method of profile
267 is generated by a call to the dump_stats() method of profile
263 objects. The profile is still shown on screen.
268 objects. The profile is still shown on screen.
264
269
265 -q
270 -q
266 suppress output to the pager. Best used with -T and/or -D above.
271 suppress output to the pager. Best used with -T and/or -D above.
267
272
268 If you want to run complete programs under the profiler's control, use
273 If you want to run complete programs under the profiler's control, use
269 ``%run -p [prof_opts] filename.py [args to program]`` where prof_opts
274 ``%run -p [prof_opts] filename.py [args to program]`` where prof_opts
270 contains profiler specific options as described here.
275 contains profiler specific options as described here.
271
276
272 You can read the complete documentation for the profile module with::
277 You can read the complete documentation for the profile module with::
273
278
274 In [1]: import profile; profile.help()
279 In [1]: import profile; profile.help()
275 """
280 """
276 opts, arg_str = self.parse_options(parameter_s, 'D:l:rs:T:q',
281 opts, arg_str = self.parse_options(parameter_s, 'D:l:rs:T:q',
277 list_all=True, posix=False)
282 list_all=True, posix=False)
278 if cell is not None:
283 if cell is not None:
279 arg_str += '\n' + cell
284 arg_str += '\n' + cell
280 arg_str = self.shell.input_splitter.transform_cell(arg_str)
285 arg_str = self.shell.input_splitter.transform_cell(arg_str)
281 return self._run_with_profiler(arg_str, opts, self.shell.user_ns)
286 return self._run_with_profiler(arg_str, opts, self.shell.user_ns)
282
287
283 def _run_with_profiler(self, code, opts, namespace):
288 def _run_with_profiler(self, code, opts, namespace):
284 """
289 """
285 Run `code` with profiler. Used by ``%prun`` and ``%run -p``.
290 Run `code` with profiler. Used by ``%prun`` and ``%run -p``.
286
291
287 Parameters
292 Parameters
288 ----------
293 ----------
289 code : str
294 code : str
290 Code to be executed.
295 Code to be executed.
291 opts : Struct
296 opts : Struct
292 Options parsed by `self.parse_options`.
297 Options parsed by `self.parse_options`.
293 namespace : dict
298 namespace : dict
294 A dictionary for Python namespace (e.g., `self.shell.user_ns`).
299 A dictionary for Python namespace (e.g., `self.shell.user_ns`).
295
300
296 """
301 """
297
302
298 # Fill default values for unspecified options:
303 # Fill default values for unspecified options:
299 opts.merge(Struct(D=[''], l=[], s=['time'], T=['']))
304 opts.merge(Struct(D=[''], l=[], s=['time'], T=['']))
300
305
301 prof = profile.Profile()
306 prof = profile.Profile()
302 try:
307 try:
303 prof = prof.runctx(code, namespace, namespace)
308 prof = prof.runctx(code, namespace, namespace)
304 sys_exit = ''
309 sys_exit = ''
305 except SystemExit:
310 except SystemExit:
306 sys_exit = """*** SystemExit exception caught in code being profiled."""
311 sys_exit = """*** SystemExit exception caught in code being profiled."""
307
312
308 stats = pstats.Stats(prof).strip_dirs().sort_stats(*opts.s)
313 stats = pstats.Stats(prof).strip_dirs().sort_stats(*opts.s)
309
314
310 lims = opts.l
315 lims = opts.l
311 if lims:
316 if lims:
312 lims = [] # rebuild lims with ints/floats/strings
317 lims = [] # rebuild lims with ints/floats/strings
313 for lim in opts.l:
318 for lim in opts.l:
314 try:
319 try:
315 lims.append(int(lim))
320 lims.append(int(lim))
316 except ValueError:
321 except ValueError:
317 try:
322 try:
318 lims.append(float(lim))
323 lims.append(float(lim))
319 except ValueError:
324 except ValueError:
320 lims.append(lim)
325 lims.append(lim)
321
326
322 # Trap output.
327 # Trap output.
323 stdout_trap = StringIO()
328 stdout_trap = StringIO()
324 stats_stream = stats.stream
329 stats_stream = stats.stream
325 try:
330 try:
326 stats.stream = stdout_trap
331 stats.stream = stdout_trap
327 stats.print_stats(*lims)
332 stats.print_stats(*lims)
328 finally:
333 finally:
329 stats.stream = stats_stream
334 stats.stream = stats_stream
330
335
331 output = stdout_trap.getvalue()
336 output = stdout_trap.getvalue()
332 output = output.rstrip()
337 output = output.rstrip()
333
338
334 if 'q' not in opts:
339 if 'q' not in opts:
335 page.page(output)
340 page.page(output)
336 print(sys_exit, end=' ')
341 print(sys_exit, end=' ')
337
342
338 dump_file = opts.D[0]
343 dump_file = opts.D[0]
339 text_file = opts.T[0]
344 text_file = opts.T[0]
340 if dump_file:
345 if dump_file:
341 prof.dump_stats(dump_file)
346 prof.dump_stats(dump_file)
342 print('\n*** Profile stats marshalled to file',\
347 print('\n*** Profile stats marshalled to file',\
343 repr(dump_file)+'.',sys_exit)
348 repr(dump_file)+'.',sys_exit)
344 if text_file:
349 if text_file:
345 pfile = open(text_file,'w')
350 pfile = open(text_file,'w')
346 pfile.write(output)
351 pfile.write(output)
347 pfile.close()
352 pfile.close()
348 print('\n*** Profile printout saved to text file',\
353 print('\n*** Profile printout saved to text file',\
349 repr(text_file)+'.',sys_exit)
354 repr(text_file)+'.',sys_exit)
350
355
351 if 'r' in opts:
356 if 'r' in opts:
352 return stats
357 return stats
353 else:
358 else:
354 return None
359 return None
355
360
356 @line_magic
361 @line_magic
357 def pdb(self, parameter_s=''):
362 def pdb(self, parameter_s=''):
358 """Control the automatic calling of the pdb interactive debugger.
363 """Control the automatic calling of the pdb interactive debugger.
359
364
360 Call as '%pdb on', '%pdb 1', '%pdb off' or '%pdb 0'. If called without
365 Call as '%pdb on', '%pdb 1', '%pdb off' or '%pdb 0'. If called without
361 argument it works as a toggle.
366 argument it works as a toggle.
362
367
363 When an exception is triggered, IPython can optionally call the
368 When an exception is triggered, IPython can optionally call the
364 interactive pdb debugger after the traceback printout. %pdb toggles
369 interactive pdb debugger after the traceback printout. %pdb toggles
365 this feature on and off.
370 this feature on and off.
366
371
367 The initial state of this feature is set in your configuration
372 The initial state of this feature is set in your configuration
368 file (the option is ``InteractiveShell.pdb``).
373 file (the option is ``InteractiveShell.pdb``).
369
374
370 If you want to just activate the debugger AFTER an exception has fired,
375 If you want to just activate the debugger AFTER an exception has fired,
371 without having to type '%pdb on' and rerunning your code, you can use
376 without having to type '%pdb on' and rerunning your code, you can use
372 the %debug magic."""
377 the %debug magic."""
373
378
374 par = parameter_s.strip().lower()
379 par = parameter_s.strip().lower()
375
380
376 if par:
381 if par:
377 try:
382 try:
378 new_pdb = {'off':0,'0':0,'on':1,'1':1}[par]
383 new_pdb = {'off':0,'0':0,'on':1,'1':1}[par]
379 except KeyError:
384 except KeyError:
380 print ('Incorrect argument. Use on/1, off/0, '
385 print ('Incorrect argument. Use on/1, off/0, '
381 'or nothing for a toggle.')
386 'or nothing for a toggle.')
382 return
387 return
383 else:
388 else:
384 # toggle
389 # toggle
385 new_pdb = not self.shell.call_pdb
390 new_pdb = not self.shell.call_pdb
386
391
387 # set on the shell
392 # set on the shell
388 self.shell.call_pdb = new_pdb
393 self.shell.call_pdb = new_pdb
389 print('Automatic pdb calling has been turned',on_off(new_pdb))
394 print('Automatic pdb calling has been turned',on_off(new_pdb))
390
395
391 @skip_doctest
396 @skip_doctest
392 @magic_arguments.magic_arguments()
397 @magic_arguments.magic_arguments()
393 @magic_arguments.argument('--breakpoint', '-b', metavar='FILE:LINE',
398 @magic_arguments.argument('--breakpoint', '-b', metavar='FILE:LINE',
394 help="""
399 help="""
395 Set break point at LINE in FILE.
400 Set break point at LINE in FILE.
396 """
401 """
397 )
402 )
398 @magic_arguments.argument('statement', nargs='*',
403 @magic_arguments.argument('statement', nargs='*',
399 help="""
404 help="""
400 Code to run in debugger.
405 Code to run in debugger.
401 You can omit this in cell magic mode.
406 You can omit this in cell magic mode.
402 """
407 """
403 )
408 )
404 @line_cell_magic
409 @line_cell_magic
405 def debug(self, line='', cell=None):
410 def debug(self, line='', cell=None):
406 """Activate the interactive debugger.
411 """Activate the interactive debugger.
407
412
408 This magic command support two ways of activating debugger.
413 This magic command support two ways of activating debugger.
409 One is to activate debugger before executing code. This way, you
414 One is to activate debugger before executing code. This way, you
410 can set a break point, to step through the code from the point.
415 can set a break point, to step through the code from the point.
411 You can use this mode by giving statements to execute and optionally
416 You can use this mode by giving statements to execute and optionally
412 a breakpoint.
417 a breakpoint.
413
418
414 The other one is to activate debugger in post-mortem mode. You can
419 The other one is to activate debugger in post-mortem mode. You can
415 activate this mode simply running %debug without any argument.
420 activate this mode simply running %debug without any argument.
416 If an exception has just occurred, this lets you inspect its stack
421 If an exception has just occurred, this lets you inspect its stack
417 frames interactively. Note that this will always work only on the last
422 frames interactively. Note that this will always work only on the last
418 traceback that occurred, so you must call this quickly after an
423 traceback that occurred, so you must call this quickly after an
419 exception that you wish to inspect has fired, because if another one
424 exception that you wish to inspect has fired, because if another one
420 occurs, it clobbers the previous one.
425 occurs, it clobbers the previous one.
421
426
422 If you want IPython to automatically do this on every exception, see
427 If you want IPython to automatically do this on every exception, see
423 the %pdb magic for more details.
428 the %pdb magic for more details.
424 """
429 """
425 args = magic_arguments.parse_argstring(self.debug, line)
430 args = magic_arguments.parse_argstring(self.debug, line)
426
431
427 if not (args.breakpoint or args.statement or cell):
432 if not (args.breakpoint or args.statement or cell):
428 self._debug_post_mortem()
433 self._debug_post_mortem()
429 else:
434 else:
430 code = "\n".join(args.statement)
435 code = "\n".join(args.statement)
431 if cell:
436 if cell:
432 code += "\n" + cell
437 code += "\n" + cell
433 self._debug_exec(code, args.breakpoint)
438 self._debug_exec(code, args.breakpoint)
434
439
435 def _debug_post_mortem(self):
440 def _debug_post_mortem(self):
436 self.shell.debugger(force=True)
441 self.shell.debugger(force=True)
437
442
438 def _debug_exec(self, code, breakpoint):
443 def _debug_exec(self, code, breakpoint):
439 if breakpoint:
444 if breakpoint:
440 (filename, bp_line) = breakpoint.rsplit(':', 1)
445 (filename, bp_line) = breakpoint.rsplit(':', 1)
441 bp_line = int(bp_line)
446 bp_line = int(bp_line)
442 else:
447 else:
443 (filename, bp_line) = (None, None)
448 (filename, bp_line) = (None, None)
444 self._run_with_debugger(code, self.shell.user_ns, filename, bp_line)
449 self._run_with_debugger(code, self.shell.user_ns, filename, bp_line)
445
450
446 @line_magic
451 @line_magic
447 def tb(self, s):
452 def tb(self, s):
448 """Print the last traceback with the currently active exception mode.
453 """Print the last traceback with the currently active exception mode.
449
454
450 See %xmode for changing exception reporting modes."""
455 See %xmode for changing exception reporting modes."""
451 self.shell.showtraceback()
456 self.shell.showtraceback()
452
457
453 @skip_doctest
458 @skip_doctest
454 @line_magic
459 @line_magic
455 def run(self, parameter_s='', runner=None,
460 def run(self, parameter_s='', runner=None,
456 file_finder=get_py_filename):
461 file_finder=get_py_filename):
457 """Run the named file inside IPython as a program.
462 """Run the named file inside IPython as a program.
458
463
459 Usage::
464 Usage::
460
465
461 %run [-n -i -e -G]
466 %run [-n -i -e -G]
462 [( -t [-N<N>] | -d [-b<N>] | -p [profile options] )]
467 [( -t [-N<N>] | -d [-b<N>] | -p [profile options] )]
463 ( -m mod | file ) [args]
468 ( -m mod | file ) [args]
464
469
465 Parameters after the filename are passed as command-line arguments to
470 Parameters after the filename are passed as command-line arguments to
466 the program (put in sys.argv). Then, control returns to IPython's
471 the program (put in sys.argv). Then, control returns to IPython's
467 prompt.
472 prompt.
468
473
469 This is similar to running at a system prompt ``python file args``,
474 This is similar to running at a system prompt ``python file args``,
470 but with the advantage of giving you IPython's tracebacks, and of
475 but with the advantage of giving you IPython's tracebacks, and of
471 loading all variables into your interactive namespace for further use
476 loading all variables into your interactive namespace for further use
472 (unless -p is used, see below).
477 (unless -p is used, see below).
473
478
474 The file is executed in a namespace initially consisting only of
479 The file is executed in a namespace initially consisting only of
475 ``__name__=='__main__'`` and sys.argv constructed as indicated. It thus
480 ``__name__=='__main__'`` and sys.argv constructed as indicated. It thus
476 sees its environment as if it were being run as a stand-alone program
481 sees its environment as if it were being run as a stand-alone program
477 (except for sharing global objects such as previously imported
482 (except for sharing global objects such as previously imported
478 modules). But after execution, the IPython interactive namespace gets
483 modules). But after execution, the IPython interactive namespace gets
479 updated with all variables defined in the program (except for __name__
484 updated with all variables defined in the program (except for __name__
480 and sys.argv). This allows for very convenient loading of code for
485 and sys.argv). This allows for very convenient loading of code for
481 interactive work, while giving each program a 'clean sheet' to run in.
486 interactive work, while giving each program a 'clean sheet' to run in.
482
487
483 Arguments are expanded using shell-like glob match. Patterns
488 Arguments are expanded using shell-like glob match. Patterns
484 '*', '?', '[seq]' and '[!seq]' can be used. Additionally,
489 '*', '?', '[seq]' and '[!seq]' can be used. Additionally,
485 tilde '~' will be expanded into user's home directory. Unlike
490 tilde '~' will be expanded into user's home directory. Unlike
486 real shells, quotation does not suppress expansions. Use
491 real shells, quotation does not suppress expansions. Use
487 *two* back slashes (e.g. ``\\\\*``) to suppress expansions.
492 *two* back slashes (e.g. ``\\\\*``) to suppress expansions.
488 To completely disable these expansions, you can use -G flag.
493 To completely disable these expansions, you can use -G flag.
489
494
490 Options:
495 Options:
491
496
492 -n
497 -n
493 __name__ is NOT set to '__main__', but to the running file's name
498 __name__ is NOT set to '__main__', but to the running file's name
494 without extension (as python does under import). This allows running
499 without extension (as python does under import). This allows running
495 scripts and reloading the definitions in them without calling code
500 scripts and reloading the definitions in them without calling code
496 protected by an ``if __name__ == "__main__"`` clause.
501 protected by an ``if __name__ == "__main__"`` clause.
497
502
498 -i
503 -i
499 run the file in IPython's namespace instead of an empty one. This
504 run the file in IPython's namespace instead of an empty one. This
500 is useful if you are experimenting with code written in a text editor
505 is useful if you are experimenting with code written in a text editor
501 which depends on variables defined interactively.
506 which depends on variables defined interactively.
502
507
503 -e
508 -e
504 ignore sys.exit() calls or SystemExit exceptions in the script
509 ignore sys.exit() calls or SystemExit exceptions in the script
505 being run. This is particularly useful if IPython is being used to
510 being run. This is particularly useful if IPython is being used to
506 run unittests, which always exit with a sys.exit() call. In such
511 run unittests, which always exit with a sys.exit() call. In such
507 cases you are interested in the output of the test results, not in
512 cases you are interested in the output of the test results, not in
508 seeing a traceback of the unittest module.
513 seeing a traceback of the unittest module.
509
514
510 -t
515 -t
511 print timing information at the end of the run. IPython will give
516 print timing information at the end of the run. IPython will give
512 you an estimated CPU time consumption for your script, which under
517 you an estimated CPU time consumption for your script, which under
513 Unix uses the resource module to avoid the wraparound problems of
518 Unix uses the resource module to avoid the wraparound problems of
514 time.clock(). Under Unix, an estimate of time spent on system tasks
519 time.clock(). Under Unix, an estimate of time spent on system tasks
515 is also given (for Windows platforms this is reported as 0.0).
520 is also given (for Windows platforms this is reported as 0.0).
516
521
517 If -t is given, an additional ``-N<N>`` option can be given, where <N>
522 If -t is given, an additional ``-N<N>`` option can be given, where <N>
518 must be an integer indicating how many times you want the script to
523 must be an integer indicating how many times you want the script to
519 run. The final timing report will include total and per run results.
524 run. The final timing report will include total and per run results.
520
525
521 For example (testing the script uniq_stable.py)::
526 For example (testing the script uniq_stable.py)::
522
527
523 In [1]: run -t uniq_stable
528 In [1]: run -t uniq_stable
524
529
525 IPython CPU timings (estimated):
530 IPython CPU timings (estimated):
526 User : 0.19597 s.
531 User : 0.19597 s.
527 System: 0.0 s.
532 System: 0.0 s.
528
533
529 In [2]: run -t -N5 uniq_stable
534 In [2]: run -t -N5 uniq_stable
530
535
531 IPython CPU timings (estimated):
536 IPython CPU timings (estimated):
532 Total runs performed: 5
537 Total runs performed: 5
533 Times : Total Per run
538 Times : Total Per run
534 User : 0.910862 s, 0.1821724 s.
539 User : 0.910862 s, 0.1821724 s.
535 System: 0.0 s, 0.0 s.
540 System: 0.0 s, 0.0 s.
536
541
537 -d
542 -d
538 run your program under the control of pdb, the Python debugger.
543 run your program under the control of pdb, the Python debugger.
539 This allows you to execute your program step by step, watch variables,
544 This allows you to execute your program step by step, watch variables,
540 etc. Internally, what IPython does is similar to calling::
545 etc. Internally, what IPython does is similar to calling::
541
546
542 pdb.run('execfile("YOURFILENAME")')
547 pdb.run('execfile("YOURFILENAME")')
543
548
544 with a breakpoint set on line 1 of your file. You can change the line
549 with a breakpoint set on line 1 of your file. You can change the line
545 number for this automatic breakpoint to be <N> by using the -bN option
550 number for this automatic breakpoint to be <N> by using the -bN option
546 (where N must be an integer). For example::
551 (where N must be an integer). For example::
547
552
548 %run -d -b40 myscript
553 %run -d -b40 myscript
549
554
550 will set the first breakpoint at line 40 in myscript.py. Note that
555 will set the first breakpoint at line 40 in myscript.py. Note that
551 the first breakpoint must be set on a line which actually does
556 the first breakpoint must be set on a line which actually does
552 something (not a comment or docstring) for it to stop execution.
557 something (not a comment or docstring) for it to stop execution.
553
558
554 Or you can specify a breakpoint in a different file::
559 Or you can specify a breakpoint in a different file::
555
560
556 %run -d -b myotherfile.py:20 myscript
561 %run -d -b myotherfile.py:20 myscript
557
562
558 When the pdb debugger starts, you will see a (Pdb) prompt. You must
563 When the pdb debugger starts, you will see a (Pdb) prompt. You must
559 first enter 'c' (without quotes) to start execution up to the first
564 first enter 'c' (without quotes) to start execution up to the first
560 breakpoint.
565 breakpoint.
561
566
562 Entering 'help' gives information about the use of the debugger. You
567 Entering 'help' gives information about the use of the debugger. You
563 can easily see pdb's full documentation with "import pdb;pdb.help()"
568 can easily see pdb's full documentation with "import pdb;pdb.help()"
564 at a prompt.
569 at a prompt.
565
570
566 -p
571 -p
567 run program under the control of the Python profiler module (which
572 run program under the control of the Python profiler module (which
568 prints a detailed report of execution times, function calls, etc).
573 prints a detailed report of execution times, function calls, etc).
569
574
570 You can pass other options after -p which affect the behavior of the
575 You can pass other options after -p which affect the behavior of the
571 profiler itself. See the docs for %prun for details.
576 profiler itself. See the docs for %prun for details.
572
577
573 In this mode, the program's variables do NOT propagate back to the
578 In this mode, the program's variables do NOT propagate back to the
574 IPython interactive namespace (because they remain in the namespace
579 IPython interactive namespace (because they remain in the namespace
575 where the profiler executes them).
580 where the profiler executes them).
576
581
577 Internally this triggers a call to %prun, see its documentation for
582 Internally this triggers a call to %prun, see its documentation for
578 details on the options available specifically for profiling.
583 details on the options available specifically for profiling.
579
584
580 There is one special usage for which the text above doesn't apply:
585 There is one special usage for which the text above doesn't apply:
581 if the filename ends with .ipy[nb], the file is run as ipython script,
586 if the filename ends with .ipy[nb], the file is run as ipython script,
582 just as if the commands were written on IPython prompt.
587 just as if the commands were written on IPython prompt.
583
588
584 -m
589 -m
585 specify module name to load instead of script path. Similar to
590 specify module name to load instead of script path. Similar to
586 the -m option for the python interpreter. Use this option last if you
591 the -m option for the python interpreter. Use this option last if you
587 want to combine with other %run options. Unlike the python interpreter
592 want to combine with other %run options. Unlike the python interpreter
588 only source modules are allowed no .pyc or .pyo files.
593 only source modules are allowed no .pyc or .pyo files.
589 For example::
594 For example::
590
595
591 %run -m example
596 %run -m example
592
597
593 will run the example module.
598 will run the example module.
594
599
595 -G
600 -G
596 disable shell-like glob expansion of arguments.
601 disable shell-like glob expansion of arguments.
597
602
598 """
603 """
599
604
600 # get arguments and set sys.argv for program to be run.
605 # get arguments and set sys.argv for program to be run.
601 opts, arg_lst = self.parse_options(parameter_s,
606 opts, arg_lst = self.parse_options(parameter_s,
602 'nidtN:b:pD:l:rs:T:em:G',
607 'nidtN:b:pD:l:rs:T:em:G',
603 mode='list', list_all=1)
608 mode='list', list_all=1)
604 if "m" in opts:
609 if "m" in opts:
605 modulename = opts["m"][0]
610 modulename = opts["m"][0]
606 modpath = find_mod(modulename)
611 modpath = find_mod(modulename)
607 if modpath is None:
612 if modpath is None:
608 warn('%r is not a valid modulename on sys.path'%modulename)
613 warn('%r is not a valid modulename on sys.path'%modulename)
609 return
614 return
610 arg_lst = [modpath] + arg_lst
615 arg_lst = [modpath] + arg_lst
611 try:
616 try:
612 filename = file_finder(arg_lst[0])
617 filename = file_finder(arg_lst[0])
613 except IndexError:
618 except IndexError:
614 warn('you must provide at least a filename.')
619 warn('you must provide at least a filename.')
615 print('\n%run:\n', oinspect.getdoc(self.run))
620 print('\n%run:\n', oinspect.getdoc(self.run))
616 return
621 return
617 except IOError as e:
622 except IOError as e:
618 try:
623 try:
619 msg = str(e)
624 msg = str(e)
620 except UnicodeError:
625 except UnicodeError:
621 msg = e.message
626 msg = e.message
622 error(msg)
627 error(msg)
623 return
628 return
624
629
625 if filename.lower().endswith(('.ipy', '.ipynb')):
630 if filename.lower().endswith(('.ipy', '.ipynb')):
626 with preserve_keys(self.shell.user_ns, '__file__'):
631 with preserve_keys(self.shell.user_ns, '__file__'):
627 self.shell.user_ns['__file__'] = filename
632 self.shell.user_ns['__file__'] = filename
628 self.shell.safe_execfile_ipy(filename)
633 self.shell.safe_execfile_ipy(filename)
629 return
634 return
630
635
631 # Control the response to exit() calls made by the script being run
636 # Control the response to exit() calls made by the script being run
632 exit_ignore = 'e' in opts
637 exit_ignore = 'e' in opts
633
638
634 # Make sure that the running script gets a proper sys.argv as if it
639 # Make sure that the running script gets a proper sys.argv as if it
635 # were run from a system shell.
640 # were run from a system shell.
636 save_argv = sys.argv # save it for later restoring
641 save_argv = sys.argv # save it for later restoring
637
642
638 if 'G' in opts:
643 if 'G' in opts:
639 args = arg_lst[1:]
644 args = arg_lst[1:]
640 else:
645 else:
641 # tilde and glob expansion
646 # tilde and glob expansion
642 args = shellglob(map(os.path.expanduser, arg_lst[1:]))
647 args = shellglob(map(os.path.expanduser, arg_lst[1:]))
643
648
644 sys.argv = [filename] + args # put in the proper filename
649 sys.argv = [filename] + args # put in the proper filename
645 # protect sys.argv from potential unicode strings on Python 2:
650 # protect sys.argv from potential unicode strings on Python 2:
646 if not py3compat.PY3:
651 if not py3compat.PY3:
647 sys.argv = [ py3compat.cast_bytes(a) for a in sys.argv ]
652 sys.argv = [ py3compat.cast_bytes(a) for a in sys.argv ]
648
653
649 if 'i' in opts:
654 if 'i' in opts:
650 # Run in user's interactive namespace
655 # Run in user's interactive namespace
651 prog_ns = self.shell.user_ns
656 prog_ns = self.shell.user_ns
652 __name__save = self.shell.user_ns['__name__']
657 __name__save = self.shell.user_ns['__name__']
653 prog_ns['__name__'] = '__main__'
658 prog_ns['__name__'] = '__main__'
654 main_mod = self.shell.user_module
659 main_mod = self.shell.user_module
655
660
656 # Since '%run foo' emulates 'python foo.py' at the cmd line, we must
661 # Since '%run foo' emulates 'python foo.py' at the cmd line, we must
657 # set the __file__ global in the script's namespace
662 # set the __file__ global in the script's namespace
658 # TK: Is this necessary in interactive mode?
663 # TK: Is this necessary in interactive mode?
659 prog_ns['__file__'] = filename
664 prog_ns['__file__'] = filename
660 else:
665 else:
661 # Run in a fresh, empty namespace
666 # Run in a fresh, empty namespace
662 if 'n' in opts:
667 if 'n' in opts:
663 name = os.path.splitext(os.path.basename(filename))[0]
668 name = os.path.splitext(os.path.basename(filename))[0]
664 else:
669 else:
665 name = '__main__'
670 name = '__main__'
666
671
667 # The shell MUST hold a reference to prog_ns so after %run
672 # The shell MUST hold a reference to prog_ns so after %run
668 # exits, the python deletion mechanism doesn't zero it out
673 # exits, the python deletion mechanism doesn't zero it out
669 # (leaving dangling references). See interactiveshell for details
674 # (leaving dangling references). See interactiveshell for details
670 main_mod = self.shell.new_main_mod(filename, name)
675 main_mod = self.shell.new_main_mod(filename, name)
671 prog_ns = main_mod.__dict__
676 prog_ns = main_mod.__dict__
672
677
673 # pickle fix. See interactiveshell for an explanation. But we need to
678 # pickle fix. See interactiveshell for an explanation. But we need to
674 # make sure that, if we overwrite __main__, we replace it at the end
679 # make sure that, if we overwrite __main__, we replace it at the end
675 main_mod_name = prog_ns['__name__']
680 main_mod_name = prog_ns['__name__']
676
681
677 if main_mod_name == '__main__':
682 if main_mod_name == '__main__':
678 restore_main = sys.modules['__main__']
683 restore_main = sys.modules['__main__']
679 else:
684 else:
680 restore_main = False
685 restore_main = False
681
686
682 # This needs to be undone at the end to prevent holding references to
687 # This needs to be undone at the end to prevent holding references to
683 # every single object ever created.
688 # every single object ever created.
684 sys.modules[main_mod_name] = main_mod
689 sys.modules[main_mod_name] = main_mod
685
690
686 if 'p' in opts or 'd' in opts:
691 if 'p' in opts or 'd' in opts:
687 if 'm' in opts:
692 if 'm' in opts:
688 code = 'run_module(modulename, prog_ns)'
693 code = 'run_module(modulename, prog_ns)'
689 code_ns = {
694 code_ns = {
690 'run_module': self.shell.safe_run_module,
695 'run_module': self.shell.safe_run_module,
691 'prog_ns': prog_ns,
696 'prog_ns': prog_ns,
692 'modulename': modulename,
697 'modulename': modulename,
693 }
698 }
694 else:
699 else:
695 if 'd' in opts:
700 if 'd' in opts:
696 # allow exceptions to raise in debug mode
701 # allow exceptions to raise in debug mode
697 code = 'execfile(filename, prog_ns, raise_exceptions=True)'
702 code = 'execfile(filename, prog_ns, raise_exceptions=True)'
698 else:
703 else:
699 code = 'execfile(filename, prog_ns)'
704 code = 'execfile(filename, prog_ns)'
700 code_ns = {
705 code_ns = {
701 'execfile': self.shell.safe_execfile,
706 'execfile': self.shell.safe_execfile,
702 'prog_ns': prog_ns,
707 'prog_ns': prog_ns,
703 'filename': get_py_filename(filename),
708 'filename': get_py_filename(filename),
704 }
709 }
705
710
706 try:
711 try:
707 stats = None
712 stats = None
708 if 'p' in opts:
713 if 'p' in opts:
709 stats = self._run_with_profiler(code, opts, code_ns)
714 stats = self._run_with_profiler(code, opts, code_ns)
710 else:
715 else:
711 if 'd' in opts:
716 if 'd' in opts:
712 bp_file, bp_line = parse_breakpoint(
717 bp_file, bp_line = parse_breakpoint(
713 opts.get('b', ['1'])[0], filename)
718 opts.get('b', ['1'])[0], filename)
714 self._run_with_debugger(
719 self._run_with_debugger(
715 code, code_ns, filename, bp_line, bp_file)
720 code, code_ns, filename, bp_line, bp_file)
716 else:
721 else:
717 if 'm' in opts:
722 if 'm' in opts:
718 def run():
723 def run():
719 self.shell.safe_run_module(modulename, prog_ns)
724 self.shell.safe_run_module(modulename, prog_ns)
720 else:
725 else:
721 if runner is None:
726 if runner is None:
722 runner = self.default_runner
727 runner = self.default_runner
723 if runner is None:
728 if runner is None:
724 runner = self.shell.safe_execfile
729 runner = self.shell.safe_execfile
725
730
726 def run():
731 def run():
727 runner(filename, prog_ns, prog_ns,
732 runner(filename, prog_ns, prog_ns,
728 exit_ignore=exit_ignore)
733 exit_ignore=exit_ignore)
729
734
730 if 't' in opts:
735 if 't' in opts:
731 # timed execution
736 # timed execution
732 try:
737 try:
733 nruns = int(opts['N'][0])
738 nruns = int(opts['N'][0])
734 if nruns < 1:
739 if nruns < 1:
735 error('Number of runs must be >=1')
740 error('Number of runs must be >=1')
736 return
741 return
737 except (KeyError):
742 except (KeyError):
738 nruns = 1
743 nruns = 1
739 self._run_with_timing(run, nruns)
744 self._run_with_timing(run, nruns)
740 else:
745 else:
741 # regular execution
746 # regular execution
742 run()
747 run()
743
748
744 if 'i' in opts:
749 if 'i' in opts:
745 self.shell.user_ns['__name__'] = __name__save
750 self.shell.user_ns['__name__'] = __name__save
746 else:
751 else:
747 # update IPython interactive namespace
752 # update IPython interactive namespace
748
753
749 # Some forms of read errors on the file may mean the
754 # Some forms of read errors on the file may mean the
750 # __name__ key was never set; using pop we don't have to
755 # __name__ key was never set; using pop we don't have to
751 # worry about a possible KeyError.
756 # worry about a possible KeyError.
752 prog_ns.pop('__name__', None)
757 prog_ns.pop('__name__', None)
753
758
754 with preserve_keys(self.shell.user_ns, '__file__'):
759 with preserve_keys(self.shell.user_ns, '__file__'):
755 self.shell.user_ns.update(prog_ns)
760 self.shell.user_ns.update(prog_ns)
756 finally:
761 finally:
757 # It's a bit of a mystery why, but __builtins__ can change from
762 # It's a bit of a mystery why, but __builtins__ can change from
758 # being a module to becoming a dict missing some key data after
763 # being a module to becoming a dict missing some key data after
759 # %run. As best I can see, this is NOT something IPython is doing
764 # %run. As best I can see, this is NOT something IPython is doing
760 # at all, and similar problems have been reported before:
765 # at all, and similar problems have been reported before:
761 # http://coding.derkeiler.com/Archive/Python/comp.lang.python/2004-10/0188.html
766 # http://coding.derkeiler.com/Archive/Python/comp.lang.python/2004-10/0188.html
762 # Since this seems to be done by the interpreter itself, the best
767 # Since this seems to be done by the interpreter itself, the best
763 # we can do is to at least restore __builtins__ for the user on
768 # we can do is to at least restore __builtins__ for the user on
764 # exit.
769 # exit.
765 self.shell.user_ns['__builtins__'] = builtin_mod
770 self.shell.user_ns['__builtins__'] = builtin_mod
766
771
767 # Ensure key global structures are restored
772 # Ensure key global structures are restored
768 sys.argv = save_argv
773 sys.argv = save_argv
769 if restore_main:
774 if restore_main:
770 sys.modules['__main__'] = restore_main
775 sys.modules['__main__'] = restore_main
771 else:
776 else:
772 # Remove from sys.modules the reference to main_mod we'd
777 # Remove from sys.modules the reference to main_mod we'd
773 # added. Otherwise it will trap references to objects
778 # added. Otherwise it will trap references to objects
774 # contained therein.
779 # contained therein.
775 del sys.modules[main_mod_name]
780 del sys.modules[main_mod_name]
776
781
777 return stats
782 return stats
778
783
779 def _run_with_debugger(self, code, code_ns, filename=None,
784 def _run_with_debugger(self, code, code_ns, filename=None,
780 bp_line=None, bp_file=None):
785 bp_line=None, bp_file=None):
781 """
786 """
782 Run `code` in debugger with a break point.
787 Run `code` in debugger with a break point.
783
788
784 Parameters
789 Parameters
785 ----------
790 ----------
786 code : str
791 code : str
787 Code to execute.
792 Code to execute.
788 code_ns : dict
793 code_ns : dict
789 A namespace in which `code` is executed.
794 A namespace in which `code` is executed.
790 filename : str
795 filename : str
791 `code` is ran as if it is in `filename`.
796 `code` is ran as if it is in `filename`.
792 bp_line : int, optional
797 bp_line : int, optional
793 Line number of the break point.
798 Line number of the break point.
794 bp_file : str, optional
799 bp_file : str, optional
795 Path to the file in which break point is specified.
800 Path to the file in which break point is specified.
796 `filename` is used if not given.
801 `filename` is used if not given.
797
802
798 Raises
803 Raises
799 ------
804 ------
800 UsageError
805 UsageError
801 If the break point given by `bp_line` is not valid.
806 If the break point given by `bp_line` is not valid.
802
807
803 """
808 """
804 deb = self.shell.InteractiveTB.pdb
809 deb = self.shell.InteractiveTB.pdb
805 if not deb:
810 if not deb:
806 self.shell.InteractiveTB.pdb = self.shell.InteractiveTB.debugger_cls()
811 self.shell.InteractiveTB.pdb = self.shell.InteractiveTB.debugger_cls()
807 deb = self.shell.InteractiveTB.pdb
812 deb = self.shell.InteractiveTB.pdb
808
813
809 # reset Breakpoint state, which is moronically kept
814 # reset Breakpoint state, which is moronically kept
810 # in a class
815 # in a class
811 bdb.Breakpoint.next = 1
816 bdb.Breakpoint.next = 1
812 bdb.Breakpoint.bplist = {}
817 bdb.Breakpoint.bplist = {}
813 bdb.Breakpoint.bpbynumber = [None]
818 bdb.Breakpoint.bpbynumber = [None]
814 if bp_line is not None:
819 if bp_line is not None:
815 # Set an initial breakpoint to stop execution
820 # Set an initial breakpoint to stop execution
816 maxtries = 10
821 maxtries = 10
817 bp_file = bp_file or filename
822 bp_file = bp_file or filename
818 checkline = deb.checkline(bp_file, bp_line)
823 checkline = deb.checkline(bp_file, bp_line)
819 if not checkline:
824 if not checkline:
820 for bp in range(bp_line + 1, bp_line + maxtries + 1):
825 for bp in range(bp_line + 1, bp_line + maxtries + 1):
821 if deb.checkline(bp_file, bp):
826 if deb.checkline(bp_file, bp):
822 break
827 break
823 else:
828 else:
824 msg = ("\nI failed to find a valid line to set "
829 msg = ("\nI failed to find a valid line to set "
825 "a breakpoint\n"
830 "a breakpoint\n"
826 "after trying up to line: %s.\n"
831 "after trying up to line: %s.\n"
827 "Please set a valid breakpoint manually "
832 "Please set a valid breakpoint manually "
828 "with the -b option." % bp)
833 "with the -b option." % bp)
829 raise UsageError(msg)
834 raise UsageError(msg)
830 # if we find a good linenumber, set the breakpoint
835 # if we find a good linenumber, set the breakpoint
831 deb.do_break('%s:%s' % (bp_file, bp_line))
836 deb.do_break('%s:%s' % (bp_file, bp_line))
832
837
833 if filename:
838 if filename:
834 # Mimic Pdb._runscript(...)
839 # Mimic Pdb._runscript(...)
835 deb._wait_for_mainpyfile = True
840 deb._wait_for_mainpyfile = True
836 deb.mainpyfile = deb.canonic(filename)
841 deb.mainpyfile = deb.canonic(filename)
837
842
838 # Start file run
843 # Start file run
839 print("NOTE: Enter 'c' at the %s prompt to continue execution." % deb.prompt)
844 print("NOTE: Enter 'c' at the %s prompt to continue execution." % deb.prompt)
840 try:
845 try:
841 if filename:
846 if filename:
842 # save filename so it can be used by methods on the deb object
847 # save filename so it can be used by methods on the deb object
843 deb._exec_filename = filename
848 deb._exec_filename = filename
844 while True:
849 while True:
845 try:
850 try:
846 deb.run(code, code_ns)
851 deb.run(code, code_ns)
847 except Restart:
852 except Restart:
848 print("Restarting")
853 print("Restarting")
849 if filename:
854 if filename:
850 deb._wait_for_mainpyfile = True
855 deb._wait_for_mainpyfile = True
851 deb.mainpyfile = deb.canonic(filename)
856 deb.mainpyfile = deb.canonic(filename)
852 continue
857 continue
853 else:
858 else:
854 break
859 break
855
860
856
861
857 except:
862 except:
858 etype, value, tb = sys.exc_info()
863 etype, value, tb = sys.exc_info()
859 # Skip three frames in the traceback: the %run one,
864 # Skip three frames in the traceback: the %run one,
860 # one inside bdb.py, and the command-line typed by the
865 # one inside bdb.py, and the command-line typed by the
861 # user (run by exec in pdb itself).
866 # user (run by exec in pdb itself).
862 self.shell.InteractiveTB(etype, value, tb, tb_offset=3)
867 self.shell.InteractiveTB(etype, value, tb, tb_offset=3)
863
868
864 @staticmethod
869 @staticmethod
865 def _run_with_timing(run, nruns):
870 def _run_with_timing(run, nruns):
866 """
871 """
867 Run function `run` and print timing information.
872 Run function `run` and print timing information.
868
873
869 Parameters
874 Parameters
870 ----------
875 ----------
871 run : callable
876 run : callable
872 Any callable object which takes no argument.
877 Any callable object which takes no argument.
873 nruns : int
878 nruns : int
874 Number of times to execute `run`.
879 Number of times to execute `run`.
875
880
876 """
881 """
877 twall0 = time.time()
882 twall0 = time.time()
878 if nruns == 1:
883 if nruns == 1:
879 t0 = clock2()
884 t0 = clock2()
880 run()
885 run()
881 t1 = clock2()
886 t1 = clock2()
882 t_usr = t1[0] - t0[0]
887 t_usr = t1[0] - t0[0]
883 t_sys = t1[1] - t0[1]
888 t_sys = t1[1] - t0[1]
884 print("\nIPython CPU timings (estimated):")
889 print("\nIPython CPU timings (estimated):")
885 print(" User : %10.2f s." % t_usr)
890 print(" User : %10.2f s." % t_usr)
886 print(" System : %10.2f s." % t_sys)
891 print(" System : %10.2f s." % t_sys)
887 else:
892 else:
888 runs = range(nruns)
893 runs = range(nruns)
889 t0 = clock2()
894 t0 = clock2()
890 for nr in runs:
895 for nr in runs:
891 run()
896 run()
892 t1 = clock2()
897 t1 = clock2()
893 t_usr = t1[0] - t0[0]
898 t_usr = t1[0] - t0[0]
894 t_sys = t1[1] - t0[1]
899 t_sys = t1[1] - t0[1]
895 print("\nIPython CPU timings (estimated):")
900 print("\nIPython CPU timings (estimated):")
896 print("Total runs performed:", nruns)
901 print("Total runs performed:", nruns)
897 print(" Times : %10s %10s" % ('Total', 'Per run'))
902 print(" Times : %10s %10s" % ('Total', 'Per run'))
898 print(" User : %10.2f s, %10.2f s." % (t_usr, t_usr / nruns))
903 print(" User : %10.2f s, %10.2f s." % (t_usr, t_usr / nruns))
899 print(" System : %10.2f s, %10.2f s." % (t_sys, t_sys / nruns))
904 print(" System : %10.2f s, %10.2f s." % (t_sys, t_sys / nruns))
900 twall1 = time.time()
905 twall1 = time.time()
901 print("Wall time: %10.2f s." % (twall1 - twall0))
906 print("Wall time: %10.2f s." % (twall1 - twall0))
902
907
903 @skip_doctest
908 @skip_doctest
904 @line_cell_magic
909 @line_cell_magic
905 def timeit(self, line='', cell=None):
910 def timeit(self, line='', cell=None):
906 """Time execution of a Python statement or expression
911 """Time execution of a Python statement or expression
907
912
908 Usage, in line mode:
913 Usage, in line mode:
909 %timeit [-n<N> -r<R> [-t|-c] -q -p<P> -o] statement
914 %timeit [-n<N> -r<R> [-t|-c] -q -p<P> -o] statement
910 or in cell mode:
915 or in cell mode:
911 %%timeit [-n<N> -r<R> [-t|-c] -q -p<P> -o] setup_code
916 %%timeit [-n<N> -r<R> [-t|-c] -q -p<P> -o] setup_code
912 code
917 code
913 code...
918 code...
914
919
915 Time execution of a Python statement or expression using the timeit
920 Time execution of a Python statement or expression using the timeit
916 module. This function can be used both as a line and cell magic:
921 module. This function can be used both as a line and cell magic:
917
922
918 - In line mode you can time a single-line statement (though multiple
923 - In line mode you can time a single-line statement (though multiple
919 ones can be chained with using semicolons).
924 ones can be chained with using semicolons).
920
925
921 - In cell mode, the statement in the first line is used as setup code
926 - In cell mode, the statement in the first line is used as setup code
922 (executed but not timed) and the body of the cell is timed. The cell
927 (executed but not timed) and the body of the cell is timed. The cell
923 body has access to any variables created in the setup code.
928 body has access to any variables created in the setup code.
924
929
925 Options:
930 Options:
926 -n<N>: execute the given statement <N> times in a loop. If this value
931 -n<N>: execute the given statement <N> times in a loop. If this value
927 is not given, a fitting value is chosen.
932 is not given, a fitting value is chosen.
928
933
929 -r<R>: repeat the loop iteration <R> times and take the best result.
934 -r<R>: repeat the loop iteration <R> times and take the best result.
930 Default: 3
935 Default: 3
931
936
932 -t: use time.time to measure the time, which is the default on Unix.
937 -t: use time.time to measure the time, which is the default on Unix.
933 This function measures wall time.
938 This function measures wall time.
934
939
935 -c: use time.clock to measure the time, which is the default on
940 -c: use time.clock to measure the time, which is the default on
936 Windows and measures wall time. On Unix, resource.getrusage is used
941 Windows and measures wall time. On Unix, resource.getrusage is used
937 instead and returns the CPU user time.
942 instead and returns the CPU user time.
938
943
939 -p<P>: use a precision of <P> digits to display the timing result.
944 -p<P>: use a precision of <P> digits to display the timing result.
940 Default: 3
945 Default: 3
941
946
942 -q: Quiet, do not print result.
947 -q: Quiet, do not print result.
943
948
944 -o: return a TimeitResult that can be stored in a variable to inspect
949 -o: return a TimeitResult that can be stored in a variable to inspect
945 the result in more details.
950 the result in more details.
946
951
947
952
948 Examples
953 Examples
949 --------
954 --------
950 ::
955 ::
951
956
952 In [1]: %timeit pass
957 In [1]: %timeit pass
953 10000000 loops, best of 3: 53.3 ns per loop
958 100000000 loops, average of 7: 5.48 ns +- 0.354 ns per loop (using standard deviation)
954
959
955 In [2]: u = None
960 In [2]: u = None
956
961
957 In [3]: %timeit u is None
962 In [3]: %timeit u is None
958 10000000 loops, best of 3: 184 ns per loop
963 10000000 loops, average of 7: 22.7 ns +- 2.33 ns per loop (using standard deviation)
959
964
960 In [4]: %timeit -r 4 u == None
965 In [4]: %timeit -r 4 u == None
961 1000000 loops, best of 4: 242 ns per loop
966 10000000 loops, average of 4: 27.5 ns +- 2.91 ns per loop (using standard deviation)
962
967
963 In [5]: import time
968 In [5]: import time
964
969
965 In [6]: %timeit -n1 time.sleep(2)
970 In [6]: %timeit -n1 time.sleep(2)
966 1 loop, best of 3: 2 s per loop
971 1 loop, average of 7: 2 s +- 4.71 Β΅s per loop (using standard deviation)
967
972
968
973
969 The times reported by %timeit will be slightly higher than those
974 The times reported by %timeit will be slightly higher than those
970 reported by the timeit.py script when variables are accessed. This is
975 reported by the timeit.py script when variables are accessed. This is
971 due to the fact that %timeit executes the statement in the namespace
976 due to the fact that %timeit executes the statement in the namespace
972 of the shell, compared with timeit.py, which uses a single setup
977 of the shell, compared with timeit.py, which uses a single setup
973 statement to import function or create variables. Generally, the bias
978 statement to import function or create variables. Generally, the bias
974 does not matter as long as results from timeit.py are not mixed with
979 does not matter as long as results from timeit.py are not mixed with
975 those from %timeit."""
980 those from %timeit."""
976
981
977 opts, stmt = self.parse_options(line,'n:r:tcp:qo',
982 opts, stmt = self.parse_options(line,'n:r:tcp:qo',
978 posix=False, strict=False)
983 posix=False, strict=False)
979 if stmt == "" and cell is None:
984 if stmt == "" and cell is None:
980 return
985 return
981
986
982 timefunc = timeit.default_timer
987 timefunc = timeit.default_timer
983 number = int(getattr(opts, "n", 0))
988 number = int(getattr(opts, "n", 0))
984 repeat = int(getattr(opts, "r", timeit.default_repeat))
989 default_repeat = 7 if timeit.default_repeat < 7 else timeit.default_repeat
990 repeat = int(getattr(opts, "r", default_repeat))
985 precision = int(getattr(opts, "p", 3))
991 precision = int(getattr(opts, "p", 3))
986 quiet = 'q' in opts
992 quiet = 'q' in opts
987 return_result = 'o' in opts
993 return_result = 'o' in opts
988 if hasattr(opts, "t"):
994 if hasattr(opts, "t"):
989 timefunc = time.time
995 timefunc = time.time
990 if hasattr(opts, "c"):
996 if hasattr(opts, "c"):
991 timefunc = clock
997 timefunc = clock
992
998
993 timer = Timer(timer=timefunc)
999 timer = Timer(timer=timefunc)
994 # this code has tight coupling to the inner workings of timeit.Timer,
1000 # this code has tight coupling to the inner workings of timeit.Timer,
995 # but is there a better way to achieve that the code stmt has access
1001 # but is there a better way to achieve that the code stmt has access
996 # to the shell namespace?
1002 # to the shell namespace?
997 transform = self.shell.input_splitter.transform_cell
1003 transform = self.shell.input_splitter.transform_cell
998
1004
999 if cell is None:
1005 if cell is None:
1000 # called as line magic
1006 # called as line magic
1001 ast_setup = self.shell.compile.ast_parse("pass")
1007 ast_setup = self.shell.compile.ast_parse("pass")
1002 ast_stmt = self.shell.compile.ast_parse(transform(stmt))
1008 ast_stmt = self.shell.compile.ast_parse(transform(stmt))
1003 else:
1009 else:
1004 ast_setup = self.shell.compile.ast_parse(transform(stmt))
1010 ast_setup = self.shell.compile.ast_parse(transform(stmt))
1005 ast_stmt = self.shell.compile.ast_parse(transform(cell))
1011 ast_stmt = self.shell.compile.ast_parse(transform(cell))
1006
1012
1007 ast_setup = self.shell.transform_ast(ast_setup)
1013 ast_setup = self.shell.transform_ast(ast_setup)
1008 ast_stmt = self.shell.transform_ast(ast_stmt)
1014 ast_stmt = self.shell.transform_ast(ast_stmt)
1009
1015
1010 # This codestring is taken from timeit.template - we fill it in as an
1016 # This codestring is taken from timeit.template - we fill it in as an
1011 # AST, so that we can apply our AST transformations to the user code
1017 # AST, so that we can apply our AST transformations to the user code
1012 # without affecting the timing code.
1018 # without affecting the timing code.
1013 timeit_ast_template = ast.parse('def inner(_it, _timer):\n'
1019 timeit_ast_template = ast.parse('def inner(_it, _timer):\n'
1014 ' setup\n'
1020 ' setup\n'
1015 ' _t0 = _timer()\n'
1021 ' _t0 = _timer()\n'
1016 ' for _i in _it:\n'
1022 ' for _i in _it:\n'
1017 ' stmt\n'
1023 ' stmt\n'
1018 ' _t1 = _timer()\n'
1024 ' _t1 = _timer()\n'
1019 ' return _t1 - _t0\n')
1025 ' return _t1 - _t0\n')
1020
1026
1021 timeit_ast = TimeitTemplateFiller(ast_setup, ast_stmt).visit(timeit_ast_template)
1027 timeit_ast = TimeitTemplateFiller(ast_setup, ast_stmt).visit(timeit_ast_template)
1022 timeit_ast = ast.fix_missing_locations(timeit_ast)
1028 timeit_ast = ast.fix_missing_locations(timeit_ast)
1023
1029
1024 # Track compilation time so it can be reported if too long
1030 # Track compilation time so it can be reported if too long
1025 # Minimum time above which compilation time will be reported
1031 # Minimum time above which compilation time will be reported
1026 tc_min = 0.1
1032 tc_min = 0.1
1027
1033
1028 t0 = clock()
1034 t0 = clock()
1029 code = self.shell.compile(timeit_ast, "<magic-timeit>", "exec")
1035 code = self.shell.compile(timeit_ast, "<magic-timeit>", "exec")
1030 tc = clock()-t0
1036 tc = clock()-t0
1031
1037
1032 ns = {}
1038 ns = {}
1033 exec(code, self.shell.user_ns, ns)
1039 exec(code, self.shell.user_ns, ns)
1034 timer.inner = ns["inner"]
1040 timer.inner = ns["inner"]
1035
1041
1036 # This is used to check if there is a huge difference between the
1042 # This is used to check if there is a huge difference between the
1037 # best and worst timings.
1043 # best and worst timings.
1038 # Issue: https://github.com/ipython/ipython/issues/6471
1044 # Issue: https://github.com/ipython/ipython/issues/6471
1039 worst_tuning = 0
1040 if number == 0:
1045 if number == 0:
1041 # determine number so that 0.2 <= total time < 2.0
1046 # determine number so that 0.2 <= total time < 2.0
1042 number = 1
1047 for index in range(0, 10):
1043 for _ in range(1, 10):
1048 number = 10 ** index
1044 time_number = timer.timeit(number)
1049 time_number = timer.timeit(number)
1045 worst_tuning = max(worst_tuning, time_number / number)
1046 if time_number >= 0.2:
1050 if time_number >= 0.2:
1047 break
1051 break
1048 number *= 10
1052
1049 all_runs = timer.repeat(repeat, number)
1053 all_runs = timer.repeat(repeat, number)
1050 best = min(all_runs) / number
1054 timings = [ dt / number for dt in all_runs]
1055
1056 def _avg(numbers):
1057 return math.fsum(numbers) / len(numbers)
1058
1059 def _stdev(numbers):
1060 mean = _avg(numbers)
1061 return (math.fsum([(x - mean) ** 2 for x in numbers]) / len(numbers)) ** 0.5
1051
1062
1052 worst = max(all_runs) / number
1063 average = _avg(timings)
1053 if worst_tuning:
1064 stdev = _stdev(timings)
1054 worst = max(worst, worst_tuning)
1055
1065
1056 if not quiet :
1066 if not quiet :
1057 # Check best timing is greater than zero to avoid a
1067 # Check best timing is greater than zero to avoid a
1058 # ZeroDivisionError.
1068 # ZeroDivisionError.
1059 # In cases where the slowest timing is lesser than a micosecond
1069 # In cases where the slowest timing is lesser than a micosecond
1060 # we assume that it does not really matter if the fastest
1070 # we assume that it does not really matter if the fastest
1061 # timing is 4 times faster than the slowest timing or not.
1071 # timing is 4 times faster than the slowest timing or not.
1062 if worst > 4 * best and best > 0 and worst > 1e-6:
1063 print("The slowest run took %0.2f times longer than the "
1064 "fastest. This could mean that an intermediate result "
1065 "is being cached." % (worst / best))
1066 if number == 1: # No s at "loops" if only one loop
1072 if number == 1: # No s at "loops" if only one loop
1067 print(u"%d loop, best of %d: %s per loop" % (number, repeat,
1073 print(u"%s loop, average of %d: %s +- %s per loop (using standard deviation)"
1068 _format_time(best, precision)))
1074 % (number, repeat,
1075 _format_time(average, precision),
1076 _format_time(stdev, precision)))
1069 else:
1077 else:
1070 print(u"%d loops, best of %d: %s per loop" % (number, repeat,
1078 print(u"%s loops, average of %d: %s +- %s per loop (using standard deviation)"
1071 _format_time(best, precision)))
1079 % (number, repeat,
1080 _format_time(average, precision),
1081 _format_time(stdev, precision)))
1072 if tc > tc_min:
1082 if tc > tc_min:
1073 print("Compiler time: %.2f s" % tc)
1083 print("Compiler time: %.2f s" % tc)
1074 if return_result:
1084 if return_result:
1075 return TimeitResult(number, repeat, best, worst, all_runs, tc, precision)
1085 return TimeitResult(number, repeat, average, stdev, all_runs, tc, precision)
1076
1086
1077 @skip_doctest
1087 @skip_doctest
1078 @needs_local_scope
1088 @needs_local_scope
1079 @line_cell_magic
1089 @line_cell_magic
1080 def time(self,line='', cell=None, local_ns=None):
1090 def time(self,line='', cell=None, local_ns=None):
1081 """Time execution of a Python statement or expression.
1091 """Time execution of a Python statement or expression.
1082
1092
1083 The CPU and wall clock times are printed, and the value of the
1093 The CPU and wall clock times are printed, and the value of the
1084 expression (if any) is returned. Note that under Win32, system time
1094 expression (if any) is returned. Note that under Win32, system time
1085 is always reported as 0, since it can not be measured.
1095 is always reported as 0, since it can not be measured.
1086
1096
1087 This function can be used both as a line and cell magic:
1097 This function can be used both as a line and cell magic:
1088
1098
1089 - In line mode you can time a single-line statement (though multiple
1099 - In line mode you can time a single-line statement (though multiple
1090 ones can be chained with using semicolons).
1100 ones can be chained with using semicolons).
1091
1101
1092 - In cell mode, you can time the cell body (a directly
1102 - In cell mode, you can time the cell body (a directly
1093 following statement raises an error).
1103 following statement raises an error).
1094
1104
1095 This function provides very basic timing functionality. Use the timeit
1105 This function provides very basic timing functionality. Use the timeit
1096 magic for more control over the measurement.
1106 magic for more control over the measurement.
1097
1107
1098 Examples
1108 Examples
1099 --------
1109 --------
1100 ::
1110 ::
1101
1111
1102 In [1]: %time 2**128
1112 In [1]: %time 2**128
1103 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1113 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1104 Wall time: 0.00
1114 Wall time: 0.00
1105 Out[1]: 340282366920938463463374607431768211456L
1115 Out[1]: 340282366920938463463374607431768211456L
1106
1116
1107 In [2]: n = 1000000
1117 In [2]: n = 1000000
1108
1118
1109 In [3]: %time sum(range(n))
1119 In [3]: %time sum(range(n))
1110 CPU times: user 1.20 s, sys: 0.05 s, total: 1.25 s
1120 CPU times: user 1.20 s, sys: 0.05 s, total: 1.25 s
1111 Wall time: 1.37
1121 Wall time: 1.37
1112 Out[3]: 499999500000L
1122 Out[3]: 499999500000L
1113
1123
1114 In [4]: %time print 'hello world'
1124 In [4]: %time print 'hello world'
1115 hello world
1125 hello world
1116 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1126 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1117 Wall time: 0.00
1127 Wall time: 0.00
1118
1128
1119 Note that the time needed by Python to compile the given expression
1129 Note that the time needed by Python to compile the given expression
1120 will be reported if it is more than 0.1s. In this example, the
1130 will be reported if it is more than 0.1s. In this example, the
1121 actual exponentiation is done by Python at compilation time, so while
1131 actual exponentiation is done by Python at compilation time, so while
1122 the expression can take a noticeable amount of time to compute, that
1132 the expression can take a noticeable amount of time to compute, that
1123 time is purely due to the compilation:
1133 time is purely due to the compilation:
1124
1134
1125 In [5]: %time 3**9999;
1135 In [5]: %time 3**9999;
1126 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1136 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1127 Wall time: 0.00 s
1137 Wall time: 0.00 s
1128
1138
1129 In [6]: %time 3**999999;
1139 In [6]: %time 3**999999;
1130 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1140 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1131 Wall time: 0.00 s
1141 Wall time: 0.00 s
1132 Compiler : 0.78 s
1142 Compiler : 0.78 s
1133 """
1143 """
1134
1144
1135 # fail immediately if the given expression can't be compiled
1145 # fail immediately if the given expression can't be compiled
1136
1146
1137 if line and cell:
1147 if line and cell:
1138 raise UsageError("Can't use statement directly after '%%time'!")
1148 raise UsageError("Can't use statement directly after '%%time'!")
1139
1149
1140 if cell:
1150 if cell:
1141 expr = self.shell.input_transformer_manager.transform_cell(cell)
1151 expr = self.shell.input_transformer_manager.transform_cell(cell)
1142 else:
1152 else:
1143 expr = self.shell.input_transformer_manager.transform_cell(line)
1153 expr = self.shell.input_transformer_manager.transform_cell(line)
1144
1154
1145 # Minimum time above which parse time will be reported
1155 # Minimum time above which parse time will be reported
1146 tp_min = 0.1
1156 tp_min = 0.1
1147
1157
1148 t0 = clock()
1158 t0 = clock()
1149 expr_ast = self.shell.compile.ast_parse(expr)
1159 expr_ast = self.shell.compile.ast_parse(expr)
1150 tp = clock()-t0
1160 tp = clock()-t0
1151
1161
1152 # Apply AST transformations
1162 # Apply AST transformations
1153 expr_ast = self.shell.transform_ast(expr_ast)
1163 expr_ast = self.shell.transform_ast(expr_ast)
1154
1164
1155 # Minimum time above which compilation time will be reported
1165 # Minimum time above which compilation time will be reported
1156 tc_min = 0.1
1166 tc_min = 0.1
1157
1167
1158 if len(expr_ast.body)==1 and isinstance(expr_ast.body[0], ast.Expr):
1168 if len(expr_ast.body)==1 and isinstance(expr_ast.body[0], ast.Expr):
1159 mode = 'eval'
1169 mode = 'eval'
1160 source = '<timed eval>'
1170 source = '<timed eval>'
1161 expr_ast = ast.Expression(expr_ast.body[0].value)
1171 expr_ast = ast.Expression(expr_ast.body[0].value)
1162 else:
1172 else:
1163 mode = 'exec'
1173 mode = 'exec'
1164 source = '<timed exec>'
1174 source = '<timed exec>'
1165 t0 = clock()
1175 t0 = clock()
1166 code = self.shell.compile(expr_ast, source, mode)
1176 code = self.shell.compile(expr_ast, source, mode)
1167 tc = clock()-t0
1177 tc = clock()-t0
1168
1178
1169 # skew measurement as little as possible
1179 # skew measurement as little as possible
1170 glob = self.shell.user_ns
1180 glob = self.shell.user_ns
1171 wtime = time.time
1181 wtime = time.time
1172 # time execution
1182 # time execution
1173 wall_st = wtime()
1183 wall_st = wtime()
1174 if mode=='eval':
1184 if mode=='eval':
1175 st = clock2()
1185 st = clock2()
1176 out = eval(code, glob, local_ns)
1186 out = eval(code, glob, local_ns)
1177 end = clock2()
1187 end = clock2()
1178 else:
1188 else:
1179 st = clock2()
1189 st = clock2()
1180 exec(code, glob, local_ns)
1190 exec(code, glob, local_ns)
1181 end = clock2()
1191 end = clock2()
1182 out = None
1192 out = None
1183 wall_end = wtime()
1193 wall_end = wtime()
1184 # Compute actual times and report
1194 # Compute actual times and report
1185 wall_time = wall_end-wall_st
1195 wall_time = wall_end-wall_st
1186 cpu_user = end[0]-st[0]
1196 cpu_user = end[0]-st[0]
1187 cpu_sys = end[1]-st[1]
1197 cpu_sys = end[1]-st[1]
1188 cpu_tot = cpu_user+cpu_sys
1198 cpu_tot = cpu_user+cpu_sys
1189 # On windows cpu_sys is always zero, so no new information to the next print
1199 # On windows cpu_sys is always zero, so no new information to the next print
1190 if sys.platform != 'win32':
1200 if sys.platform != 'win32':
1191 print("CPU times: user %s, sys: %s, total: %s" % \
1201 print("CPU times: user %s, sys: %s, total: %s" % \
1192 (_format_time(cpu_user),_format_time(cpu_sys),_format_time(cpu_tot)))
1202 (_format_time(cpu_user),_format_time(cpu_sys),_format_time(cpu_tot)))
1193 print("Wall time: %s" % _format_time(wall_time))
1203 print("Wall time: %s" % _format_time(wall_time))
1194 if tc > tc_min:
1204 if tc > tc_min:
1195 print("Compiler : %s" % _format_time(tc))
1205 print("Compiler : %s" % _format_time(tc))
1196 if tp > tp_min:
1206 if tp > tp_min:
1197 print("Parser : %s" % _format_time(tp))
1207 print("Parser : %s" % _format_time(tp))
1198 return out
1208 return out
1199
1209
1200 @skip_doctest
1210 @skip_doctest
1201 @line_magic
1211 @line_magic
1202 def macro(self, parameter_s=''):
1212 def macro(self, parameter_s=''):
1203 """Define a macro for future re-execution. It accepts ranges of history,
1213 """Define a macro for future re-execution. It accepts ranges of history,
1204 filenames or string objects.
1214 filenames or string objects.
1205
1215
1206 Usage:\\
1216 Usage:\\
1207 %macro [options] name n1-n2 n3-n4 ... n5 .. n6 ...
1217 %macro [options] name n1-n2 n3-n4 ... n5 .. n6 ...
1208
1218
1209 Options:
1219 Options:
1210
1220
1211 -r: use 'raw' input. By default, the 'processed' history is used,
1221 -r: use 'raw' input. By default, the 'processed' history is used,
1212 so that magics are loaded in their transformed version to valid
1222 so that magics are loaded in their transformed version to valid
1213 Python. If this option is given, the raw input as typed at the
1223 Python. If this option is given, the raw input as typed at the
1214 command line is used instead.
1224 command line is used instead.
1215
1225
1216 -q: quiet macro definition. By default, a tag line is printed
1226 -q: quiet macro definition. By default, a tag line is printed
1217 to indicate the macro has been created, and then the contents of
1227 to indicate the macro has been created, and then the contents of
1218 the macro are printed. If this option is given, then no printout
1228 the macro are printed. If this option is given, then no printout
1219 is produced once the macro is created.
1229 is produced once the macro is created.
1220
1230
1221 This will define a global variable called `name` which is a string
1231 This will define a global variable called `name` which is a string
1222 made of joining the slices and lines you specify (n1,n2,... numbers
1232 made of joining the slices and lines you specify (n1,n2,... numbers
1223 above) from your input history into a single string. This variable
1233 above) from your input history into a single string. This variable
1224 acts like an automatic function which re-executes those lines as if
1234 acts like an automatic function which re-executes those lines as if
1225 you had typed them. You just type 'name' at the prompt and the code
1235 you had typed them. You just type 'name' at the prompt and the code
1226 executes.
1236 executes.
1227
1237
1228 The syntax for indicating input ranges is described in %history.
1238 The syntax for indicating input ranges is described in %history.
1229
1239
1230 Note: as a 'hidden' feature, you can also use traditional python slice
1240 Note: as a 'hidden' feature, you can also use traditional python slice
1231 notation, where N:M means numbers N through M-1.
1241 notation, where N:M means numbers N through M-1.
1232
1242
1233 For example, if your history contains (print using %hist -n )::
1243 For example, if your history contains (print using %hist -n )::
1234
1244
1235 44: x=1
1245 44: x=1
1236 45: y=3
1246 45: y=3
1237 46: z=x+y
1247 46: z=x+y
1238 47: print x
1248 47: print x
1239 48: a=5
1249 48: a=5
1240 49: print 'x',x,'y',y
1250 49: print 'x',x,'y',y
1241
1251
1242 you can create a macro with lines 44 through 47 (included) and line 49
1252 you can create a macro with lines 44 through 47 (included) and line 49
1243 called my_macro with::
1253 called my_macro with::
1244
1254
1245 In [55]: %macro my_macro 44-47 49
1255 In [55]: %macro my_macro 44-47 49
1246
1256
1247 Now, typing `my_macro` (without quotes) will re-execute all this code
1257 Now, typing `my_macro` (without quotes) will re-execute all this code
1248 in one pass.
1258 in one pass.
1249
1259
1250 You don't need to give the line-numbers in order, and any given line
1260 You don't need to give the line-numbers in order, and any given line
1251 number can appear multiple times. You can assemble macros with any
1261 number can appear multiple times. You can assemble macros with any
1252 lines from your input history in any order.
1262 lines from your input history in any order.
1253
1263
1254 The macro is a simple object which holds its value in an attribute,
1264 The macro is a simple object which holds its value in an attribute,
1255 but IPython's display system checks for macros and executes them as
1265 but IPython's display system checks for macros and executes them as
1256 code instead of printing them when you type their name.
1266 code instead of printing them when you type their name.
1257
1267
1258 You can view a macro's contents by explicitly printing it with::
1268 You can view a macro's contents by explicitly printing it with::
1259
1269
1260 print macro_name
1270 print macro_name
1261
1271
1262 """
1272 """
1263 opts,args = self.parse_options(parameter_s,'rq',mode='list')
1273 opts,args = self.parse_options(parameter_s,'rq',mode='list')
1264 if not args: # List existing macros
1274 if not args: # List existing macros
1265 return sorted(k for k,v in iteritems(self.shell.user_ns) if\
1275 return sorted(k for k,v in iteritems(self.shell.user_ns) if\
1266 isinstance(v, Macro))
1276 isinstance(v, Macro))
1267 if len(args) == 1:
1277 if len(args) == 1:
1268 raise UsageError(
1278 raise UsageError(
1269 "%macro insufficient args; usage '%macro name n1-n2 n3-4...")
1279 "%macro insufficient args; usage '%macro name n1-n2 n3-4...")
1270 name, codefrom = args[0], " ".join(args[1:])
1280 name, codefrom = args[0], " ".join(args[1:])
1271
1281
1272 #print 'rng',ranges # dbg
1282 #print 'rng',ranges # dbg
1273 try:
1283 try:
1274 lines = self.shell.find_user_code(codefrom, 'r' in opts)
1284 lines = self.shell.find_user_code(codefrom, 'r' in opts)
1275 except (ValueError, TypeError) as e:
1285 except (ValueError, TypeError) as e:
1276 print(e.args[0])
1286 print(e.args[0])
1277 return
1287 return
1278 macro = Macro(lines)
1288 macro = Macro(lines)
1279 self.shell.define_macro(name, macro)
1289 self.shell.define_macro(name, macro)
1280 if not ( 'q' in opts) :
1290 if not ( 'q' in opts) :
1281 print('Macro `%s` created. To execute, type its name (without quotes).' % name)
1291 print('Macro `%s` created. To execute, type its name (without quotes).' % name)
1282 print('=== Macro contents: ===')
1292 print('=== Macro contents: ===')
1283 print(macro, end=' ')
1293 print(macro, end=' ')
1284
1294
1285 @magic_arguments.magic_arguments()
1295 @magic_arguments.magic_arguments()
1286 @magic_arguments.argument('output', type=str, default='', nargs='?',
1296 @magic_arguments.argument('output', type=str, default='', nargs='?',
1287 help="""The name of the variable in which to store output.
1297 help="""The name of the variable in which to store output.
1288 This is a utils.io.CapturedIO object with stdout/err attributes
1298 This is a utils.io.CapturedIO object with stdout/err attributes
1289 for the text of the captured output.
1299 for the text of the captured output.
1290
1300
1291 CapturedOutput also has a show() method for displaying the output,
1301 CapturedOutput also has a show() method for displaying the output,
1292 and __call__ as well, so you can use that to quickly display the
1302 and __call__ as well, so you can use that to quickly display the
1293 output.
1303 output.
1294
1304
1295 If unspecified, captured output is discarded.
1305 If unspecified, captured output is discarded.
1296 """
1306 """
1297 )
1307 )
1298 @magic_arguments.argument('--no-stderr', action="store_true",
1308 @magic_arguments.argument('--no-stderr', action="store_true",
1299 help="""Don't capture stderr."""
1309 help="""Don't capture stderr."""
1300 )
1310 )
1301 @magic_arguments.argument('--no-stdout', action="store_true",
1311 @magic_arguments.argument('--no-stdout', action="store_true",
1302 help="""Don't capture stdout."""
1312 help="""Don't capture stdout."""
1303 )
1313 )
1304 @magic_arguments.argument('--no-display', action="store_true",
1314 @magic_arguments.argument('--no-display', action="store_true",
1305 help="""Don't capture IPython's rich display."""
1315 help="""Don't capture IPython's rich display."""
1306 )
1316 )
1307 @cell_magic
1317 @cell_magic
1308 def capture(self, line, cell):
1318 def capture(self, line, cell):
1309 """run the cell, capturing stdout, stderr, and IPython's rich display() calls."""
1319 """run the cell, capturing stdout, stderr, and IPython's rich display() calls."""
1310 args = magic_arguments.parse_argstring(self.capture, line)
1320 args = magic_arguments.parse_argstring(self.capture, line)
1311 out = not args.no_stdout
1321 out = not args.no_stdout
1312 err = not args.no_stderr
1322 err = not args.no_stderr
1313 disp = not args.no_display
1323 disp = not args.no_display
1314 with capture_output(out, err, disp) as io:
1324 with capture_output(out, err, disp) as io:
1315 self.shell.run_cell(cell)
1325 self.shell.run_cell(cell)
1316 if args.output:
1326 if args.output:
1317 self.shell.user_ns[args.output] = io
1327 self.shell.user_ns[args.output] = io
1318
1328
1319 def parse_breakpoint(text, current_file):
1329 def parse_breakpoint(text, current_file):
1320 '''Returns (file, line) for file:line and (current_file, line) for line'''
1330 '''Returns (file, line) for file:line and (current_file, line) for line'''
1321 colon = text.find(':')
1331 colon = text.find(':')
1322 if colon == -1:
1332 if colon == -1:
1323 return current_file, int(text)
1333 return current_file, int(text)
1324 else:
1334 else:
1325 return text[:colon], int(text[colon+1:])
1335 return text[:colon], int(text[colon+1:])
1326
1336
1327 def _format_time(timespan, precision=3):
1337 def _format_time(timespan, precision=3):
1328 """Formats the timespan in a human readable form"""
1338 """Formats the timespan in a human readable form"""
1329 import math
1339 import math
1330
1340
1331 if timespan >= 60.0:
1341 if timespan >= 60.0:
1332 # we have more than a minute, format that in a human readable form
1342 # we have more than a minute, format that in a human readable form
1333 # Idea from http://snipplr.com/view/5713/
1343 # Idea from http://snipplr.com/view/5713/
1334 parts = [("d", 60*60*24),("h", 60*60),("min", 60), ("s", 1)]
1344 parts = [("d", 60*60*24),("h", 60*60),("min", 60), ("s", 1)]
1335 time = []
1345 time = []
1336 leftover = timespan
1346 leftover = timespan
1337 for suffix, length in parts:
1347 for suffix, length in parts:
1338 value = int(leftover / length)
1348 value = int(leftover / length)
1339 if value > 0:
1349 if value > 0:
1340 leftover = leftover % length
1350 leftover = leftover % length
1341 time.append(u'%s%s' % (str(value), suffix))
1351 time.append(u'%s%s' % (str(value), suffix))
1342 if leftover < 1:
1352 if leftover < 1:
1343 break
1353 break
1344 return " ".join(time)
1354 return " ".join(time)
1345
1355
1346
1356
1347 # Unfortunately the unicode 'micro' symbol can cause problems in
1357 # Unfortunately the unicode 'micro' symbol can cause problems in
1348 # certain terminals.
1358 # certain terminals.
1349 # See bug: https://bugs.launchpad.net/ipython/+bug/348466
1359 # See bug: https://bugs.launchpad.net/ipython/+bug/348466
1350 # Try to prevent crashes by being more secure than it needs to
1360 # Try to prevent crashes by being more secure than it needs to
1351 # E.g. eclipse is able to print a Β΅, but has no sys.stdout.encoding set.
1361 # E.g. eclipse is able to print a Β΅, but has no sys.stdout.encoding set.
1352 units = [u"s", u"ms",u'us',"ns"] # the save value
1362 units = [u"s", u"ms",u'us',"ns"] # the save value
1353 if hasattr(sys.stdout, 'encoding') and sys.stdout.encoding:
1363 if hasattr(sys.stdout, 'encoding') and sys.stdout.encoding:
1354 try:
1364 try:
1355 u'\xb5'.encode(sys.stdout.encoding)
1365 u'\xb5'.encode(sys.stdout.encoding)
1356 units = [u"s", u"ms",u'\xb5s',"ns"]
1366 units = [u"s", u"ms",u'\xb5s',"ns"]
1357 except:
1367 except:
1358 pass
1368 pass
1359 scaling = [1, 1e3, 1e6, 1e9]
1369 scaling = [1, 1e3, 1e6, 1e9]
1360
1370
1361 if timespan > 0.0:
1371 if timespan > 0.0:
1362 order = min(-int(math.floor(math.log10(timespan)) // 3), 3)
1372 order = min(-int(math.floor(math.log10(timespan)) // 3), 3)
1363 else:
1373 else:
1364 order = 3
1374 order = 3
1365 return u"%.*g %s" % (precision, timespan * scaling[order], units[order])
1375 return u"%.*g %s" % (precision, timespan * scaling[order], units[order])
@@ -1,950 +1,950 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Tests for the key interactiveshell module.
2 """Tests for the key interactiveshell module.
3
3
4 Historically the main classes in interactiveshell have been under-tested. This
4 Historically the main classes in interactiveshell have been under-tested. This
5 module should grow as many single-method tests as possible to trap many of the
5 module should grow as many single-method tests as possible to trap many of the
6 recurring bugs we seem to encounter with high-level interaction.
6 recurring bugs we seem to encounter with high-level interaction.
7 """
7 """
8
8
9 # Copyright (c) IPython Development Team.
9 # Copyright (c) IPython Development Team.
10 # Distributed under the terms of the Modified BSD License.
10 # Distributed under the terms of the Modified BSD License.
11
11
12 import ast
12 import ast
13 import os
13 import os
14 import signal
14 import signal
15 import shutil
15 import shutil
16 import sys
16 import sys
17 import tempfile
17 import tempfile
18 import unittest
18 import unittest
19 try:
19 try:
20 from unittest import mock
20 from unittest import mock
21 except ImportError:
21 except ImportError:
22 import mock
22 import mock
23 from os.path import join
23 from os.path import join
24
24
25 import nose.tools as nt
25 import nose.tools as nt
26
26
27 from IPython.core.error import InputRejected
27 from IPython.core.error import InputRejected
28 from IPython.core.inputtransformer import InputTransformer
28 from IPython.core.inputtransformer import InputTransformer
29 from IPython.testing.decorators import (
29 from IPython.testing.decorators import (
30 skipif, skip_win32, onlyif_unicode_paths, onlyif_cmds_exist,
30 skipif, skip_win32, onlyif_unicode_paths, onlyif_cmds_exist,
31 )
31 )
32 from IPython.testing import tools as tt
32 from IPython.testing import tools as tt
33 from IPython.utils.process import find_cmd
33 from IPython.utils.process import find_cmd
34 from IPython.utils import py3compat
34 from IPython.utils import py3compat
35 from IPython.utils.py3compat import unicode_type, PY3
35 from IPython.utils.py3compat import unicode_type, PY3
36
36
37 if PY3:
37 if PY3:
38 from io import StringIO
38 from io import StringIO
39 else:
39 else:
40 from StringIO import StringIO
40 from StringIO import StringIO
41
41
42 #-----------------------------------------------------------------------------
42 #-----------------------------------------------------------------------------
43 # Globals
43 # Globals
44 #-----------------------------------------------------------------------------
44 #-----------------------------------------------------------------------------
45 # This is used by every single test, no point repeating it ad nauseam
45 # This is used by every single test, no point repeating it ad nauseam
46 ip = get_ipython()
46 ip = get_ipython()
47
47
48 #-----------------------------------------------------------------------------
48 #-----------------------------------------------------------------------------
49 # Tests
49 # Tests
50 #-----------------------------------------------------------------------------
50 #-----------------------------------------------------------------------------
51
51
52 class DerivedInterrupt(KeyboardInterrupt):
52 class DerivedInterrupt(KeyboardInterrupt):
53 pass
53 pass
54
54
55 class InteractiveShellTestCase(unittest.TestCase):
55 class InteractiveShellTestCase(unittest.TestCase):
56 def test_naked_string_cells(self):
56 def test_naked_string_cells(self):
57 """Test that cells with only naked strings are fully executed"""
57 """Test that cells with only naked strings are fully executed"""
58 # First, single-line inputs
58 # First, single-line inputs
59 ip.run_cell('"a"\n')
59 ip.run_cell('"a"\n')
60 self.assertEqual(ip.user_ns['_'], 'a')
60 self.assertEqual(ip.user_ns['_'], 'a')
61 # And also multi-line cells
61 # And also multi-line cells
62 ip.run_cell('"""a\nb"""\n')
62 ip.run_cell('"""a\nb"""\n')
63 self.assertEqual(ip.user_ns['_'], 'a\nb')
63 self.assertEqual(ip.user_ns['_'], 'a\nb')
64
64
65 def test_run_empty_cell(self):
65 def test_run_empty_cell(self):
66 """Just make sure we don't get a horrible error with a blank
66 """Just make sure we don't get a horrible error with a blank
67 cell of input. Yes, I did overlook that."""
67 cell of input. Yes, I did overlook that."""
68 old_xc = ip.execution_count
68 old_xc = ip.execution_count
69 res = ip.run_cell('')
69 res = ip.run_cell('')
70 self.assertEqual(ip.execution_count, old_xc)
70 self.assertEqual(ip.execution_count, old_xc)
71 self.assertEqual(res.execution_count, None)
71 self.assertEqual(res.execution_count, None)
72
72
73 def test_run_cell_multiline(self):
73 def test_run_cell_multiline(self):
74 """Multi-block, multi-line cells must execute correctly.
74 """Multi-block, multi-line cells must execute correctly.
75 """
75 """
76 src = '\n'.join(["x=1",
76 src = '\n'.join(["x=1",
77 "y=2",
77 "y=2",
78 "if 1:",
78 "if 1:",
79 " x += 1",
79 " x += 1",
80 " y += 1",])
80 " y += 1",])
81 res = ip.run_cell(src)
81 res = ip.run_cell(src)
82 self.assertEqual(ip.user_ns['x'], 2)
82 self.assertEqual(ip.user_ns['x'], 2)
83 self.assertEqual(ip.user_ns['y'], 3)
83 self.assertEqual(ip.user_ns['y'], 3)
84 self.assertEqual(res.success, True)
84 self.assertEqual(res.success, True)
85 self.assertEqual(res.result, None)
85 self.assertEqual(res.result, None)
86
86
87 def test_multiline_string_cells(self):
87 def test_multiline_string_cells(self):
88 "Code sprinkled with multiline strings should execute (GH-306)"
88 "Code sprinkled with multiline strings should execute (GH-306)"
89 ip.run_cell('tmp=0')
89 ip.run_cell('tmp=0')
90 self.assertEqual(ip.user_ns['tmp'], 0)
90 self.assertEqual(ip.user_ns['tmp'], 0)
91 res = ip.run_cell('tmp=1;"""a\nb"""\n')
91 res = ip.run_cell('tmp=1;"""a\nb"""\n')
92 self.assertEqual(ip.user_ns['tmp'], 1)
92 self.assertEqual(ip.user_ns['tmp'], 1)
93 self.assertEqual(res.success, True)
93 self.assertEqual(res.success, True)
94 self.assertEqual(res.result, "a\nb")
94 self.assertEqual(res.result, "a\nb")
95
95
96 def test_dont_cache_with_semicolon(self):
96 def test_dont_cache_with_semicolon(self):
97 "Ending a line with semicolon should not cache the returned object (GH-307)"
97 "Ending a line with semicolon should not cache the returned object (GH-307)"
98 oldlen = len(ip.user_ns['Out'])
98 oldlen = len(ip.user_ns['Out'])
99 for cell in ['1;', '1;1;']:
99 for cell in ['1;', '1;1;']:
100 res = ip.run_cell(cell, store_history=True)
100 res = ip.run_cell(cell, store_history=True)
101 newlen = len(ip.user_ns['Out'])
101 newlen = len(ip.user_ns['Out'])
102 self.assertEqual(oldlen, newlen)
102 self.assertEqual(oldlen, newlen)
103 self.assertIsNone(res.result)
103 self.assertIsNone(res.result)
104 i = 0
104 i = 0
105 #also test the default caching behavior
105 #also test the default caching behavior
106 for cell in ['1', '1;1']:
106 for cell in ['1', '1;1']:
107 ip.run_cell(cell, store_history=True)
107 ip.run_cell(cell, store_history=True)
108 newlen = len(ip.user_ns['Out'])
108 newlen = len(ip.user_ns['Out'])
109 i += 1
109 i += 1
110 self.assertEqual(oldlen+i, newlen)
110 self.assertEqual(oldlen+i, newlen)
111
111
112 def test_syntax_error(self):
112 def test_syntax_error(self):
113 res = ip.run_cell("raise = 3")
113 res = ip.run_cell("raise = 3")
114 self.assertIsInstance(res.error_before_exec, SyntaxError)
114 self.assertIsInstance(res.error_before_exec, SyntaxError)
115
115
116 def test_In_variable(self):
116 def test_In_variable(self):
117 "Verify that In variable grows with user input (GH-284)"
117 "Verify that In variable grows with user input (GH-284)"
118 oldlen = len(ip.user_ns['In'])
118 oldlen = len(ip.user_ns['In'])
119 ip.run_cell('1;', store_history=True)
119 ip.run_cell('1;', store_history=True)
120 newlen = len(ip.user_ns['In'])
120 newlen = len(ip.user_ns['In'])
121 self.assertEqual(oldlen+1, newlen)
121 self.assertEqual(oldlen+1, newlen)
122 self.assertEqual(ip.user_ns['In'][-1],'1;')
122 self.assertEqual(ip.user_ns['In'][-1],'1;')
123
123
124 def test_magic_names_in_string(self):
124 def test_magic_names_in_string(self):
125 ip.run_cell('a = """\n%exit\n"""')
125 ip.run_cell('a = """\n%exit\n"""')
126 self.assertEqual(ip.user_ns['a'], '\n%exit\n')
126 self.assertEqual(ip.user_ns['a'], '\n%exit\n')
127
127
128 def test_trailing_newline(self):
128 def test_trailing_newline(self):
129 """test that running !(command) does not raise a SyntaxError"""
129 """test that running !(command) does not raise a SyntaxError"""
130 ip.run_cell('!(true)\n', False)
130 ip.run_cell('!(true)\n', False)
131 ip.run_cell('!(true)\n\n\n', False)
131 ip.run_cell('!(true)\n\n\n', False)
132
132
133 def test_gh_597(self):
133 def test_gh_597(self):
134 """Pretty-printing lists of objects with non-ascii reprs may cause
134 """Pretty-printing lists of objects with non-ascii reprs may cause
135 problems."""
135 problems."""
136 class Spam(object):
136 class Spam(object):
137 def __repr__(self):
137 def __repr__(self):
138 return "\xe9"*50
138 return "\xe9"*50
139 import IPython.core.formatters
139 import IPython.core.formatters
140 f = IPython.core.formatters.PlainTextFormatter()
140 f = IPython.core.formatters.PlainTextFormatter()
141 f([Spam(),Spam()])
141 f([Spam(),Spam()])
142
142
143
143
144 def test_future_flags(self):
144 def test_future_flags(self):
145 """Check that future flags are used for parsing code (gh-777)"""
145 """Check that future flags are used for parsing code (gh-777)"""
146 ip.run_cell('from __future__ import print_function')
146 ip.run_cell('from __future__ import print_function')
147 try:
147 try:
148 ip.run_cell('prfunc_return_val = print(1,2, sep=" ")')
148 ip.run_cell('prfunc_return_val = print(1,2, sep=" ")')
149 assert 'prfunc_return_val' in ip.user_ns
149 assert 'prfunc_return_val' in ip.user_ns
150 finally:
150 finally:
151 # Reset compiler flags so we don't mess up other tests.
151 # Reset compiler flags so we don't mess up other tests.
152 ip.compile.reset_compiler_flags()
152 ip.compile.reset_compiler_flags()
153
153
154 def test_future_unicode(self):
154 def test_future_unicode(self):
155 """Check that unicode_literals is imported from __future__ (gh #786)"""
155 """Check that unicode_literals is imported from __future__ (gh #786)"""
156 try:
156 try:
157 ip.run_cell(u'byte_str = "a"')
157 ip.run_cell(u'byte_str = "a"')
158 assert isinstance(ip.user_ns['byte_str'], str) # string literals are byte strings by default
158 assert isinstance(ip.user_ns['byte_str'], str) # string literals are byte strings by default
159 ip.run_cell('from __future__ import unicode_literals')
159 ip.run_cell('from __future__ import unicode_literals')
160 ip.run_cell(u'unicode_str = "a"')
160 ip.run_cell(u'unicode_str = "a"')
161 assert isinstance(ip.user_ns['unicode_str'], unicode_type) # strings literals are now unicode
161 assert isinstance(ip.user_ns['unicode_str'], unicode_type) # strings literals are now unicode
162 finally:
162 finally:
163 # Reset compiler flags so we don't mess up other tests.
163 # Reset compiler flags so we don't mess up other tests.
164 ip.compile.reset_compiler_flags()
164 ip.compile.reset_compiler_flags()
165
165
166 def test_can_pickle(self):
166 def test_can_pickle(self):
167 "Can we pickle objects defined interactively (GH-29)"
167 "Can we pickle objects defined interactively (GH-29)"
168 ip = get_ipython()
168 ip = get_ipython()
169 ip.reset()
169 ip.reset()
170 ip.run_cell(("class Mylist(list):\n"
170 ip.run_cell(("class Mylist(list):\n"
171 " def __init__(self,x=[]):\n"
171 " def __init__(self,x=[]):\n"
172 " list.__init__(self,x)"))
172 " list.__init__(self,x)"))
173 ip.run_cell("w=Mylist([1,2,3])")
173 ip.run_cell("w=Mylist([1,2,3])")
174
174
175 from pickle import dumps
175 from pickle import dumps
176
176
177 # We need to swap in our main module - this is only necessary
177 # We need to swap in our main module - this is only necessary
178 # inside the test framework, because IPython puts the interactive module
178 # inside the test framework, because IPython puts the interactive module
179 # in place (but the test framework undoes this).
179 # in place (but the test framework undoes this).
180 _main = sys.modules['__main__']
180 _main = sys.modules['__main__']
181 sys.modules['__main__'] = ip.user_module
181 sys.modules['__main__'] = ip.user_module
182 try:
182 try:
183 res = dumps(ip.user_ns["w"])
183 res = dumps(ip.user_ns["w"])
184 finally:
184 finally:
185 sys.modules['__main__'] = _main
185 sys.modules['__main__'] = _main
186 self.assertTrue(isinstance(res, bytes))
186 self.assertTrue(isinstance(res, bytes))
187
187
188 def test_global_ns(self):
188 def test_global_ns(self):
189 "Code in functions must be able to access variables outside them."
189 "Code in functions must be able to access variables outside them."
190 ip = get_ipython()
190 ip = get_ipython()
191 ip.run_cell("a = 10")
191 ip.run_cell("a = 10")
192 ip.run_cell(("def f(x):\n"
192 ip.run_cell(("def f(x):\n"
193 " return x + a"))
193 " return x + a"))
194 ip.run_cell("b = f(12)")
194 ip.run_cell("b = f(12)")
195 self.assertEqual(ip.user_ns["b"], 22)
195 self.assertEqual(ip.user_ns["b"], 22)
196
196
197 def test_bad_custom_tb(self):
197 def test_bad_custom_tb(self):
198 """Check that InteractiveShell is protected from bad custom exception handlers"""
198 """Check that InteractiveShell is protected from bad custom exception handlers"""
199 ip.set_custom_exc((IOError,), lambda etype,value,tb: 1/0)
199 ip.set_custom_exc((IOError,), lambda etype,value,tb: 1/0)
200 self.assertEqual(ip.custom_exceptions, (IOError,))
200 self.assertEqual(ip.custom_exceptions, (IOError,))
201 with tt.AssertPrints("Custom TB Handler failed", channel='stderr'):
201 with tt.AssertPrints("Custom TB Handler failed", channel='stderr'):
202 ip.run_cell(u'raise IOError("foo")')
202 ip.run_cell(u'raise IOError("foo")')
203 self.assertEqual(ip.custom_exceptions, ())
203 self.assertEqual(ip.custom_exceptions, ())
204
204
205 def test_bad_custom_tb_return(self):
205 def test_bad_custom_tb_return(self):
206 """Check that InteractiveShell is protected from bad return types in custom exception handlers"""
206 """Check that InteractiveShell is protected from bad return types in custom exception handlers"""
207 ip.set_custom_exc((NameError,),lambda etype,value,tb, tb_offset=None: 1)
207 ip.set_custom_exc((NameError,),lambda etype,value,tb, tb_offset=None: 1)
208 self.assertEqual(ip.custom_exceptions, (NameError,))
208 self.assertEqual(ip.custom_exceptions, (NameError,))
209 with tt.AssertPrints("Custom TB Handler failed", channel='stderr'):
209 with tt.AssertPrints("Custom TB Handler failed", channel='stderr'):
210 ip.run_cell(u'a=abracadabra')
210 ip.run_cell(u'a=abracadabra')
211 self.assertEqual(ip.custom_exceptions, ())
211 self.assertEqual(ip.custom_exceptions, ())
212
212
213 def test_drop_by_id(self):
213 def test_drop_by_id(self):
214 myvars = {"a":object(), "b":object(), "c": object()}
214 myvars = {"a":object(), "b":object(), "c": object()}
215 ip.push(myvars, interactive=False)
215 ip.push(myvars, interactive=False)
216 for name in myvars:
216 for name in myvars:
217 assert name in ip.user_ns, name
217 assert name in ip.user_ns, name
218 assert name in ip.user_ns_hidden, name
218 assert name in ip.user_ns_hidden, name
219 ip.user_ns['b'] = 12
219 ip.user_ns['b'] = 12
220 ip.drop_by_id(myvars)
220 ip.drop_by_id(myvars)
221 for name in ["a", "c"]:
221 for name in ["a", "c"]:
222 assert name not in ip.user_ns, name
222 assert name not in ip.user_ns, name
223 assert name not in ip.user_ns_hidden, name
223 assert name not in ip.user_ns_hidden, name
224 assert ip.user_ns['b'] == 12
224 assert ip.user_ns['b'] == 12
225 ip.reset()
225 ip.reset()
226
226
227 def test_var_expand(self):
227 def test_var_expand(self):
228 ip.user_ns['f'] = u'Ca\xf1o'
228 ip.user_ns['f'] = u'Ca\xf1o'
229 self.assertEqual(ip.var_expand(u'echo $f'), u'echo Ca\xf1o')
229 self.assertEqual(ip.var_expand(u'echo $f'), u'echo Ca\xf1o')
230 self.assertEqual(ip.var_expand(u'echo {f}'), u'echo Ca\xf1o')
230 self.assertEqual(ip.var_expand(u'echo {f}'), u'echo Ca\xf1o')
231 self.assertEqual(ip.var_expand(u'echo {f[:-1]}'), u'echo Ca\xf1')
231 self.assertEqual(ip.var_expand(u'echo {f[:-1]}'), u'echo Ca\xf1')
232 self.assertEqual(ip.var_expand(u'echo {1*2}'), u'echo 2')
232 self.assertEqual(ip.var_expand(u'echo {1*2}'), u'echo 2')
233
233
234 ip.user_ns['f'] = b'Ca\xc3\xb1o'
234 ip.user_ns['f'] = b'Ca\xc3\xb1o'
235 # This should not raise any exception:
235 # This should not raise any exception:
236 ip.var_expand(u'echo $f')
236 ip.var_expand(u'echo $f')
237
237
238 def test_var_expand_local(self):
238 def test_var_expand_local(self):
239 """Test local variable expansion in !system and %magic calls"""
239 """Test local variable expansion in !system and %magic calls"""
240 # !system
240 # !system
241 ip.run_cell('def test():\n'
241 ip.run_cell('def test():\n'
242 ' lvar = "ttt"\n'
242 ' lvar = "ttt"\n'
243 ' ret = !echo {lvar}\n'
243 ' ret = !echo {lvar}\n'
244 ' return ret[0]\n')
244 ' return ret[0]\n')
245 res = ip.user_ns['test']()
245 res = ip.user_ns['test']()
246 nt.assert_in('ttt', res)
246 nt.assert_in('ttt', res)
247
247
248 # %magic
248 # %magic
249 ip.run_cell('def makemacro():\n'
249 ip.run_cell('def makemacro():\n'
250 ' macroname = "macro_var_expand_locals"\n'
250 ' macroname = "macro_var_expand_locals"\n'
251 ' %macro {macroname} codestr\n')
251 ' %macro {macroname} codestr\n')
252 ip.user_ns['codestr'] = "str(12)"
252 ip.user_ns['codestr'] = "str(12)"
253 ip.run_cell('makemacro()')
253 ip.run_cell('makemacro()')
254 nt.assert_in('macro_var_expand_locals', ip.user_ns)
254 nt.assert_in('macro_var_expand_locals', ip.user_ns)
255
255
256 def test_var_expand_self(self):
256 def test_var_expand_self(self):
257 """Test variable expansion with the name 'self', which was failing.
257 """Test variable expansion with the name 'self', which was failing.
258
258
259 See https://github.com/ipython/ipython/issues/1878#issuecomment-7698218
259 See https://github.com/ipython/ipython/issues/1878#issuecomment-7698218
260 """
260 """
261 ip.run_cell('class cTest:\n'
261 ip.run_cell('class cTest:\n'
262 ' classvar="see me"\n'
262 ' classvar="see me"\n'
263 ' def test(self):\n'
263 ' def test(self):\n'
264 ' res = !echo Variable: {self.classvar}\n'
264 ' res = !echo Variable: {self.classvar}\n'
265 ' return res[0]\n')
265 ' return res[0]\n')
266 nt.assert_in('see me', ip.user_ns['cTest']().test())
266 nt.assert_in('see me', ip.user_ns['cTest']().test())
267
267
268 def test_bad_var_expand(self):
268 def test_bad_var_expand(self):
269 """var_expand on invalid formats shouldn't raise"""
269 """var_expand on invalid formats shouldn't raise"""
270 # SyntaxError
270 # SyntaxError
271 self.assertEqual(ip.var_expand(u"{'a':5}"), u"{'a':5}")
271 self.assertEqual(ip.var_expand(u"{'a':5}"), u"{'a':5}")
272 # NameError
272 # NameError
273 self.assertEqual(ip.var_expand(u"{asdf}"), u"{asdf}")
273 self.assertEqual(ip.var_expand(u"{asdf}"), u"{asdf}")
274 # ZeroDivisionError
274 # ZeroDivisionError
275 self.assertEqual(ip.var_expand(u"{1/0}"), u"{1/0}")
275 self.assertEqual(ip.var_expand(u"{1/0}"), u"{1/0}")
276
276
277 def test_silent_postexec(self):
277 def test_silent_postexec(self):
278 """run_cell(silent=True) doesn't invoke pre/post_run_cell callbacks"""
278 """run_cell(silent=True) doesn't invoke pre/post_run_cell callbacks"""
279 pre_explicit = mock.Mock()
279 pre_explicit = mock.Mock()
280 pre_always = mock.Mock()
280 pre_always = mock.Mock()
281 post_explicit = mock.Mock()
281 post_explicit = mock.Mock()
282 post_always = mock.Mock()
282 post_always = mock.Mock()
283
283
284 ip.events.register('pre_run_cell', pre_explicit)
284 ip.events.register('pre_run_cell', pre_explicit)
285 ip.events.register('pre_execute', pre_always)
285 ip.events.register('pre_execute', pre_always)
286 ip.events.register('post_run_cell', post_explicit)
286 ip.events.register('post_run_cell', post_explicit)
287 ip.events.register('post_execute', post_always)
287 ip.events.register('post_execute', post_always)
288
288
289 try:
289 try:
290 ip.run_cell("1", silent=True)
290 ip.run_cell("1", silent=True)
291 assert pre_always.called
291 assert pre_always.called
292 assert not pre_explicit.called
292 assert not pre_explicit.called
293 assert post_always.called
293 assert post_always.called
294 assert not post_explicit.called
294 assert not post_explicit.called
295 # double-check that non-silent exec did what we expected
295 # double-check that non-silent exec did what we expected
296 # silent to avoid
296 # silent to avoid
297 ip.run_cell("1")
297 ip.run_cell("1")
298 assert pre_explicit.called
298 assert pre_explicit.called
299 assert post_explicit.called
299 assert post_explicit.called
300 finally:
300 finally:
301 # remove post-exec
301 # remove post-exec
302 ip.events.unregister('pre_run_cell', pre_explicit)
302 ip.events.unregister('pre_run_cell', pre_explicit)
303 ip.events.unregister('pre_execute', pre_always)
303 ip.events.unregister('pre_execute', pre_always)
304 ip.events.unregister('post_run_cell', post_explicit)
304 ip.events.unregister('post_run_cell', post_explicit)
305 ip.events.unregister('post_execute', post_always)
305 ip.events.unregister('post_execute', post_always)
306
306
307 def test_silent_noadvance(self):
307 def test_silent_noadvance(self):
308 """run_cell(silent=True) doesn't advance execution_count"""
308 """run_cell(silent=True) doesn't advance execution_count"""
309 ec = ip.execution_count
309 ec = ip.execution_count
310 # silent should force store_history=False
310 # silent should force store_history=False
311 ip.run_cell("1", store_history=True, silent=True)
311 ip.run_cell("1", store_history=True, silent=True)
312
312
313 self.assertEqual(ec, ip.execution_count)
313 self.assertEqual(ec, ip.execution_count)
314 # double-check that non-silent exec did what we expected
314 # double-check that non-silent exec did what we expected
315 # silent to avoid
315 # silent to avoid
316 ip.run_cell("1", store_history=True)
316 ip.run_cell("1", store_history=True)
317 self.assertEqual(ec+1, ip.execution_count)
317 self.assertEqual(ec+1, ip.execution_count)
318
318
319 def test_silent_nodisplayhook(self):
319 def test_silent_nodisplayhook(self):
320 """run_cell(silent=True) doesn't trigger displayhook"""
320 """run_cell(silent=True) doesn't trigger displayhook"""
321 d = dict(called=False)
321 d = dict(called=False)
322
322
323 trap = ip.display_trap
323 trap = ip.display_trap
324 save_hook = trap.hook
324 save_hook = trap.hook
325
325
326 def failing_hook(*args, **kwargs):
326 def failing_hook(*args, **kwargs):
327 d['called'] = True
327 d['called'] = True
328
328
329 try:
329 try:
330 trap.hook = failing_hook
330 trap.hook = failing_hook
331 res = ip.run_cell("1", silent=True)
331 res = ip.run_cell("1", silent=True)
332 self.assertFalse(d['called'])
332 self.assertFalse(d['called'])
333 self.assertIsNone(res.result)
333 self.assertIsNone(res.result)
334 # double-check that non-silent exec did what we expected
334 # double-check that non-silent exec did what we expected
335 # silent to avoid
335 # silent to avoid
336 ip.run_cell("1")
336 ip.run_cell("1")
337 self.assertTrue(d['called'])
337 self.assertTrue(d['called'])
338 finally:
338 finally:
339 trap.hook = save_hook
339 trap.hook = save_hook
340
340
341 @skipif(sys.version_info[0] >= 3, "softspace removed in py3")
341 @skipif(sys.version_info[0] >= 3, "softspace removed in py3")
342 def test_print_softspace(self):
342 def test_print_softspace(self):
343 """Verify that softspace is handled correctly when executing multiple
343 """Verify that softspace is handled correctly when executing multiple
344 statements.
344 statements.
345
345
346 In [1]: print 1; print 2
346 In [1]: print 1; print 2
347 1
347 1
348 2
348 2
349
349
350 In [2]: print 1,; print 2
350 In [2]: print 1,; print 2
351 1 2
351 1 2
352 """
352 """
353
353
354 def test_ofind_line_magic(self):
354 def test_ofind_line_magic(self):
355 from IPython.core.magic import register_line_magic
355 from IPython.core.magic import register_line_magic
356
356
357 @register_line_magic
357 @register_line_magic
358 def lmagic(line):
358 def lmagic(line):
359 "A line magic"
359 "A line magic"
360
360
361 # Get info on line magic
361 # Get info on line magic
362 lfind = ip._ofind('lmagic')
362 lfind = ip._ofind('lmagic')
363 info = dict(found=True, isalias=False, ismagic=True,
363 info = dict(found=True, isalias=False, ismagic=True,
364 namespace = 'IPython internal', obj= lmagic.__wrapped__,
364 namespace = 'IPython internal', obj= lmagic.__wrapped__,
365 parent = None)
365 parent = None)
366 nt.assert_equal(lfind, info)
366 nt.assert_equal(lfind, info)
367
367
368 def test_ofind_cell_magic(self):
368 def test_ofind_cell_magic(self):
369 from IPython.core.magic import register_cell_magic
369 from IPython.core.magic import register_cell_magic
370
370
371 @register_cell_magic
371 @register_cell_magic
372 def cmagic(line, cell):
372 def cmagic(line, cell):
373 "A cell magic"
373 "A cell magic"
374
374
375 # Get info on cell magic
375 # Get info on cell magic
376 find = ip._ofind('cmagic')
376 find = ip._ofind('cmagic')
377 info = dict(found=True, isalias=False, ismagic=True,
377 info = dict(found=True, isalias=False, ismagic=True,
378 namespace = 'IPython internal', obj= cmagic.__wrapped__,
378 namespace = 'IPython internal', obj= cmagic.__wrapped__,
379 parent = None)
379 parent = None)
380 nt.assert_equal(find, info)
380 nt.assert_equal(find, info)
381
381
382 def test_ofind_property_with_error(self):
382 def test_ofind_property_with_error(self):
383 class A(object):
383 class A(object):
384 @property
384 @property
385 def foo(self):
385 def foo(self):
386 raise NotImplementedError()
386 raise NotImplementedError()
387 a = A()
387 a = A()
388
388
389 found = ip._ofind('a.foo', [('locals', locals())])
389 found = ip._ofind('a.foo', [('locals', locals())])
390 info = dict(found=True, isalias=False, ismagic=False,
390 info = dict(found=True, isalias=False, ismagic=False,
391 namespace='locals', obj=A.foo, parent=a)
391 namespace='locals', obj=A.foo, parent=a)
392 nt.assert_equal(found, info)
392 nt.assert_equal(found, info)
393
393
394 def test_ofind_multiple_attribute_lookups(self):
394 def test_ofind_multiple_attribute_lookups(self):
395 class A(object):
395 class A(object):
396 @property
396 @property
397 def foo(self):
397 def foo(self):
398 raise NotImplementedError()
398 raise NotImplementedError()
399
399
400 a = A()
400 a = A()
401 a.a = A()
401 a.a = A()
402 a.a.a = A()
402 a.a.a = A()
403
403
404 found = ip._ofind('a.a.a.foo', [('locals', locals())])
404 found = ip._ofind('a.a.a.foo', [('locals', locals())])
405 info = dict(found=True, isalias=False, ismagic=False,
405 info = dict(found=True, isalias=False, ismagic=False,
406 namespace='locals', obj=A.foo, parent=a.a.a)
406 namespace='locals', obj=A.foo, parent=a.a.a)
407 nt.assert_equal(found, info)
407 nt.assert_equal(found, info)
408
408
409 def test_ofind_slotted_attributes(self):
409 def test_ofind_slotted_attributes(self):
410 class A(object):
410 class A(object):
411 __slots__ = ['foo']
411 __slots__ = ['foo']
412 def __init__(self):
412 def __init__(self):
413 self.foo = 'bar'
413 self.foo = 'bar'
414
414
415 a = A()
415 a = A()
416 found = ip._ofind('a.foo', [('locals', locals())])
416 found = ip._ofind('a.foo', [('locals', locals())])
417 info = dict(found=True, isalias=False, ismagic=False,
417 info = dict(found=True, isalias=False, ismagic=False,
418 namespace='locals', obj=a.foo, parent=a)
418 namespace='locals', obj=a.foo, parent=a)
419 nt.assert_equal(found, info)
419 nt.assert_equal(found, info)
420
420
421 found = ip._ofind('a.bar', [('locals', locals())])
421 found = ip._ofind('a.bar', [('locals', locals())])
422 info = dict(found=False, isalias=False, ismagic=False,
422 info = dict(found=False, isalias=False, ismagic=False,
423 namespace=None, obj=None, parent=a)
423 namespace=None, obj=None, parent=a)
424 nt.assert_equal(found, info)
424 nt.assert_equal(found, info)
425
425
426 def test_ofind_prefers_property_to_instance_level_attribute(self):
426 def test_ofind_prefers_property_to_instance_level_attribute(self):
427 class A(object):
427 class A(object):
428 @property
428 @property
429 def foo(self):
429 def foo(self):
430 return 'bar'
430 return 'bar'
431 a = A()
431 a = A()
432 a.__dict__['foo'] = 'baz'
432 a.__dict__['foo'] = 'baz'
433 nt.assert_equal(a.foo, 'bar')
433 nt.assert_equal(a.foo, 'bar')
434 found = ip._ofind('a.foo', [('locals', locals())])
434 found = ip._ofind('a.foo', [('locals', locals())])
435 nt.assert_is(found['obj'], A.foo)
435 nt.assert_is(found['obj'], A.foo)
436
436
437 def test_custom_syntaxerror_exception(self):
437 def test_custom_syntaxerror_exception(self):
438 called = []
438 called = []
439 def my_handler(shell, etype, value, tb, tb_offset=None):
439 def my_handler(shell, etype, value, tb, tb_offset=None):
440 called.append(etype)
440 called.append(etype)
441 shell.showtraceback((etype, value, tb), tb_offset=tb_offset)
441 shell.showtraceback((etype, value, tb), tb_offset=tb_offset)
442
442
443 ip.set_custom_exc((SyntaxError,), my_handler)
443 ip.set_custom_exc((SyntaxError,), my_handler)
444 try:
444 try:
445 ip.run_cell("1f")
445 ip.run_cell("1f")
446 # Check that this was called, and only once.
446 # Check that this was called, and only once.
447 self.assertEqual(called, [SyntaxError])
447 self.assertEqual(called, [SyntaxError])
448 finally:
448 finally:
449 # Reset the custom exception hook
449 # Reset the custom exception hook
450 ip.set_custom_exc((), None)
450 ip.set_custom_exc((), None)
451
451
452 def test_custom_exception(self):
452 def test_custom_exception(self):
453 called = []
453 called = []
454 def my_handler(shell, etype, value, tb, tb_offset=None):
454 def my_handler(shell, etype, value, tb, tb_offset=None):
455 called.append(etype)
455 called.append(etype)
456 shell.showtraceback((etype, value, tb), tb_offset=tb_offset)
456 shell.showtraceback((etype, value, tb), tb_offset=tb_offset)
457
457
458 ip.set_custom_exc((ValueError,), my_handler)
458 ip.set_custom_exc((ValueError,), my_handler)
459 try:
459 try:
460 res = ip.run_cell("raise ValueError('test')")
460 res = ip.run_cell("raise ValueError('test')")
461 # Check that this was called, and only once.
461 # Check that this was called, and only once.
462 self.assertEqual(called, [ValueError])
462 self.assertEqual(called, [ValueError])
463 # Check that the error is on the result object
463 # Check that the error is on the result object
464 self.assertIsInstance(res.error_in_exec, ValueError)
464 self.assertIsInstance(res.error_in_exec, ValueError)
465 finally:
465 finally:
466 # Reset the custom exception hook
466 # Reset the custom exception hook
467 ip.set_custom_exc((), None)
467 ip.set_custom_exc((), None)
468
468
469 @skipif(sys.version_info[0] >= 3, "no differences with __future__ in py3")
469 @skipif(sys.version_info[0] >= 3, "no differences with __future__ in py3")
470 def test_future_environment(self):
470 def test_future_environment(self):
471 "Can we run code with & without the shell's __future__ imports?"
471 "Can we run code with & without the shell's __future__ imports?"
472 ip.run_cell("from __future__ import division")
472 ip.run_cell("from __future__ import division")
473 ip.run_cell("a = 1/2", shell_futures=True)
473 ip.run_cell("a = 1/2", shell_futures=True)
474 self.assertEqual(ip.user_ns['a'], 0.5)
474 self.assertEqual(ip.user_ns['a'], 0.5)
475 ip.run_cell("b = 1/2", shell_futures=False)
475 ip.run_cell("b = 1/2", shell_futures=False)
476 self.assertEqual(ip.user_ns['b'], 0)
476 self.assertEqual(ip.user_ns['b'], 0)
477
477
478 ip.compile.reset_compiler_flags()
478 ip.compile.reset_compiler_flags()
479 # This shouldn't leak to the shell's compiler
479 # This shouldn't leak to the shell's compiler
480 ip.run_cell("from __future__ import division \nc=1/2", shell_futures=False)
480 ip.run_cell("from __future__ import division \nc=1/2", shell_futures=False)
481 self.assertEqual(ip.user_ns['c'], 0.5)
481 self.assertEqual(ip.user_ns['c'], 0.5)
482 ip.run_cell("d = 1/2", shell_futures=True)
482 ip.run_cell("d = 1/2", shell_futures=True)
483 self.assertEqual(ip.user_ns['d'], 0)
483 self.assertEqual(ip.user_ns['d'], 0)
484
484
485 def test_mktempfile(self):
485 def test_mktempfile(self):
486 filename = ip.mktempfile()
486 filename = ip.mktempfile()
487 # Check that we can open the file again on Windows
487 # Check that we can open the file again on Windows
488 with open(filename, 'w') as f:
488 with open(filename, 'w') as f:
489 f.write('abc')
489 f.write('abc')
490
490
491 filename = ip.mktempfile(data='blah')
491 filename = ip.mktempfile(data='blah')
492 with open(filename, 'r') as f:
492 with open(filename, 'r') as f:
493 self.assertEqual(f.read(), 'blah')
493 self.assertEqual(f.read(), 'blah')
494
494
495 def test_new_main_mod(self):
495 def test_new_main_mod(self):
496 # Smoketest to check that this accepts a unicode module name
496 # Smoketest to check that this accepts a unicode module name
497 name = u'jiefmw'
497 name = u'jiefmw'
498 mod = ip.new_main_mod(u'%s.py' % name, name)
498 mod = ip.new_main_mod(u'%s.py' % name, name)
499 self.assertEqual(mod.__name__, name)
499 self.assertEqual(mod.__name__, name)
500
500
501 def test_get_exception_only(self):
501 def test_get_exception_only(self):
502 try:
502 try:
503 raise KeyboardInterrupt
503 raise KeyboardInterrupt
504 except KeyboardInterrupt:
504 except KeyboardInterrupt:
505 msg = ip.get_exception_only()
505 msg = ip.get_exception_only()
506 self.assertEqual(msg, 'KeyboardInterrupt\n')
506 self.assertEqual(msg, 'KeyboardInterrupt\n')
507
507
508 try:
508 try:
509 raise DerivedInterrupt("foo")
509 raise DerivedInterrupt("foo")
510 except KeyboardInterrupt:
510 except KeyboardInterrupt:
511 msg = ip.get_exception_only()
511 msg = ip.get_exception_only()
512 if sys.version_info[0] <= 2:
512 if sys.version_info[0] <= 2:
513 self.assertEqual(msg, 'DerivedInterrupt: foo\n')
513 self.assertEqual(msg, 'DerivedInterrupt: foo\n')
514 else:
514 else:
515 self.assertEqual(msg, 'IPython.core.tests.test_interactiveshell.DerivedInterrupt: foo\n')
515 self.assertEqual(msg, 'IPython.core.tests.test_interactiveshell.DerivedInterrupt: foo\n')
516
516
517 def test_inspect_text(self):
517 def test_inspect_text(self):
518 ip.run_cell('a = 5')
518 ip.run_cell('a = 5')
519 text = ip.object_inspect_text('a')
519 text = ip.object_inspect_text('a')
520 self.assertIsInstance(text, unicode_type)
520 self.assertIsInstance(text, unicode_type)
521
521
522
522
523 class TestSafeExecfileNonAsciiPath(unittest.TestCase):
523 class TestSafeExecfileNonAsciiPath(unittest.TestCase):
524
524
525 @onlyif_unicode_paths
525 @onlyif_unicode_paths
526 def setUp(self):
526 def setUp(self):
527 self.BASETESTDIR = tempfile.mkdtemp()
527 self.BASETESTDIR = tempfile.mkdtemp()
528 self.TESTDIR = join(self.BASETESTDIR, u"Γ₯Àâ")
528 self.TESTDIR = join(self.BASETESTDIR, u"Γ₯Àâ")
529 os.mkdir(self.TESTDIR)
529 os.mkdir(self.TESTDIR)
530 with open(join(self.TESTDIR, u"Γ₯Àâtestscript.py"), "w") as sfile:
530 with open(join(self.TESTDIR, u"Γ₯Àâtestscript.py"), "w") as sfile:
531 sfile.write("pass\n")
531 sfile.write("pass\n")
532 self.oldpath = py3compat.getcwd()
532 self.oldpath = py3compat.getcwd()
533 os.chdir(self.TESTDIR)
533 os.chdir(self.TESTDIR)
534 self.fname = u"Γ₯Àâtestscript.py"
534 self.fname = u"Γ₯Àâtestscript.py"
535
535
536 def tearDown(self):
536 def tearDown(self):
537 os.chdir(self.oldpath)
537 os.chdir(self.oldpath)
538 shutil.rmtree(self.BASETESTDIR)
538 shutil.rmtree(self.BASETESTDIR)
539
539
540 @onlyif_unicode_paths
540 @onlyif_unicode_paths
541 def test_1(self):
541 def test_1(self):
542 """Test safe_execfile with non-ascii path
542 """Test safe_execfile with non-ascii path
543 """
543 """
544 ip.safe_execfile(self.fname, {}, raise_exceptions=True)
544 ip.safe_execfile(self.fname, {}, raise_exceptions=True)
545
545
546 class ExitCodeChecks(tt.TempFileMixin):
546 class ExitCodeChecks(tt.TempFileMixin):
547 def test_exit_code_ok(self):
547 def test_exit_code_ok(self):
548 self.system('exit 0')
548 self.system('exit 0')
549 self.assertEqual(ip.user_ns['_exit_code'], 0)
549 self.assertEqual(ip.user_ns['_exit_code'], 0)
550
550
551 def test_exit_code_error(self):
551 def test_exit_code_error(self):
552 self.system('exit 1')
552 self.system('exit 1')
553 self.assertEqual(ip.user_ns['_exit_code'], 1)
553 self.assertEqual(ip.user_ns['_exit_code'], 1)
554
554
555 @skipif(not hasattr(signal, 'SIGALRM'))
555 @skipif(not hasattr(signal, 'SIGALRM'))
556 def test_exit_code_signal(self):
556 def test_exit_code_signal(self):
557 self.mktmp("import signal, time\n"
557 self.mktmp("import signal, time\n"
558 "signal.setitimer(signal.ITIMER_REAL, 0.1)\n"
558 "signal.setitimer(signal.ITIMER_REAL, 0.1)\n"
559 "time.sleep(1)\n")
559 "time.sleep(1)\n")
560 self.system("%s %s" % (sys.executable, self.fname))
560 self.system("%s %s" % (sys.executable, self.fname))
561 self.assertEqual(ip.user_ns['_exit_code'], -signal.SIGALRM)
561 self.assertEqual(ip.user_ns['_exit_code'], -signal.SIGALRM)
562
562
563 @onlyif_cmds_exist("csh")
563 @onlyif_cmds_exist("csh")
564 def test_exit_code_signal_csh(self):
564 def test_exit_code_signal_csh(self):
565 SHELL = os.environ.get('SHELL', None)
565 SHELL = os.environ.get('SHELL', None)
566 os.environ['SHELL'] = find_cmd("csh")
566 os.environ['SHELL'] = find_cmd("csh")
567 try:
567 try:
568 self.test_exit_code_signal()
568 self.test_exit_code_signal()
569 finally:
569 finally:
570 if SHELL is not None:
570 if SHELL is not None:
571 os.environ['SHELL'] = SHELL
571 os.environ['SHELL'] = SHELL
572 else:
572 else:
573 del os.environ['SHELL']
573 del os.environ['SHELL']
574
574
575 class TestSystemRaw(unittest.TestCase, ExitCodeChecks):
575 class TestSystemRaw(unittest.TestCase, ExitCodeChecks):
576 system = ip.system_raw
576 system = ip.system_raw
577
577
578 @onlyif_unicode_paths
578 @onlyif_unicode_paths
579 def test_1(self):
579 def test_1(self):
580 """Test system_raw with non-ascii cmd
580 """Test system_raw with non-ascii cmd
581 """
581 """
582 cmd = u'''python -c "'Γ₯Àâ'" '''
582 cmd = u'''python -c "'Γ₯Àâ'" '''
583 ip.system_raw(cmd)
583 ip.system_raw(cmd)
584
584
585 @mock.patch('subprocess.call', side_effect=KeyboardInterrupt)
585 @mock.patch('subprocess.call', side_effect=KeyboardInterrupt)
586 @mock.patch('os.system', side_effect=KeyboardInterrupt)
586 @mock.patch('os.system', side_effect=KeyboardInterrupt)
587 def test_control_c(self, *mocks):
587 def test_control_c(self, *mocks):
588 try:
588 try:
589 self.system("sleep 1 # wont happen")
589 self.system("sleep 1 # wont happen")
590 except KeyboardInterrupt:
590 except KeyboardInterrupt:
591 self.fail("system call should intercept "
591 self.fail("system call should intercept "
592 "keyboard interrupt from subprocess.call")
592 "keyboard interrupt from subprocess.call")
593 self.assertEqual(ip.user_ns['_exit_code'], -signal.SIGINT)
593 self.assertEqual(ip.user_ns['_exit_code'], -signal.SIGINT)
594
594
595 # TODO: Exit codes are currently ignored on Windows.
595 # TODO: Exit codes are currently ignored on Windows.
596 class TestSystemPipedExitCode(unittest.TestCase, ExitCodeChecks):
596 class TestSystemPipedExitCode(unittest.TestCase, ExitCodeChecks):
597 system = ip.system_piped
597 system = ip.system_piped
598
598
599 @skip_win32
599 @skip_win32
600 def test_exit_code_ok(self):
600 def test_exit_code_ok(self):
601 ExitCodeChecks.test_exit_code_ok(self)
601 ExitCodeChecks.test_exit_code_ok(self)
602
602
603 @skip_win32
603 @skip_win32
604 def test_exit_code_error(self):
604 def test_exit_code_error(self):
605 ExitCodeChecks.test_exit_code_error(self)
605 ExitCodeChecks.test_exit_code_error(self)
606
606
607 @skip_win32
607 @skip_win32
608 def test_exit_code_signal(self):
608 def test_exit_code_signal(self):
609 ExitCodeChecks.test_exit_code_signal(self)
609 ExitCodeChecks.test_exit_code_signal(self)
610
610
611 class TestModules(unittest.TestCase, tt.TempFileMixin):
611 class TestModules(unittest.TestCase, tt.TempFileMixin):
612 def test_extraneous_loads(self):
612 def test_extraneous_loads(self):
613 """Test we're not loading modules on startup that we shouldn't.
613 """Test we're not loading modules on startup that we shouldn't.
614 """
614 """
615 self.mktmp("import sys\n"
615 self.mktmp("import sys\n"
616 "print('numpy' in sys.modules)\n"
616 "print('numpy' in sys.modules)\n"
617 "print('ipyparallel' in sys.modules)\n"
617 "print('ipyparallel' in sys.modules)\n"
618 "print('ipykernel' in sys.modules)\n"
618 "print('ipykernel' in sys.modules)\n"
619 )
619 )
620 out = "False\nFalse\nFalse\n"
620 out = "False\nFalse\nFalse\n"
621 tt.ipexec_validate(self.fname, out)
621 tt.ipexec_validate(self.fname, out)
622
622
623 class Negator(ast.NodeTransformer):
623 class Negator(ast.NodeTransformer):
624 """Negates all number literals in an AST."""
624 """Negates all number literals in an AST."""
625 def visit_Num(self, node):
625 def visit_Num(self, node):
626 node.n = -node.n
626 node.n = -node.n
627 return node
627 return node
628
628
629 class TestAstTransform(unittest.TestCase):
629 class TestAstTransform(unittest.TestCase):
630 def setUp(self):
630 def setUp(self):
631 self.negator = Negator()
631 self.negator = Negator()
632 ip.ast_transformers.append(self.negator)
632 ip.ast_transformers.append(self.negator)
633
633
634 def tearDown(self):
634 def tearDown(self):
635 ip.ast_transformers.remove(self.negator)
635 ip.ast_transformers.remove(self.negator)
636
636
637 def test_run_cell(self):
637 def test_run_cell(self):
638 with tt.AssertPrints('-34'):
638 with tt.AssertPrints('-34'):
639 ip.run_cell('print (12 + 22)')
639 ip.run_cell('print (12 + 22)')
640
640
641 # A named reference to a number shouldn't be transformed.
641 # A named reference to a number shouldn't be transformed.
642 ip.user_ns['n'] = 55
642 ip.user_ns['n'] = 55
643 with tt.AssertNotPrints('-55'):
643 with tt.AssertNotPrints('-55'):
644 ip.run_cell('print (n)')
644 ip.run_cell('print (n)')
645
645
646 def test_timeit(self):
646 def test_timeit(self):
647 called = set()
647 called = set()
648 def f(x):
648 def f(x):
649 called.add(x)
649 called.add(x)
650 ip.push({'f':f})
650 ip.push({'f':f})
651
651
652 with tt.AssertPrints("best of "):
652 with tt.AssertPrints("average of "):
653 ip.run_line_magic("timeit", "-n1 f(1)")
653 ip.run_line_magic("timeit", "-n1 f(1)")
654 self.assertEqual(called, {-1})
654 self.assertEqual(called, {-1})
655 called.clear()
655 called.clear()
656
656
657 with tt.AssertPrints("best of "):
657 with tt.AssertPrints("average of "):
658 ip.run_cell_magic("timeit", "-n1 f(2)", "f(3)")
658 ip.run_cell_magic("timeit", "-n1 f(2)", "f(3)")
659 self.assertEqual(called, {-2, -3})
659 self.assertEqual(called, {-2, -3})
660
660
661 def test_time(self):
661 def test_time(self):
662 called = []
662 called = []
663 def f(x):
663 def f(x):
664 called.append(x)
664 called.append(x)
665 ip.push({'f':f})
665 ip.push({'f':f})
666
666
667 # Test with an expression
667 # Test with an expression
668 with tt.AssertPrints("Wall time: "):
668 with tt.AssertPrints("Wall time: "):
669 ip.run_line_magic("time", "f(5+9)")
669 ip.run_line_magic("time", "f(5+9)")
670 self.assertEqual(called, [-14])
670 self.assertEqual(called, [-14])
671 called[:] = []
671 called[:] = []
672
672
673 # Test with a statement (different code path)
673 # Test with a statement (different code path)
674 with tt.AssertPrints("Wall time: "):
674 with tt.AssertPrints("Wall time: "):
675 ip.run_line_magic("time", "a = f(-3 + -2)")
675 ip.run_line_magic("time", "a = f(-3 + -2)")
676 self.assertEqual(called, [5])
676 self.assertEqual(called, [5])
677
677
678 def test_macro(self):
678 def test_macro(self):
679 ip.push({'a':10})
679 ip.push({'a':10})
680 # The AST transformation makes this do a+=-1
680 # The AST transformation makes this do a+=-1
681 ip.define_macro("amacro", "a+=1\nprint(a)")
681 ip.define_macro("amacro", "a+=1\nprint(a)")
682
682
683 with tt.AssertPrints("9"):
683 with tt.AssertPrints("9"):
684 ip.run_cell("amacro")
684 ip.run_cell("amacro")
685 with tt.AssertPrints("8"):
685 with tt.AssertPrints("8"):
686 ip.run_cell("amacro")
686 ip.run_cell("amacro")
687
687
688 class IntegerWrapper(ast.NodeTransformer):
688 class IntegerWrapper(ast.NodeTransformer):
689 """Wraps all integers in a call to Integer()"""
689 """Wraps all integers in a call to Integer()"""
690 def visit_Num(self, node):
690 def visit_Num(self, node):
691 if isinstance(node.n, int):
691 if isinstance(node.n, int):
692 return ast.Call(func=ast.Name(id='Integer', ctx=ast.Load()),
692 return ast.Call(func=ast.Name(id='Integer', ctx=ast.Load()),
693 args=[node], keywords=[])
693 args=[node], keywords=[])
694 return node
694 return node
695
695
696 class TestAstTransform2(unittest.TestCase):
696 class TestAstTransform2(unittest.TestCase):
697 def setUp(self):
697 def setUp(self):
698 self.intwrapper = IntegerWrapper()
698 self.intwrapper = IntegerWrapper()
699 ip.ast_transformers.append(self.intwrapper)
699 ip.ast_transformers.append(self.intwrapper)
700
700
701 self.calls = []
701 self.calls = []
702 def Integer(*args):
702 def Integer(*args):
703 self.calls.append(args)
703 self.calls.append(args)
704 return args
704 return args
705 ip.push({"Integer": Integer})
705 ip.push({"Integer": Integer})
706
706
707 def tearDown(self):
707 def tearDown(self):
708 ip.ast_transformers.remove(self.intwrapper)
708 ip.ast_transformers.remove(self.intwrapper)
709 del ip.user_ns['Integer']
709 del ip.user_ns['Integer']
710
710
711 def test_run_cell(self):
711 def test_run_cell(self):
712 ip.run_cell("n = 2")
712 ip.run_cell("n = 2")
713 self.assertEqual(self.calls, [(2,)])
713 self.assertEqual(self.calls, [(2,)])
714
714
715 # This shouldn't throw an error
715 # This shouldn't throw an error
716 ip.run_cell("o = 2.0")
716 ip.run_cell("o = 2.0")
717 self.assertEqual(ip.user_ns['o'], 2.0)
717 self.assertEqual(ip.user_ns['o'], 2.0)
718
718
719 def test_timeit(self):
719 def test_timeit(self):
720 called = set()
720 called = set()
721 def f(x):
721 def f(x):
722 called.add(x)
722 called.add(x)
723 ip.push({'f':f})
723 ip.push({'f':f})
724
724
725 with tt.AssertPrints("best of "):
725 with tt.AssertPrints("average of "):
726 ip.run_line_magic("timeit", "-n1 f(1)")
726 ip.run_line_magic("timeit", "-n1 f(1)")
727 self.assertEqual(called, {(1,)})
727 self.assertEqual(called, {(1,)})
728 called.clear()
728 called.clear()
729
729
730 with tt.AssertPrints("best of "):
730 with tt.AssertPrints("average of "):
731 ip.run_cell_magic("timeit", "-n1 f(2)", "f(3)")
731 ip.run_cell_magic("timeit", "-n1 f(2)", "f(3)")
732 self.assertEqual(called, {(2,), (3,)})
732 self.assertEqual(called, {(2,), (3,)})
733
733
734 class ErrorTransformer(ast.NodeTransformer):
734 class ErrorTransformer(ast.NodeTransformer):
735 """Throws an error when it sees a number."""
735 """Throws an error when it sees a number."""
736 def visit_Num(self, node):
736 def visit_Num(self, node):
737 raise ValueError("test")
737 raise ValueError("test")
738
738
739 class TestAstTransformError(unittest.TestCase):
739 class TestAstTransformError(unittest.TestCase):
740 def test_unregistering(self):
740 def test_unregistering(self):
741 err_transformer = ErrorTransformer()
741 err_transformer = ErrorTransformer()
742 ip.ast_transformers.append(err_transformer)
742 ip.ast_transformers.append(err_transformer)
743
743
744 with tt.AssertPrints("unregister", channel='stderr'):
744 with tt.AssertPrints("unregister", channel='stderr'):
745 ip.run_cell("1 + 2")
745 ip.run_cell("1 + 2")
746
746
747 # This should have been removed.
747 # This should have been removed.
748 nt.assert_not_in(err_transformer, ip.ast_transformers)
748 nt.assert_not_in(err_transformer, ip.ast_transformers)
749
749
750
750
751 class StringRejector(ast.NodeTransformer):
751 class StringRejector(ast.NodeTransformer):
752 """Throws an InputRejected when it sees a string literal.
752 """Throws an InputRejected when it sees a string literal.
753
753
754 Used to verify that NodeTransformers can signal that a piece of code should
754 Used to verify that NodeTransformers can signal that a piece of code should
755 not be executed by throwing an InputRejected.
755 not be executed by throwing an InputRejected.
756 """
756 """
757
757
758 def visit_Str(self, node):
758 def visit_Str(self, node):
759 raise InputRejected("test")
759 raise InputRejected("test")
760
760
761
761
762 class TestAstTransformInputRejection(unittest.TestCase):
762 class TestAstTransformInputRejection(unittest.TestCase):
763
763
764 def setUp(self):
764 def setUp(self):
765 self.transformer = StringRejector()
765 self.transformer = StringRejector()
766 ip.ast_transformers.append(self.transformer)
766 ip.ast_transformers.append(self.transformer)
767
767
768 def tearDown(self):
768 def tearDown(self):
769 ip.ast_transformers.remove(self.transformer)
769 ip.ast_transformers.remove(self.transformer)
770
770
771 def test_input_rejection(self):
771 def test_input_rejection(self):
772 """Check that NodeTransformers can reject input."""
772 """Check that NodeTransformers can reject input."""
773
773
774 expect_exception_tb = tt.AssertPrints("InputRejected: test")
774 expect_exception_tb = tt.AssertPrints("InputRejected: test")
775 expect_no_cell_output = tt.AssertNotPrints("'unsafe'", suppress=False)
775 expect_no_cell_output = tt.AssertNotPrints("'unsafe'", suppress=False)
776
776
777 # Run the same check twice to verify that the transformer is not
777 # Run the same check twice to verify that the transformer is not
778 # disabled after raising.
778 # disabled after raising.
779 with expect_exception_tb, expect_no_cell_output:
779 with expect_exception_tb, expect_no_cell_output:
780 ip.run_cell("'unsafe'")
780 ip.run_cell("'unsafe'")
781
781
782 with expect_exception_tb, expect_no_cell_output:
782 with expect_exception_tb, expect_no_cell_output:
783 res = ip.run_cell("'unsafe'")
783 res = ip.run_cell("'unsafe'")
784
784
785 self.assertIsInstance(res.error_before_exec, InputRejected)
785 self.assertIsInstance(res.error_before_exec, InputRejected)
786
786
787 def test__IPYTHON__():
787 def test__IPYTHON__():
788 # This shouldn't raise a NameError, that's all
788 # This shouldn't raise a NameError, that's all
789 __IPYTHON__
789 __IPYTHON__
790
790
791
791
792 class DummyRepr(object):
792 class DummyRepr(object):
793 def __repr__(self):
793 def __repr__(self):
794 return "DummyRepr"
794 return "DummyRepr"
795
795
796 def _repr_html_(self):
796 def _repr_html_(self):
797 return "<b>dummy</b>"
797 return "<b>dummy</b>"
798
798
799 def _repr_javascript_(self):
799 def _repr_javascript_(self):
800 return "console.log('hi');", {'key': 'value'}
800 return "console.log('hi');", {'key': 'value'}
801
801
802
802
803 def test_user_variables():
803 def test_user_variables():
804 # enable all formatters
804 # enable all formatters
805 ip.display_formatter.active_types = ip.display_formatter.format_types
805 ip.display_formatter.active_types = ip.display_formatter.format_types
806
806
807 ip.user_ns['dummy'] = d = DummyRepr()
807 ip.user_ns['dummy'] = d = DummyRepr()
808 keys = {'dummy', 'doesnotexist'}
808 keys = {'dummy', 'doesnotexist'}
809 r = ip.user_expressions({ key:key for key in keys})
809 r = ip.user_expressions({ key:key for key in keys})
810
810
811 nt.assert_equal(keys, set(r.keys()))
811 nt.assert_equal(keys, set(r.keys()))
812 dummy = r['dummy']
812 dummy = r['dummy']
813 nt.assert_equal({'status', 'data', 'metadata'}, set(dummy.keys()))
813 nt.assert_equal({'status', 'data', 'metadata'}, set(dummy.keys()))
814 nt.assert_equal(dummy['status'], 'ok')
814 nt.assert_equal(dummy['status'], 'ok')
815 data = dummy['data']
815 data = dummy['data']
816 metadata = dummy['metadata']
816 metadata = dummy['metadata']
817 nt.assert_equal(data.get('text/html'), d._repr_html_())
817 nt.assert_equal(data.get('text/html'), d._repr_html_())
818 js, jsmd = d._repr_javascript_()
818 js, jsmd = d._repr_javascript_()
819 nt.assert_equal(data.get('application/javascript'), js)
819 nt.assert_equal(data.get('application/javascript'), js)
820 nt.assert_equal(metadata.get('application/javascript'), jsmd)
820 nt.assert_equal(metadata.get('application/javascript'), jsmd)
821
821
822 dne = r['doesnotexist']
822 dne = r['doesnotexist']
823 nt.assert_equal(dne['status'], 'error')
823 nt.assert_equal(dne['status'], 'error')
824 nt.assert_equal(dne['ename'], 'NameError')
824 nt.assert_equal(dne['ename'], 'NameError')
825
825
826 # back to text only
826 # back to text only
827 ip.display_formatter.active_types = ['text/plain']
827 ip.display_formatter.active_types = ['text/plain']
828
828
829 def test_user_expression():
829 def test_user_expression():
830 # enable all formatters
830 # enable all formatters
831 ip.display_formatter.active_types = ip.display_formatter.format_types
831 ip.display_formatter.active_types = ip.display_formatter.format_types
832 query = {
832 query = {
833 'a' : '1 + 2',
833 'a' : '1 + 2',
834 'b' : '1/0',
834 'b' : '1/0',
835 }
835 }
836 r = ip.user_expressions(query)
836 r = ip.user_expressions(query)
837 import pprint
837 import pprint
838 pprint.pprint(r)
838 pprint.pprint(r)
839 nt.assert_equal(set(r.keys()), set(query.keys()))
839 nt.assert_equal(set(r.keys()), set(query.keys()))
840 a = r['a']
840 a = r['a']
841 nt.assert_equal({'status', 'data', 'metadata'}, set(a.keys()))
841 nt.assert_equal({'status', 'data', 'metadata'}, set(a.keys()))
842 nt.assert_equal(a['status'], 'ok')
842 nt.assert_equal(a['status'], 'ok')
843 data = a['data']
843 data = a['data']
844 metadata = a['metadata']
844 metadata = a['metadata']
845 nt.assert_equal(data.get('text/plain'), '3')
845 nt.assert_equal(data.get('text/plain'), '3')
846
846
847 b = r['b']
847 b = r['b']
848 nt.assert_equal(b['status'], 'error')
848 nt.assert_equal(b['status'], 'error')
849 nt.assert_equal(b['ename'], 'ZeroDivisionError')
849 nt.assert_equal(b['ename'], 'ZeroDivisionError')
850
850
851 # back to text only
851 # back to text only
852 ip.display_formatter.active_types = ['text/plain']
852 ip.display_formatter.active_types = ['text/plain']
853
853
854
854
855
855
856
856
857
857
858 class TestSyntaxErrorTransformer(unittest.TestCase):
858 class TestSyntaxErrorTransformer(unittest.TestCase):
859 """Check that SyntaxError raised by an input transformer is handled by run_cell()"""
859 """Check that SyntaxError raised by an input transformer is handled by run_cell()"""
860
860
861 class SyntaxErrorTransformer(InputTransformer):
861 class SyntaxErrorTransformer(InputTransformer):
862
862
863 def push(self, line):
863 def push(self, line):
864 pos = line.find('syntaxerror')
864 pos = line.find('syntaxerror')
865 if pos >= 0:
865 if pos >= 0:
866 e = SyntaxError('input contains "syntaxerror"')
866 e = SyntaxError('input contains "syntaxerror"')
867 e.text = line
867 e.text = line
868 e.offset = pos + 1
868 e.offset = pos + 1
869 raise e
869 raise e
870 return line
870 return line
871
871
872 def reset(self):
872 def reset(self):
873 pass
873 pass
874
874
875 def setUp(self):
875 def setUp(self):
876 self.transformer = TestSyntaxErrorTransformer.SyntaxErrorTransformer()
876 self.transformer = TestSyntaxErrorTransformer.SyntaxErrorTransformer()
877 ip.input_splitter.python_line_transforms.append(self.transformer)
877 ip.input_splitter.python_line_transforms.append(self.transformer)
878 ip.input_transformer_manager.python_line_transforms.append(self.transformer)
878 ip.input_transformer_manager.python_line_transforms.append(self.transformer)
879
879
880 def tearDown(self):
880 def tearDown(self):
881 ip.input_splitter.python_line_transforms.remove(self.transformer)
881 ip.input_splitter.python_line_transforms.remove(self.transformer)
882 ip.input_transformer_manager.python_line_transforms.remove(self.transformer)
882 ip.input_transformer_manager.python_line_transforms.remove(self.transformer)
883
883
884 def test_syntaxerror_input_transformer(self):
884 def test_syntaxerror_input_transformer(self):
885 with tt.AssertPrints('1234'):
885 with tt.AssertPrints('1234'):
886 ip.run_cell('1234')
886 ip.run_cell('1234')
887 with tt.AssertPrints('SyntaxError: invalid syntax'):
887 with tt.AssertPrints('SyntaxError: invalid syntax'):
888 ip.run_cell('1 2 3') # plain python syntax error
888 ip.run_cell('1 2 3') # plain python syntax error
889 with tt.AssertPrints('SyntaxError: input contains "syntaxerror"'):
889 with tt.AssertPrints('SyntaxError: input contains "syntaxerror"'):
890 ip.run_cell('2345 # syntaxerror') # input transformer syntax error
890 ip.run_cell('2345 # syntaxerror') # input transformer syntax error
891 with tt.AssertPrints('3456'):
891 with tt.AssertPrints('3456'):
892 ip.run_cell('3456')
892 ip.run_cell('3456')
893
893
894
894
895
895
896 def test_warning_suppression():
896 def test_warning_suppression():
897 ip.run_cell("import warnings")
897 ip.run_cell("import warnings")
898 try:
898 try:
899 with tt.AssertPrints("UserWarning: asdf", channel="stderr"):
899 with tt.AssertPrints("UserWarning: asdf", channel="stderr"):
900 ip.run_cell("warnings.warn('asdf')")
900 ip.run_cell("warnings.warn('asdf')")
901 # Here's the real test -- if we run that again, we should get the
901 # Here's the real test -- if we run that again, we should get the
902 # warning again. Traditionally, each warning was only issued once per
902 # warning again. Traditionally, each warning was only issued once per
903 # IPython session (approximately), even if the user typed in new and
903 # IPython session (approximately), even if the user typed in new and
904 # different code that should have also triggered the warning, leading
904 # different code that should have also triggered the warning, leading
905 # to much confusion.
905 # to much confusion.
906 with tt.AssertPrints("UserWarning: asdf", channel="stderr"):
906 with tt.AssertPrints("UserWarning: asdf", channel="stderr"):
907 ip.run_cell("warnings.warn('asdf')")
907 ip.run_cell("warnings.warn('asdf')")
908 finally:
908 finally:
909 ip.run_cell("del warnings")
909 ip.run_cell("del warnings")
910
910
911
911
912 def test_deprecation_warning():
912 def test_deprecation_warning():
913 ip.run_cell("""
913 ip.run_cell("""
914 import warnings
914 import warnings
915 def wrn():
915 def wrn():
916 warnings.warn(
916 warnings.warn(
917 "I AM A WARNING",
917 "I AM A WARNING",
918 DeprecationWarning
918 DeprecationWarning
919 )
919 )
920 """)
920 """)
921 try:
921 try:
922 with tt.AssertPrints("I AM A WARNING", channel="stderr"):
922 with tt.AssertPrints("I AM A WARNING", channel="stderr"):
923 ip.run_cell("wrn()")
923 ip.run_cell("wrn()")
924 finally:
924 finally:
925 ip.run_cell("del warnings")
925 ip.run_cell("del warnings")
926 ip.run_cell("del wrn")
926 ip.run_cell("del wrn")
927
927
928
928
929 class TestImportNoDeprecate(tt.TempFileMixin):
929 class TestImportNoDeprecate(tt.TempFileMixin):
930
930
931 def setup(self):
931 def setup(self):
932 """Make a valid python temp file."""
932 """Make a valid python temp file."""
933 self.mktmp("""
933 self.mktmp("""
934 import warnings
934 import warnings
935 def wrn():
935 def wrn():
936 warnings.warn(
936 warnings.warn(
937 "I AM A WARNING",
937 "I AM A WARNING",
938 DeprecationWarning
938 DeprecationWarning
939 )
939 )
940 """)
940 """)
941
941
942 def test_no_dep(self):
942 def test_no_dep(self):
943 """
943 """
944 No deprecation warning should be raised from imported functions
944 No deprecation warning should be raised from imported functions
945 """
945 """
946 ip.run_cell("from {} import wrn".format(self.fname))
946 ip.run_cell("from {} import wrn".format(self.fname))
947
947
948 with tt.AssertNotPrints("I AM A WARNING"):
948 with tt.AssertNotPrints("I AM A WARNING"):
949 ip.run_cell("wrn()")
949 ip.run_cell("wrn()")
950 ip.run_cell("del wrn")
950 ip.run_cell("del wrn")
General Comments 0
You need to be logged in to leave comments. Login now