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