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