##// END OF EJS Templates
capture_output does not respect trailing semicolon (#13940)...
Matthias Bussonnier -
r28128:75ecfe93 merge
parent child Browse files
Show More
@@ -1,1512 +1,1516 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
7
8 import ast
8 import ast
9 import bdb
9 import bdb
10 import builtins as builtin_mod
10 import builtins as builtin_mod
11 import cProfile as profile
11 import cProfile as profile
12 import gc
12 import gc
13 import itertools
13 import itertools
14 import math
14 import math
15 import os
15 import os
16 import pstats
16 import pstats
17 import re
17 import re
18 import shlex
18 import shlex
19 import sys
19 import sys
20 import time
20 import time
21 import timeit
21 import timeit
22 from ast import Module
22 from ast import Module
23 from io import StringIO
23 from io import StringIO
24 from logging import error
24 from logging import error
25 from pathlib import Path
25 from pathlib import Path
26 from pdb import Restart
26 from pdb import Restart
27 from warnings import warn
27 from warnings import warn
28
28
29 from IPython.core import magic_arguments, oinspect, page
29 from IPython.core import magic_arguments, oinspect, page
30 from IPython.core.error import UsageError
30 from IPython.core.error import UsageError
31 from IPython.core.macro import Macro
31 from IPython.core.macro import Macro
32 from IPython.core.magic import (
32 from IPython.core.magic import (
33 Magics,
33 Magics,
34 cell_magic,
34 cell_magic,
35 line_cell_magic,
35 line_cell_magic,
36 line_magic,
36 line_magic,
37 magics_class,
37 magics_class,
38 needs_local_scope,
38 needs_local_scope,
39 no_var_expand,
39 no_var_expand,
40 output_can_be_silenced,
40 output_can_be_silenced,
41 on_off,
41 on_off,
42 )
42 )
43 from IPython.testing.skipdoctest import skip_doctest
43 from IPython.testing.skipdoctest import skip_doctest
44 from IPython.utils.capture import capture_output
44 from IPython.utils.capture import capture_output
45 from IPython.utils.contexts import preserve_keys
45 from IPython.utils.contexts import preserve_keys
46 from IPython.utils.ipstruct import Struct
46 from IPython.utils.ipstruct import Struct
47 from IPython.utils.module_paths import find_mod
47 from IPython.utils.module_paths import find_mod
48 from IPython.utils.path import get_py_filename, shellglob
48 from IPython.utils.path import get_py_filename, shellglob
49 from IPython.utils.timing import clock, clock2
49 from IPython.utils.timing import clock, clock2
50 from IPython.core.displayhook import DisplayHook
50
51
51 #-----------------------------------------------------------------------------
52 #-----------------------------------------------------------------------------
52 # Magic implementation classes
53 # Magic implementation classes
53 #-----------------------------------------------------------------------------
54 #-----------------------------------------------------------------------------
54
55
55
56
56 class TimeitResult(object):
57 class TimeitResult(object):
57 """
58 """
58 Object returned by the timeit magic with info about the run.
59 Object returned by the timeit magic with info about the run.
59
60
60 Contains the following attributes :
61 Contains the following attributes :
61
62
62 loops: (int) number of loops done per measurement
63 loops: (int) number of loops done per measurement
63 repeat: (int) number of times the measurement has been repeated
64 repeat: (int) number of times the measurement has been repeated
64 best: (float) best execution time / number
65 best: (float) best execution time / number
65 all_runs: (list of float) execution time of each run (in s)
66 all_runs: (list of float) execution time of each run (in s)
66 compile_time: (float) time of statement compilation (s)
67 compile_time: (float) time of statement compilation (s)
67
68
68 """
69 """
69 def __init__(self, loops, repeat, best, worst, all_runs, compile_time, precision):
70 def __init__(self, loops, repeat, best, worst, all_runs, compile_time, precision):
70 self.loops = loops
71 self.loops = loops
71 self.repeat = repeat
72 self.repeat = repeat
72 self.best = best
73 self.best = best
73 self.worst = worst
74 self.worst = worst
74 self.all_runs = all_runs
75 self.all_runs = all_runs
75 self.compile_time = compile_time
76 self.compile_time = compile_time
76 self._precision = precision
77 self._precision = precision
77 self.timings = [ dt / self.loops for dt in all_runs]
78 self.timings = [ dt / self.loops for dt in all_runs]
78
79
79 @property
80 @property
80 def average(self):
81 def average(self):
81 return math.fsum(self.timings) / len(self.timings)
82 return math.fsum(self.timings) / len(self.timings)
82
83
83 @property
84 @property
84 def stdev(self):
85 def stdev(self):
85 mean = self.average
86 mean = self.average
86 return (math.fsum([(x - mean) ** 2 for x in self.timings]) / len(self.timings)) ** 0.5
87 return (math.fsum([(x - mean) ** 2 for x in self.timings]) / len(self.timings)) ** 0.5
87
88
88 def __str__(self):
89 def __str__(self):
89 pm = '+-'
90 pm = '+-'
90 if hasattr(sys.stdout, 'encoding') and sys.stdout.encoding:
91 if hasattr(sys.stdout, 'encoding') and sys.stdout.encoding:
91 try:
92 try:
92 u'\xb1'.encode(sys.stdout.encoding)
93 u'\xb1'.encode(sys.stdout.encoding)
93 pm = u'\xb1'
94 pm = u'\xb1'
94 except:
95 except:
95 pass
96 pass
96 return "{mean} {pm} {std} per loop (mean {pm} std. dev. of {runs} run{run_plural}, {loops:,} loop{loop_plural} each)".format(
97 return "{mean} {pm} {std} per loop (mean {pm} std. dev. of {runs} run{run_plural}, {loops:,} loop{loop_plural} each)".format(
97 pm=pm,
98 pm=pm,
98 runs=self.repeat,
99 runs=self.repeat,
99 loops=self.loops,
100 loops=self.loops,
100 loop_plural="" if self.loops == 1 else "s",
101 loop_plural="" if self.loops == 1 else "s",
101 run_plural="" if self.repeat == 1 else "s",
102 run_plural="" if self.repeat == 1 else "s",
102 mean=_format_time(self.average, self._precision),
103 mean=_format_time(self.average, self._precision),
103 std=_format_time(self.stdev, self._precision),
104 std=_format_time(self.stdev, self._precision),
104 )
105 )
105
106
106 def _repr_pretty_(self, p , cycle):
107 def _repr_pretty_(self, p , cycle):
107 unic = self.__str__()
108 unic = self.__str__()
108 p.text(u'<TimeitResult : '+unic+u'>')
109 p.text(u'<TimeitResult : '+unic+u'>')
109
110
110
111
111 class TimeitTemplateFiller(ast.NodeTransformer):
112 class TimeitTemplateFiller(ast.NodeTransformer):
112 """Fill in the AST template for timing execution.
113 """Fill in the AST template for timing execution.
113
114
114 This is quite closely tied to the template definition, which is in
115 This is quite closely tied to the template definition, which is in
115 :meth:`ExecutionMagics.timeit`.
116 :meth:`ExecutionMagics.timeit`.
116 """
117 """
117 def __init__(self, ast_setup, ast_stmt):
118 def __init__(self, ast_setup, ast_stmt):
118 self.ast_setup = ast_setup
119 self.ast_setup = ast_setup
119 self.ast_stmt = ast_stmt
120 self.ast_stmt = ast_stmt
120
121
121 def visit_FunctionDef(self, node):
122 def visit_FunctionDef(self, node):
122 "Fill in the setup statement"
123 "Fill in the setup statement"
123 self.generic_visit(node)
124 self.generic_visit(node)
124 if node.name == "inner":
125 if node.name == "inner":
125 node.body[:1] = self.ast_setup.body
126 node.body[:1] = self.ast_setup.body
126
127
127 return node
128 return node
128
129
129 def visit_For(self, node):
130 def visit_For(self, node):
130 "Fill in the statement to be timed"
131 "Fill in the statement to be timed"
131 if getattr(getattr(node.body[0], 'value', None), 'id', None) == 'stmt':
132 if getattr(getattr(node.body[0], 'value', None), 'id', None) == 'stmt':
132 node.body = self.ast_stmt.body
133 node.body = self.ast_stmt.body
133 return node
134 return node
134
135
135
136
136 class Timer(timeit.Timer):
137 class Timer(timeit.Timer):
137 """Timer class that explicitly uses self.inner
138 """Timer class that explicitly uses self.inner
138
139
139 which is an undocumented implementation detail of CPython,
140 which is an undocumented implementation detail of CPython,
140 not shared by PyPy.
141 not shared by PyPy.
141 """
142 """
142 # Timer.timeit copied from CPython 3.4.2
143 # Timer.timeit copied from CPython 3.4.2
143 def timeit(self, number=timeit.default_number):
144 def timeit(self, number=timeit.default_number):
144 """Time 'number' executions of the main statement.
145 """Time 'number' executions of the main statement.
145
146
146 To be precise, this executes the setup statement once, and
147 To be precise, this executes the setup statement once, and
147 then returns the time it takes to execute the main statement
148 then returns the time it takes to execute the main statement
148 a number of times, as a float measured in seconds. The
149 a number of times, as a float measured in seconds. The
149 argument is the number of times through the loop, defaulting
150 argument is the number of times through the loop, defaulting
150 to one million. The main statement, the setup statement and
151 to one million. The main statement, the setup statement and
151 the timer function to be used are passed to the constructor.
152 the timer function to be used are passed to the constructor.
152 """
153 """
153 it = itertools.repeat(None, number)
154 it = itertools.repeat(None, number)
154 gcold = gc.isenabled()
155 gcold = gc.isenabled()
155 gc.disable()
156 gc.disable()
156 try:
157 try:
157 timing = self.inner(it, self.timer)
158 timing = self.inner(it, self.timer)
158 finally:
159 finally:
159 if gcold:
160 if gcold:
160 gc.enable()
161 gc.enable()
161 return timing
162 return timing
162
163
163
164
164 @magics_class
165 @magics_class
165 class ExecutionMagics(Magics):
166 class ExecutionMagics(Magics):
166 """Magics related to code execution, debugging, profiling, etc.
167 """Magics related to code execution, debugging, profiling, etc.
167
168
168 """
169 """
169
170
170 def __init__(self, shell):
171 def __init__(self, shell):
171 super(ExecutionMagics, self).__init__(shell)
172 super(ExecutionMagics, self).__init__(shell)
172 # Default execution function used to actually run user code.
173 # Default execution function used to actually run user code.
173 self.default_runner = None
174 self.default_runner = None
174
175
175 @skip_doctest
176 @skip_doctest
176 @no_var_expand
177 @no_var_expand
177 @line_cell_magic
178 @line_cell_magic
178 def prun(self, parameter_s='', cell=None):
179 def prun(self, parameter_s='', cell=None):
179
180
180 """Run a statement through the python code profiler.
181 """Run a statement through the python code profiler.
181
182
182 Usage, in line mode:
183 Usage, in line mode:
183 %prun [options] statement
184 %prun [options] statement
184
185
185 Usage, in cell mode:
186 Usage, in cell mode:
186 %%prun [options] [statement]
187 %%prun [options] [statement]
187 code...
188 code...
188 code...
189 code...
189
190
190 In cell mode, the additional code lines are appended to the (possibly
191 In cell mode, the additional code lines are appended to the (possibly
191 empty) statement in the first line. Cell mode allows you to easily
192 empty) statement in the first line. Cell mode allows you to easily
192 profile multiline blocks without having to put them in a separate
193 profile multiline blocks without having to put them in a separate
193 function.
194 function.
194
195
195 The given statement (which doesn't require quote marks) is run via the
196 The given statement (which doesn't require quote marks) is run via the
196 python profiler in a manner similar to the profile.run() function.
197 python profiler in a manner similar to the profile.run() function.
197 Namespaces are internally managed to work correctly; profile.run
198 Namespaces are internally managed to work correctly; profile.run
198 cannot be used in IPython because it makes certain assumptions about
199 cannot be used in IPython because it makes certain assumptions about
199 namespaces which do not hold under IPython.
200 namespaces which do not hold under IPython.
200
201
201 Options:
202 Options:
202
203
203 -l <limit>
204 -l <limit>
204 you can place restrictions on what or how much of the
205 you can place restrictions on what or how much of the
205 profile gets printed. The limit value can be:
206 profile gets printed. The limit value can be:
206
207
207 * A string: only information for function names containing this string
208 * A string: only information for function names containing this string
208 is printed.
209 is printed.
209
210
210 * An integer: only these many lines are printed.
211 * An integer: only these many lines are printed.
211
212
212 * A float (between 0 and 1): this fraction of the report is printed
213 * A float (between 0 and 1): this fraction of the report is printed
213 (for example, use a limit of 0.4 to see the topmost 40% only).
214 (for example, use a limit of 0.4 to see the topmost 40% only).
214
215
215 You can combine several limits with repeated use of the option. For
216 You can combine several limits with repeated use of the option. For
216 example, ``-l __init__ -l 5`` will print only the topmost 5 lines of
217 example, ``-l __init__ -l 5`` will print only the topmost 5 lines of
217 information about class constructors.
218 information about class constructors.
218
219
219 -r
220 -r
220 return the pstats.Stats object generated by the profiling. This
221 return the pstats.Stats object generated by the profiling. This
221 object has all the information about the profile in it, and you can
222 object has all the information about the profile in it, and you can
222 later use it for further analysis or in other functions.
223 later use it for further analysis or in other functions.
223
224
224 -s <key>
225 -s <key>
225 sort profile by given key. You can provide more than one key
226 sort profile by given key. You can provide more than one key
226 by using the option several times: '-s key1 -s key2 -s key3...'. The
227 by using the option several times: '-s key1 -s key2 -s key3...'. The
227 default sorting key is 'time'.
228 default sorting key is 'time'.
228
229
229 The following is copied verbatim from the profile documentation
230 The following is copied verbatim from the profile documentation
230 referenced below:
231 referenced below:
231
232
232 When more than one key is provided, additional keys are used as
233 When more than one key is provided, additional keys are used as
233 secondary criteria when the there is equality in all keys selected
234 secondary criteria when the there is equality in all keys selected
234 before them.
235 before them.
235
236
236 Abbreviations can be used for any key names, as long as the
237 Abbreviations can be used for any key names, as long as the
237 abbreviation is unambiguous. The following are the keys currently
238 abbreviation is unambiguous. The following are the keys currently
238 defined:
239 defined:
239
240
240 ============ =====================
241 ============ =====================
241 Valid Arg Meaning
242 Valid Arg Meaning
242 ============ =====================
243 ============ =====================
243 "calls" call count
244 "calls" call count
244 "cumulative" cumulative time
245 "cumulative" cumulative time
245 "file" file name
246 "file" file name
246 "module" file name
247 "module" file name
247 "pcalls" primitive call count
248 "pcalls" primitive call count
248 "line" line number
249 "line" line number
249 "name" function name
250 "name" function name
250 "nfl" name/file/line
251 "nfl" name/file/line
251 "stdname" standard name
252 "stdname" standard name
252 "time" internal time
253 "time" internal time
253 ============ =====================
254 ============ =====================
254
255
255 Note that all sorts on statistics are in descending order (placing
256 Note that all sorts on statistics are in descending order (placing
256 most time consuming items first), where as name, file, and line number
257 most time consuming items first), where as name, file, and line number
257 searches are in ascending order (i.e., alphabetical). The subtle
258 searches are in ascending order (i.e., alphabetical). The subtle
258 distinction between "nfl" and "stdname" is that the standard name is a
259 distinction between "nfl" and "stdname" is that the standard name is a
259 sort of the name as printed, which means that the embedded line
260 sort of the name as printed, which means that the embedded line
260 numbers get compared in an odd way. For example, lines 3, 20, and 40
261 numbers get compared in an odd way. For example, lines 3, 20, and 40
261 would (if the file names were the same) appear in the string order
262 would (if the file names were the same) appear in the string order
262 "20" "3" and "40". In contrast, "nfl" does a numeric compare of the
263 "20" "3" and "40". In contrast, "nfl" does a numeric compare of the
263 line numbers. In fact, sort_stats("nfl") is the same as
264 line numbers. In fact, sort_stats("nfl") is the same as
264 sort_stats("name", "file", "line").
265 sort_stats("name", "file", "line").
265
266
266 -T <filename>
267 -T <filename>
267 save profile results as shown on screen to a text
268 save profile results as shown on screen to a text
268 file. The profile is still shown on screen.
269 file. The profile is still shown on screen.
269
270
270 -D <filename>
271 -D <filename>
271 save (via dump_stats) profile statistics to given
272 save (via dump_stats) profile statistics to given
272 filename. This data is in a format understood by the pstats module, and
273 filename. This data is in a format understood by the pstats module, and
273 is generated by a call to the dump_stats() method of profile
274 is generated by a call to the dump_stats() method of profile
274 objects. The profile is still shown on screen.
275 objects. The profile is still shown on screen.
275
276
276 -q
277 -q
277 suppress output to the pager. Best used with -T and/or -D above.
278 suppress output to the pager. Best used with -T and/or -D above.
278
279
279 If you want to run complete programs under the profiler's control, use
280 If you want to run complete programs under the profiler's control, use
280 ``%run -p [prof_opts] filename.py [args to program]`` where prof_opts
281 ``%run -p [prof_opts] filename.py [args to program]`` where prof_opts
281 contains profiler specific options as described here.
282 contains profiler specific options as described here.
282
283
283 You can read the complete documentation for the profile module with::
284 You can read the complete documentation for the profile module with::
284
285
285 In [1]: import profile; profile.help()
286 In [1]: import profile; profile.help()
286
287
287 .. versionchanged:: 7.3
288 .. versionchanged:: 7.3
288 User variables are no longer expanded,
289 User variables are no longer expanded,
289 the magic line is always left unmodified.
290 the magic line is always left unmodified.
290
291
291 """
292 """
292 opts, arg_str = self.parse_options(parameter_s, 'D:l:rs:T:q',
293 opts, arg_str = self.parse_options(parameter_s, 'D:l:rs:T:q',
293 list_all=True, posix=False)
294 list_all=True, posix=False)
294 if cell is not None:
295 if cell is not None:
295 arg_str += '\n' + cell
296 arg_str += '\n' + cell
296 arg_str = self.shell.transform_cell(arg_str)
297 arg_str = self.shell.transform_cell(arg_str)
297 return self._run_with_profiler(arg_str, opts, self.shell.user_ns)
298 return self._run_with_profiler(arg_str, opts, self.shell.user_ns)
298
299
299 def _run_with_profiler(self, code, opts, namespace):
300 def _run_with_profiler(self, code, opts, namespace):
300 """
301 """
301 Run `code` with profiler. Used by ``%prun`` and ``%run -p``.
302 Run `code` with profiler. Used by ``%prun`` and ``%run -p``.
302
303
303 Parameters
304 Parameters
304 ----------
305 ----------
305 code : str
306 code : str
306 Code to be executed.
307 Code to be executed.
307 opts : Struct
308 opts : Struct
308 Options parsed by `self.parse_options`.
309 Options parsed by `self.parse_options`.
309 namespace : dict
310 namespace : dict
310 A dictionary for Python namespace (e.g., `self.shell.user_ns`).
311 A dictionary for Python namespace (e.g., `self.shell.user_ns`).
311
312
312 """
313 """
313
314
314 # Fill default values for unspecified options:
315 # Fill default values for unspecified options:
315 opts.merge(Struct(D=[''], l=[], s=['time'], T=['']))
316 opts.merge(Struct(D=[''], l=[], s=['time'], T=['']))
316
317
317 prof = profile.Profile()
318 prof = profile.Profile()
318 try:
319 try:
319 prof = prof.runctx(code, namespace, namespace)
320 prof = prof.runctx(code, namespace, namespace)
320 sys_exit = ''
321 sys_exit = ''
321 except SystemExit:
322 except SystemExit:
322 sys_exit = """*** SystemExit exception caught in code being profiled."""
323 sys_exit = """*** SystemExit exception caught in code being profiled."""
323
324
324 stats = pstats.Stats(prof).strip_dirs().sort_stats(*opts.s)
325 stats = pstats.Stats(prof).strip_dirs().sort_stats(*opts.s)
325
326
326 lims = opts.l
327 lims = opts.l
327 if lims:
328 if lims:
328 lims = [] # rebuild lims with ints/floats/strings
329 lims = [] # rebuild lims with ints/floats/strings
329 for lim in opts.l:
330 for lim in opts.l:
330 try:
331 try:
331 lims.append(int(lim))
332 lims.append(int(lim))
332 except ValueError:
333 except ValueError:
333 try:
334 try:
334 lims.append(float(lim))
335 lims.append(float(lim))
335 except ValueError:
336 except ValueError:
336 lims.append(lim)
337 lims.append(lim)
337
338
338 # Trap output.
339 # Trap output.
339 stdout_trap = StringIO()
340 stdout_trap = StringIO()
340 stats_stream = stats.stream
341 stats_stream = stats.stream
341 try:
342 try:
342 stats.stream = stdout_trap
343 stats.stream = stdout_trap
343 stats.print_stats(*lims)
344 stats.print_stats(*lims)
344 finally:
345 finally:
345 stats.stream = stats_stream
346 stats.stream = stats_stream
346
347
347 output = stdout_trap.getvalue()
348 output = stdout_trap.getvalue()
348 output = output.rstrip()
349 output = output.rstrip()
349
350
350 if 'q' not in opts:
351 if 'q' not in opts:
351 page.page(output)
352 page.page(output)
352 print(sys_exit, end=' ')
353 print(sys_exit, end=' ')
353
354
354 dump_file = opts.D[0]
355 dump_file = opts.D[0]
355 text_file = opts.T[0]
356 text_file = opts.T[0]
356 if dump_file:
357 if dump_file:
357 prof.dump_stats(dump_file)
358 prof.dump_stats(dump_file)
358 print(
359 print(
359 f"\n*** Profile stats marshalled to file {repr(dump_file)}.{sys_exit}"
360 f"\n*** Profile stats marshalled to file {repr(dump_file)}.{sys_exit}"
360 )
361 )
361 if text_file:
362 if text_file:
362 pfile = Path(text_file)
363 pfile = Path(text_file)
363 pfile.touch(exist_ok=True)
364 pfile.touch(exist_ok=True)
364 pfile.write_text(output, encoding="utf-8")
365 pfile.write_text(output, encoding="utf-8")
365
366
366 print(
367 print(
367 f"\n*** Profile printout saved to text file {repr(text_file)}.{sys_exit}"
368 f"\n*** Profile printout saved to text file {repr(text_file)}.{sys_exit}"
368 )
369 )
369
370
370 if 'r' in opts:
371 if 'r' in opts:
371 return stats
372 return stats
372
373
373 return None
374 return None
374
375
375 @line_magic
376 @line_magic
376 def pdb(self, parameter_s=''):
377 def pdb(self, parameter_s=''):
377 """Control the automatic calling of the pdb interactive debugger.
378 """Control the automatic calling of the pdb interactive debugger.
378
379
379 Call as '%pdb on', '%pdb 1', '%pdb off' or '%pdb 0'. If called without
380 Call as '%pdb on', '%pdb 1', '%pdb off' or '%pdb 0'. If called without
380 argument it works as a toggle.
381 argument it works as a toggle.
381
382
382 When an exception is triggered, IPython can optionally call the
383 When an exception is triggered, IPython can optionally call the
383 interactive pdb debugger after the traceback printout. %pdb toggles
384 interactive pdb debugger after the traceback printout. %pdb toggles
384 this feature on and off.
385 this feature on and off.
385
386
386 The initial state of this feature is set in your configuration
387 The initial state of this feature is set in your configuration
387 file (the option is ``InteractiveShell.pdb``).
388 file (the option is ``InteractiveShell.pdb``).
388
389
389 If you want to just activate the debugger AFTER an exception has fired,
390 If you want to just activate the debugger AFTER an exception has fired,
390 without having to type '%pdb on' and rerunning your code, you can use
391 without having to type '%pdb on' and rerunning your code, you can use
391 the %debug magic."""
392 the %debug magic."""
392
393
393 par = parameter_s.strip().lower()
394 par = parameter_s.strip().lower()
394
395
395 if par:
396 if par:
396 try:
397 try:
397 new_pdb = {'off':0,'0':0,'on':1,'1':1}[par]
398 new_pdb = {'off':0,'0':0,'on':1,'1':1}[par]
398 except KeyError:
399 except KeyError:
399 print ('Incorrect argument. Use on/1, off/0, '
400 print ('Incorrect argument. Use on/1, off/0, '
400 'or nothing for a toggle.')
401 'or nothing for a toggle.')
401 return
402 return
402 else:
403 else:
403 # toggle
404 # toggle
404 new_pdb = not self.shell.call_pdb
405 new_pdb = not self.shell.call_pdb
405
406
406 # set on the shell
407 # set on the shell
407 self.shell.call_pdb = new_pdb
408 self.shell.call_pdb = new_pdb
408 print('Automatic pdb calling has been turned',on_off(new_pdb))
409 print('Automatic pdb calling has been turned',on_off(new_pdb))
409
410
410 @magic_arguments.magic_arguments()
411 @magic_arguments.magic_arguments()
411 @magic_arguments.argument('--breakpoint', '-b', metavar='FILE:LINE',
412 @magic_arguments.argument('--breakpoint', '-b', metavar='FILE:LINE',
412 help="""
413 help="""
413 Set break point at LINE in FILE.
414 Set break point at LINE in FILE.
414 """
415 """
415 )
416 )
416 @magic_arguments.argument('statement', nargs='*',
417 @magic_arguments.argument('statement', nargs='*',
417 help="""
418 help="""
418 Code to run in debugger.
419 Code to run in debugger.
419 You can omit this in cell magic mode.
420 You can omit this in cell magic mode.
420 """
421 """
421 )
422 )
422 @no_var_expand
423 @no_var_expand
423 @line_cell_magic
424 @line_cell_magic
424 def debug(self, line='', cell=None):
425 def debug(self, line='', cell=None):
425 """Activate the interactive debugger.
426 """Activate the interactive debugger.
426
427
427 This magic command support two ways of activating debugger.
428 This magic command support two ways of activating debugger.
428 One is to activate debugger before executing code. This way, you
429 One is to activate debugger before executing code. This way, you
429 can set a break point, to step through the code from the point.
430 can set a break point, to step through the code from the point.
430 You can use this mode by giving statements to execute and optionally
431 You can use this mode by giving statements to execute and optionally
431 a breakpoint.
432 a breakpoint.
432
433
433 The other one is to activate debugger in post-mortem mode. You can
434 The other one is to activate debugger in post-mortem mode. You can
434 activate this mode simply running %debug without any argument.
435 activate this mode simply running %debug without any argument.
435 If an exception has just occurred, this lets you inspect its stack
436 If an exception has just occurred, this lets you inspect its stack
436 frames interactively. Note that this will always work only on the last
437 frames interactively. Note that this will always work only on the last
437 traceback that occurred, so you must call this quickly after an
438 traceback that occurred, so you must call this quickly after an
438 exception that you wish to inspect has fired, because if another one
439 exception that you wish to inspect has fired, because if another one
439 occurs, it clobbers the previous one.
440 occurs, it clobbers the previous one.
440
441
441 If you want IPython to automatically do this on every exception, see
442 If you want IPython to automatically do this on every exception, see
442 the %pdb magic for more details.
443 the %pdb magic for more details.
443
444
444 .. versionchanged:: 7.3
445 .. versionchanged:: 7.3
445 When running code, user variables are no longer expanded,
446 When running code, user variables are no longer expanded,
446 the magic line is always left unmodified.
447 the magic line is always left unmodified.
447
448
448 """
449 """
449 args = magic_arguments.parse_argstring(self.debug, line)
450 args = magic_arguments.parse_argstring(self.debug, line)
450
451
451 if not (args.breakpoint or args.statement or cell):
452 if not (args.breakpoint or args.statement or cell):
452 self._debug_post_mortem()
453 self._debug_post_mortem()
453 elif not (args.breakpoint or cell):
454 elif not (args.breakpoint or cell):
454 # If there is no breakpoints, the line is just code to execute
455 # If there is no breakpoints, the line is just code to execute
455 self._debug_exec(line, None)
456 self._debug_exec(line, None)
456 else:
457 else:
457 # Here we try to reconstruct the code from the output of
458 # Here we try to reconstruct the code from the output of
458 # parse_argstring. This might not work if the code has spaces
459 # parse_argstring. This might not work if the code has spaces
459 # For example this fails for `print("a b")`
460 # For example this fails for `print("a b")`
460 code = "\n".join(args.statement)
461 code = "\n".join(args.statement)
461 if cell:
462 if cell:
462 code += "\n" + cell
463 code += "\n" + cell
463 self._debug_exec(code, args.breakpoint)
464 self._debug_exec(code, args.breakpoint)
464
465
465 def _debug_post_mortem(self):
466 def _debug_post_mortem(self):
466 self.shell.debugger(force=True)
467 self.shell.debugger(force=True)
467
468
468 def _debug_exec(self, code, breakpoint):
469 def _debug_exec(self, code, breakpoint):
469 if breakpoint:
470 if breakpoint:
470 (filename, bp_line) = breakpoint.rsplit(':', 1)
471 (filename, bp_line) = breakpoint.rsplit(':', 1)
471 bp_line = int(bp_line)
472 bp_line = int(bp_line)
472 else:
473 else:
473 (filename, bp_line) = (None, None)
474 (filename, bp_line) = (None, None)
474 self._run_with_debugger(code, self.shell.user_ns, filename, bp_line)
475 self._run_with_debugger(code, self.shell.user_ns, filename, bp_line)
475
476
476 @line_magic
477 @line_magic
477 def tb(self, s):
478 def tb(self, s):
478 """Print the last traceback.
479 """Print the last traceback.
479
480
480 Optionally, specify an exception reporting mode, tuning the
481 Optionally, specify an exception reporting mode, tuning the
481 verbosity of the traceback. By default the currently-active exception
482 verbosity of the traceback. By default the currently-active exception
482 mode is used. See %xmode for changing exception reporting modes.
483 mode is used. See %xmode for changing exception reporting modes.
483
484
484 Valid modes: Plain, Context, Verbose, and Minimal.
485 Valid modes: Plain, Context, Verbose, and Minimal.
485 """
486 """
486 interactive_tb = self.shell.InteractiveTB
487 interactive_tb = self.shell.InteractiveTB
487 if s:
488 if s:
488 # Switch exception reporting mode for this one call.
489 # Switch exception reporting mode for this one call.
489 # Ensure it is switched back.
490 # Ensure it is switched back.
490 def xmode_switch_err(name):
491 def xmode_switch_err(name):
491 warn('Error changing %s exception modes.\n%s' %
492 warn('Error changing %s exception modes.\n%s' %
492 (name,sys.exc_info()[1]))
493 (name,sys.exc_info()[1]))
493
494
494 new_mode = s.strip().capitalize()
495 new_mode = s.strip().capitalize()
495 original_mode = interactive_tb.mode
496 original_mode = interactive_tb.mode
496 try:
497 try:
497 try:
498 try:
498 interactive_tb.set_mode(mode=new_mode)
499 interactive_tb.set_mode(mode=new_mode)
499 except Exception:
500 except Exception:
500 xmode_switch_err('user')
501 xmode_switch_err('user')
501 else:
502 else:
502 self.shell.showtraceback()
503 self.shell.showtraceback()
503 finally:
504 finally:
504 interactive_tb.set_mode(mode=original_mode)
505 interactive_tb.set_mode(mode=original_mode)
505 else:
506 else:
506 self.shell.showtraceback()
507 self.shell.showtraceback()
507
508
508 @skip_doctest
509 @skip_doctest
509 @line_magic
510 @line_magic
510 def run(self, parameter_s='', runner=None,
511 def run(self, parameter_s='', runner=None,
511 file_finder=get_py_filename):
512 file_finder=get_py_filename):
512 """Run the named file inside IPython as a program.
513 """Run the named file inside IPython as a program.
513
514
514 Usage::
515 Usage::
515
516
516 %run [-n -i -e -G]
517 %run [-n -i -e -G]
517 [( -t [-N<N>] | -d [-b<N>] | -p [profile options] )]
518 [( -t [-N<N>] | -d [-b<N>] | -p [profile options] )]
518 ( -m mod | filename ) [args]
519 ( -m mod | filename ) [args]
519
520
520 The filename argument should be either a pure Python script (with
521 The filename argument should be either a pure Python script (with
521 extension ``.py``), or a file with custom IPython syntax (such as
522 extension ``.py``), or a file with custom IPython syntax (such as
522 magics). If the latter, the file can be either a script with ``.ipy``
523 magics). If the latter, the file can be either a script with ``.ipy``
523 extension, or a Jupyter notebook with ``.ipynb`` extension. When running
524 extension, or a Jupyter notebook with ``.ipynb`` extension. When running
524 a Jupyter notebook, the output from print statements and other
525 a Jupyter notebook, the output from print statements and other
525 displayed objects will appear in the terminal (even matplotlib figures
526 displayed objects will appear in the terminal (even matplotlib figures
526 will open, if a terminal-compliant backend is being used). Note that,
527 will open, if a terminal-compliant backend is being used). Note that,
527 at the system command line, the ``jupyter run`` command offers similar
528 at the system command line, the ``jupyter run`` command offers similar
528 functionality for executing notebooks (albeit currently with some
529 functionality for executing notebooks (albeit currently with some
529 differences in supported options).
530 differences in supported options).
530
531
531 Parameters after the filename are passed as command-line arguments to
532 Parameters after the filename are passed as command-line arguments to
532 the program (put in sys.argv). Then, control returns to IPython's
533 the program (put in sys.argv). Then, control returns to IPython's
533 prompt.
534 prompt.
534
535
535 This is similar to running at a system prompt ``python file args``,
536 This is similar to running at a system prompt ``python file args``,
536 but with the advantage of giving you IPython's tracebacks, and of
537 but with the advantage of giving you IPython's tracebacks, and of
537 loading all variables into your interactive namespace for further use
538 loading all variables into your interactive namespace for further use
538 (unless -p is used, see below).
539 (unless -p is used, see below).
539
540
540 The file is executed in a namespace initially consisting only of
541 The file is executed in a namespace initially consisting only of
541 ``__name__=='__main__'`` and sys.argv constructed as indicated. It thus
542 ``__name__=='__main__'`` and sys.argv constructed as indicated. It thus
542 sees its environment as if it were being run as a stand-alone program
543 sees its environment as if it were being run as a stand-alone program
543 (except for sharing global objects such as previously imported
544 (except for sharing global objects such as previously imported
544 modules). But after execution, the IPython interactive namespace gets
545 modules). But after execution, the IPython interactive namespace gets
545 updated with all variables defined in the program (except for __name__
546 updated with all variables defined in the program (except for __name__
546 and sys.argv). This allows for very convenient loading of code for
547 and sys.argv). This allows for very convenient loading of code for
547 interactive work, while giving each program a 'clean sheet' to run in.
548 interactive work, while giving each program a 'clean sheet' to run in.
548
549
549 Arguments are expanded using shell-like glob match. Patterns
550 Arguments are expanded using shell-like glob match. Patterns
550 '*', '?', '[seq]' and '[!seq]' can be used. Additionally,
551 '*', '?', '[seq]' and '[!seq]' can be used. Additionally,
551 tilde '~' will be expanded into user's home directory. Unlike
552 tilde '~' will be expanded into user's home directory. Unlike
552 real shells, quotation does not suppress expansions. Use
553 real shells, quotation does not suppress expansions. Use
553 *two* back slashes (e.g. ``\\\\*``) to suppress expansions.
554 *two* back slashes (e.g. ``\\\\*``) to suppress expansions.
554 To completely disable these expansions, you can use -G flag.
555 To completely disable these expansions, you can use -G flag.
555
556
556 On Windows systems, the use of single quotes `'` when specifying
557 On Windows systems, the use of single quotes `'` when specifying
557 a file is not supported. Use double quotes `"`.
558 a file is not supported. Use double quotes `"`.
558
559
559 Options:
560 Options:
560
561
561 -n
562 -n
562 __name__ is NOT set to '__main__', but to the running file's name
563 __name__ is NOT set to '__main__', but to the running file's name
563 without extension (as python does under import). This allows running
564 without extension (as python does under import). This allows running
564 scripts and reloading the definitions in them without calling code
565 scripts and reloading the definitions in them without calling code
565 protected by an ``if __name__ == "__main__"`` clause.
566 protected by an ``if __name__ == "__main__"`` clause.
566
567
567 -i
568 -i
568 run the file in IPython's namespace instead of an empty one. This
569 run the file in IPython's namespace instead of an empty one. This
569 is useful if you are experimenting with code written in a text editor
570 is useful if you are experimenting with code written in a text editor
570 which depends on variables defined interactively.
571 which depends on variables defined interactively.
571
572
572 -e
573 -e
573 ignore sys.exit() calls or SystemExit exceptions in the script
574 ignore sys.exit() calls or SystemExit exceptions in the script
574 being run. This is particularly useful if IPython is being used to
575 being run. This is particularly useful if IPython is being used to
575 run unittests, which always exit with a sys.exit() call. In such
576 run unittests, which always exit with a sys.exit() call. In such
576 cases you are interested in the output of the test results, not in
577 cases you are interested in the output of the test results, not in
577 seeing a traceback of the unittest module.
578 seeing a traceback of the unittest module.
578
579
579 -t
580 -t
580 print timing information at the end of the run. IPython will give
581 print timing information at the end of the run. IPython will give
581 you an estimated CPU time consumption for your script, which under
582 you an estimated CPU time consumption for your script, which under
582 Unix uses the resource module to avoid the wraparound problems of
583 Unix uses the resource module to avoid the wraparound problems of
583 time.clock(). Under Unix, an estimate of time spent on system tasks
584 time.clock(). Under Unix, an estimate of time spent on system tasks
584 is also given (for Windows platforms this is reported as 0.0).
585 is also given (for Windows platforms this is reported as 0.0).
585
586
586 If -t is given, an additional ``-N<N>`` option can be given, where <N>
587 If -t is given, an additional ``-N<N>`` option can be given, where <N>
587 must be an integer indicating how many times you want the script to
588 must be an integer indicating how many times you want the script to
588 run. The final timing report will include total and per run results.
589 run. The final timing report will include total and per run results.
589
590
590 For example (testing the script uniq_stable.py)::
591 For example (testing the script uniq_stable.py)::
591
592
592 In [1]: run -t uniq_stable
593 In [1]: run -t uniq_stable
593
594
594 IPython CPU timings (estimated):
595 IPython CPU timings (estimated):
595 User : 0.19597 s.
596 User : 0.19597 s.
596 System: 0.0 s.
597 System: 0.0 s.
597
598
598 In [2]: run -t -N5 uniq_stable
599 In [2]: run -t -N5 uniq_stable
599
600
600 IPython CPU timings (estimated):
601 IPython CPU timings (estimated):
601 Total runs performed: 5
602 Total runs performed: 5
602 Times : Total Per run
603 Times : Total Per run
603 User : 0.910862 s, 0.1821724 s.
604 User : 0.910862 s, 0.1821724 s.
604 System: 0.0 s, 0.0 s.
605 System: 0.0 s, 0.0 s.
605
606
606 -d
607 -d
607 run your program under the control of pdb, the Python debugger.
608 run your program under the control of pdb, the Python debugger.
608 This allows you to execute your program step by step, watch variables,
609 This allows you to execute your program step by step, watch variables,
609 etc. Internally, what IPython does is similar to calling::
610 etc. Internally, what IPython does is similar to calling::
610
611
611 pdb.run('execfile("YOURFILENAME")')
612 pdb.run('execfile("YOURFILENAME")')
612
613
613 with a breakpoint set on line 1 of your file. You can change the line
614 with a breakpoint set on line 1 of your file. You can change the line
614 number for this automatic breakpoint to be <N> by using the -bN option
615 number for this automatic breakpoint to be <N> by using the -bN option
615 (where N must be an integer). For example::
616 (where N must be an integer). For example::
616
617
617 %run -d -b40 myscript
618 %run -d -b40 myscript
618
619
619 will set the first breakpoint at line 40 in myscript.py. Note that
620 will set the first breakpoint at line 40 in myscript.py. Note that
620 the first breakpoint must be set on a line which actually does
621 the first breakpoint must be set on a line which actually does
621 something (not a comment or docstring) for it to stop execution.
622 something (not a comment or docstring) for it to stop execution.
622
623
623 Or you can specify a breakpoint in a different file::
624 Or you can specify a breakpoint in a different file::
624
625
625 %run -d -b myotherfile.py:20 myscript
626 %run -d -b myotherfile.py:20 myscript
626
627
627 When the pdb debugger starts, you will see a (Pdb) prompt. You must
628 When the pdb debugger starts, you will see a (Pdb) prompt. You must
628 first enter 'c' (without quotes) to start execution up to the first
629 first enter 'c' (without quotes) to start execution up to the first
629 breakpoint.
630 breakpoint.
630
631
631 Entering 'help' gives information about the use of the debugger. You
632 Entering 'help' gives information about the use of the debugger. You
632 can easily see pdb's full documentation with "import pdb;pdb.help()"
633 can easily see pdb's full documentation with "import pdb;pdb.help()"
633 at a prompt.
634 at a prompt.
634
635
635 -p
636 -p
636 run program under the control of the Python profiler module (which
637 run program under the control of the Python profiler module (which
637 prints a detailed report of execution times, function calls, etc).
638 prints a detailed report of execution times, function calls, etc).
638
639
639 You can pass other options after -p which affect the behavior of the
640 You can pass other options after -p which affect the behavior of the
640 profiler itself. See the docs for %prun for details.
641 profiler itself. See the docs for %prun for details.
641
642
642 In this mode, the program's variables do NOT propagate back to the
643 In this mode, the program's variables do NOT propagate back to the
643 IPython interactive namespace (because they remain in the namespace
644 IPython interactive namespace (because they remain in the namespace
644 where the profiler executes them).
645 where the profiler executes them).
645
646
646 Internally this triggers a call to %prun, see its documentation for
647 Internally this triggers a call to %prun, see its documentation for
647 details on the options available specifically for profiling.
648 details on the options available specifically for profiling.
648
649
649 There is one special usage for which the text above doesn't apply:
650 There is one special usage for which the text above doesn't apply:
650 if the filename ends with .ipy[nb], the file is run as ipython script,
651 if the filename ends with .ipy[nb], the file is run as ipython script,
651 just as if the commands were written on IPython prompt.
652 just as if the commands were written on IPython prompt.
652
653
653 -m
654 -m
654 specify module name to load instead of script path. Similar to
655 specify module name to load instead of script path. Similar to
655 the -m option for the python interpreter. Use this option last if you
656 the -m option for the python interpreter. Use this option last if you
656 want to combine with other %run options. Unlike the python interpreter
657 want to combine with other %run options. Unlike the python interpreter
657 only source modules are allowed no .pyc or .pyo files.
658 only source modules are allowed no .pyc or .pyo files.
658 For example::
659 For example::
659
660
660 %run -m example
661 %run -m example
661
662
662 will run the example module.
663 will run the example module.
663
664
664 -G
665 -G
665 disable shell-like glob expansion of arguments.
666 disable shell-like glob expansion of arguments.
666
667
667 """
668 """
668
669
669 # Logic to handle issue #3664
670 # Logic to handle issue #3664
670 # Add '--' after '-m <module_name>' to ignore additional args passed to a module.
671 # Add '--' after '-m <module_name>' to ignore additional args passed to a module.
671 if '-m' in parameter_s and '--' not in parameter_s:
672 if '-m' in parameter_s and '--' not in parameter_s:
672 argv = shlex.split(parameter_s, posix=(os.name == 'posix'))
673 argv = shlex.split(parameter_s, posix=(os.name == 'posix'))
673 for idx, arg in enumerate(argv):
674 for idx, arg in enumerate(argv):
674 if arg and arg.startswith('-') and arg != '-':
675 if arg and arg.startswith('-') and arg != '-':
675 if arg == '-m':
676 if arg == '-m':
676 argv.insert(idx + 2, '--')
677 argv.insert(idx + 2, '--')
677 break
678 break
678 else:
679 else:
679 # Positional arg, break
680 # Positional arg, break
680 break
681 break
681 parameter_s = ' '.join(shlex.quote(arg) for arg in argv)
682 parameter_s = ' '.join(shlex.quote(arg) for arg in argv)
682
683
683 # get arguments and set sys.argv for program to be run.
684 # get arguments and set sys.argv for program to be run.
684 opts, arg_lst = self.parse_options(parameter_s,
685 opts, arg_lst = self.parse_options(parameter_s,
685 'nidtN:b:pD:l:rs:T:em:G',
686 'nidtN:b:pD:l:rs:T:em:G',
686 mode='list', list_all=1)
687 mode='list', list_all=1)
687 if "m" in opts:
688 if "m" in opts:
688 modulename = opts["m"][0]
689 modulename = opts["m"][0]
689 modpath = find_mod(modulename)
690 modpath = find_mod(modulename)
690 if modpath is None:
691 if modpath is None:
691 msg = '%r is not a valid modulename on sys.path'%modulename
692 msg = '%r is not a valid modulename on sys.path'%modulename
692 raise Exception(msg)
693 raise Exception(msg)
693 arg_lst = [modpath] + arg_lst
694 arg_lst = [modpath] + arg_lst
694 try:
695 try:
695 fpath = None # initialize to make sure fpath is in scope later
696 fpath = None # initialize to make sure fpath is in scope later
696 fpath = arg_lst[0]
697 fpath = arg_lst[0]
697 filename = file_finder(fpath)
698 filename = file_finder(fpath)
698 except IndexError as e:
699 except IndexError as e:
699 msg = 'you must provide at least a filename.'
700 msg = 'you must provide at least a filename.'
700 raise Exception(msg) from e
701 raise Exception(msg) from e
701 except IOError as e:
702 except IOError as e:
702 try:
703 try:
703 msg = str(e)
704 msg = str(e)
704 except UnicodeError:
705 except UnicodeError:
705 msg = e.message
706 msg = e.message
706 if os.name == 'nt' and re.match(r"^'.*'$",fpath):
707 if os.name == 'nt' and re.match(r"^'.*'$",fpath):
707 warn('For Windows, use double quotes to wrap a filename: %run "mypath\\myfile.py"')
708 warn('For Windows, use double quotes to wrap a filename: %run "mypath\\myfile.py"')
708 raise Exception(msg) from e
709 raise Exception(msg) from e
709 except TypeError:
710 except TypeError:
710 if fpath in sys.meta_path:
711 if fpath in sys.meta_path:
711 filename = ""
712 filename = ""
712 else:
713 else:
713 raise
714 raise
714
715
715 if filename.lower().endswith(('.ipy', '.ipynb')):
716 if filename.lower().endswith(('.ipy', '.ipynb')):
716 with preserve_keys(self.shell.user_ns, '__file__'):
717 with preserve_keys(self.shell.user_ns, '__file__'):
717 self.shell.user_ns['__file__'] = filename
718 self.shell.user_ns['__file__'] = filename
718 self.shell.safe_execfile_ipy(filename, raise_exceptions=True)
719 self.shell.safe_execfile_ipy(filename, raise_exceptions=True)
719 return
720 return
720
721
721 # Control the response to exit() calls made by the script being run
722 # Control the response to exit() calls made by the script being run
722 exit_ignore = 'e' in opts
723 exit_ignore = 'e' in opts
723
724
724 # Make sure that the running script gets a proper sys.argv as if it
725 # Make sure that the running script gets a proper sys.argv as if it
725 # were run from a system shell.
726 # were run from a system shell.
726 save_argv = sys.argv # save it for later restoring
727 save_argv = sys.argv # save it for later restoring
727
728
728 if 'G' in opts:
729 if 'G' in opts:
729 args = arg_lst[1:]
730 args = arg_lst[1:]
730 else:
731 else:
731 # tilde and glob expansion
732 # tilde and glob expansion
732 args = shellglob(map(os.path.expanduser, arg_lst[1:]))
733 args = shellglob(map(os.path.expanduser, arg_lst[1:]))
733
734
734 sys.argv = [filename] + args # put in the proper filename
735 sys.argv = [filename] + args # put in the proper filename
735
736
736 if 'n' in opts:
737 if 'n' in opts:
737 name = Path(filename).stem
738 name = Path(filename).stem
738 else:
739 else:
739 name = '__main__'
740 name = '__main__'
740
741
741 if 'i' in opts:
742 if 'i' in opts:
742 # Run in user's interactive namespace
743 # Run in user's interactive namespace
743 prog_ns = self.shell.user_ns
744 prog_ns = self.shell.user_ns
744 __name__save = self.shell.user_ns['__name__']
745 __name__save = self.shell.user_ns['__name__']
745 prog_ns['__name__'] = name
746 prog_ns['__name__'] = name
746 main_mod = self.shell.user_module
747 main_mod = self.shell.user_module
747
748
748 # Since '%run foo' emulates 'python foo.py' at the cmd line, we must
749 # Since '%run foo' emulates 'python foo.py' at the cmd line, we must
749 # set the __file__ global in the script's namespace
750 # set the __file__ global in the script's namespace
750 # TK: Is this necessary in interactive mode?
751 # TK: Is this necessary in interactive mode?
751 prog_ns['__file__'] = filename
752 prog_ns['__file__'] = filename
752 else:
753 else:
753 # Run in a fresh, empty namespace
754 # Run in a fresh, empty namespace
754
755
755 # The shell MUST hold a reference to prog_ns so after %run
756 # The shell MUST hold a reference to prog_ns so after %run
756 # exits, the python deletion mechanism doesn't zero it out
757 # exits, the python deletion mechanism doesn't zero it out
757 # (leaving dangling references). See interactiveshell for details
758 # (leaving dangling references). See interactiveshell for details
758 main_mod = self.shell.new_main_mod(filename, name)
759 main_mod = self.shell.new_main_mod(filename, name)
759 prog_ns = main_mod.__dict__
760 prog_ns = main_mod.__dict__
760
761
761 # pickle fix. See interactiveshell for an explanation. But we need to
762 # pickle fix. See interactiveshell for an explanation. But we need to
762 # make sure that, if we overwrite __main__, we replace it at the end
763 # make sure that, if we overwrite __main__, we replace it at the end
763 main_mod_name = prog_ns['__name__']
764 main_mod_name = prog_ns['__name__']
764
765
765 if main_mod_name == '__main__':
766 if main_mod_name == '__main__':
766 restore_main = sys.modules['__main__']
767 restore_main = sys.modules['__main__']
767 else:
768 else:
768 restore_main = False
769 restore_main = False
769
770
770 # This needs to be undone at the end to prevent holding references to
771 # This needs to be undone at the end to prevent holding references to
771 # every single object ever created.
772 # every single object ever created.
772 sys.modules[main_mod_name] = main_mod
773 sys.modules[main_mod_name] = main_mod
773
774
774 if 'p' in opts or 'd' in opts:
775 if 'p' in opts or 'd' in opts:
775 if 'm' in opts:
776 if 'm' in opts:
776 code = 'run_module(modulename, prog_ns)'
777 code = 'run_module(modulename, prog_ns)'
777 code_ns = {
778 code_ns = {
778 'run_module': self.shell.safe_run_module,
779 'run_module': self.shell.safe_run_module,
779 'prog_ns': prog_ns,
780 'prog_ns': prog_ns,
780 'modulename': modulename,
781 'modulename': modulename,
781 }
782 }
782 else:
783 else:
783 if 'd' in opts:
784 if 'd' in opts:
784 # allow exceptions to raise in debug mode
785 # allow exceptions to raise in debug mode
785 code = 'execfile(filename, prog_ns, raise_exceptions=True)'
786 code = 'execfile(filename, prog_ns, raise_exceptions=True)'
786 else:
787 else:
787 code = 'execfile(filename, prog_ns)'
788 code = 'execfile(filename, prog_ns)'
788 code_ns = {
789 code_ns = {
789 'execfile': self.shell.safe_execfile,
790 'execfile': self.shell.safe_execfile,
790 'prog_ns': prog_ns,
791 'prog_ns': prog_ns,
791 'filename': get_py_filename(filename),
792 'filename': get_py_filename(filename),
792 }
793 }
793
794
794 try:
795 try:
795 stats = None
796 stats = None
796 if 'p' in opts:
797 if 'p' in opts:
797 stats = self._run_with_profiler(code, opts, code_ns)
798 stats = self._run_with_profiler(code, opts, code_ns)
798 else:
799 else:
799 if 'd' in opts:
800 if 'd' in opts:
800 bp_file, bp_line = parse_breakpoint(
801 bp_file, bp_line = parse_breakpoint(
801 opts.get('b', ['1'])[0], filename)
802 opts.get('b', ['1'])[0], filename)
802 self._run_with_debugger(
803 self._run_with_debugger(
803 code, code_ns, filename, bp_line, bp_file)
804 code, code_ns, filename, bp_line, bp_file)
804 else:
805 else:
805 if 'm' in opts:
806 if 'm' in opts:
806 def run():
807 def run():
807 self.shell.safe_run_module(modulename, prog_ns)
808 self.shell.safe_run_module(modulename, prog_ns)
808 else:
809 else:
809 if runner is None:
810 if runner is None:
810 runner = self.default_runner
811 runner = self.default_runner
811 if runner is None:
812 if runner is None:
812 runner = self.shell.safe_execfile
813 runner = self.shell.safe_execfile
813
814
814 def run():
815 def run():
815 runner(filename, prog_ns, prog_ns,
816 runner(filename, prog_ns, prog_ns,
816 exit_ignore=exit_ignore)
817 exit_ignore=exit_ignore)
817
818
818 if 't' in opts:
819 if 't' in opts:
819 # timed execution
820 # timed execution
820 try:
821 try:
821 nruns = int(opts['N'][0])
822 nruns = int(opts['N'][0])
822 if nruns < 1:
823 if nruns < 1:
823 error('Number of runs must be >=1')
824 error('Number of runs must be >=1')
824 return
825 return
825 except (KeyError):
826 except (KeyError):
826 nruns = 1
827 nruns = 1
827 self._run_with_timing(run, nruns)
828 self._run_with_timing(run, nruns)
828 else:
829 else:
829 # regular execution
830 # regular execution
830 run()
831 run()
831
832
832 if 'i' in opts:
833 if 'i' in opts:
833 self.shell.user_ns['__name__'] = __name__save
834 self.shell.user_ns['__name__'] = __name__save
834 else:
835 else:
835 # update IPython interactive namespace
836 # update IPython interactive namespace
836
837
837 # Some forms of read errors on the file may mean the
838 # Some forms of read errors on the file may mean the
838 # __name__ key was never set; using pop we don't have to
839 # __name__ key was never set; using pop we don't have to
839 # worry about a possible KeyError.
840 # worry about a possible KeyError.
840 prog_ns.pop('__name__', None)
841 prog_ns.pop('__name__', None)
841
842
842 with preserve_keys(self.shell.user_ns, '__file__'):
843 with preserve_keys(self.shell.user_ns, '__file__'):
843 self.shell.user_ns.update(prog_ns)
844 self.shell.user_ns.update(prog_ns)
844 finally:
845 finally:
845 # It's a bit of a mystery why, but __builtins__ can change from
846 # It's a bit of a mystery why, but __builtins__ can change from
846 # being a module to becoming a dict missing some key data after
847 # being a module to becoming a dict missing some key data after
847 # %run. As best I can see, this is NOT something IPython is doing
848 # %run. As best I can see, this is NOT something IPython is doing
848 # at all, and similar problems have been reported before:
849 # at all, and similar problems have been reported before:
849 # http://coding.derkeiler.com/Archive/Python/comp.lang.python/2004-10/0188.html
850 # http://coding.derkeiler.com/Archive/Python/comp.lang.python/2004-10/0188.html
850 # Since this seems to be done by the interpreter itself, the best
851 # Since this seems to be done by the interpreter itself, the best
851 # we can do is to at least restore __builtins__ for the user on
852 # we can do is to at least restore __builtins__ for the user on
852 # exit.
853 # exit.
853 self.shell.user_ns['__builtins__'] = builtin_mod
854 self.shell.user_ns['__builtins__'] = builtin_mod
854
855
855 # Ensure key global structures are restored
856 # Ensure key global structures are restored
856 sys.argv = save_argv
857 sys.argv = save_argv
857 if restore_main:
858 if restore_main:
858 sys.modules['__main__'] = restore_main
859 sys.modules['__main__'] = restore_main
859 if '__mp_main__' in sys.modules:
860 if '__mp_main__' in sys.modules:
860 sys.modules['__mp_main__'] = restore_main
861 sys.modules['__mp_main__'] = restore_main
861 else:
862 else:
862 # Remove from sys.modules the reference to main_mod we'd
863 # Remove from sys.modules the reference to main_mod we'd
863 # added. Otherwise it will trap references to objects
864 # added. Otherwise it will trap references to objects
864 # contained therein.
865 # contained therein.
865 del sys.modules[main_mod_name]
866 del sys.modules[main_mod_name]
866
867
867 return stats
868 return stats
868
869
869 def _run_with_debugger(self, code, code_ns, filename=None,
870 def _run_with_debugger(self, code, code_ns, filename=None,
870 bp_line=None, bp_file=None):
871 bp_line=None, bp_file=None):
871 """
872 """
872 Run `code` in debugger with a break point.
873 Run `code` in debugger with a break point.
873
874
874 Parameters
875 Parameters
875 ----------
876 ----------
876 code : str
877 code : str
877 Code to execute.
878 Code to execute.
878 code_ns : dict
879 code_ns : dict
879 A namespace in which `code` is executed.
880 A namespace in which `code` is executed.
880 filename : str
881 filename : str
881 `code` is ran as if it is in `filename`.
882 `code` is ran as if it is in `filename`.
882 bp_line : int, optional
883 bp_line : int, optional
883 Line number of the break point.
884 Line number of the break point.
884 bp_file : str, optional
885 bp_file : str, optional
885 Path to the file in which break point is specified.
886 Path to the file in which break point is specified.
886 `filename` is used if not given.
887 `filename` is used if not given.
887
888
888 Raises
889 Raises
889 ------
890 ------
890 UsageError
891 UsageError
891 If the break point given by `bp_line` is not valid.
892 If the break point given by `bp_line` is not valid.
892
893
893 """
894 """
894 deb = self.shell.InteractiveTB.pdb
895 deb = self.shell.InteractiveTB.pdb
895 if not deb:
896 if not deb:
896 self.shell.InteractiveTB.pdb = self.shell.InteractiveTB.debugger_cls()
897 self.shell.InteractiveTB.pdb = self.shell.InteractiveTB.debugger_cls()
897 deb = self.shell.InteractiveTB.pdb
898 deb = self.shell.InteractiveTB.pdb
898
899
899 # deb.checkline() fails if deb.curframe exists but is None; it can
900 # deb.checkline() fails if deb.curframe exists but is None; it can
900 # handle it not existing. https://github.com/ipython/ipython/issues/10028
901 # handle it not existing. https://github.com/ipython/ipython/issues/10028
901 if hasattr(deb, 'curframe'):
902 if hasattr(deb, 'curframe'):
902 del deb.curframe
903 del deb.curframe
903
904
904 # reset Breakpoint state, which is moronically kept
905 # reset Breakpoint state, which is moronically kept
905 # in a class
906 # in a class
906 bdb.Breakpoint.next = 1
907 bdb.Breakpoint.next = 1
907 bdb.Breakpoint.bplist = {}
908 bdb.Breakpoint.bplist = {}
908 bdb.Breakpoint.bpbynumber = [None]
909 bdb.Breakpoint.bpbynumber = [None]
909 deb.clear_all_breaks()
910 deb.clear_all_breaks()
910 if bp_line is not None:
911 if bp_line is not None:
911 # Set an initial breakpoint to stop execution
912 # Set an initial breakpoint to stop execution
912 maxtries = 10
913 maxtries = 10
913 bp_file = bp_file or filename
914 bp_file = bp_file or filename
914 checkline = deb.checkline(bp_file, bp_line)
915 checkline = deb.checkline(bp_file, bp_line)
915 if not checkline:
916 if not checkline:
916 for bp in range(bp_line + 1, bp_line + maxtries + 1):
917 for bp in range(bp_line + 1, bp_line + maxtries + 1):
917 if deb.checkline(bp_file, bp):
918 if deb.checkline(bp_file, bp):
918 break
919 break
919 else:
920 else:
920 msg = ("\nI failed to find a valid line to set "
921 msg = ("\nI failed to find a valid line to set "
921 "a breakpoint\n"
922 "a breakpoint\n"
922 "after trying up to line: %s.\n"
923 "after trying up to line: %s.\n"
923 "Please set a valid breakpoint manually "
924 "Please set a valid breakpoint manually "
924 "with the -b option." % bp)
925 "with the -b option." % bp)
925 raise UsageError(msg)
926 raise UsageError(msg)
926 # if we find a good linenumber, set the breakpoint
927 # if we find a good linenumber, set the breakpoint
927 deb.do_break('%s:%s' % (bp_file, bp_line))
928 deb.do_break('%s:%s' % (bp_file, bp_line))
928
929
929 if filename:
930 if filename:
930 # Mimic Pdb._runscript(...)
931 # Mimic Pdb._runscript(...)
931 deb._wait_for_mainpyfile = True
932 deb._wait_for_mainpyfile = True
932 deb.mainpyfile = deb.canonic(filename)
933 deb.mainpyfile = deb.canonic(filename)
933
934
934 # Start file run
935 # Start file run
935 print("NOTE: Enter 'c' at the %s prompt to continue execution." % deb.prompt)
936 print("NOTE: Enter 'c' at the %s prompt to continue execution." % deb.prompt)
936 try:
937 try:
937 if filename:
938 if filename:
938 # save filename so it can be used by methods on the deb object
939 # save filename so it can be used by methods on the deb object
939 deb._exec_filename = filename
940 deb._exec_filename = filename
940 while True:
941 while True:
941 try:
942 try:
942 trace = sys.gettrace()
943 trace = sys.gettrace()
943 deb.run(code, code_ns)
944 deb.run(code, code_ns)
944 except Restart:
945 except Restart:
945 print("Restarting")
946 print("Restarting")
946 if filename:
947 if filename:
947 deb._wait_for_mainpyfile = True
948 deb._wait_for_mainpyfile = True
948 deb.mainpyfile = deb.canonic(filename)
949 deb.mainpyfile = deb.canonic(filename)
949 continue
950 continue
950 else:
951 else:
951 break
952 break
952 finally:
953 finally:
953 sys.settrace(trace)
954 sys.settrace(trace)
954
955
955
956
956 except:
957 except:
957 etype, value, tb = sys.exc_info()
958 etype, value, tb = sys.exc_info()
958 # Skip three frames in the traceback: the %run one,
959 # Skip three frames in the traceback: the %run one,
959 # one inside bdb.py, and the command-line typed by the
960 # one inside bdb.py, and the command-line typed by the
960 # user (run by exec in pdb itself).
961 # user (run by exec in pdb itself).
961 self.shell.InteractiveTB(etype, value, tb, tb_offset=3)
962 self.shell.InteractiveTB(etype, value, tb, tb_offset=3)
962
963
963 @staticmethod
964 @staticmethod
964 def _run_with_timing(run, nruns):
965 def _run_with_timing(run, nruns):
965 """
966 """
966 Run function `run` and print timing information.
967 Run function `run` and print timing information.
967
968
968 Parameters
969 Parameters
969 ----------
970 ----------
970 run : callable
971 run : callable
971 Any callable object which takes no argument.
972 Any callable object which takes no argument.
972 nruns : int
973 nruns : int
973 Number of times to execute `run`.
974 Number of times to execute `run`.
974
975
975 """
976 """
976 twall0 = time.perf_counter()
977 twall0 = time.perf_counter()
977 if nruns == 1:
978 if nruns == 1:
978 t0 = clock2()
979 t0 = clock2()
979 run()
980 run()
980 t1 = clock2()
981 t1 = clock2()
981 t_usr = t1[0] - t0[0]
982 t_usr = t1[0] - t0[0]
982 t_sys = t1[1] - t0[1]
983 t_sys = t1[1] - t0[1]
983 print("\nIPython CPU timings (estimated):")
984 print("\nIPython CPU timings (estimated):")
984 print(" User : %10.2f s." % t_usr)
985 print(" User : %10.2f s." % t_usr)
985 print(" System : %10.2f s." % t_sys)
986 print(" System : %10.2f s." % t_sys)
986 else:
987 else:
987 runs = range(nruns)
988 runs = range(nruns)
988 t0 = clock2()
989 t0 = clock2()
989 for nr in runs:
990 for nr in runs:
990 run()
991 run()
991 t1 = clock2()
992 t1 = clock2()
992 t_usr = t1[0] - t0[0]
993 t_usr = t1[0] - t0[0]
993 t_sys = t1[1] - t0[1]
994 t_sys = t1[1] - t0[1]
994 print("\nIPython CPU timings (estimated):")
995 print("\nIPython CPU timings (estimated):")
995 print("Total runs performed:", nruns)
996 print("Total runs performed:", nruns)
996 print(" Times : %10s %10s" % ('Total', 'Per run'))
997 print(" Times : %10s %10s" % ('Total', 'Per run'))
997 print(" User : %10.2f s, %10.2f s." % (t_usr, t_usr / nruns))
998 print(" User : %10.2f s, %10.2f s." % (t_usr, t_usr / nruns))
998 print(" System : %10.2f s, %10.2f s." % (t_sys, t_sys / nruns))
999 print(" System : %10.2f s, %10.2f s." % (t_sys, t_sys / nruns))
999 twall1 = time.perf_counter()
1000 twall1 = time.perf_counter()
1000 print("Wall time: %10.2f s." % (twall1 - twall0))
1001 print("Wall time: %10.2f s." % (twall1 - twall0))
1001
1002
1002 @skip_doctest
1003 @skip_doctest
1003 @no_var_expand
1004 @no_var_expand
1004 @line_cell_magic
1005 @line_cell_magic
1005 @needs_local_scope
1006 @needs_local_scope
1006 def timeit(self, line='', cell=None, local_ns=None):
1007 def timeit(self, line='', cell=None, local_ns=None):
1007 """Time execution of a Python statement or expression
1008 """Time execution of a Python statement or expression
1008
1009
1009 Usage, in line mode:
1010 Usage, in line mode:
1010 %timeit [-n<N> -r<R> [-t|-c] -q -p<P> -o] statement
1011 %timeit [-n<N> -r<R> [-t|-c] -q -p<P> -o] statement
1011 or in cell mode:
1012 or in cell mode:
1012 %%timeit [-n<N> -r<R> [-t|-c] -q -p<P> -o] setup_code
1013 %%timeit [-n<N> -r<R> [-t|-c] -q -p<P> -o] setup_code
1013 code
1014 code
1014 code...
1015 code...
1015
1016
1016 Time execution of a Python statement or expression using the timeit
1017 Time execution of a Python statement or expression using the timeit
1017 module. This function can be used both as a line and cell magic:
1018 module. This function can be used both as a line and cell magic:
1018
1019
1019 - In line mode you can time a single-line statement (though multiple
1020 - In line mode you can time a single-line statement (though multiple
1020 ones can be chained with using semicolons).
1021 ones can be chained with using semicolons).
1021
1022
1022 - In cell mode, the statement in the first line is used as setup code
1023 - In cell mode, the statement in the first line is used as setup code
1023 (executed but not timed) and the body of the cell is timed. The cell
1024 (executed but not timed) and the body of the cell is timed. The cell
1024 body has access to any variables created in the setup code.
1025 body has access to any variables created in the setup code.
1025
1026
1026 Options:
1027 Options:
1027 -n<N>: execute the given statement <N> times in a loop. If <N> is not
1028 -n<N>: execute the given statement <N> times in a loop. If <N> is not
1028 provided, <N> is determined so as to get sufficient accuracy.
1029 provided, <N> is determined so as to get sufficient accuracy.
1029
1030
1030 -r<R>: number of repeats <R>, each consisting of <N> loops, and take the
1031 -r<R>: number of repeats <R>, each consisting of <N> loops, and take the
1031 best result.
1032 best result.
1032 Default: 7
1033 Default: 7
1033
1034
1034 -t: use time.time to measure the time, which is the default on Unix.
1035 -t: use time.time to measure the time, which is the default on Unix.
1035 This function measures wall time.
1036 This function measures wall time.
1036
1037
1037 -c: use time.clock to measure the time, which is the default on
1038 -c: use time.clock to measure the time, which is the default on
1038 Windows and measures wall time. On Unix, resource.getrusage is used
1039 Windows and measures wall time. On Unix, resource.getrusage is used
1039 instead and returns the CPU user time.
1040 instead and returns the CPU user time.
1040
1041
1041 -p<P>: use a precision of <P> digits to display the timing result.
1042 -p<P>: use a precision of <P> digits to display the timing result.
1042 Default: 3
1043 Default: 3
1043
1044
1044 -q: Quiet, do not print result.
1045 -q: Quiet, do not print result.
1045
1046
1046 -o: return a TimeitResult that can be stored in a variable to inspect
1047 -o: return a TimeitResult that can be stored in a variable to inspect
1047 the result in more details.
1048 the result in more details.
1048
1049
1049 .. versionchanged:: 7.3
1050 .. versionchanged:: 7.3
1050 User variables are no longer expanded,
1051 User variables are no longer expanded,
1051 the magic line is always left unmodified.
1052 the magic line is always left unmodified.
1052
1053
1053 Examples
1054 Examples
1054 --------
1055 --------
1055 ::
1056 ::
1056
1057
1057 In [1]: %timeit pass
1058 In [1]: %timeit pass
1058 8.26 ns Β± 0.12 ns per loop (mean Β± std. dev. of 7 runs, 100000000 loops each)
1059 8.26 ns Β± 0.12 ns per loop (mean Β± std. dev. of 7 runs, 100000000 loops each)
1059
1060
1060 In [2]: u = None
1061 In [2]: u = None
1061
1062
1062 In [3]: %timeit u is None
1063 In [3]: %timeit u is None
1063 29.9 ns Β± 0.643 ns per loop (mean Β± std. dev. of 7 runs, 10000000 loops each)
1064 29.9 ns Β± 0.643 ns per loop (mean Β± std. dev. of 7 runs, 10000000 loops each)
1064
1065
1065 In [4]: %timeit -r 4 u == None
1066 In [4]: %timeit -r 4 u == None
1066
1067
1067 In [5]: import time
1068 In [5]: import time
1068
1069
1069 In [6]: %timeit -n1 time.sleep(2)
1070 In [6]: %timeit -n1 time.sleep(2)
1070
1071
1071 The times reported by %timeit will be slightly higher than those
1072 The times reported by %timeit will be slightly higher than those
1072 reported by the timeit.py script when variables are accessed. This is
1073 reported by the timeit.py script when variables are accessed. This is
1073 due to the fact that %timeit executes the statement in the namespace
1074 due to the fact that %timeit executes the statement in the namespace
1074 of the shell, compared with timeit.py, which uses a single setup
1075 of the shell, compared with timeit.py, which uses a single setup
1075 statement to import function or create variables. Generally, the bias
1076 statement to import function or create variables. Generally, the bias
1076 does not matter as long as results from timeit.py are not mixed with
1077 does not matter as long as results from timeit.py are not mixed with
1077 those from %timeit."""
1078 those from %timeit."""
1078
1079
1079 opts, stmt = self.parse_options(
1080 opts, stmt = self.parse_options(
1080 line, "n:r:tcp:qo", posix=False, strict=False, preserve_non_opts=True
1081 line, "n:r:tcp:qo", posix=False, strict=False, preserve_non_opts=True
1081 )
1082 )
1082 if stmt == "" and cell is None:
1083 if stmt == "" and cell is None:
1083 return
1084 return
1084
1085
1085 timefunc = timeit.default_timer
1086 timefunc = timeit.default_timer
1086 number = int(getattr(opts, "n", 0))
1087 number = int(getattr(opts, "n", 0))
1087 default_repeat = 7 if timeit.default_repeat < 7 else timeit.default_repeat
1088 default_repeat = 7 if timeit.default_repeat < 7 else timeit.default_repeat
1088 repeat = int(getattr(opts, "r", default_repeat))
1089 repeat = int(getattr(opts, "r", default_repeat))
1089 precision = int(getattr(opts, "p", 3))
1090 precision = int(getattr(opts, "p", 3))
1090 quiet = 'q' in opts
1091 quiet = 'q' in opts
1091 return_result = 'o' in opts
1092 return_result = 'o' in opts
1092 if hasattr(opts, "t"):
1093 if hasattr(opts, "t"):
1093 timefunc = time.time
1094 timefunc = time.time
1094 if hasattr(opts, "c"):
1095 if hasattr(opts, "c"):
1095 timefunc = clock
1096 timefunc = clock
1096
1097
1097 timer = Timer(timer=timefunc)
1098 timer = Timer(timer=timefunc)
1098 # this code has tight coupling to the inner workings of timeit.Timer,
1099 # this code has tight coupling to the inner workings of timeit.Timer,
1099 # but is there a better way to achieve that the code stmt has access
1100 # but is there a better way to achieve that the code stmt has access
1100 # to the shell namespace?
1101 # to the shell namespace?
1101 transform = self.shell.transform_cell
1102 transform = self.shell.transform_cell
1102
1103
1103 if cell is None:
1104 if cell is None:
1104 # called as line magic
1105 # called as line magic
1105 ast_setup = self.shell.compile.ast_parse("pass")
1106 ast_setup = self.shell.compile.ast_parse("pass")
1106 ast_stmt = self.shell.compile.ast_parse(transform(stmt))
1107 ast_stmt = self.shell.compile.ast_parse(transform(stmt))
1107 else:
1108 else:
1108 ast_setup = self.shell.compile.ast_parse(transform(stmt))
1109 ast_setup = self.shell.compile.ast_parse(transform(stmt))
1109 ast_stmt = self.shell.compile.ast_parse(transform(cell))
1110 ast_stmt = self.shell.compile.ast_parse(transform(cell))
1110
1111
1111 ast_setup = self.shell.transform_ast(ast_setup)
1112 ast_setup = self.shell.transform_ast(ast_setup)
1112 ast_stmt = self.shell.transform_ast(ast_stmt)
1113 ast_stmt = self.shell.transform_ast(ast_stmt)
1113
1114
1114 # Check that these compile to valid Python code *outside* the timer func
1115 # Check that these compile to valid Python code *outside* the timer func
1115 # Invalid code may become valid when put inside the function & loop,
1116 # Invalid code may become valid when put inside the function & loop,
1116 # which messes up error messages.
1117 # which messes up error messages.
1117 # https://github.com/ipython/ipython/issues/10636
1118 # https://github.com/ipython/ipython/issues/10636
1118 self.shell.compile(ast_setup, "<magic-timeit-setup>", "exec")
1119 self.shell.compile(ast_setup, "<magic-timeit-setup>", "exec")
1119 self.shell.compile(ast_stmt, "<magic-timeit-stmt>", "exec")
1120 self.shell.compile(ast_stmt, "<magic-timeit-stmt>", "exec")
1120
1121
1121 # This codestring is taken from timeit.template - we fill it in as an
1122 # This codestring is taken from timeit.template - we fill it in as an
1122 # AST, so that we can apply our AST transformations to the user code
1123 # AST, so that we can apply our AST transformations to the user code
1123 # without affecting the timing code.
1124 # without affecting the timing code.
1124 timeit_ast_template = ast.parse('def inner(_it, _timer):\n'
1125 timeit_ast_template = ast.parse('def inner(_it, _timer):\n'
1125 ' setup\n'
1126 ' setup\n'
1126 ' _t0 = _timer()\n'
1127 ' _t0 = _timer()\n'
1127 ' for _i in _it:\n'
1128 ' for _i in _it:\n'
1128 ' stmt\n'
1129 ' stmt\n'
1129 ' _t1 = _timer()\n'
1130 ' _t1 = _timer()\n'
1130 ' return _t1 - _t0\n')
1131 ' return _t1 - _t0\n')
1131
1132
1132 timeit_ast = TimeitTemplateFiller(ast_setup, ast_stmt).visit(timeit_ast_template)
1133 timeit_ast = TimeitTemplateFiller(ast_setup, ast_stmt).visit(timeit_ast_template)
1133 timeit_ast = ast.fix_missing_locations(timeit_ast)
1134 timeit_ast = ast.fix_missing_locations(timeit_ast)
1134
1135
1135 # Track compilation time so it can be reported if too long
1136 # Track compilation time so it can be reported if too long
1136 # Minimum time above which compilation time will be reported
1137 # Minimum time above which compilation time will be reported
1137 tc_min = 0.1
1138 tc_min = 0.1
1138
1139
1139 t0 = clock()
1140 t0 = clock()
1140 code = self.shell.compile(timeit_ast, "<magic-timeit>", "exec")
1141 code = self.shell.compile(timeit_ast, "<magic-timeit>", "exec")
1141 tc = clock()-t0
1142 tc = clock()-t0
1142
1143
1143 ns = {}
1144 ns = {}
1144 glob = self.shell.user_ns
1145 glob = self.shell.user_ns
1145 # handles global vars with same name as local vars. We store them in conflict_globs.
1146 # handles global vars with same name as local vars. We store them in conflict_globs.
1146 conflict_globs = {}
1147 conflict_globs = {}
1147 if local_ns and cell is None:
1148 if local_ns and cell is None:
1148 for var_name, var_val in glob.items():
1149 for var_name, var_val in glob.items():
1149 if var_name in local_ns:
1150 if var_name in local_ns:
1150 conflict_globs[var_name] = var_val
1151 conflict_globs[var_name] = var_val
1151 glob.update(local_ns)
1152 glob.update(local_ns)
1152
1153
1153 exec(code, glob, ns)
1154 exec(code, glob, ns)
1154 timer.inner = ns["inner"]
1155 timer.inner = ns["inner"]
1155
1156
1156 # This is used to check if there is a huge difference between the
1157 # This is used to check if there is a huge difference between the
1157 # best and worst timings.
1158 # best and worst timings.
1158 # Issue: https://github.com/ipython/ipython/issues/6471
1159 # Issue: https://github.com/ipython/ipython/issues/6471
1159 if number == 0:
1160 if number == 0:
1160 # determine number so that 0.2 <= total time < 2.0
1161 # determine number so that 0.2 <= total time < 2.0
1161 for index in range(0, 10):
1162 for index in range(0, 10):
1162 number = 10 ** index
1163 number = 10 ** index
1163 time_number = timer.timeit(number)
1164 time_number = timer.timeit(number)
1164 if time_number >= 0.2:
1165 if time_number >= 0.2:
1165 break
1166 break
1166
1167
1167 all_runs = timer.repeat(repeat, number)
1168 all_runs = timer.repeat(repeat, number)
1168 best = min(all_runs) / number
1169 best = min(all_runs) / number
1169 worst = max(all_runs) / number
1170 worst = max(all_runs) / number
1170 timeit_result = TimeitResult(number, repeat, best, worst, all_runs, tc, precision)
1171 timeit_result = TimeitResult(number, repeat, best, worst, all_runs, tc, precision)
1171
1172
1172 # Restore global vars from conflict_globs
1173 # Restore global vars from conflict_globs
1173 if conflict_globs:
1174 if conflict_globs:
1174 glob.update(conflict_globs)
1175 glob.update(conflict_globs)
1175
1176
1176 if not quiet :
1177 if not quiet :
1177 # Check best timing is greater than zero to avoid a
1178 # Check best timing is greater than zero to avoid a
1178 # ZeroDivisionError.
1179 # ZeroDivisionError.
1179 # In cases where the slowest timing is lesser than a microsecond
1180 # In cases where the slowest timing is lesser than a microsecond
1180 # we assume that it does not really matter if the fastest
1181 # we assume that it does not really matter if the fastest
1181 # timing is 4 times faster than the slowest timing or not.
1182 # timing is 4 times faster than the slowest timing or not.
1182 if worst > 4 * best and best > 0 and worst > 1e-6:
1183 if worst > 4 * best and best > 0 and worst > 1e-6:
1183 print("The slowest run took %0.2f times longer than the "
1184 print("The slowest run took %0.2f times longer than the "
1184 "fastest. This could mean that an intermediate result "
1185 "fastest. This could mean that an intermediate result "
1185 "is being cached." % (worst / best))
1186 "is being cached." % (worst / best))
1186
1187
1187 print( timeit_result )
1188 print( timeit_result )
1188
1189
1189 if tc > tc_min:
1190 if tc > tc_min:
1190 print("Compiler time: %.2f s" % tc)
1191 print("Compiler time: %.2f s" % tc)
1191 if return_result:
1192 if return_result:
1192 return timeit_result
1193 return timeit_result
1193
1194
1194 @skip_doctest
1195 @skip_doctest
1195 @no_var_expand
1196 @no_var_expand
1196 @needs_local_scope
1197 @needs_local_scope
1197 @line_cell_magic
1198 @line_cell_magic
1198 @output_can_be_silenced
1199 @output_can_be_silenced
1199 def time(self,line='', cell=None, local_ns=None):
1200 def time(self,line='', cell=None, local_ns=None):
1200 """Time execution of a Python statement or expression.
1201 """Time execution of a Python statement or expression.
1201
1202
1202 The CPU and wall clock times are printed, and the value of the
1203 The CPU and wall clock times are printed, and the value of the
1203 expression (if any) is returned. Note that under Win32, system time
1204 expression (if any) is returned. Note that under Win32, system time
1204 is always reported as 0, since it can not be measured.
1205 is always reported as 0, since it can not be measured.
1205
1206
1206 This function can be used both as a line and cell magic:
1207 This function can be used both as a line and cell magic:
1207
1208
1208 - In line mode you can time a single-line statement (though multiple
1209 - In line mode you can time a single-line statement (though multiple
1209 ones can be chained with using semicolons).
1210 ones can be chained with using semicolons).
1210
1211
1211 - In cell mode, you can time the cell body (a directly
1212 - In cell mode, you can time the cell body (a directly
1212 following statement raises an error).
1213 following statement raises an error).
1213
1214
1214 This function provides very basic timing functionality. Use the timeit
1215 This function provides very basic timing functionality. Use the timeit
1215 magic for more control over the measurement.
1216 magic for more control over the measurement.
1216
1217
1217 .. versionchanged:: 7.3
1218 .. versionchanged:: 7.3
1218 User variables are no longer expanded,
1219 User variables are no longer expanded,
1219 the magic line is always left unmodified.
1220 the magic line is always left unmodified.
1220
1221
1221 Examples
1222 Examples
1222 --------
1223 --------
1223 ::
1224 ::
1224
1225
1225 In [1]: %time 2**128
1226 In [1]: %time 2**128
1226 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1227 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1227 Wall time: 0.00
1228 Wall time: 0.00
1228 Out[1]: 340282366920938463463374607431768211456L
1229 Out[1]: 340282366920938463463374607431768211456L
1229
1230
1230 In [2]: n = 1000000
1231 In [2]: n = 1000000
1231
1232
1232 In [3]: %time sum(range(n))
1233 In [3]: %time sum(range(n))
1233 CPU times: user 1.20 s, sys: 0.05 s, total: 1.25 s
1234 CPU times: user 1.20 s, sys: 0.05 s, total: 1.25 s
1234 Wall time: 1.37
1235 Wall time: 1.37
1235 Out[3]: 499999500000L
1236 Out[3]: 499999500000L
1236
1237
1237 In [4]: %time print 'hello world'
1238 In [4]: %time print 'hello world'
1238 hello world
1239 hello world
1239 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1240 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1240 Wall time: 0.00
1241 Wall time: 0.00
1241
1242
1242 .. note::
1243 .. note::
1243 The time needed by Python to compile the given expression will be
1244 The time needed by Python to compile the given expression will be
1244 reported if it is more than 0.1s.
1245 reported if it is more than 0.1s.
1245
1246
1246 In the example below, the actual exponentiation is done by Python
1247 In the example below, the actual exponentiation is done by Python
1247 at compilation time, so while the expression can take a noticeable
1248 at compilation time, so while the expression can take a noticeable
1248 amount of time to compute, that time is purely due to the
1249 amount of time to compute, that time is purely due to the
1249 compilation::
1250 compilation::
1250
1251
1251 In [5]: %time 3**9999;
1252 In [5]: %time 3**9999;
1252 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1253 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1253 Wall time: 0.00 s
1254 Wall time: 0.00 s
1254
1255
1255 In [6]: %time 3**999999;
1256 In [6]: %time 3**999999;
1256 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1257 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1257 Wall time: 0.00 s
1258 Wall time: 0.00 s
1258 Compiler : 0.78 s
1259 Compiler : 0.78 s
1259 """
1260 """
1260 # fail immediately if the given expression can't be compiled
1261 # fail immediately if the given expression can't be compiled
1261
1262
1262 if line and cell:
1263 if line and cell:
1263 raise UsageError("Can't use statement directly after '%%time'!")
1264 raise UsageError("Can't use statement directly after '%%time'!")
1264
1265
1265 if cell:
1266 if cell:
1266 expr = self.shell.transform_cell(cell)
1267 expr = self.shell.transform_cell(cell)
1267 else:
1268 else:
1268 expr = self.shell.transform_cell(line)
1269 expr = self.shell.transform_cell(line)
1269
1270
1270 # Minimum time above which parse time will be reported
1271 # Minimum time above which parse time will be reported
1271 tp_min = 0.1
1272 tp_min = 0.1
1272
1273
1273 t0 = clock()
1274 t0 = clock()
1274 expr_ast = self.shell.compile.ast_parse(expr)
1275 expr_ast = self.shell.compile.ast_parse(expr)
1275 tp = clock()-t0
1276 tp = clock()-t0
1276
1277
1277 # Apply AST transformations
1278 # Apply AST transformations
1278 expr_ast = self.shell.transform_ast(expr_ast)
1279 expr_ast = self.shell.transform_ast(expr_ast)
1279
1280
1280 # Minimum time above which compilation time will be reported
1281 # Minimum time above which compilation time will be reported
1281 tc_min = 0.1
1282 tc_min = 0.1
1282
1283
1283 expr_val=None
1284 expr_val=None
1284 if len(expr_ast.body)==1 and isinstance(expr_ast.body[0], ast.Expr):
1285 if len(expr_ast.body)==1 and isinstance(expr_ast.body[0], ast.Expr):
1285 mode = 'eval'
1286 mode = 'eval'
1286 source = '<timed eval>'
1287 source = '<timed eval>'
1287 expr_ast = ast.Expression(expr_ast.body[0].value)
1288 expr_ast = ast.Expression(expr_ast.body[0].value)
1288 else:
1289 else:
1289 mode = 'exec'
1290 mode = 'exec'
1290 source = '<timed exec>'
1291 source = '<timed exec>'
1291 # multi-line %%time case
1292 # multi-line %%time case
1292 if len(expr_ast.body) > 1 and isinstance(expr_ast.body[-1], ast.Expr):
1293 if len(expr_ast.body) > 1 and isinstance(expr_ast.body[-1], ast.Expr):
1293 expr_val= expr_ast.body[-1]
1294 expr_val= expr_ast.body[-1]
1294 expr_ast = expr_ast.body[:-1]
1295 expr_ast = expr_ast.body[:-1]
1295 expr_ast = Module(expr_ast, [])
1296 expr_ast = Module(expr_ast, [])
1296 expr_val = ast.Expression(expr_val.value)
1297 expr_val = ast.Expression(expr_val.value)
1297
1298
1298 t0 = clock()
1299 t0 = clock()
1299 code = self.shell.compile(expr_ast, source, mode)
1300 code = self.shell.compile(expr_ast, source, mode)
1300 tc = clock()-t0
1301 tc = clock()-t0
1301
1302
1302 # skew measurement as little as possible
1303 # skew measurement as little as possible
1303 glob = self.shell.user_ns
1304 glob = self.shell.user_ns
1304 wtime = time.time
1305 wtime = time.time
1305 # time execution
1306 # time execution
1306 wall_st = wtime()
1307 wall_st = wtime()
1307 if mode=='eval':
1308 if mode=='eval':
1308 st = clock2()
1309 st = clock2()
1309 try:
1310 try:
1310 out = eval(code, glob, local_ns)
1311 out = eval(code, glob, local_ns)
1311 except:
1312 except:
1312 self.shell.showtraceback()
1313 self.shell.showtraceback()
1313 return
1314 return
1314 end = clock2()
1315 end = clock2()
1315 else:
1316 else:
1316 st = clock2()
1317 st = clock2()
1317 try:
1318 try:
1318 exec(code, glob, local_ns)
1319 exec(code, glob, local_ns)
1319 out=None
1320 out=None
1320 # multi-line %%time case
1321 # multi-line %%time case
1321 if expr_val is not None:
1322 if expr_val is not None:
1322 code_2 = self.shell.compile(expr_val, source, 'eval')
1323 code_2 = self.shell.compile(expr_val, source, 'eval')
1323 out = eval(code_2, glob, local_ns)
1324 out = eval(code_2, glob, local_ns)
1324 except:
1325 except:
1325 self.shell.showtraceback()
1326 self.shell.showtraceback()
1326 return
1327 return
1327 end = clock2()
1328 end = clock2()
1328
1329
1329 wall_end = wtime()
1330 wall_end = wtime()
1330 # Compute actual times and report
1331 # Compute actual times and report
1331 wall_time = wall_end - wall_st
1332 wall_time = wall_end - wall_st
1332 cpu_user = end[0] - st[0]
1333 cpu_user = end[0] - st[0]
1333 cpu_sys = end[1] - st[1]
1334 cpu_sys = end[1] - st[1]
1334 cpu_tot = cpu_user + cpu_sys
1335 cpu_tot = cpu_user + cpu_sys
1335 # On windows cpu_sys is always zero, so only total is displayed
1336 # On windows cpu_sys is always zero, so only total is displayed
1336 if sys.platform != "win32":
1337 if sys.platform != "win32":
1337 print(
1338 print(
1338 f"CPU times: user {_format_time(cpu_user)}, sys: {_format_time(cpu_sys)}, total: {_format_time(cpu_tot)}"
1339 f"CPU times: user {_format_time(cpu_user)}, sys: {_format_time(cpu_sys)}, total: {_format_time(cpu_tot)}"
1339 )
1340 )
1340 else:
1341 else:
1341 print(f"CPU times: total: {_format_time(cpu_tot)}")
1342 print(f"CPU times: total: {_format_time(cpu_tot)}")
1342 print(f"Wall time: {_format_time(wall_time)}")
1343 print(f"Wall time: {_format_time(wall_time)}")
1343 if tc > tc_min:
1344 if tc > tc_min:
1344 print(f"Compiler : {_format_time(tc)}")
1345 print(f"Compiler : {_format_time(tc)}")
1345 if tp > tp_min:
1346 if tp > tp_min:
1346 print(f"Parser : {_format_time(tp)}")
1347 print(f"Parser : {_format_time(tp)}")
1347 return out
1348 return out
1348
1349
1349 @skip_doctest
1350 @skip_doctest
1350 @line_magic
1351 @line_magic
1351 def macro(self, parameter_s=''):
1352 def macro(self, parameter_s=''):
1352 """Define a macro for future re-execution. It accepts ranges of history,
1353 """Define a macro for future re-execution. It accepts ranges of history,
1353 filenames or string objects.
1354 filenames or string objects.
1354
1355
1355 Usage:\\
1356 Usage:\\
1356 %macro [options] name n1-n2 n3-n4 ... n5 .. n6 ...
1357 %macro [options] name n1-n2 n3-n4 ... n5 .. n6 ...
1357
1358
1358 Options:
1359 Options:
1359
1360
1360 -r: use 'raw' input. By default, the 'processed' history is used,
1361 -r: use 'raw' input. By default, the 'processed' history is used,
1361 so that magics are loaded in their transformed version to valid
1362 so that magics are loaded in their transformed version to valid
1362 Python. If this option is given, the raw input as typed at the
1363 Python. If this option is given, the raw input as typed at the
1363 command line is used instead.
1364 command line is used instead.
1364
1365
1365 -q: quiet macro definition. By default, a tag line is printed
1366 -q: quiet macro definition. By default, a tag line is printed
1366 to indicate the macro has been created, and then the contents of
1367 to indicate the macro has been created, and then the contents of
1367 the macro are printed. If this option is given, then no printout
1368 the macro are printed. If this option is given, then no printout
1368 is produced once the macro is created.
1369 is produced once the macro is created.
1369
1370
1370 This will define a global variable called `name` which is a string
1371 This will define a global variable called `name` which is a string
1371 made of joining the slices and lines you specify (n1,n2,... numbers
1372 made of joining the slices and lines you specify (n1,n2,... numbers
1372 above) from your input history into a single string. This variable
1373 above) from your input history into a single string. This variable
1373 acts like an automatic function which re-executes those lines as if
1374 acts like an automatic function which re-executes those lines as if
1374 you had typed them. You just type 'name' at the prompt and the code
1375 you had typed them. You just type 'name' at the prompt and the code
1375 executes.
1376 executes.
1376
1377
1377 The syntax for indicating input ranges is described in %history.
1378 The syntax for indicating input ranges is described in %history.
1378
1379
1379 Note: as a 'hidden' feature, you can also use traditional python slice
1380 Note: as a 'hidden' feature, you can also use traditional python slice
1380 notation, where N:M means numbers N through M-1.
1381 notation, where N:M means numbers N through M-1.
1381
1382
1382 For example, if your history contains (print using %hist -n )::
1383 For example, if your history contains (print using %hist -n )::
1383
1384
1384 44: x=1
1385 44: x=1
1385 45: y=3
1386 45: y=3
1386 46: z=x+y
1387 46: z=x+y
1387 47: print x
1388 47: print x
1388 48: a=5
1389 48: a=5
1389 49: print 'x',x,'y',y
1390 49: print 'x',x,'y',y
1390
1391
1391 you can create a macro with lines 44 through 47 (included) and line 49
1392 you can create a macro with lines 44 through 47 (included) and line 49
1392 called my_macro with::
1393 called my_macro with::
1393
1394
1394 In [55]: %macro my_macro 44-47 49
1395 In [55]: %macro my_macro 44-47 49
1395
1396
1396 Now, typing `my_macro` (without quotes) will re-execute all this code
1397 Now, typing `my_macro` (without quotes) will re-execute all this code
1397 in one pass.
1398 in one pass.
1398
1399
1399 You don't need to give the line-numbers in order, and any given line
1400 You don't need to give the line-numbers in order, and any given line
1400 number can appear multiple times. You can assemble macros with any
1401 number can appear multiple times. You can assemble macros with any
1401 lines from your input history in any order.
1402 lines from your input history in any order.
1402
1403
1403 The macro is a simple object which holds its value in an attribute,
1404 The macro is a simple object which holds its value in an attribute,
1404 but IPython's display system checks for macros and executes them as
1405 but IPython's display system checks for macros and executes them as
1405 code instead of printing them when you type their name.
1406 code instead of printing them when you type their name.
1406
1407
1407 You can view a macro's contents by explicitly printing it with::
1408 You can view a macro's contents by explicitly printing it with::
1408
1409
1409 print macro_name
1410 print macro_name
1410
1411
1411 """
1412 """
1412 opts,args = self.parse_options(parameter_s,'rq',mode='list')
1413 opts,args = self.parse_options(parameter_s,'rq',mode='list')
1413 if not args: # List existing macros
1414 if not args: # List existing macros
1414 return sorted(k for k,v in self.shell.user_ns.items() if isinstance(v, Macro))
1415 return sorted(k for k,v in self.shell.user_ns.items() if isinstance(v, Macro))
1415 if len(args) == 1:
1416 if len(args) == 1:
1416 raise UsageError(
1417 raise UsageError(
1417 "%macro insufficient args; usage '%macro name n1-n2 n3-4...")
1418 "%macro insufficient args; usage '%macro name n1-n2 n3-4...")
1418 name, codefrom = args[0], " ".join(args[1:])
1419 name, codefrom = args[0], " ".join(args[1:])
1419
1420
1420 #print 'rng',ranges # dbg
1421 #print 'rng',ranges # dbg
1421 try:
1422 try:
1422 lines = self.shell.find_user_code(codefrom, 'r' in opts)
1423 lines = self.shell.find_user_code(codefrom, 'r' in opts)
1423 except (ValueError, TypeError) as e:
1424 except (ValueError, TypeError) as e:
1424 print(e.args[0])
1425 print(e.args[0])
1425 return
1426 return
1426 macro = Macro(lines)
1427 macro = Macro(lines)
1427 self.shell.define_macro(name, macro)
1428 self.shell.define_macro(name, macro)
1428 if not ( 'q' in opts) :
1429 if not ( 'q' in opts) :
1429 print('Macro `%s` created. To execute, type its name (without quotes).' % name)
1430 print('Macro `%s` created. To execute, type its name (without quotes).' % name)
1430 print('=== Macro contents: ===')
1431 print('=== Macro contents: ===')
1431 print(macro, end=' ')
1432 print(macro, end=' ')
1432
1433
1433 @magic_arguments.magic_arguments()
1434 @magic_arguments.magic_arguments()
1434 @magic_arguments.argument('output', type=str, default='', nargs='?',
1435 @magic_arguments.argument('output', type=str, default='', nargs='?',
1435 help="""The name of the variable in which to store output.
1436 help="""The name of the variable in which to store output.
1436 This is a utils.io.CapturedIO object with stdout/err attributes
1437 This is a utils.io.CapturedIO object with stdout/err attributes
1437 for the text of the captured output.
1438 for the text of the captured output.
1438
1439
1439 CapturedOutput also has a show() method for displaying the output,
1440 CapturedOutput also has a show() method for displaying the output,
1440 and __call__ as well, so you can use that to quickly display the
1441 and __call__ as well, so you can use that to quickly display the
1441 output.
1442 output.
1442
1443
1443 If unspecified, captured output is discarded.
1444 If unspecified, captured output is discarded.
1444 """
1445 """
1445 )
1446 )
1446 @magic_arguments.argument('--no-stderr', action="store_true",
1447 @magic_arguments.argument('--no-stderr', action="store_true",
1447 help="""Don't capture stderr."""
1448 help="""Don't capture stderr."""
1448 )
1449 )
1449 @magic_arguments.argument('--no-stdout', action="store_true",
1450 @magic_arguments.argument('--no-stdout', action="store_true",
1450 help="""Don't capture stdout."""
1451 help="""Don't capture stdout."""
1451 )
1452 )
1452 @magic_arguments.argument('--no-display', action="store_true",
1453 @magic_arguments.argument('--no-display', action="store_true",
1453 help="""Don't capture IPython's rich display."""
1454 help="""Don't capture IPython's rich display."""
1454 )
1455 )
1455 @cell_magic
1456 @cell_magic
1456 def capture(self, line, cell):
1457 def capture(self, line, cell):
1457 """run the cell, capturing stdout, stderr, and IPython's rich display() calls."""
1458 """run the cell, capturing stdout, stderr, and IPython's rich display() calls."""
1458 args = magic_arguments.parse_argstring(self.capture, line)
1459 args = magic_arguments.parse_argstring(self.capture, line)
1459 out = not args.no_stdout
1460 out = not args.no_stdout
1460 err = not args.no_stderr
1461 err = not args.no_stderr
1461 disp = not args.no_display
1462 disp = not args.no_display
1462 with capture_output(out, err, disp) as io:
1463 with capture_output(out, err, disp) as io:
1463 self.shell.run_cell(cell)
1464 self.shell.run_cell(cell)
1464 if args.output:
1465 if DisplayHook.semicolon_at_end_of_expression(cell):
1466 if args.output in self.shell.user_ns:
1467 del self.shell.user_ns[args.output]
1468 elif args.output:
1465 self.shell.user_ns[args.output] = io
1469 self.shell.user_ns[args.output] = io
1466
1470
1467 def parse_breakpoint(text, current_file):
1471 def parse_breakpoint(text, current_file):
1468 '''Returns (file, line) for file:line and (current_file, line) for line'''
1472 '''Returns (file, line) for file:line and (current_file, line) for line'''
1469 colon = text.find(':')
1473 colon = text.find(':')
1470 if colon == -1:
1474 if colon == -1:
1471 return current_file, int(text)
1475 return current_file, int(text)
1472 else:
1476 else:
1473 return text[:colon], int(text[colon+1:])
1477 return text[:colon], int(text[colon+1:])
1474
1478
1475 def _format_time(timespan, precision=3):
1479 def _format_time(timespan, precision=3):
1476 """Formats the timespan in a human readable form"""
1480 """Formats the timespan in a human readable form"""
1477
1481
1478 if timespan >= 60.0:
1482 if timespan >= 60.0:
1479 # we have more than a minute, format that in a human readable form
1483 # we have more than a minute, format that in a human readable form
1480 # Idea from http://snipplr.com/view/5713/
1484 # Idea from http://snipplr.com/view/5713/
1481 parts = [("d", 60*60*24),("h", 60*60),("min", 60), ("s", 1)]
1485 parts = [("d", 60*60*24),("h", 60*60),("min", 60), ("s", 1)]
1482 time = []
1486 time = []
1483 leftover = timespan
1487 leftover = timespan
1484 for suffix, length in parts:
1488 for suffix, length in parts:
1485 value = int(leftover / length)
1489 value = int(leftover / length)
1486 if value > 0:
1490 if value > 0:
1487 leftover = leftover % length
1491 leftover = leftover % length
1488 time.append(u'%s%s' % (str(value), suffix))
1492 time.append(u'%s%s' % (str(value), suffix))
1489 if leftover < 1:
1493 if leftover < 1:
1490 break
1494 break
1491 return " ".join(time)
1495 return " ".join(time)
1492
1496
1493
1497
1494 # Unfortunately the unicode 'micro' symbol can cause problems in
1498 # Unfortunately the unicode 'micro' symbol can cause problems in
1495 # certain terminals.
1499 # certain terminals.
1496 # See bug: https://bugs.launchpad.net/ipython/+bug/348466
1500 # See bug: https://bugs.launchpad.net/ipython/+bug/348466
1497 # Try to prevent crashes by being more secure than it needs to
1501 # Try to prevent crashes by being more secure than it needs to
1498 # E.g. eclipse is able to print a Β΅, but has no sys.stdout.encoding set.
1502 # E.g. eclipse is able to print a Β΅, but has no sys.stdout.encoding set.
1499 units = [u"s", u"ms",u'us',"ns"] # the save value
1503 units = [u"s", u"ms",u'us',"ns"] # the save value
1500 if hasattr(sys.stdout, 'encoding') and sys.stdout.encoding:
1504 if hasattr(sys.stdout, 'encoding') and sys.stdout.encoding:
1501 try:
1505 try:
1502 u'\xb5'.encode(sys.stdout.encoding)
1506 u'\xb5'.encode(sys.stdout.encoding)
1503 units = [u"s", u"ms",u'\xb5s',"ns"]
1507 units = [u"s", u"ms",u'\xb5s',"ns"]
1504 except:
1508 except:
1505 pass
1509 pass
1506 scaling = [1, 1e3, 1e6, 1e9]
1510 scaling = [1, 1e3, 1e6, 1e9]
1507
1511
1508 if timespan > 0.0:
1512 if timespan > 0.0:
1509 order = min(-int(math.floor(math.log10(timespan)) // 3), 3)
1513 order = min(-int(math.floor(math.log10(timespan)) // 3), 3)
1510 else:
1514 else:
1511 order = 3
1515 order = 3
1512 return u"%.*g %s" % (precision, timespan * scaling[order], units[order])
1516 return u"%.*g %s" % (precision, timespan * scaling[order], units[order])
@@ -1,1512 +1,1531 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Tests for various magic functions."""
2 """Tests for various magic functions."""
3
3
4 import gc
4 import gc
5 import io
5 import io
6 import os
6 import os
7 import re
7 import re
8 import shlex
8 import shlex
9 import sys
9 import sys
10 import warnings
10 import warnings
11 from importlib import invalidate_caches
11 from importlib import invalidate_caches
12 from io import StringIO
12 from io import StringIO
13 from pathlib import Path
13 from pathlib import Path
14 from textwrap import dedent
14 from textwrap import dedent
15 from unittest import TestCase, mock
15 from unittest import TestCase, mock
16
16
17 import pytest
17 import pytest
18
18
19 from IPython import get_ipython
19 from IPython import get_ipython
20 from IPython.core import magic
20 from IPython.core import magic
21 from IPython.core.error import UsageError
21 from IPython.core.error import UsageError
22 from IPython.core.magic import (
22 from IPython.core.magic import (
23 Magics,
23 Magics,
24 cell_magic,
24 cell_magic,
25 line_magic,
25 line_magic,
26 magics_class,
26 magics_class,
27 register_cell_magic,
27 register_cell_magic,
28 register_line_magic,
28 register_line_magic,
29 )
29 )
30 from IPython.core.magics import code, execution, logging, osm, script
30 from IPython.core.magics import code, execution, logging, osm, script
31 from IPython.testing import decorators as dec
31 from IPython.testing import decorators as dec
32 from IPython.testing import tools as tt
32 from IPython.testing import tools as tt
33 from IPython.utils.io import capture_output
33 from IPython.utils.io import capture_output
34 from IPython.utils.process import find_cmd
34 from IPython.utils.process import find_cmd
35 from IPython.utils.tempdir import TemporaryDirectory, TemporaryWorkingDirectory
35 from IPython.utils.tempdir import TemporaryDirectory, TemporaryWorkingDirectory
36 from IPython.utils.syspathcontext import prepended_to_syspath
36 from IPython.utils.syspathcontext import prepended_to_syspath
37
37
38 from .test_debugger import PdbTestInput
38 from .test_debugger import PdbTestInput
39
39
40 from tempfile import NamedTemporaryFile
40 from tempfile import NamedTemporaryFile
41
41
42 @magic.magics_class
42 @magic.magics_class
43 class DummyMagics(magic.Magics): pass
43 class DummyMagics(magic.Magics): pass
44
44
45 def test_extract_code_ranges():
45 def test_extract_code_ranges():
46 instr = "1 3 5-6 7-9 10:15 17: :10 10- -13 :"
46 instr = "1 3 5-6 7-9 10:15 17: :10 10- -13 :"
47 expected = [
47 expected = [
48 (0, 1),
48 (0, 1),
49 (2, 3),
49 (2, 3),
50 (4, 6),
50 (4, 6),
51 (6, 9),
51 (6, 9),
52 (9, 14),
52 (9, 14),
53 (16, None),
53 (16, None),
54 (None, 9),
54 (None, 9),
55 (9, None),
55 (9, None),
56 (None, 13),
56 (None, 13),
57 (None, None),
57 (None, None),
58 ]
58 ]
59 actual = list(code.extract_code_ranges(instr))
59 actual = list(code.extract_code_ranges(instr))
60 assert actual == expected
60 assert actual == expected
61
61
62 def test_extract_symbols():
62 def test_extract_symbols():
63 source = """import foo\na = 10\ndef b():\n return 42\n\n\nclass A: pass\n\n\n"""
63 source = """import foo\na = 10\ndef b():\n return 42\n\n\nclass A: pass\n\n\n"""
64 symbols_args = ["a", "b", "A", "A,b", "A,a", "z"]
64 symbols_args = ["a", "b", "A", "A,b", "A,a", "z"]
65 expected = [([], ['a']),
65 expected = [([], ['a']),
66 (["def b():\n return 42\n"], []),
66 (["def b():\n return 42\n"], []),
67 (["class A: pass\n"], []),
67 (["class A: pass\n"], []),
68 (["class A: pass\n", "def b():\n return 42\n"], []),
68 (["class A: pass\n", "def b():\n return 42\n"], []),
69 (["class A: pass\n"], ['a']),
69 (["class A: pass\n"], ['a']),
70 ([], ['z'])]
70 ([], ['z'])]
71 for symbols, exp in zip(symbols_args, expected):
71 for symbols, exp in zip(symbols_args, expected):
72 assert code.extract_symbols(source, symbols) == exp
72 assert code.extract_symbols(source, symbols) == exp
73
73
74
74
75 def test_extract_symbols_raises_exception_with_non_python_code():
75 def test_extract_symbols_raises_exception_with_non_python_code():
76 source = ("=begin A Ruby program :)=end\n"
76 source = ("=begin A Ruby program :)=end\n"
77 "def hello\n"
77 "def hello\n"
78 "puts 'Hello world'\n"
78 "puts 'Hello world'\n"
79 "end")
79 "end")
80 with pytest.raises(SyntaxError):
80 with pytest.raises(SyntaxError):
81 code.extract_symbols(source, "hello")
81 code.extract_symbols(source, "hello")
82
82
83
83
84 def test_magic_not_found():
84 def test_magic_not_found():
85 # magic not found raises UsageError
85 # magic not found raises UsageError
86 with pytest.raises(UsageError):
86 with pytest.raises(UsageError):
87 _ip.run_line_magic("doesntexist", "")
87 _ip.run_line_magic("doesntexist", "")
88
88
89 # ensure result isn't success when a magic isn't found
89 # ensure result isn't success when a magic isn't found
90 result = _ip.run_cell('%doesntexist')
90 result = _ip.run_cell('%doesntexist')
91 assert isinstance(result.error_in_exec, UsageError)
91 assert isinstance(result.error_in_exec, UsageError)
92
92
93
93
94 def test_cell_magic_not_found():
94 def test_cell_magic_not_found():
95 # magic not found raises UsageError
95 # magic not found raises UsageError
96 with pytest.raises(UsageError):
96 with pytest.raises(UsageError):
97 _ip.run_cell_magic('doesntexist', 'line', 'cell')
97 _ip.run_cell_magic('doesntexist', 'line', 'cell')
98
98
99 # ensure result isn't success when a magic isn't found
99 # ensure result isn't success when a magic isn't found
100 result = _ip.run_cell('%%doesntexist')
100 result = _ip.run_cell('%%doesntexist')
101 assert isinstance(result.error_in_exec, UsageError)
101 assert isinstance(result.error_in_exec, UsageError)
102
102
103
103
104 def test_magic_error_status():
104 def test_magic_error_status():
105 def fail(shell):
105 def fail(shell):
106 1/0
106 1/0
107 _ip.register_magic_function(fail)
107 _ip.register_magic_function(fail)
108 result = _ip.run_cell('%fail')
108 result = _ip.run_cell('%fail')
109 assert isinstance(result.error_in_exec, ZeroDivisionError)
109 assert isinstance(result.error_in_exec, ZeroDivisionError)
110
110
111
111
112 def test_config():
112 def test_config():
113 """ test that config magic does not raise
113 """ test that config magic does not raise
114 can happen if Configurable init is moved too early into
114 can happen if Configurable init is moved too early into
115 Magics.__init__ as then a Config object will be registered as a
115 Magics.__init__ as then a Config object will be registered as a
116 magic.
116 magic.
117 """
117 """
118 ## should not raise.
118 ## should not raise.
119 _ip.run_line_magic("config", "")
119 _ip.run_line_magic("config", "")
120
120
121
121
122 def test_config_available_configs():
122 def test_config_available_configs():
123 """ test that config magic prints available configs in unique and
123 """ test that config magic prints available configs in unique and
124 sorted order. """
124 sorted order. """
125 with capture_output() as captured:
125 with capture_output() as captured:
126 _ip.run_line_magic("config", "")
126 _ip.run_line_magic("config", "")
127
127
128 stdout = captured.stdout
128 stdout = captured.stdout
129 config_classes = stdout.strip().split('\n')[1:]
129 config_classes = stdout.strip().split('\n')[1:]
130 assert config_classes == sorted(set(config_classes))
130 assert config_classes == sorted(set(config_classes))
131
131
132 def test_config_print_class():
132 def test_config_print_class():
133 """ test that config with a classname prints the class's options. """
133 """ test that config with a classname prints the class's options. """
134 with capture_output() as captured:
134 with capture_output() as captured:
135 _ip.run_line_magic("config", "TerminalInteractiveShell")
135 _ip.run_line_magic("config", "TerminalInteractiveShell")
136
136
137 stdout = captured.stdout
137 stdout = captured.stdout
138 assert re.match(
138 assert re.match(
139 "TerminalInteractiveShell.* options", stdout.splitlines()[0]
139 "TerminalInteractiveShell.* options", stdout.splitlines()[0]
140 ), f"{stdout}\n\n1st line of stdout not like 'TerminalInteractiveShell.* options'"
140 ), f"{stdout}\n\n1st line of stdout not like 'TerminalInteractiveShell.* options'"
141
141
142
142
143 def test_rehashx():
143 def test_rehashx():
144 # clear up everything
144 # clear up everything
145 _ip.alias_manager.clear_aliases()
145 _ip.alias_manager.clear_aliases()
146 del _ip.db['syscmdlist']
146 del _ip.db['syscmdlist']
147
147
148 _ip.run_line_magic("rehashx", "")
148 _ip.run_line_magic("rehashx", "")
149 # Practically ALL ipython development systems will have more than 10 aliases
149 # Practically ALL ipython development systems will have more than 10 aliases
150
150
151 assert len(_ip.alias_manager.aliases) > 10
151 assert len(_ip.alias_manager.aliases) > 10
152 for name, cmd in _ip.alias_manager.aliases:
152 for name, cmd in _ip.alias_manager.aliases:
153 # we must strip dots from alias names
153 # we must strip dots from alias names
154 assert "." not in name
154 assert "." not in name
155
155
156 # rehashx must fill up syscmdlist
156 # rehashx must fill up syscmdlist
157 scoms = _ip.db['syscmdlist']
157 scoms = _ip.db['syscmdlist']
158 assert len(scoms) > 10
158 assert len(scoms) > 10
159
159
160
160
161 def test_magic_parse_options():
161 def test_magic_parse_options():
162 """Test that we don't mangle paths when parsing magic options."""
162 """Test that we don't mangle paths when parsing magic options."""
163 ip = get_ipython()
163 ip = get_ipython()
164 path = 'c:\\x'
164 path = 'c:\\x'
165 m = DummyMagics(ip)
165 m = DummyMagics(ip)
166 opts = m.parse_options('-f %s' % path,'f:')[0]
166 opts = m.parse_options('-f %s' % path,'f:')[0]
167 # argv splitting is os-dependent
167 # argv splitting is os-dependent
168 if os.name == 'posix':
168 if os.name == 'posix':
169 expected = 'c:x'
169 expected = 'c:x'
170 else:
170 else:
171 expected = path
171 expected = path
172 assert opts["f"] == expected
172 assert opts["f"] == expected
173
173
174
174
175 def test_magic_parse_long_options():
175 def test_magic_parse_long_options():
176 """Magic.parse_options can handle --foo=bar long options"""
176 """Magic.parse_options can handle --foo=bar long options"""
177 ip = get_ipython()
177 ip = get_ipython()
178 m = DummyMagics(ip)
178 m = DummyMagics(ip)
179 opts, _ = m.parse_options("--foo --bar=bubble", "a", "foo", "bar=")
179 opts, _ = m.parse_options("--foo --bar=bubble", "a", "foo", "bar=")
180 assert "foo" in opts
180 assert "foo" in opts
181 assert "bar" in opts
181 assert "bar" in opts
182 assert opts["bar"] == "bubble"
182 assert opts["bar"] == "bubble"
183
183
184
184
185 def doctest_hist_f():
185 def doctest_hist_f():
186 """Test %hist -f with temporary filename.
186 """Test %hist -f with temporary filename.
187
187
188 In [9]: import tempfile
188 In [9]: import tempfile
189
189
190 In [10]: tfile = tempfile.mktemp('.py','tmp-ipython-')
190 In [10]: tfile = tempfile.mktemp('.py','tmp-ipython-')
191
191
192 In [11]: %hist -nl -f $tfile 3
192 In [11]: %hist -nl -f $tfile 3
193
193
194 In [13]: import os; os.unlink(tfile)
194 In [13]: import os; os.unlink(tfile)
195 """
195 """
196
196
197
197
198 def doctest_hist_op():
198 def doctest_hist_op():
199 """Test %hist -op
199 """Test %hist -op
200
200
201 In [1]: class b(float):
201 In [1]: class b(float):
202 ...: pass
202 ...: pass
203 ...:
203 ...:
204
204
205 In [2]: class s(object):
205 In [2]: class s(object):
206 ...: def __str__(self):
206 ...: def __str__(self):
207 ...: return 's'
207 ...: return 's'
208 ...:
208 ...:
209
209
210 In [3]:
210 In [3]:
211
211
212 In [4]: class r(b):
212 In [4]: class r(b):
213 ...: def __repr__(self):
213 ...: def __repr__(self):
214 ...: return 'r'
214 ...: return 'r'
215 ...:
215 ...:
216
216
217 In [5]: class sr(s,r): pass
217 In [5]: class sr(s,r): pass
218 ...:
218 ...:
219
219
220 In [6]:
220 In [6]:
221
221
222 In [7]: bb=b()
222 In [7]: bb=b()
223
223
224 In [8]: ss=s()
224 In [8]: ss=s()
225
225
226 In [9]: rr=r()
226 In [9]: rr=r()
227
227
228 In [10]: ssrr=sr()
228 In [10]: ssrr=sr()
229
229
230 In [11]: 4.5
230 In [11]: 4.5
231 Out[11]: 4.5
231 Out[11]: 4.5
232
232
233 In [12]: str(ss)
233 In [12]: str(ss)
234 Out[12]: 's'
234 Out[12]: 's'
235
235
236 In [13]:
236 In [13]:
237
237
238 In [14]: %hist -op
238 In [14]: %hist -op
239 >>> class b:
239 >>> class b:
240 ... pass
240 ... pass
241 ...
241 ...
242 >>> class s(b):
242 >>> class s(b):
243 ... def __str__(self):
243 ... def __str__(self):
244 ... return 's'
244 ... return 's'
245 ...
245 ...
246 >>>
246 >>>
247 >>> class r(b):
247 >>> class r(b):
248 ... def __repr__(self):
248 ... def __repr__(self):
249 ... return 'r'
249 ... return 'r'
250 ...
250 ...
251 >>> class sr(s,r): pass
251 >>> class sr(s,r): pass
252 >>>
252 >>>
253 >>> bb=b()
253 >>> bb=b()
254 >>> ss=s()
254 >>> ss=s()
255 >>> rr=r()
255 >>> rr=r()
256 >>> ssrr=sr()
256 >>> ssrr=sr()
257 >>> 4.5
257 >>> 4.5
258 4.5
258 4.5
259 >>> str(ss)
259 >>> str(ss)
260 's'
260 's'
261 >>>
261 >>>
262 """
262 """
263
263
264 def test_hist_pof():
264 def test_hist_pof():
265 ip = get_ipython()
265 ip = get_ipython()
266 ip.run_cell("1+2", store_history=True)
266 ip.run_cell("1+2", store_history=True)
267 #raise Exception(ip.history_manager.session_number)
267 #raise Exception(ip.history_manager.session_number)
268 #raise Exception(list(ip.history_manager._get_range_session()))
268 #raise Exception(list(ip.history_manager._get_range_session()))
269 with TemporaryDirectory() as td:
269 with TemporaryDirectory() as td:
270 tf = os.path.join(td, 'hist.py')
270 tf = os.path.join(td, 'hist.py')
271 ip.run_line_magic('history', '-pof %s' % tf)
271 ip.run_line_magic('history', '-pof %s' % tf)
272 assert os.path.isfile(tf)
272 assert os.path.isfile(tf)
273
273
274
274
275 def test_macro():
275 def test_macro():
276 ip = get_ipython()
276 ip = get_ipython()
277 ip.history_manager.reset() # Clear any existing history.
277 ip.history_manager.reset() # Clear any existing history.
278 cmds = ["a=1", "def b():\n return a**2", "print(a,b())"]
278 cmds = ["a=1", "def b():\n return a**2", "print(a,b())"]
279 for i, cmd in enumerate(cmds, start=1):
279 for i, cmd in enumerate(cmds, start=1):
280 ip.history_manager.store_inputs(i, cmd)
280 ip.history_manager.store_inputs(i, cmd)
281 ip.run_line_magic("macro", "test 1-3")
281 ip.run_line_magic("macro", "test 1-3")
282 assert ip.user_ns["test"].value == "\n".join(cmds) + "\n"
282 assert ip.user_ns["test"].value == "\n".join(cmds) + "\n"
283
283
284 # List macros
284 # List macros
285 assert "test" in ip.run_line_magic("macro", "")
285 assert "test" in ip.run_line_magic("macro", "")
286
286
287
287
288 def test_macro_run():
288 def test_macro_run():
289 """Test that we can run a multi-line macro successfully."""
289 """Test that we can run a multi-line macro successfully."""
290 ip = get_ipython()
290 ip = get_ipython()
291 ip.history_manager.reset()
291 ip.history_manager.reset()
292 cmds = ["a=10", "a+=1", "print(a)", "%macro test 2-3"]
292 cmds = ["a=10", "a+=1", "print(a)", "%macro test 2-3"]
293 for cmd in cmds:
293 for cmd in cmds:
294 ip.run_cell(cmd, store_history=True)
294 ip.run_cell(cmd, store_history=True)
295 assert ip.user_ns["test"].value == "a+=1\nprint(a)\n"
295 assert ip.user_ns["test"].value == "a+=1\nprint(a)\n"
296 with tt.AssertPrints("12"):
296 with tt.AssertPrints("12"):
297 ip.run_cell("test")
297 ip.run_cell("test")
298 with tt.AssertPrints("13"):
298 with tt.AssertPrints("13"):
299 ip.run_cell("test")
299 ip.run_cell("test")
300
300
301
301
302 def test_magic_magic():
302 def test_magic_magic():
303 """Test %magic"""
303 """Test %magic"""
304 ip = get_ipython()
304 ip = get_ipython()
305 with capture_output() as captured:
305 with capture_output() as captured:
306 ip.run_line_magic("magic", "")
306 ip.run_line_magic("magic", "")
307
307
308 stdout = captured.stdout
308 stdout = captured.stdout
309 assert "%magic" in stdout
309 assert "%magic" in stdout
310 assert "IPython" in stdout
310 assert "IPython" in stdout
311 assert "Available" in stdout
311 assert "Available" in stdout
312
312
313
313
314 @dec.skipif_not_numpy
314 @dec.skipif_not_numpy
315 def test_numpy_reset_array_undec():
315 def test_numpy_reset_array_undec():
316 "Test '%reset array' functionality"
316 "Test '%reset array' functionality"
317 _ip.ex("import numpy as np")
317 _ip.ex("import numpy as np")
318 _ip.ex("a = np.empty(2)")
318 _ip.ex("a = np.empty(2)")
319 assert "a" in _ip.user_ns
319 assert "a" in _ip.user_ns
320 _ip.run_line_magic("reset", "-f array")
320 _ip.run_line_magic("reset", "-f array")
321 assert "a" not in _ip.user_ns
321 assert "a" not in _ip.user_ns
322
322
323
323
324 def test_reset_out():
324 def test_reset_out():
325 "Test '%reset out' magic"
325 "Test '%reset out' magic"
326 _ip.run_cell("parrot = 'dead'", store_history=True)
326 _ip.run_cell("parrot = 'dead'", store_history=True)
327 # test '%reset -f out', make an Out prompt
327 # test '%reset -f out', make an Out prompt
328 _ip.run_cell("parrot", store_history=True)
328 _ip.run_cell("parrot", store_history=True)
329 assert "dead" in [_ip.user_ns[x] for x in ("_", "__", "___")]
329 assert "dead" in [_ip.user_ns[x] for x in ("_", "__", "___")]
330 _ip.run_line_magic("reset", "-f out")
330 _ip.run_line_magic("reset", "-f out")
331 assert "dead" not in [_ip.user_ns[x] for x in ("_", "__", "___")]
331 assert "dead" not in [_ip.user_ns[x] for x in ("_", "__", "___")]
332 assert len(_ip.user_ns["Out"]) == 0
332 assert len(_ip.user_ns["Out"]) == 0
333
333
334
334
335 def test_reset_in():
335 def test_reset_in():
336 "Test '%reset in' magic"
336 "Test '%reset in' magic"
337 # test '%reset -f in'
337 # test '%reset -f in'
338 _ip.run_cell("parrot", store_history=True)
338 _ip.run_cell("parrot", store_history=True)
339 assert "parrot" in [_ip.user_ns[x] for x in ("_i", "_ii", "_iii")]
339 assert "parrot" in [_ip.user_ns[x] for x in ("_i", "_ii", "_iii")]
340 _ip.run_line_magic("reset", "-f in")
340 _ip.run_line_magic("reset", "-f in")
341 assert "parrot" not in [_ip.user_ns[x] for x in ("_i", "_ii", "_iii")]
341 assert "parrot" not in [_ip.user_ns[x] for x in ("_i", "_ii", "_iii")]
342 assert len(set(_ip.user_ns["In"])) == 1
342 assert len(set(_ip.user_ns["In"])) == 1
343
343
344
344
345 def test_reset_dhist():
345 def test_reset_dhist():
346 "Test '%reset dhist' magic"
346 "Test '%reset dhist' magic"
347 _ip.run_cell("tmp = [d for d in _dh]") # copy before clearing
347 _ip.run_cell("tmp = [d for d in _dh]") # copy before clearing
348 _ip.run_line_magic("cd", os.path.dirname(pytest.__file__))
348 _ip.run_line_magic("cd", os.path.dirname(pytest.__file__))
349 _ip.run_line_magic("cd", "-")
349 _ip.run_line_magic("cd", "-")
350 assert len(_ip.user_ns["_dh"]) > 0
350 assert len(_ip.user_ns["_dh"]) > 0
351 _ip.run_line_magic("reset", "-f dhist")
351 _ip.run_line_magic("reset", "-f dhist")
352 assert len(_ip.user_ns["_dh"]) == 0
352 assert len(_ip.user_ns["_dh"]) == 0
353 _ip.run_cell("_dh = [d for d in tmp]") # restore
353 _ip.run_cell("_dh = [d for d in tmp]") # restore
354
354
355
355
356 def test_reset_in_length():
356 def test_reset_in_length():
357 "Test that '%reset in' preserves In[] length"
357 "Test that '%reset in' preserves In[] length"
358 _ip.run_cell("print 'foo'")
358 _ip.run_cell("print 'foo'")
359 _ip.run_cell("reset -f in")
359 _ip.run_cell("reset -f in")
360 assert len(_ip.user_ns["In"]) == _ip.displayhook.prompt_count + 1
360 assert len(_ip.user_ns["In"]) == _ip.displayhook.prompt_count + 1
361
361
362
362
363 class TestResetErrors(TestCase):
363 class TestResetErrors(TestCase):
364
364
365 def test_reset_redefine(self):
365 def test_reset_redefine(self):
366
366
367 @magics_class
367 @magics_class
368 class KernelMagics(Magics):
368 class KernelMagics(Magics):
369 @line_magic
369 @line_magic
370 def less(self, shell): pass
370 def less(self, shell): pass
371
371
372 _ip.register_magics(KernelMagics)
372 _ip.register_magics(KernelMagics)
373
373
374 with self.assertLogs() as cm:
374 with self.assertLogs() as cm:
375 # hack, we want to just capture logs, but assertLogs fails if not
375 # hack, we want to just capture logs, but assertLogs fails if not
376 # logs get produce.
376 # logs get produce.
377 # so log one things we ignore.
377 # so log one things we ignore.
378 import logging as log_mod
378 import logging as log_mod
379 log = log_mod.getLogger()
379 log = log_mod.getLogger()
380 log.info('Nothing')
380 log.info('Nothing')
381 # end hack.
381 # end hack.
382 _ip.run_cell("reset -f")
382 _ip.run_cell("reset -f")
383
383
384 assert len(cm.output) == 1
384 assert len(cm.output) == 1
385 for out in cm.output:
385 for out in cm.output:
386 assert "Invalid alias" not in out
386 assert "Invalid alias" not in out
387
387
388 def test_tb_syntaxerror():
388 def test_tb_syntaxerror():
389 """test %tb after a SyntaxError"""
389 """test %tb after a SyntaxError"""
390 ip = get_ipython()
390 ip = get_ipython()
391 ip.run_cell("for")
391 ip.run_cell("for")
392
392
393 # trap and validate stdout
393 # trap and validate stdout
394 save_stdout = sys.stdout
394 save_stdout = sys.stdout
395 try:
395 try:
396 sys.stdout = StringIO()
396 sys.stdout = StringIO()
397 ip.run_cell("%tb")
397 ip.run_cell("%tb")
398 out = sys.stdout.getvalue()
398 out = sys.stdout.getvalue()
399 finally:
399 finally:
400 sys.stdout = save_stdout
400 sys.stdout = save_stdout
401 # trim output, and only check the last line
401 # trim output, and only check the last line
402 last_line = out.rstrip().splitlines()[-1].strip()
402 last_line = out.rstrip().splitlines()[-1].strip()
403 assert last_line == "SyntaxError: invalid syntax"
403 assert last_line == "SyntaxError: invalid syntax"
404
404
405
405
406 def test_time():
406 def test_time():
407 ip = get_ipython()
407 ip = get_ipython()
408
408
409 with tt.AssertPrints("Wall time: "):
409 with tt.AssertPrints("Wall time: "):
410 ip.run_cell("%time None")
410 ip.run_cell("%time None")
411
411
412 ip.run_cell("def f(kmjy):\n"
412 ip.run_cell("def f(kmjy):\n"
413 " %time print (2*kmjy)")
413 " %time print (2*kmjy)")
414
414
415 with tt.AssertPrints("Wall time: "):
415 with tt.AssertPrints("Wall time: "):
416 with tt.AssertPrints("hihi", suppress=False):
416 with tt.AssertPrints("hihi", suppress=False):
417 ip.run_cell("f('hi')")
417 ip.run_cell("f('hi')")
418
418
419
419
420 # ';' at the end of %time prevents instruction value to be printed.
420 # ';' at the end of %time prevents instruction value to be printed.
421 # This tests fix for #13837.
421 # This tests fix for #13837.
422 def test_time_no_output_with_semicolon():
422 def test_time_no_output_with_semicolon():
423 ip = get_ipython()
423 ip = get_ipython()
424
424
425 # Test %time cases
425 # Test %time cases
426 with tt.AssertPrints(" 123456"):
426 with tt.AssertPrints(" 123456"):
427 with tt.AssertPrints("Wall time: ", suppress=False):
427 with tt.AssertPrints("Wall time: ", suppress=False):
428 with tt.AssertPrints("CPU times: ", suppress=False):
428 with tt.AssertPrints("CPU times: ", suppress=False):
429 ip.run_cell("%time 123000+456")
429 ip.run_cell("%time 123000+456")
430
430
431 with tt.AssertNotPrints(" 123456"):
431 with tt.AssertNotPrints(" 123456"):
432 with tt.AssertPrints("Wall time: ", suppress=False):
432 with tt.AssertPrints("Wall time: ", suppress=False):
433 with tt.AssertPrints("CPU times: ", suppress=False):
433 with tt.AssertPrints("CPU times: ", suppress=False):
434 ip.run_cell("%time 123000+456;")
434 ip.run_cell("%time 123000+456;")
435
435
436 with tt.AssertPrints(" 123456"):
436 with tt.AssertPrints(" 123456"):
437 with tt.AssertPrints("Wall time: ", suppress=False):
437 with tt.AssertPrints("Wall time: ", suppress=False):
438 with tt.AssertPrints("CPU times: ", suppress=False):
438 with tt.AssertPrints("CPU times: ", suppress=False):
439 ip.run_cell("%time 123000+456 # Comment")
439 ip.run_cell("%time 123000+456 # Comment")
440
440
441 with tt.AssertNotPrints(" 123456"):
441 with tt.AssertNotPrints(" 123456"):
442 with tt.AssertPrints("Wall time: ", suppress=False):
442 with tt.AssertPrints("Wall time: ", suppress=False):
443 with tt.AssertPrints("CPU times: ", suppress=False):
443 with tt.AssertPrints("CPU times: ", suppress=False):
444 ip.run_cell("%time 123000+456; # Comment")
444 ip.run_cell("%time 123000+456; # Comment")
445
445
446 with tt.AssertPrints(" 123456"):
446 with tt.AssertPrints(" 123456"):
447 with tt.AssertPrints("Wall time: ", suppress=False):
447 with tt.AssertPrints("Wall time: ", suppress=False):
448 with tt.AssertPrints("CPU times: ", suppress=False):
448 with tt.AssertPrints("CPU times: ", suppress=False):
449 ip.run_cell("%time 123000+456 # ;Comment")
449 ip.run_cell("%time 123000+456 # ;Comment")
450
450
451 # Test %%time cases
451 # Test %%time cases
452 with tt.AssertPrints("123456"):
452 with tt.AssertPrints("123456"):
453 with tt.AssertPrints("Wall time: ", suppress=False):
453 with tt.AssertPrints("Wall time: ", suppress=False):
454 with tt.AssertPrints("CPU times: ", suppress=False):
454 with tt.AssertPrints("CPU times: ", suppress=False):
455 ip.run_cell("%%time\n123000+456\n\n\n")
455 ip.run_cell("%%time\n123000+456\n\n\n")
456
456
457 with tt.AssertNotPrints("123456"):
457 with tt.AssertNotPrints("123456"):
458 with tt.AssertPrints("Wall time: ", suppress=False):
458 with tt.AssertPrints("Wall time: ", suppress=False):
459 with tt.AssertPrints("CPU times: ", suppress=False):
459 with tt.AssertPrints("CPU times: ", suppress=False):
460 ip.run_cell("%%time\n123000+456;\n\n\n")
460 ip.run_cell("%%time\n123000+456;\n\n\n")
461
461
462 with tt.AssertPrints("123456"):
462 with tt.AssertPrints("123456"):
463 with tt.AssertPrints("Wall time: ", suppress=False):
463 with tt.AssertPrints("Wall time: ", suppress=False):
464 with tt.AssertPrints("CPU times: ", suppress=False):
464 with tt.AssertPrints("CPU times: ", suppress=False):
465 ip.run_cell("%%time\n123000+456 # Comment\n\n\n")
465 ip.run_cell("%%time\n123000+456 # Comment\n\n\n")
466
466
467 with tt.AssertNotPrints("123456"):
467 with tt.AssertNotPrints("123456"):
468 with tt.AssertPrints("Wall time: ", suppress=False):
468 with tt.AssertPrints("Wall time: ", suppress=False):
469 with tt.AssertPrints("CPU times: ", suppress=False):
469 with tt.AssertPrints("CPU times: ", suppress=False):
470 ip.run_cell("%%time\n123000+456; # Comment\n\n\n")
470 ip.run_cell("%%time\n123000+456; # Comment\n\n\n")
471
471
472 with tt.AssertPrints("123456"):
472 with tt.AssertPrints("123456"):
473 with tt.AssertPrints("Wall time: ", suppress=False):
473 with tt.AssertPrints("Wall time: ", suppress=False):
474 with tt.AssertPrints("CPU times: ", suppress=False):
474 with tt.AssertPrints("CPU times: ", suppress=False):
475 ip.run_cell("%%time\n123000+456 # ;Comment\n\n\n")
475 ip.run_cell("%%time\n123000+456 # ;Comment\n\n\n")
476
476
477
477
478 def test_time_last_not_expression():
478 def test_time_last_not_expression():
479 ip.run_cell("%%time\n"
479 ip.run_cell("%%time\n"
480 "var_1 = 1\n"
480 "var_1 = 1\n"
481 "var_2 = 2\n")
481 "var_2 = 2\n")
482 assert ip.user_ns['var_1'] == 1
482 assert ip.user_ns['var_1'] == 1
483 del ip.user_ns['var_1']
483 del ip.user_ns['var_1']
484 assert ip.user_ns['var_2'] == 2
484 assert ip.user_ns['var_2'] == 2
485 del ip.user_ns['var_2']
485 del ip.user_ns['var_2']
486
486
487
487
488 @dec.skip_win32
488 @dec.skip_win32
489 def test_time2():
489 def test_time2():
490 ip = get_ipython()
490 ip = get_ipython()
491
491
492 with tt.AssertPrints("CPU times: user "):
492 with tt.AssertPrints("CPU times: user "):
493 ip.run_cell("%time None")
493 ip.run_cell("%time None")
494
494
495 def test_time3():
495 def test_time3():
496 """Erroneous magic function calls, issue gh-3334"""
496 """Erroneous magic function calls, issue gh-3334"""
497 ip = get_ipython()
497 ip = get_ipython()
498 ip.user_ns.pop('run', None)
498 ip.user_ns.pop('run', None)
499
499
500 with tt.AssertNotPrints("not found", channel='stderr'):
500 with tt.AssertNotPrints("not found", channel='stderr'):
501 ip.run_cell("%%time\n"
501 ip.run_cell("%%time\n"
502 "run = 0\n"
502 "run = 0\n"
503 "run += 1")
503 "run += 1")
504
504
505 def test_multiline_time():
505 def test_multiline_time():
506 """Make sure last statement from time return a value."""
506 """Make sure last statement from time return a value."""
507 ip = get_ipython()
507 ip = get_ipython()
508 ip.user_ns.pop('run', None)
508 ip.user_ns.pop('run', None)
509
509
510 ip.run_cell(
510 ip.run_cell(
511 dedent(
511 dedent(
512 """\
512 """\
513 %%time
513 %%time
514 a = "ho"
514 a = "ho"
515 b = "hey"
515 b = "hey"
516 a+b
516 a+b
517 """
517 """
518 )
518 )
519 )
519 )
520 assert ip.user_ns_hidden["_"] == "hohey"
520 assert ip.user_ns_hidden["_"] == "hohey"
521
521
522
522
523 def test_time_local_ns():
523 def test_time_local_ns():
524 """
524 """
525 Test that local_ns is actually global_ns when running a cell magic
525 Test that local_ns is actually global_ns when running a cell magic
526 """
526 """
527 ip = get_ipython()
527 ip = get_ipython()
528 ip.run_cell("%%time\n" "myvar = 1")
528 ip.run_cell("%%time\n" "myvar = 1")
529 assert ip.user_ns["myvar"] == 1
529 assert ip.user_ns["myvar"] == 1
530 del ip.user_ns["myvar"]
530 del ip.user_ns["myvar"]
531
531
532
532
533 # Test %%capture magic. Added to test issue #13926
534 def test_capture():
535 ip = get_ipython()
536
537 # Test %%capture nominal case
538 ip.run_cell("%%capture abc\n1+2")
539 with tt.AssertPrints("True", suppress=False):
540 ip.run_cell("'abc' in locals()")
541 with tt.AssertPrints("True", suppress=False):
542 ip.run_cell("'outputs' in dir(abc)")
543 with tt.AssertPrints("3", suppress=False):
544 ip.run_cell("abc.outputs[0]")
545
546 # Test %%capture with ';' at end of expression
547 ip.run_cell("%%capture abc\n7+8;")
548 with tt.AssertPrints("False", suppress=False):
549 ip.run_cell("'abc' in locals()")
550
551
533 def test_doctest_mode():
552 def test_doctest_mode():
534 "Toggle doctest_mode twice, it should be a no-op and run without error"
553 "Toggle doctest_mode twice, it should be a no-op and run without error"
535 _ip.run_line_magic("doctest_mode", "")
554 _ip.run_line_magic("doctest_mode", "")
536 _ip.run_line_magic("doctest_mode", "")
555 _ip.run_line_magic("doctest_mode", "")
537
556
538
557
539 def test_parse_options():
558 def test_parse_options():
540 """Tests for basic options parsing in magics."""
559 """Tests for basic options parsing in magics."""
541 # These are only the most minimal of tests, more should be added later. At
560 # These are only the most minimal of tests, more should be added later. At
542 # the very least we check that basic text/unicode calls work OK.
561 # the very least we check that basic text/unicode calls work OK.
543 m = DummyMagics(_ip)
562 m = DummyMagics(_ip)
544 assert m.parse_options("foo", "")[1] == "foo"
563 assert m.parse_options("foo", "")[1] == "foo"
545 assert m.parse_options("foo", "")[1] == "foo"
564 assert m.parse_options("foo", "")[1] == "foo"
546
565
547
566
548 def test_parse_options_preserve_non_option_string():
567 def test_parse_options_preserve_non_option_string():
549 """Test to assert preservation of non-option part of magic-block, while parsing magic options."""
568 """Test to assert preservation of non-option part of magic-block, while parsing magic options."""
550 m = DummyMagics(_ip)
569 m = DummyMagics(_ip)
551 opts, stmt = m.parse_options(
570 opts, stmt = m.parse_options(
552 " -n1 -r 13 _ = 314 + foo", "n:r:", preserve_non_opts=True
571 " -n1 -r 13 _ = 314 + foo", "n:r:", preserve_non_opts=True
553 )
572 )
554 assert opts == {"n": "1", "r": "13"}
573 assert opts == {"n": "1", "r": "13"}
555 assert stmt == "_ = 314 + foo"
574 assert stmt == "_ = 314 + foo"
556
575
557
576
558 def test_run_magic_preserve_code_block():
577 def test_run_magic_preserve_code_block():
559 """Test to assert preservation of non-option part of magic-block, while running magic."""
578 """Test to assert preservation of non-option part of magic-block, while running magic."""
560 _ip.user_ns["spaces"] = []
579 _ip.user_ns["spaces"] = []
561 _ip.run_line_magic(
580 _ip.run_line_magic(
562 "timeit", "-n1 -r1 spaces.append([s.count(' ') for s in ['document']])"
581 "timeit", "-n1 -r1 spaces.append([s.count(' ') for s in ['document']])"
563 )
582 )
564 assert _ip.user_ns["spaces"] == [[0]]
583 assert _ip.user_ns["spaces"] == [[0]]
565
584
566
585
567 def test_dirops():
586 def test_dirops():
568 """Test various directory handling operations."""
587 """Test various directory handling operations."""
569 # curpath = lambda :os.path.splitdrive(os.getcwd())[1].replace('\\','/')
588 # curpath = lambda :os.path.splitdrive(os.getcwd())[1].replace('\\','/')
570 curpath = os.getcwd
589 curpath = os.getcwd
571 startdir = os.getcwd()
590 startdir = os.getcwd()
572 ipdir = os.path.realpath(_ip.ipython_dir)
591 ipdir = os.path.realpath(_ip.ipython_dir)
573 try:
592 try:
574 _ip.run_line_magic("cd", '"%s"' % ipdir)
593 _ip.run_line_magic("cd", '"%s"' % ipdir)
575 assert curpath() == ipdir
594 assert curpath() == ipdir
576 _ip.run_line_magic("cd", "-")
595 _ip.run_line_magic("cd", "-")
577 assert curpath() == startdir
596 assert curpath() == startdir
578 _ip.run_line_magic("pushd", '"%s"' % ipdir)
597 _ip.run_line_magic("pushd", '"%s"' % ipdir)
579 assert curpath() == ipdir
598 assert curpath() == ipdir
580 _ip.run_line_magic("popd", "")
599 _ip.run_line_magic("popd", "")
581 assert curpath() == startdir
600 assert curpath() == startdir
582 finally:
601 finally:
583 os.chdir(startdir)
602 os.chdir(startdir)
584
603
585
604
586 def test_cd_force_quiet():
605 def test_cd_force_quiet():
587 """Test OSMagics.cd_force_quiet option"""
606 """Test OSMagics.cd_force_quiet option"""
588 _ip.config.OSMagics.cd_force_quiet = True
607 _ip.config.OSMagics.cd_force_quiet = True
589 osmagics = osm.OSMagics(shell=_ip)
608 osmagics = osm.OSMagics(shell=_ip)
590
609
591 startdir = os.getcwd()
610 startdir = os.getcwd()
592 ipdir = os.path.realpath(_ip.ipython_dir)
611 ipdir = os.path.realpath(_ip.ipython_dir)
593
612
594 try:
613 try:
595 with tt.AssertNotPrints(ipdir):
614 with tt.AssertNotPrints(ipdir):
596 osmagics.cd('"%s"' % ipdir)
615 osmagics.cd('"%s"' % ipdir)
597 with tt.AssertNotPrints(startdir):
616 with tt.AssertNotPrints(startdir):
598 osmagics.cd('-')
617 osmagics.cd('-')
599 finally:
618 finally:
600 os.chdir(startdir)
619 os.chdir(startdir)
601
620
602
621
603 def test_xmode():
622 def test_xmode():
604 # Calling xmode three times should be a no-op
623 # Calling xmode three times should be a no-op
605 xmode = _ip.InteractiveTB.mode
624 xmode = _ip.InteractiveTB.mode
606 for i in range(4):
625 for i in range(4):
607 _ip.run_line_magic("xmode", "")
626 _ip.run_line_magic("xmode", "")
608 assert _ip.InteractiveTB.mode == xmode
627 assert _ip.InteractiveTB.mode == xmode
609
628
610 def test_reset_hard():
629 def test_reset_hard():
611 monitor = []
630 monitor = []
612 class A(object):
631 class A(object):
613 def __del__(self):
632 def __del__(self):
614 monitor.append(1)
633 monitor.append(1)
615 def __repr__(self):
634 def __repr__(self):
616 return "<A instance>"
635 return "<A instance>"
617
636
618 _ip.user_ns["a"] = A()
637 _ip.user_ns["a"] = A()
619 _ip.run_cell("a")
638 _ip.run_cell("a")
620
639
621 assert monitor == []
640 assert monitor == []
622 _ip.run_line_magic("reset", "-f")
641 _ip.run_line_magic("reset", "-f")
623 assert monitor == [1]
642 assert monitor == [1]
624
643
625 class TestXdel(tt.TempFileMixin):
644 class TestXdel(tt.TempFileMixin):
626 def test_xdel(self):
645 def test_xdel(self):
627 """Test that references from %run are cleared by xdel."""
646 """Test that references from %run are cleared by xdel."""
628 src = ("class A(object):\n"
647 src = ("class A(object):\n"
629 " monitor = []\n"
648 " monitor = []\n"
630 " def __del__(self):\n"
649 " def __del__(self):\n"
631 " self.monitor.append(1)\n"
650 " self.monitor.append(1)\n"
632 "a = A()\n")
651 "a = A()\n")
633 self.mktmp(src)
652 self.mktmp(src)
634 # %run creates some hidden references...
653 # %run creates some hidden references...
635 _ip.run_line_magic("run", "%s" % self.fname)
654 _ip.run_line_magic("run", "%s" % self.fname)
636 # ... as does the displayhook.
655 # ... as does the displayhook.
637 _ip.run_cell("a")
656 _ip.run_cell("a")
638
657
639 monitor = _ip.user_ns["A"].monitor
658 monitor = _ip.user_ns["A"].monitor
640 assert monitor == []
659 assert monitor == []
641
660
642 _ip.run_line_magic("xdel", "a")
661 _ip.run_line_magic("xdel", "a")
643
662
644 # Check that a's __del__ method has been called.
663 # Check that a's __del__ method has been called.
645 gc.collect(0)
664 gc.collect(0)
646 assert monitor == [1]
665 assert monitor == [1]
647
666
648 def doctest_who():
667 def doctest_who():
649 """doctest for %who
668 """doctest for %who
650
669
651 In [1]: %reset -sf
670 In [1]: %reset -sf
652
671
653 In [2]: alpha = 123
672 In [2]: alpha = 123
654
673
655 In [3]: beta = 'beta'
674 In [3]: beta = 'beta'
656
675
657 In [4]: %who int
676 In [4]: %who int
658 alpha
677 alpha
659
678
660 In [5]: %who str
679 In [5]: %who str
661 beta
680 beta
662
681
663 In [6]: %whos
682 In [6]: %whos
664 Variable Type Data/Info
683 Variable Type Data/Info
665 ----------------------------
684 ----------------------------
666 alpha int 123
685 alpha int 123
667 beta str beta
686 beta str beta
668
687
669 In [7]: %who_ls
688 In [7]: %who_ls
670 Out[7]: ['alpha', 'beta']
689 Out[7]: ['alpha', 'beta']
671 """
690 """
672
691
673 def test_whos():
692 def test_whos():
674 """Check that whos is protected against objects where repr() fails."""
693 """Check that whos is protected against objects where repr() fails."""
675 class A(object):
694 class A(object):
676 def __repr__(self):
695 def __repr__(self):
677 raise Exception()
696 raise Exception()
678 _ip.user_ns['a'] = A()
697 _ip.user_ns['a'] = A()
679 _ip.run_line_magic("whos", "")
698 _ip.run_line_magic("whos", "")
680
699
681 def doctest_precision():
700 def doctest_precision():
682 """doctest for %precision
701 """doctest for %precision
683
702
684 In [1]: f = get_ipython().display_formatter.formatters['text/plain']
703 In [1]: f = get_ipython().display_formatter.formatters['text/plain']
685
704
686 In [2]: %precision 5
705 In [2]: %precision 5
687 Out[2]: '%.5f'
706 Out[2]: '%.5f'
688
707
689 In [3]: f.float_format
708 In [3]: f.float_format
690 Out[3]: '%.5f'
709 Out[3]: '%.5f'
691
710
692 In [4]: %precision %e
711 In [4]: %precision %e
693 Out[4]: '%e'
712 Out[4]: '%e'
694
713
695 In [5]: f(3.1415927)
714 In [5]: f(3.1415927)
696 Out[5]: '3.141593e+00'
715 Out[5]: '3.141593e+00'
697 """
716 """
698
717
699 def test_debug_magic():
718 def test_debug_magic():
700 """Test debugging a small code with %debug
719 """Test debugging a small code with %debug
701
720
702 In [1]: with PdbTestInput(['c']):
721 In [1]: with PdbTestInput(['c']):
703 ...: %debug print("a b") #doctest: +ELLIPSIS
722 ...: %debug print("a b") #doctest: +ELLIPSIS
704 ...:
723 ...:
705 ...
724 ...
706 ipdb> c
725 ipdb> c
707 a b
726 a b
708 In [2]:
727 In [2]:
709 """
728 """
710
729
711 def test_psearch():
730 def test_psearch():
712 with tt.AssertPrints("dict.fromkeys"):
731 with tt.AssertPrints("dict.fromkeys"):
713 _ip.run_cell("dict.fr*?")
732 _ip.run_cell("dict.fr*?")
714 with tt.AssertPrints("Ο€.is_integer"):
733 with tt.AssertPrints("Ο€.is_integer"):
715 _ip.run_cell("Ο€ = 3.14;\nΟ€.is_integ*?")
734 _ip.run_cell("Ο€ = 3.14;\nΟ€.is_integ*?")
716
735
717 def test_timeit_shlex():
736 def test_timeit_shlex():
718 """test shlex issues with timeit (#1109)"""
737 """test shlex issues with timeit (#1109)"""
719 _ip.ex("def f(*a,**kw): pass")
738 _ip.ex("def f(*a,**kw): pass")
720 _ip.run_line_magic("timeit", '-n1 "this is a bug".count(" ")')
739 _ip.run_line_magic("timeit", '-n1 "this is a bug".count(" ")')
721 _ip.run_line_magic("timeit", '-r1 -n1 f(" ", 1)')
740 _ip.run_line_magic("timeit", '-r1 -n1 f(" ", 1)')
722 _ip.run_line_magic("timeit", '-r1 -n1 f(" ", 1, " ", 2, " ")')
741 _ip.run_line_magic("timeit", '-r1 -n1 f(" ", 1, " ", 2, " ")')
723 _ip.run_line_magic("timeit", '-r1 -n1 ("a " + "b")')
742 _ip.run_line_magic("timeit", '-r1 -n1 ("a " + "b")')
724 _ip.run_line_magic("timeit", '-r1 -n1 f("a " + "b")')
743 _ip.run_line_magic("timeit", '-r1 -n1 f("a " + "b")')
725 _ip.run_line_magic("timeit", '-r1 -n1 f("a " + "b ")')
744 _ip.run_line_magic("timeit", '-r1 -n1 f("a " + "b ")')
726
745
727
746
728 def test_timeit_special_syntax():
747 def test_timeit_special_syntax():
729 "Test %%timeit with IPython special syntax"
748 "Test %%timeit with IPython special syntax"
730 @register_line_magic
749 @register_line_magic
731 def lmagic(line):
750 def lmagic(line):
732 ip = get_ipython()
751 ip = get_ipython()
733 ip.user_ns['lmagic_out'] = line
752 ip.user_ns['lmagic_out'] = line
734
753
735 # line mode test
754 # line mode test
736 _ip.run_line_magic("timeit", "-n1 -r1 %lmagic my line")
755 _ip.run_line_magic("timeit", "-n1 -r1 %lmagic my line")
737 assert _ip.user_ns["lmagic_out"] == "my line"
756 assert _ip.user_ns["lmagic_out"] == "my line"
738 # cell mode test
757 # cell mode test
739 _ip.run_cell_magic("timeit", "-n1 -r1", "%lmagic my line2")
758 _ip.run_cell_magic("timeit", "-n1 -r1", "%lmagic my line2")
740 assert _ip.user_ns["lmagic_out"] == "my line2"
759 assert _ip.user_ns["lmagic_out"] == "my line2"
741
760
742
761
743 def test_timeit_return():
762 def test_timeit_return():
744 """
763 """
745 test whether timeit -o return object
764 test whether timeit -o return object
746 """
765 """
747
766
748 res = _ip.run_line_magic('timeit','-n10 -r10 -o 1')
767 res = _ip.run_line_magic('timeit','-n10 -r10 -o 1')
749 assert(res is not None)
768 assert(res is not None)
750
769
751 def test_timeit_quiet():
770 def test_timeit_quiet():
752 """
771 """
753 test quiet option of timeit magic
772 test quiet option of timeit magic
754 """
773 """
755 with tt.AssertNotPrints("loops"):
774 with tt.AssertNotPrints("loops"):
756 _ip.run_cell("%timeit -n1 -r1 -q 1")
775 _ip.run_cell("%timeit -n1 -r1 -q 1")
757
776
758 def test_timeit_return_quiet():
777 def test_timeit_return_quiet():
759 with tt.AssertNotPrints("loops"):
778 with tt.AssertNotPrints("loops"):
760 res = _ip.run_line_magic('timeit', '-n1 -r1 -q -o 1')
779 res = _ip.run_line_magic('timeit', '-n1 -r1 -q -o 1')
761 assert (res is not None)
780 assert (res is not None)
762
781
763 def test_timeit_invalid_return():
782 def test_timeit_invalid_return():
764 with pytest.raises(SyntaxError):
783 with pytest.raises(SyntaxError):
765 _ip.run_line_magic('timeit', 'return')
784 _ip.run_line_magic('timeit', 'return')
766
785
767 @dec.skipif(execution.profile is None)
786 @dec.skipif(execution.profile is None)
768 def test_prun_special_syntax():
787 def test_prun_special_syntax():
769 "Test %%prun with IPython special syntax"
788 "Test %%prun with IPython special syntax"
770 @register_line_magic
789 @register_line_magic
771 def lmagic(line):
790 def lmagic(line):
772 ip = get_ipython()
791 ip = get_ipython()
773 ip.user_ns['lmagic_out'] = line
792 ip.user_ns['lmagic_out'] = line
774
793
775 # line mode test
794 # line mode test
776 _ip.run_line_magic("prun", "-q %lmagic my line")
795 _ip.run_line_magic("prun", "-q %lmagic my line")
777 assert _ip.user_ns["lmagic_out"] == "my line"
796 assert _ip.user_ns["lmagic_out"] == "my line"
778 # cell mode test
797 # cell mode test
779 _ip.run_cell_magic("prun", "-q", "%lmagic my line2")
798 _ip.run_cell_magic("prun", "-q", "%lmagic my line2")
780 assert _ip.user_ns["lmagic_out"] == "my line2"
799 assert _ip.user_ns["lmagic_out"] == "my line2"
781
800
782
801
783 @dec.skipif(execution.profile is None)
802 @dec.skipif(execution.profile is None)
784 def test_prun_quotes():
803 def test_prun_quotes():
785 "Test that prun does not clobber string escapes (GH #1302)"
804 "Test that prun does not clobber string escapes (GH #1302)"
786 _ip.magic(r"prun -q x = '\t'")
805 _ip.magic(r"prun -q x = '\t'")
787 assert _ip.user_ns["x"] == "\t"
806 assert _ip.user_ns["x"] == "\t"
788
807
789
808
790 def test_extension():
809 def test_extension():
791 # Debugging information for failures of this test
810 # Debugging information for failures of this test
792 print('sys.path:')
811 print('sys.path:')
793 for p in sys.path:
812 for p in sys.path:
794 print(' ', p)
813 print(' ', p)
795 print('CWD', os.getcwd())
814 print('CWD', os.getcwd())
796
815
797 pytest.raises(ImportError, _ip.magic, "load_ext daft_extension")
816 pytest.raises(ImportError, _ip.magic, "load_ext daft_extension")
798 daft_path = os.path.join(os.path.dirname(__file__), "daft_extension")
817 daft_path = os.path.join(os.path.dirname(__file__), "daft_extension")
799 sys.path.insert(0, daft_path)
818 sys.path.insert(0, daft_path)
800 try:
819 try:
801 _ip.user_ns.pop('arq', None)
820 _ip.user_ns.pop('arq', None)
802 invalidate_caches() # Clear import caches
821 invalidate_caches() # Clear import caches
803 _ip.run_line_magic("load_ext", "daft_extension")
822 _ip.run_line_magic("load_ext", "daft_extension")
804 assert _ip.user_ns["arq"] == 185
823 assert _ip.user_ns["arq"] == 185
805 _ip.run_line_magic("unload_ext", "daft_extension")
824 _ip.run_line_magic("unload_ext", "daft_extension")
806 assert 'arq' not in _ip.user_ns
825 assert 'arq' not in _ip.user_ns
807 finally:
826 finally:
808 sys.path.remove(daft_path)
827 sys.path.remove(daft_path)
809
828
810
829
811 def test_notebook_export_json():
830 def test_notebook_export_json():
812 pytest.importorskip("nbformat")
831 pytest.importorskip("nbformat")
813 _ip = get_ipython()
832 _ip = get_ipython()
814 _ip.history_manager.reset() # Clear any existing history.
833 _ip.history_manager.reset() # Clear any existing history.
815 cmds = ["a=1", "def b():\n return a**2", "print('noΓ«l, Γ©tΓ©', b())"]
834 cmds = ["a=1", "def b():\n return a**2", "print('noΓ«l, Γ©tΓ©', b())"]
816 for i, cmd in enumerate(cmds, start=1):
835 for i, cmd in enumerate(cmds, start=1):
817 _ip.history_manager.store_inputs(i, cmd)
836 _ip.history_manager.store_inputs(i, cmd)
818 with TemporaryDirectory() as td:
837 with TemporaryDirectory() as td:
819 outfile = os.path.join(td, "nb.ipynb")
838 outfile = os.path.join(td, "nb.ipynb")
820 _ip.run_line_magic("notebook", "%s" % outfile)
839 _ip.run_line_magic("notebook", "%s" % outfile)
821
840
822
841
823 class TestEnv(TestCase):
842 class TestEnv(TestCase):
824
843
825 def test_env(self):
844 def test_env(self):
826 env = _ip.run_line_magic("env", "")
845 env = _ip.run_line_magic("env", "")
827 self.assertTrue(isinstance(env, dict))
846 self.assertTrue(isinstance(env, dict))
828
847
829 def test_env_secret(self):
848 def test_env_secret(self):
830 env = _ip.run_line_magic("env", "")
849 env = _ip.run_line_magic("env", "")
831 hidden = "<hidden>"
850 hidden = "<hidden>"
832 with mock.patch.dict(
851 with mock.patch.dict(
833 os.environ,
852 os.environ,
834 {
853 {
835 "API_KEY": "abc123",
854 "API_KEY": "abc123",
836 "SECRET_THING": "ssshhh",
855 "SECRET_THING": "ssshhh",
837 "JUPYTER_TOKEN": "",
856 "JUPYTER_TOKEN": "",
838 "VAR": "abc"
857 "VAR": "abc"
839 }
858 }
840 ):
859 ):
841 env = _ip.run_line_magic("env", "")
860 env = _ip.run_line_magic("env", "")
842 assert env["API_KEY"] == hidden
861 assert env["API_KEY"] == hidden
843 assert env["SECRET_THING"] == hidden
862 assert env["SECRET_THING"] == hidden
844 assert env["JUPYTER_TOKEN"] == hidden
863 assert env["JUPYTER_TOKEN"] == hidden
845 assert env["VAR"] == "abc"
864 assert env["VAR"] == "abc"
846
865
847 def test_env_get_set_simple(self):
866 def test_env_get_set_simple(self):
848 env = _ip.run_line_magic("env", "var val1")
867 env = _ip.run_line_magic("env", "var val1")
849 self.assertEqual(env, None)
868 self.assertEqual(env, None)
850 self.assertEqual(os.environ["var"], "val1")
869 self.assertEqual(os.environ["var"], "val1")
851 self.assertEqual(_ip.run_line_magic("env", "var"), "val1")
870 self.assertEqual(_ip.run_line_magic("env", "var"), "val1")
852 env = _ip.run_line_magic("env", "var=val2")
871 env = _ip.run_line_magic("env", "var=val2")
853 self.assertEqual(env, None)
872 self.assertEqual(env, None)
854 self.assertEqual(os.environ['var'], 'val2')
873 self.assertEqual(os.environ['var'], 'val2')
855
874
856 def test_env_get_set_complex(self):
875 def test_env_get_set_complex(self):
857 env = _ip.run_line_magic("env", "var 'val1 '' 'val2")
876 env = _ip.run_line_magic("env", "var 'val1 '' 'val2")
858 self.assertEqual(env, None)
877 self.assertEqual(env, None)
859 self.assertEqual(os.environ['var'], "'val1 '' 'val2")
878 self.assertEqual(os.environ['var'], "'val1 '' 'val2")
860 self.assertEqual(_ip.run_line_magic("env", "var"), "'val1 '' 'val2")
879 self.assertEqual(_ip.run_line_magic("env", "var"), "'val1 '' 'val2")
861 env = _ip.run_line_magic("env", 'var=val2 val3="val4')
880 env = _ip.run_line_magic("env", 'var=val2 val3="val4')
862 self.assertEqual(env, None)
881 self.assertEqual(env, None)
863 self.assertEqual(os.environ['var'], 'val2 val3="val4')
882 self.assertEqual(os.environ['var'], 'val2 val3="val4')
864
883
865 def test_env_set_bad_input(self):
884 def test_env_set_bad_input(self):
866 self.assertRaises(UsageError, lambda: _ip.run_line_magic("set_env", "var"))
885 self.assertRaises(UsageError, lambda: _ip.run_line_magic("set_env", "var"))
867
886
868 def test_env_set_whitespace(self):
887 def test_env_set_whitespace(self):
869 self.assertRaises(UsageError, lambda: _ip.run_line_magic("env", "var A=B"))
888 self.assertRaises(UsageError, lambda: _ip.run_line_magic("env", "var A=B"))
870
889
871
890
872 class CellMagicTestCase(TestCase):
891 class CellMagicTestCase(TestCase):
873
892
874 def check_ident(self, magic):
893 def check_ident(self, magic):
875 # Manually called, we get the result
894 # Manually called, we get the result
876 out = _ip.run_cell_magic(magic, "a", "b")
895 out = _ip.run_cell_magic(magic, "a", "b")
877 assert out == ("a", "b")
896 assert out == ("a", "b")
878 # Via run_cell, it goes into the user's namespace via displayhook
897 # Via run_cell, it goes into the user's namespace via displayhook
879 _ip.run_cell("%%" + magic + " c\nd\n")
898 _ip.run_cell("%%" + magic + " c\nd\n")
880 assert _ip.user_ns["_"] == ("c", "d\n")
899 assert _ip.user_ns["_"] == ("c", "d\n")
881
900
882 def test_cell_magic_func_deco(self):
901 def test_cell_magic_func_deco(self):
883 "Cell magic using simple decorator"
902 "Cell magic using simple decorator"
884 @register_cell_magic
903 @register_cell_magic
885 def cellm(line, cell):
904 def cellm(line, cell):
886 return line, cell
905 return line, cell
887
906
888 self.check_ident('cellm')
907 self.check_ident('cellm')
889
908
890 def test_cell_magic_reg(self):
909 def test_cell_magic_reg(self):
891 "Cell magic manually registered"
910 "Cell magic manually registered"
892 def cellm(line, cell):
911 def cellm(line, cell):
893 return line, cell
912 return line, cell
894
913
895 _ip.register_magic_function(cellm, 'cell', 'cellm2')
914 _ip.register_magic_function(cellm, 'cell', 'cellm2')
896 self.check_ident('cellm2')
915 self.check_ident('cellm2')
897
916
898 def test_cell_magic_class(self):
917 def test_cell_magic_class(self):
899 "Cell magics declared via a class"
918 "Cell magics declared via a class"
900 @magics_class
919 @magics_class
901 class MyMagics(Magics):
920 class MyMagics(Magics):
902
921
903 @cell_magic
922 @cell_magic
904 def cellm3(self, line, cell):
923 def cellm3(self, line, cell):
905 return line, cell
924 return line, cell
906
925
907 _ip.register_magics(MyMagics)
926 _ip.register_magics(MyMagics)
908 self.check_ident('cellm3')
927 self.check_ident('cellm3')
909
928
910 def test_cell_magic_class2(self):
929 def test_cell_magic_class2(self):
911 "Cell magics declared via a class, #2"
930 "Cell magics declared via a class, #2"
912 @magics_class
931 @magics_class
913 class MyMagics2(Magics):
932 class MyMagics2(Magics):
914
933
915 @cell_magic('cellm4')
934 @cell_magic('cellm4')
916 def cellm33(self, line, cell):
935 def cellm33(self, line, cell):
917 return line, cell
936 return line, cell
918
937
919 _ip.register_magics(MyMagics2)
938 _ip.register_magics(MyMagics2)
920 self.check_ident('cellm4')
939 self.check_ident('cellm4')
921 # Check that nothing is registered as 'cellm33'
940 # Check that nothing is registered as 'cellm33'
922 c33 = _ip.find_cell_magic('cellm33')
941 c33 = _ip.find_cell_magic('cellm33')
923 assert c33 == None
942 assert c33 == None
924
943
925 def test_file():
944 def test_file():
926 """Basic %%writefile"""
945 """Basic %%writefile"""
927 ip = get_ipython()
946 ip = get_ipython()
928 with TemporaryDirectory() as td:
947 with TemporaryDirectory() as td:
929 fname = os.path.join(td, "file1")
948 fname = os.path.join(td, "file1")
930 ip.run_cell_magic(
949 ip.run_cell_magic(
931 "writefile",
950 "writefile",
932 fname,
951 fname,
933 "\n".join(
952 "\n".join(
934 [
953 [
935 "line1",
954 "line1",
936 "line2",
955 "line2",
937 ]
956 ]
938 ),
957 ),
939 )
958 )
940 s = Path(fname).read_text(encoding="utf-8")
959 s = Path(fname).read_text(encoding="utf-8")
941 assert "line1\n" in s
960 assert "line1\n" in s
942 assert "line2" in s
961 assert "line2" in s
943
962
944
963
945 @dec.skip_win32
964 @dec.skip_win32
946 def test_file_single_quote():
965 def test_file_single_quote():
947 """Basic %%writefile with embedded single quotes"""
966 """Basic %%writefile with embedded single quotes"""
948 ip = get_ipython()
967 ip = get_ipython()
949 with TemporaryDirectory() as td:
968 with TemporaryDirectory() as td:
950 fname = os.path.join(td, "'file1'")
969 fname = os.path.join(td, "'file1'")
951 ip.run_cell_magic(
970 ip.run_cell_magic(
952 "writefile",
971 "writefile",
953 fname,
972 fname,
954 "\n".join(
973 "\n".join(
955 [
974 [
956 "line1",
975 "line1",
957 "line2",
976 "line2",
958 ]
977 ]
959 ),
978 ),
960 )
979 )
961 s = Path(fname).read_text(encoding="utf-8")
980 s = Path(fname).read_text(encoding="utf-8")
962 assert "line1\n" in s
981 assert "line1\n" in s
963 assert "line2" in s
982 assert "line2" in s
964
983
965
984
966 @dec.skip_win32
985 @dec.skip_win32
967 def test_file_double_quote():
986 def test_file_double_quote():
968 """Basic %%writefile with embedded double quotes"""
987 """Basic %%writefile with embedded double quotes"""
969 ip = get_ipython()
988 ip = get_ipython()
970 with TemporaryDirectory() as td:
989 with TemporaryDirectory() as td:
971 fname = os.path.join(td, '"file1"')
990 fname = os.path.join(td, '"file1"')
972 ip.run_cell_magic(
991 ip.run_cell_magic(
973 "writefile",
992 "writefile",
974 fname,
993 fname,
975 "\n".join(
994 "\n".join(
976 [
995 [
977 "line1",
996 "line1",
978 "line2",
997 "line2",
979 ]
998 ]
980 ),
999 ),
981 )
1000 )
982 s = Path(fname).read_text(encoding="utf-8")
1001 s = Path(fname).read_text(encoding="utf-8")
983 assert "line1\n" in s
1002 assert "line1\n" in s
984 assert "line2" in s
1003 assert "line2" in s
985
1004
986
1005
987 def test_file_var_expand():
1006 def test_file_var_expand():
988 """%%writefile $filename"""
1007 """%%writefile $filename"""
989 ip = get_ipython()
1008 ip = get_ipython()
990 with TemporaryDirectory() as td:
1009 with TemporaryDirectory() as td:
991 fname = os.path.join(td, "file1")
1010 fname = os.path.join(td, "file1")
992 ip.user_ns["filename"] = fname
1011 ip.user_ns["filename"] = fname
993 ip.run_cell_magic(
1012 ip.run_cell_magic(
994 "writefile",
1013 "writefile",
995 "$filename",
1014 "$filename",
996 "\n".join(
1015 "\n".join(
997 [
1016 [
998 "line1",
1017 "line1",
999 "line2",
1018 "line2",
1000 ]
1019 ]
1001 ),
1020 ),
1002 )
1021 )
1003 s = Path(fname).read_text(encoding="utf-8")
1022 s = Path(fname).read_text(encoding="utf-8")
1004 assert "line1\n" in s
1023 assert "line1\n" in s
1005 assert "line2" in s
1024 assert "line2" in s
1006
1025
1007
1026
1008 def test_file_unicode():
1027 def test_file_unicode():
1009 """%%writefile with unicode cell"""
1028 """%%writefile with unicode cell"""
1010 ip = get_ipython()
1029 ip = get_ipython()
1011 with TemporaryDirectory() as td:
1030 with TemporaryDirectory() as td:
1012 fname = os.path.join(td, 'file1')
1031 fname = os.path.join(td, 'file1')
1013 ip.run_cell_magic("writefile", fname, u'\n'.join([
1032 ip.run_cell_magic("writefile", fname, u'\n'.join([
1014 u'linΓ©1',
1033 u'linΓ©1',
1015 u'linΓ©2',
1034 u'linΓ©2',
1016 ]))
1035 ]))
1017 with io.open(fname, encoding='utf-8') as f:
1036 with io.open(fname, encoding='utf-8') as f:
1018 s = f.read()
1037 s = f.read()
1019 assert "linΓ©1\n" in s
1038 assert "linΓ©1\n" in s
1020 assert "linΓ©2" in s
1039 assert "linΓ©2" in s
1021
1040
1022
1041
1023 def test_file_amend():
1042 def test_file_amend():
1024 """%%writefile -a amends files"""
1043 """%%writefile -a amends files"""
1025 ip = get_ipython()
1044 ip = get_ipython()
1026 with TemporaryDirectory() as td:
1045 with TemporaryDirectory() as td:
1027 fname = os.path.join(td, "file2")
1046 fname = os.path.join(td, "file2")
1028 ip.run_cell_magic(
1047 ip.run_cell_magic(
1029 "writefile",
1048 "writefile",
1030 fname,
1049 fname,
1031 "\n".join(
1050 "\n".join(
1032 [
1051 [
1033 "line1",
1052 "line1",
1034 "line2",
1053 "line2",
1035 ]
1054 ]
1036 ),
1055 ),
1037 )
1056 )
1038 ip.run_cell_magic(
1057 ip.run_cell_magic(
1039 "writefile",
1058 "writefile",
1040 "-a %s" % fname,
1059 "-a %s" % fname,
1041 "\n".join(
1060 "\n".join(
1042 [
1061 [
1043 "line3",
1062 "line3",
1044 "line4",
1063 "line4",
1045 ]
1064 ]
1046 ),
1065 ),
1047 )
1066 )
1048 s = Path(fname).read_text(encoding="utf-8")
1067 s = Path(fname).read_text(encoding="utf-8")
1049 assert "line1\n" in s
1068 assert "line1\n" in s
1050 assert "line3\n" in s
1069 assert "line3\n" in s
1051
1070
1052
1071
1053 def test_file_spaces():
1072 def test_file_spaces():
1054 """%%file with spaces in filename"""
1073 """%%file with spaces in filename"""
1055 ip = get_ipython()
1074 ip = get_ipython()
1056 with TemporaryWorkingDirectory() as td:
1075 with TemporaryWorkingDirectory() as td:
1057 fname = "file name"
1076 fname = "file name"
1058 ip.run_cell_magic(
1077 ip.run_cell_magic(
1059 "file",
1078 "file",
1060 '"%s"' % fname,
1079 '"%s"' % fname,
1061 "\n".join(
1080 "\n".join(
1062 [
1081 [
1063 "line1",
1082 "line1",
1064 "line2",
1083 "line2",
1065 ]
1084 ]
1066 ),
1085 ),
1067 )
1086 )
1068 s = Path(fname).read_text(encoding="utf-8")
1087 s = Path(fname).read_text(encoding="utf-8")
1069 assert "line1\n" in s
1088 assert "line1\n" in s
1070 assert "line2" in s
1089 assert "line2" in s
1071
1090
1072
1091
1073 def test_script_config():
1092 def test_script_config():
1074 ip = get_ipython()
1093 ip = get_ipython()
1075 ip.config.ScriptMagics.script_magics = ['whoda']
1094 ip.config.ScriptMagics.script_magics = ['whoda']
1076 sm = script.ScriptMagics(shell=ip)
1095 sm = script.ScriptMagics(shell=ip)
1077 assert "whoda" in sm.magics["cell"]
1096 assert "whoda" in sm.magics["cell"]
1078
1097
1079
1098
1080 def test_script_out():
1099 def test_script_out():
1081 ip = get_ipython()
1100 ip = get_ipython()
1082 ip.run_cell_magic("script", f"--out output {sys.executable}", "print('hi')")
1101 ip.run_cell_magic("script", f"--out output {sys.executable}", "print('hi')")
1083 assert ip.user_ns["output"].strip() == "hi"
1102 assert ip.user_ns["output"].strip() == "hi"
1084
1103
1085
1104
1086 def test_script_err():
1105 def test_script_err():
1087 ip = get_ipython()
1106 ip = get_ipython()
1088 ip.run_cell_magic(
1107 ip.run_cell_magic(
1089 "script",
1108 "script",
1090 f"--err error {sys.executable}",
1109 f"--err error {sys.executable}",
1091 "import sys; print('hello', file=sys.stderr)",
1110 "import sys; print('hello', file=sys.stderr)",
1092 )
1111 )
1093 assert ip.user_ns["error"].strip() == "hello"
1112 assert ip.user_ns["error"].strip() == "hello"
1094
1113
1095
1114
1096 def test_script_out_err():
1115 def test_script_out_err():
1097 ip = get_ipython()
1116 ip = get_ipython()
1098 ip.run_cell_magic(
1117 ip.run_cell_magic(
1099 "script",
1118 "script",
1100 f"--out output --err error {sys.executable}",
1119 f"--out output --err error {sys.executable}",
1101 "\n".join(
1120 "\n".join(
1102 [
1121 [
1103 "import sys",
1122 "import sys",
1104 "print('hi')",
1123 "print('hi')",
1105 "print('hello', file=sys.stderr)",
1124 "print('hello', file=sys.stderr)",
1106 ]
1125 ]
1107 ),
1126 ),
1108 )
1127 )
1109 assert ip.user_ns["output"].strip() == "hi"
1128 assert ip.user_ns["output"].strip() == "hi"
1110 assert ip.user_ns["error"].strip() == "hello"
1129 assert ip.user_ns["error"].strip() == "hello"
1111
1130
1112
1131
1113 async def test_script_bg_out():
1132 async def test_script_bg_out():
1114 ip = get_ipython()
1133 ip = get_ipython()
1115 ip.run_cell_magic("script", f"--bg --out output {sys.executable}", "print('hi')")
1134 ip.run_cell_magic("script", f"--bg --out output {sys.executable}", "print('hi')")
1116 assert (await ip.user_ns["output"].read()).strip() == b"hi"
1135 assert (await ip.user_ns["output"].read()).strip() == b"hi"
1117 assert ip.user_ns["output"].at_eof()
1136 assert ip.user_ns["output"].at_eof()
1118
1137
1119
1138
1120 async def test_script_bg_err():
1139 async def test_script_bg_err():
1121 ip = get_ipython()
1140 ip = get_ipython()
1122 ip.run_cell_magic(
1141 ip.run_cell_magic(
1123 "script",
1142 "script",
1124 f"--bg --err error {sys.executable}",
1143 f"--bg --err error {sys.executable}",
1125 "import sys; print('hello', file=sys.stderr)",
1144 "import sys; print('hello', file=sys.stderr)",
1126 )
1145 )
1127 assert (await ip.user_ns["error"].read()).strip() == b"hello"
1146 assert (await ip.user_ns["error"].read()).strip() == b"hello"
1128 assert ip.user_ns["error"].at_eof()
1147 assert ip.user_ns["error"].at_eof()
1129
1148
1130
1149
1131 async def test_script_bg_out_err():
1150 async def test_script_bg_out_err():
1132 ip = get_ipython()
1151 ip = get_ipython()
1133 ip.run_cell_magic(
1152 ip.run_cell_magic(
1134 "script",
1153 "script",
1135 f"--bg --out output --err error {sys.executable}",
1154 f"--bg --out output --err error {sys.executable}",
1136 "\n".join(
1155 "\n".join(
1137 [
1156 [
1138 "import sys",
1157 "import sys",
1139 "print('hi')",
1158 "print('hi')",
1140 "print('hello', file=sys.stderr)",
1159 "print('hello', file=sys.stderr)",
1141 ]
1160 ]
1142 ),
1161 ),
1143 )
1162 )
1144 assert (await ip.user_ns["output"].read()).strip() == b"hi"
1163 assert (await ip.user_ns["output"].read()).strip() == b"hi"
1145 assert (await ip.user_ns["error"].read()).strip() == b"hello"
1164 assert (await ip.user_ns["error"].read()).strip() == b"hello"
1146 assert ip.user_ns["output"].at_eof()
1165 assert ip.user_ns["output"].at_eof()
1147 assert ip.user_ns["error"].at_eof()
1166 assert ip.user_ns["error"].at_eof()
1148
1167
1149
1168
1150 async def test_script_bg_proc():
1169 async def test_script_bg_proc():
1151 ip = get_ipython()
1170 ip = get_ipython()
1152 ip.run_cell_magic(
1171 ip.run_cell_magic(
1153 "script",
1172 "script",
1154 f"--bg --out output --proc p {sys.executable}",
1173 f"--bg --out output --proc p {sys.executable}",
1155 "\n".join(
1174 "\n".join(
1156 [
1175 [
1157 "import sys",
1176 "import sys",
1158 "print('hi')",
1177 "print('hi')",
1159 "print('hello', file=sys.stderr)",
1178 "print('hello', file=sys.stderr)",
1160 ]
1179 ]
1161 ),
1180 ),
1162 )
1181 )
1163 p = ip.user_ns["p"]
1182 p = ip.user_ns["p"]
1164 await p.wait()
1183 await p.wait()
1165 assert p.returncode == 0
1184 assert p.returncode == 0
1166 assert (await p.stdout.read()).strip() == b"hi"
1185 assert (await p.stdout.read()).strip() == b"hi"
1167 # not captured, so empty
1186 # not captured, so empty
1168 assert (await p.stderr.read()) == b""
1187 assert (await p.stderr.read()) == b""
1169 assert p.stdout.at_eof()
1188 assert p.stdout.at_eof()
1170 assert p.stderr.at_eof()
1189 assert p.stderr.at_eof()
1171
1190
1172
1191
1173 def test_script_defaults():
1192 def test_script_defaults():
1174 ip = get_ipython()
1193 ip = get_ipython()
1175 for cmd in ['sh', 'bash', 'perl', 'ruby']:
1194 for cmd in ['sh', 'bash', 'perl', 'ruby']:
1176 try:
1195 try:
1177 find_cmd(cmd)
1196 find_cmd(cmd)
1178 except Exception:
1197 except Exception:
1179 pass
1198 pass
1180 else:
1199 else:
1181 assert cmd in ip.magics_manager.magics["cell"]
1200 assert cmd in ip.magics_manager.magics["cell"]
1182
1201
1183
1202
1184 @magics_class
1203 @magics_class
1185 class FooFoo(Magics):
1204 class FooFoo(Magics):
1186 """class with both %foo and %%foo magics"""
1205 """class with both %foo and %%foo magics"""
1187 @line_magic('foo')
1206 @line_magic('foo')
1188 def line_foo(self, line):
1207 def line_foo(self, line):
1189 "I am line foo"
1208 "I am line foo"
1190 pass
1209 pass
1191
1210
1192 @cell_magic("foo")
1211 @cell_magic("foo")
1193 def cell_foo(self, line, cell):
1212 def cell_foo(self, line, cell):
1194 "I am cell foo, not line foo"
1213 "I am cell foo, not line foo"
1195 pass
1214 pass
1196
1215
1197 def test_line_cell_info():
1216 def test_line_cell_info():
1198 """%%foo and %foo magics are distinguishable to inspect"""
1217 """%%foo and %foo magics are distinguishable to inspect"""
1199 ip = get_ipython()
1218 ip = get_ipython()
1200 ip.magics_manager.register(FooFoo)
1219 ip.magics_manager.register(FooFoo)
1201 oinfo = ip.object_inspect("foo")
1220 oinfo = ip.object_inspect("foo")
1202 assert oinfo["found"] is True
1221 assert oinfo["found"] is True
1203 assert oinfo["ismagic"] is True
1222 assert oinfo["ismagic"] is True
1204
1223
1205 oinfo = ip.object_inspect("%%foo")
1224 oinfo = ip.object_inspect("%%foo")
1206 assert oinfo["found"] is True
1225 assert oinfo["found"] is True
1207 assert oinfo["ismagic"] is True
1226 assert oinfo["ismagic"] is True
1208 assert oinfo["docstring"] == FooFoo.cell_foo.__doc__
1227 assert oinfo["docstring"] == FooFoo.cell_foo.__doc__
1209
1228
1210 oinfo = ip.object_inspect("%foo")
1229 oinfo = ip.object_inspect("%foo")
1211 assert oinfo["found"] is True
1230 assert oinfo["found"] is True
1212 assert oinfo["ismagic"] is True
1231 assert oinfo["ismagic"] is True
1213 assert oinfo["docstring"] == FooFoo.line_foo.__doc__
1232 assert oinfo["docstring"] == FooFoo.line_foo.__doc__
1214
1233
1215
1234
1216 def test_multiple_magics():
1235 def test_multiple_magics():
1217 ip = get_ipython()
1236 ip = get_ipython()
1218 foo1 = FooFoo(ip)
1237 foo1 = FooFoo(ip)
1219 foo2 = FooFoo(ip)
1238 foo2 = FooFoo(ip)
1220 mm = ip.magics_manager
1239 mm = ip.magics_manager
1221 mm.register(foo1)
1240 mm.register(foo1)
1222 assert mm.magics["line"]["foo"].__self__ is foo1
1241 assert mm.magics["line"]["foo"].__self__ is foo1
1223 mm.register(foo2)
1242 mm.register(foo2)
1224 assert mm.magics["line"]["foo"].__self__ is foo2
1243 assert mm.magics["line"]["foo"].__self__ is foo2
1225
1244
1226
1245
1227 def test_alias_magic():
1246 def test_alias_magic():
1228 """Test %alias_magic."""
1247 """Test %alias_magic."""
1229 ip = get_ipython()
1248 ip = get_ipython()
1230 mm = ip.magics_manager
1249 mm = ip.magics_manager
1231
1250
1232 # Basic operation: both cell and line magics are created, if possible.
1251 # Basic operation: both cell and line magics are created, if possible.
1233 ip.run_line_magic("alias_magic", "timeit_alias timeit")
1252 ip.run_line_magic("alias_magic", "timeit_alias timeit")
1234 assert "timeit_alias" in mm.magics["line"]
1253 assert "timeit_alias" in mm.magics["line"]
1235 assert "timeit_alias" in mm.magics["cell"]
1254 assert "timeit_alias" in mm.magics["cell"]
1236
1255
1237 # --cell is specified, line magic not created.
1256 # --cell is specified, line magic not created.
1238 ip.run_line_magic("alias_magic", "--cell timeit_cell_alias timeit")
1257 ip.run_line_magic("alias_magic", "--cell timeit_cell_alias timeit")
1239 assert "timeit_cell_alias" not in mm.magics["line"]
1258 assert "timeit_cell_alias" not in mm.magics["line"]
1240 assert "timeit_cell_alias" in mm.magics["cell"]
1259 assert "timeit_cell_alias" in mm.magics["cell"]
1241
1260
1242 # Test that line alias is created successfully.
1261 # Test that line alias is created successfully.
1243 ip.run_line_magic("alias_magic", "--line env_alias env")
1262 ip.run_line_magic("alias_magic", "--line env_alias env")
1244 assert ip.run_line_magic("env", "") == ip.run_line_magic("env_alias", "")
1263 assert ip.run_line_magic("env", "") == ip.run_line_magic("env_alias", "")
1245
1264
1246 # Test that line alias with parameters passed in is created successfully.
1265 # Test that line alias with parameters passed in is created successfully.
1247 ip.run_line_magic(
1266 ip.run_line_magic(
1248 "alias_magic", "--line history_alias history --params " + shlex.quote("3")
1267 "alias_magic", "--line history_alias history --params " + shlex.quote("3")
1249 )
1268 )
1250 assert "history_alias" in mm.magics["line"]
1269 assert "history_alias" in mm.magics["line"]
1251
1270
1252
1271
1253 def test_save():
1272 def test_save():
1254 """Test %save."""
1273 """Test %save."""
1255 ip = get_ipython()
1274 ip = get_ipython()
1256 ip.history_manager.reset() # Clear any existing history.
1275 ip.history_manager.reset() # Clear any existing history.
1257 cmds = ["a=1", "def b():\n return a**2", "print(a, b())"]
1276 cmds = ["a=1", "def b():\n return a**2", "print(a, b())"]
1258 for i, cmd in enumerate(cmds, start=1):
1277 for i, cmd in enumerate(cmds, start=1):
1259 ip.history_manager.store_inputs(i, cmd)
1278 ip.history_manager.store_inputs(i, cmd)
1260 with TemporaryDirectory() as tmpdir:
1279 with TemporaryDirectory() as tmpdir:
1261 file = os.path.join(tmpdir, "testsave.py")
1280 file = os.path.join(tmpdir, "testsave.py")
1262 ip.run_line_magic("save", "%s 1-10" % file)
1281 ip.run_line_magic("save", "%s 1-10" % file)
1263 content = Path(file).read_text(encoding="utf-8")
1282 content = Path(file).read_text(encoding="utf-8")
1264 assert content.count(cmds[0]) == 1
1283 assert content.count(cmds[0]) == 1
1265 assert "coding: utf-8" in content
1284 assert "coding: utf-8" in content
1266 ip.run_line_magic("save", "-a %s 1-10" % file)
1285 ip.run_line_magic("save", "-a %s 1-10" % file)
1267 content = Path(file).read_text(encoding="utf-8")
1286 content = Path(file).read_text(encoding="utf-8")
1268 assert content.count(cmds[0]) == 2
1287 assert content.count(cmds[0]) == 2
1269 assert "coding: utf-8" in content
1288 assert "coding: utf-8" in content
1270
1289
1271
1290
1272 def test_save_with_no_args():
1291 def test_save_with_no_args():
1273 ip = get_ipython()
1292 ip = get_ipython()
1274 ip.history_manager.reset() # Clear any existing history.
1293 ip.history_manager.reset() # Clear any existing history.
1275 cmds = ["a=1", "def b():\n return a**2", "print(a, b())", "%save"]
1294 cmds = ["a=1", "def b():\n return a**2", "print(a, b())", "%save"]
1276 for i, cmd in enumerate(cmds, start=1):
1295 for i, cmd in enumerate(cmds, start=1):
1277 ip.history_manager.store_inputs(i, cmd)
1296 ip.history_manager.store_inputs(i, cmd)
1278
1297
1279 with TemporaryDirectory() as tmpdir:
1298 with TemporaryDirectory() as tmpdir:
1280 path = os.path.join(tmpdir, "testsave.py")
1299 path = os.path.join(tmpdir, "testsave.py")
1281 ip.run_line_magic("save", path)
1300 ip.run_line_magic("save", path)
1282 content = Path(path).read_text(encoding="utf-8")
1301 content = Path(path).read_text(encoding="utf-8")
1283 expected_content = dedent(
1302 expected_content = dedent(
1284 """\
1303 """\
1285 # coding: utf-8
1304 # coding: utf-8
1286 a=1
1305 a=1
1287 def b():
1306 def b():
1288 return a**2
1307 return a**2
1289 print(a, b())
1308 print(a, b())
1290 """
1309 """
1291 )
1310 )
1292 assert content == expected_content
1311 assert content == expected_content
1293
1312
1294
1313
1295 def test_store():
1314 def test_store():
1296 """Test %store."""
1315 """Test %store."""
1297 ip = get_ipython()
1316 ip = get_ipython()
1298 ip.run_line_magic('load_ext', 'storemagic')
1317 ip.run_line_magic('load_ext', 'storemagic')
1299
1318
1300 # make sure the storage is empty
1319 # make sure the storage is empty
1301 ip.run_line_magic("store", "-z")
1320 ip.run_line_magic("store", "-z")
1302 ip.user_ns["var"] = 42
1321 ip.user_ns["var"] = 42
1303 ip.run_line_magic("store", "var")
1322 ip.run_line_magic("store", "var")
1304 ip.user_ns["var"] = 39
1323 ip.user_ns["var"] = 39
1305 ip.run_line_magic("store", "-r")
1324 ip.run_line_magic("store", "-r")
1306 assert ip.user_ns["var"] == 42
1325 assert ip.user_ns["var"] == 42
1307
1326
1308 ip.run_line_magic("store", "-d var")
1327 ip.run_line_magic("store", "-d var")
1309 ip.user_ns["var"] = 39
1328 ip.user_ns["var"] = 39
1310 ip.run_line_magic("store", "-r")
1329 ip.run_line_magic("store", "-r")
1311 assert ip.user_ns["var"] == 39
1330 assert ip.user_ns["var"] == 39
1312
1331
1313
1332
1314 def _run_edit_test(arg_s, exp_filename=None,
1333 def _run_edit_test(arg_s, exp_filename=None,
1315 exp_lineno=-1,
1334 exp_lineno=-1,
1316 exp_contents=None,
1335 exp_contents=None,
1317 exp_is_temp=None):
1336 exp_is_temp=None):
1318 ip = get_ipython()
1337 ip = get_ipython()
1319 M = code.CodeMagics(ip)
1338 M = code.CodeMagics(ip)
1320 last_call = ['','']
1339 last_call = ['','']
1321 opts,args = M.parse_options(arg_s,'prxn:')
1340 opts,args = M.parse_options(arg_s,'prxn:')
1322 filename, lineno, is_temp = M._find_edit_target(ip, args, opts, last_call)
1341 filename, lineno, is_temp = M._find_edit_target(ip, args, opts, last_call)
1323
1342
1324 if exp_filename is not None:
1343 if exp_filename is not None:
1325 assert exp_filename == filename
1344 assert exp_filename == filename
1326 if exp_contents is not None:
1345 if exp_contents is not None:
1327 with io.open(filename, 'r', encoding='utf-8') as f:
1346 with io.open(filename, 'r', encoding='utf-8') as f:
1328 contents = f.read()
1347 contents = f.read()
1329 assert exp_contents == contents
1348 assert exp_contents == contents
1330 if exp_lineno != -1:
1349 if exp_lineno != -1:
1331 assert exp_lineno == lineno
1350 assert exp_lineno == lineno
1332 if exp_is_temp is not None:
1351 if exp_is_temp is not None:
1333 assert exp_is_temp == is_temp
1352 assert exp_is_temp == is_temp
1334
1353
1335
1354
1336 def test_edit_interactive():
1355 def test_edit_interactive():
1337 """%edit on interactively defined objects"""
1356 """%edit on interactively defined objects"""
1338 ip = get_ipython()
1357 ip = get_ipython()
1339 n = ip.execution_count
1358 n = ip.execution_count
1340 ip.run_cell("def foo(): return 1", store_history=True)
1359 ip.run_cell("def foo(): return 1", store_history=True)
1341
1360
1342 with pytest.raises(code.InteractivelyDefined) as e:
1361 with pytest.raises(code.InteractivelyDefined) as e:
1343 _run_edit_test("foo")
1362 _run_edit_test("foo")
1344 assert e.value.index == n
1363 assert e.value.index == n
1345
1364
1346
1365
1347 def test_edit_cell():
1366 def test_edit_cell():
1348 """%edit [cell id]"""
1367 """%edit [cell id]"""
1349 ip = get_ipython()
1368 ip = get_ipython()
1350
1369
1351 ip.run_cell("def foo(): return 1", store_history=True)
1370 ip.run_cell("def foo(): return 1", store_history=True)
1352
1371
1353 # test
1372 # test
1354 _run_edit_test("1", exp_contents=ip.user_ns['In'][1], exp_is_temp=True)
1373 _run_edit_test("1", exp_contents=ip.user_ns['In'][1], exp_is_temp=True)
1355
1374
1356 def test_edit_fname():
1375 def test_edit_fname():
1357 """%edit file"""
1376 """%edit file"""
1358 # test
1377 # test
1359 _run_edit_test("test file.py", exp_filename="test file.py")
1378 _run_edit_test("test file.py", exp_filename="test file.py")
1360
1379
1361 def test_bookmark():
1380 def test_bookmark():
1362 ip = get_ipython()
1381 ip = get_ipython()
1363 ip.run_line_magic('bookmark', 'bmname')
1382 ip.run_line_magic('bookmark', 'bmname')
1364 with tt.AssertPrints('bmname'):
1383 with tt.AssertPrints('bmname'):
1365 ip.run_line_magic('bookmark', '-l')
1384 ip.run_line_magic('bookmark', '-l')
1366 ip.run_line_magic('bookmark', '-d bmname')
1385 ip.run_line_magic('bookmark', '-d bmname')
1367
1386
1368 def test_ls_magic():
1387 def test_ls_magic():
1369 ip = get_ipython()
1388 ip = get_ipython()
1370 json_formatter = ip.display_formatter.formatters['application/json']
1389 json_formatter = ip.display_formatter.formatters['application/json']
1371 json_formatter.enabled = True
1390 json_formatter.enabled = True
1372 lsmagic = ip.run_line_magic("lsmagic", "")
1391 lsmagic = ip.run_line_magic("lsmagic", "")
1373 with warnings.catch_warnings(record=True) as w:
1392 with warnings.catch_warnings(record=True) as w:
1374 j = json_formatter(lsmagic)
1393 j = json_formatter(lsmagic)
1375 assert sorted(j) == ["cell", "line"]
1394 assert sorted(j) == ["cell", "line"]
1376 assert w == [] # no warnings
1395 assert w == [] # no warnings
1377
1396
1378
1397
1379 def test_strip_initial_indent():
1398 def test_strip_initial_indent():
1380 def sii(s):
1399 def sii(s):
1381 lines = s.splitlines()
1400 lines = s.splitlines()
1382 return '\n'.join(code.strip_initial_indent(lines))
1401 return '\n'.join(code.strip_initial_indent(lines))
1383
1402
1384 assert sii(" a = 1\nb = 2") == "a = 1\nb = 2"
1403 assert sii(" a = 1\nb = 2") == "a = 1\nb = 2"
1385 assert sii(" a\n b\nc") == "a\n b\nc"
1404 assert sii(" a\n b\nc") == "a\n b\nc"
1386 assert sii("a\n b") == "a\n b"
1405 assert sii("a\n b") == "a\n b"
1387
1406
1388 def test_logging_magic_quiet_from_arg():
1407 def test_logging_magic_quiet_from_arg():
1389 _ip.config.LoggingMagics.quiet = False
1408 _ip.config.LoggingMagics.quiet = False
1390 lm = logging.LoggingMagics(shell=_ip)
1409 lm = logging.LoggingMagics(shell=_ip)
1391 with TemporaryDirectory() as td:
1410 with TemporaryDirectory() as td:
1392 try:
1411 try:
1393 with tt.AssertNotPrints(re.compile("Activating.*")):
1412 with tt.AssertNotPrints(re.compile("Activating.*")):
1394 lm.logstart('-q {}'.format(
1413 lm.logstart('-q {}'.format(
1395 os.path.join(td, "quiet_from_arg.log")))
1414 os.path.join(td, "quiet_from_arg.log")))
1396 finally:
1415 finally:
1397 _ip.logger.logstop()
1416 _ip.logger.logstop()
1398
1417
1399 def test_logging_magic_quiet_from_config():
1418 def test_logging_magic_quiet_from_config():
1400 _ip.config.LoggingMagics.quiet = True
1419 _ip.config.LoggingMagics.quiet = True
1401 lm = logging.LoggingMagics(shell=_ip)
1420 lm = logging.LoggingMagics(shell=_ip)
1402 with TemporaryDirectory() as td:
1421 with TemporaryDirectory() as td:
1403 try:
1422 try:
1404 with tt.AssertNotPrints(re.compile("Activating.*")):
1423 with tt.AssertNotPrints(re.compile("Activating.*")):
1405 lm.logstart(os.path.join(td, "quiet_from_config.log"))
1424 lm.logstart(os.path.join(td, "quiet_from_config.log"))
1406 finally:
1425 finally:
1407 _ip.logger.logstop()
1426 _ip.logger.logstop()
1408
1427
1409
1428
1410 def test_logging_magic_not_quiet():
1429 def test_logging_magic_not_quiet():
1411 _ip.config.LoggingMagics.quiet = False
1430 _ip.config.LoggingMagics.quiet = False
1412 lm = logging.LoggingMagics(shell=_ip)
1431 lm = logging.LoggingMagics(shell=_ip)
1413 with TemporaryDirectory() as td:
1432 with TemporaryDirectory() as td:
1414 try:
1433 try:
1415 with tt.AssertPrints(re.compile("Activating.*")):
1434 with tt.AssertPrints(re.compile("Activating.*")):
1416 lm.logstart(os.path.join(td, "not_quiet.log"))
1435 lm.logstart(os.path.join(td, "not_quiet.log"))
1417 finally:
1436 finally:
1418 _ip.logger.logstop()
1437 _ip.logger.logstop()
1419
1438
1420
1439
1421 def test_time_no_var_expand():
1440 def test_time_no_var_expand():
1422 _ip.user_ns["a"] = 5
1441 _ip.user_ns["a"] = 5
1423 _ip.user_ns["b"] = []
1442 _ip.user_ns["b"] = []
1424 _ip.run_line_magic("time", 'b.append("{a}")')
1443 _ip.run_line_magic("time", 'b.append("{a}")')
1425 assert _ip.user_ns["b"] == ["{a}"]
1444 assert _ip.user_ns["b"] == ["{a}"]
1426
1445
1427
1446
1428 # this is slow, put at the end for local testing.
1447 # this is slow, put at the end for local testing.
1429 def test_timeit_arguments():
1448 def test_timeit_arguments():
1430 "Test valid timeit arguments, should not cause SyntaxError (GH #1269)"
1449 "Test valid timeit arguments, should not cause SyntaxError (GH #1269)"
1431 _ip.run_line_magic("timeit", "-n1 -r1 a=('#')")
1450 _ip.run_line_magic("timeit", "-n1 -r1 a=('#')")
1432
1451
1433
1452
1434 MINIMAL_LAZY_MAGIC = """
1453 MINIMAL_LAZY_MAGIC = """
1435 from IPython.core.magic import (
1454 from IPython.core.magic import (
1436 Magics,
1455 Magics,
1437 magics_class,
1456 magics_class,
1438 line_magic,
1457 line_magic,
1439 cell_magic,
1458 cell_magic,
1440 )
1459 )
1441
1460
1442
1461
1443 @magics_class
1462 @magics_class
1444 class LazyMagics(Magics):
1463 class LazyMagics(Magics):
1445 @line_magic
1464 @line_magic
1446 def lazy_line(self, line):
1465 def lazy_line(self, line):
1447 print("Lazy Line")
1466 print("Lazy Line")
1448
1467
1449 @cell_magic
1468 @cell_magic
1450 def lazy_cell(self, line, cell):
1469 def lazy_cell(self, line, cell):
1451 print("Lazy Cell")
1470 print("Lazy Cell")
1452
1471
1453
1472
1454 def load_ipython_extension(ipython):
1473 def load_ipython_extension(ipython):
1455 ipython.register_magics(LazyMagics)
1474 ipython.register_magics(LazyMagics)
1456 """
1475 """
1457
1476
1458
1477
1459 def test_lazy_magics():
1478 def test_lazy_magics():
1460 with pytest.raises(UsageError):
1479 with pytest.raises(UsageError):
1461 ip.run_line_magic("lazy_line", "")
1480 ip.run_line_magic("lazy_line", "")
1462
1481
1463 startdir = os.getcwd()
1482 startdir = os.getcwd()
1464
1483
1465 with TemporaryDirectory() as tmpdir:
1484 with TemporaryDirectory() as tmpdir:
1466 with prepended_to_syspath(tmpdir):
1485 with prepended_to_syspath(tmpdir):
1467 ptempdir = Path(tmpdir)
1486 ptempdir = Path(tmpdir)
1468 tf = ptempdir / "lazy_magic_module.py"
1487 tf = ptempdir / "lazy_magic_module.py"
1469 tf.write_text(MINIMAL_LAZY_MAGIC)
1488 tf.write_text(MINIMAL_LAZY_MAGIC)
1470 ip.magics_manager.register_lazy("lazy_line", Path(tf.name).name[:-3])
1489 ip.magics_manager.register_lazy("lazy_line", Path(tf.name).name[:-3])
1471 with tt.AssertPrints("Lazy Line"):
1490 with tt.AssertPrints("Lazy Line"):
1472 ip.run_line_magic("lazy_line", "")
1491 ip.run_line_magic("lazy_line", "")
1473
1492
1474
1493
1475 TEST_MODULE = """
1494 TEST_MODULE = """
1476 print('Loaded my_tmp')
1495 print('Loaded my_tmp')
1477 if __name__ == "__main__":
1496 if __name__ == "__main__":
1478 print('I just ran a script')
1497 print('I just ran a script')
1479 """
1498 """
1480
1499
1481 def test_run_module_from_import_hook():
1500 def test_run_module_from_import_hook():
1482 "Test that a module can be loaded via an import hook"
1501 "Test that a module can be loaded via an import hook"
1483 with TemporaryDirectory() as tmpdir:
1502 with TemporaryDirectory() as tmpdir:
1484 fullpath = os.path.join(tmpdir, "my_tmp.py")
1503 fullpath = os.path.join(tmpdir, "my_tmp.py")
1485 Path(fullpath).write_text(TEST_MODULE, encoding="utf-8")
1504 Path(fullpath).write_text(TEST_MODULE, encoding="utf-8")
1486
1505
1487 import importlib.abc
1506 import importlib.abc
1488 import importlib.util
1507 import importlib.util
1489
1508
1490 class MyTempImporter(importlib.abc.MetaPathFinder, importlib.abc.SourceLoader):
1509 class MyTempImporter(importlib.abc.MetaPathFinder, importlib.abc.SourceLoader):
1491 def find_spec(self, fullname, path, target=None):
1510 def find_spec(self, fullname, path, target=None):
1492 if fullname == "my_tmp":
1511 if fullname == "my_tmp":
1493 return importlib.util.spec_from_loader(fullname, self)
1512 return importlib.util.spec_from_loader(fullname, self)
1494
1513
1495 def get_filename(self, fullname):
1514 def get_filename(self, fullname):
1496 assert fullname == "my_tmp"
1515 assert fullname == "my_tmp"
1497 return fullpath
1516 return fullpath
1498
1517
1499 def get_data(self, path):
1518 def get_data(self, path):
1500 assert Path(path).samefile(fullpath)
1519 assert Path(path).samefile(fullpath)
1501 return Path(fullpath).read_text(encoding="utf-8")
1520 return Path(fullpath).read_text(encoding="utf-8")
1502
1521
1503 sys.meta_path.insert(0, MyTempImporter())
1522 sys.meta_path.insert(0, MyTempImporter())
1504
1523
1505 with capture_output() as captured:
1524 with capture_output() as captured:
1506 _ip.run_line_magic("run", "-m my_tmp")
1525 _ip.run_line_magic("run", "-m my_tmp")
1507 _ip.run_cell("import my_tmp")
1526 _ip.run_cell("import my_tmp")
1508
1527
1509 output = "Loaded my_tmp\nI just ran a script\nLoaded my_tmp\n"
1528 output = "Loaded my_tmp\nI just ran a script\nLoaded my_tmp\n"
1510 assert output == captured.stdout
1529 assert output == captured.stdout
1511
1530
1512 sys.meta_path.pop(0)
1531 sys.meta_path.pop(0)
General Comments 0
You need to be logged in to leave comments. Login now