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