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