##// END OF EJS Templates
Merge pull request #12301 from datadesk/run-magic-raise-errors
Matthias Bussonnier -
r25792:c24e8af4 merge
parent child Browse files
Show More
@@ -1,1492 +1,1490 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 454 else:
455 455 code = "\n".join(args.statement)
456 456 if cell:
457 457 code += "\n" + cell
458 458 self._debug_exec(code, args.breakpoint)
459 459
460 460 def _debug_post_mortem(self):
461 461 self.shell.debugger(force=True)
462 462
463 463 def _debug_exec(self, code, breakpoint):
464 464 if breakpoint:
465 465 (filename, bp_line) = breakpoint.rsplit(':', 1)
466 466 bp_line = int(bp_line)
467 467 else:
468 468 (filename, bp_line) = (None, None)
469 469 self._run_with_debugger(code, self.shell.user_ns, filename, bp_line)
470 470
471 471 @line_magic
472 472 def tb(self, s):
473 473 """Print the last traceback.
474 474
475 475 Optionally, specify an exception reporting mode, tuning the
476 476 verbosity of the traceback. By default the currently-active exception
477 477 mode is used. See %xmode for changing exception reporting modes.
478 478
479 479 Valid modes: Plain, Context, Verbose, and Minimal.
480 480 """
481 481 interactive_tb = self.shell.InteractiveTB
482 482 if s:
483 483 # Switch exception reporting mode for this one call.
484 484 # Ensure it is switched back.
485 485 def xmode_switch_err(name):
486 486 warn('Error changing %s exception modes.\n%s' %
487 487 (name,sys.exc_info()[1]))
488 488
489 489 new_mode = s.strip().capitalize()
490 490 original_mode = interactive_tb.mode
491 491 try:
492 492 try:
493 493 interactive_tb.set_mode(mode=new_mode)
494 494 except Exception:
495 495 xmode_switch_err('user')
496 496 else:
497 497 self.shell.showtraceback()
498 498 finally:
499 499 interactive_tb.set_mode(mode=original_mode)
500 500 else:
501 501 self.shell.showtraceback()
502 502
503 503 @skip_doctest
504 504 @line_magic
505 505 def run(self, parameter_s='', runner=None,
506 506 file_finder=get_py_filename):
507 507 """Run the named file inside IPython as a program.
508 508
509 509 Usage::
510 510
511 511 %run [-n -i -e -G]
512 512 [( -t [-N<N>] | -d [-b<N>] | -p [profile options] )]
513 513 ( -m mod | file ) [args]
514 514
515 515 Parameters after the filename are passed as command-line arguments to
516 516 the program (put in sys.argv). Then, control returns to IPython's
517 517 prompt.
518 518
519 519 This is similar to running at a system prompt ``python file args``,
520 520 but with the advantage of giving you IPython's tracebacks, and of
521 521 loading all variables into your interactive namespace for further use
522 522 (unless -p is used, see below).
523 523
524 524 The file is executed in a namespace initially consisting only of
525 525 ``__name__=='__main__'`` and sys.argv constructed as indicated. It thus
526 526 sees its environment as if it were being run as a stand-alone program
527 527 (except for sharing global objects such as previously imported
528 528 modules). But after execution, the IPython interactive namespace gets
529 529 updated with all variables defined in the program (except for __name__
530 530 and sys.argv). This allows for very convenient loading of code for
531 531 interactive work, while giving each program a 'clean sheet' to run in.
532 532
533 533 Arguments are expanded using shell-like glob match. Patterns
534 534 '*', '?', '[seq]' and '[!seq]' can be used. Additionally,
535 535 tilde '~' will be expanded into user's home directory. Unlike
536 536 real shells, quotation does not suppress expansions. Use
537 537 *two* back slashes (e.g. ``\\\\*``) to suppress expansions.
538 538 To completely disable these expansions, you can use -G flag.
539 539
540 540 On Windows systems, the use of single quotes `'` when specifying
541 541 a file is not supported. Use double quotes `"`.
542 542
543 543 Options:
544 544
545 545 -n
546 546 __name__ is NOT set to '__main__', but to the running file's name
547 547 without extension (as python does under import). This allows running
548 548 scripts and reloading the definitions in them without calling code
549 549 protected by an ``if __name__ == "__main__"`` clause.
550 550
551 551 -i
552 552 run the file in IPython's namespace instead of an empty one. This
553 553 is useful if you are experimenting with code written in a text editor
554 554 which depends on variables defined interactively.
555 555
556 556 -e
557 557 ignore sys.exit() calls or SystemExit exceptions in the script
558 558 being run. This is particularly useful if IPython is being used to
559 559 run unittests, which always exit with a sys.exit() call. In such
560 560 cases you are interested in the output of the test results, not in
561 561 seeing a traceback of the unittest module.
562 562
563 563 -t
564 564 print timing information at the end of the run. IPython will give
565 565 you an estimated CPU time consumption for your script, which under
566 566 Unix uses the resource module to avoid the wraparound problems of
567 567 time.clock(). Under Unix, an estimate of time spent on system tasks
568 568 is also given (for Windows platforms this is reported as 0.0).
569 569
570 570 If -t is given, an additional ``-N<N>`` option can be given, where <N>
571 571 must be an integer indicating how many times you want the script to
572 572 run. The final timing report will include total and per run results.
573 573
574 574 For example (testing the script uniq_stable.py)::
575 575
576 576 In [1]: run -t uniq_stable
577 577
578 578 IPython CPU timings (estimated):
579 579 User : 0.19597 s.
580 580 System: 0.0 s.
581 581
582 582 In [2]: run -t -N5 uniq_stable
583 583
584 584 IPython CPU timings (estimated):
585 585 Total runs performed: 5
586 586 Times : Total Per run
587 587 User : 0.910862 s, 0.1821724 s.
588 588 System: 0.0 s, 0.0 s.
589 589
590 590 -d
591 591 run your program under the control of pdb, the Python debugger.
592 592 This allows you to execute your program step by step, watch variables,
593 593 etc. Internally, what IPython does is similar to calling::
594 594
595 595 pdb.run('execfile("YOURFILENAME")')
596 596
597 597 with a breakpoint set on line 1 of your file. You can change the line
598 598 number for this automatic breakpoint to be <N> by using the -bN option
599 599 (where N must be an integer). For example::
600 600
601 601 %run -d -b40 myscript
602 602
603 603 will set the first breakpoint at line 40 in myscript.py. Note that
604 604 the first breakpoint must be set on a line which actually does
605 605 something (not a comment or docstring) for it to stop execution.
606 606
607 607 Or you can specify a breakpoint in a different file::
608 608
609 609 %run -d -b myotherfile.py:20 myscript
610 610
611 611 When the pdb debugger starts, you will see a (Pdb) prompt. You must
612 612 first enter 'c' (without quotes) to start execution up to the first
613 613 breakpoint.
614 614
615 615 Entering 'help' gives information about the use of the debugger. You
616 616 can easily see pdb's full documentation with "import pdb;pdb.help()"
617 617 at a prompt.
618 618
619 619 -p
620 620 run program under the control of the Python profiler module (which
621 621 prints a detailed report of execution times, function calls, etc).
622 622
623 623 You can pass other options after -p which affect the behavior of the
624 624 profiler itself. See the docs for %prun for details.
625 625
626 626 In this mode, the program's variables do NOT propagate back to the
627 627 IPython interactive namespace (because they remain in the namespace
628 628 where the profiler executes them).
629 629
630 630 Internally this triggers a call to %prun, see its documentation for
631 631 details on the options available specifically for profiling.
632 632
633 633 There is one special usage for which the text above doesn't apply:
634 634 if the filename ends with .ipy[nb], the file is run as ipython script,
635 635 just as if the commands were written on IPython prompt.
636 636
637 637 -m
638 638 specify module name to load instead of script path. Similar to
639 639 the -m option for the python interpreter. Use this option last if you
640 640 want to combine with other %run options. Unlike the python interpreter
641 641 only source modules are allowed no .pyc or .pyo files.
642 642 For example::
643 643
644 644 %run -m example
645 645
646 646 will run the example module.
647 647
648 648 -G
649 649 disable shell-like glob expansion of arguments.
650 650
651 651 """
652 652
653 653 # Logic to handle issue #3664
654 654 # Add '--' after '-m <module_name>' to ignore additional args passed to a module.
655 655 if '-m' in parameter_s and '--' not in parameter_s:
656 656 argv = shlex.split(parameter_s, posix=(os.name == 'posix'))
657 657 for idx, arg in enumerate(argv):
658 658 if arg and arg.startswith('-') and arg != '-':
659 659 if arg == '-m':
660 660 argv.insert(idx + 2, '--')
661 661 break
662 662 else:
663 663 # Positional arg, break
664 664 break
665 665 parameter_s = ' '.join(shlex.quote(arg) for arg in argv)
666 666
667 667 # get arguments and set sys.argv for program to be run.
668 668 opts, arg_lst = self.parse_options(parameter_s,
669 669 'nidtN:b:pD:l:rs:T:em:G',
670 670 mode='list', list_all=1)
671 671 if "m" in opts:
672 672 modulename = opts["m"][0]
673 673 modpath = find_mod(modulename)
674 674 if modpath is None:
675 warn('%r is not a valid modulename on sys.path'%modulename)
676 return
675 msg = '%r is not a valid modulename on sys.path'%modulename
676 raise Exception(msg)
677 677 arg_lst = [modpath] + arg_lst
678 678 try:
679 679 fpath = None # initialize to make sure fpath is in scope later
680 680 fpath = arg_lst[0]
681 681 filename = file_finder(fpath)
682 682 except IndexError:
683 warn('you must provide at least a filename.')
684 print('\n%run:\n', oinspect.getdoc(self.run))
685 return
683 msg = 'you must provide at least a filename.'
684 raise Exception(msg)
686 685 except IOError as e:
687 686 try:
688 687 msg = str(e)
689 688 except UnicodeError:
690 689 msg = e.message
691 690 if os.name == 'nt' and re.match(r"^'.*'$",fpath):
692 691 warn('For Windows, use double quotes to wrap a filename: %run "mypath\\myfile.py"')
693 error(msg)
694 return
692 raise Exception(msg)
695 693 except TypeError:
696 694 if fpath in sys.meta_path:
697 695 filename = ""
698 696 else:
699 697 raise
700 698
701 699 if filename.lower().endswith(('.ipy', '.ipynb')):
702 700 with preserve_keys(self.shell.user_ns, '__file__'):
703 701 self.shell.user_ns['__file__'] = filename
704 self.shell.safe_execfile_ipy(filename)
702 self.shell.safe_execfile_ipy(filename, raise_exceptions=True)
705 703 return
706 704
707 705 # Control the response to exit() calls made by the script being run
708 706 exit_ignore = 'e' in opts
709 707
710 708 # Make sure that the running script gets a proper sys.argv as if it
711 709 # were run from a system shell.
712 710 save_argv = sys.argv # save it for later restoring
713 711
714 712 if 'G' in opts:
715 713 args = arg_lst[1:]
716 714 else:
717 715 # tilde and glob expansion
718 716 args = shellglob(map(os.path.expanduser, arg_lst[1:]))
719 717
720 718 sys.argv = [filename] + args # put in the proper filename
721 719
722 720 if 'n' in opts:
723 721 name = os.path.splitext(os.path.basename(filename))[0]
724 722 else:
725 723 name = '__main__'
726 724
727 725 if 'i' in opts:
728 726 # Run in user's interactive namespace
729 727 prog_ns = self.shell.user_ns
730 728 __name__save = self.shell.user_ns['__name__']
731 729 prog_ns['__name__'] = name
732 730 main_mod = self.shell.user_module
733 731
734 732 # Since '%run foo' emulates 'python foo.py' at the cmd line, we must
735 733 # set the __file__ global in the script's namespace
736 734 # TK: Is this necessary in interactive mode?
737 735 prog_ns['__file__'] = filename
738 736 else:
739 737 # Run in a fresh, empty namespace
740 738
741 739 # The shell MUST hold a reference to prog_ns so after %run
742 740 # exits, the python deletion mechanism doesn't zero it out
743 741 # (leaving dangling references). See interactiveshell for details
744 742 main_mod = self.shell.new_main_mod(filename, name)
745 743 prog_ns = main_mod.__dict__
746 744
747 745 # pickle fix. See interactiveshell for an explanation. But we need to
748 746 # make sure that, if we overwrite __main__, we replace it at the end
749 747 main_mod_name = prog_ns['__name__']
750 748
751 749 if main_mod_name == '__main__':
752 750 restore_main = sys.modules['__main__']
753 751 else:
754 752 restore_main = False
755 753
756 754 # This needs to be undone at the end to prevent holding references to
757 755 # every single object ever created.
758 756 sys.modules[main_mod_name] = main_mod
759 757
760 758 if 'p' in opts or 'd' in opts:
761 759 if 'm' in opts:
762 760 code = 'run_module(modulename, prog_ns)'
763 761 code_ns = {
764 762 'run_module': self.shell.safe_run_module,
765 763 'prog_ns': prog_ns,
766 764 'modulename': modulename,
767 765 }
768 766 else:
769 767 if 'd' in opts:
770 768 # allow exceptions to raise in debug mode
771 769 code = 'execfile(filename, prog_ns, raise_exceptions=True)'
772 770 else:
773 771 code = 'execfile(filename, prog_ns)'
774 772 code_ns = {
775 773 'execfile': self.shell.safe_execfile,
776 774 'prog_ns': prog_ns,
777 775 'filename': get_py_filename(filename),
778 776 }
779 777
780 778 try:
781 779 stats = None
782 780 if 'p' in opts:
783 781 stats = self._run_with_profiler(code, opts, code_ns)
784 782 else:
785 783 if 'd' in opts:
786 784 bp_file, bp_line = parse_breakpoint(
787 785 opts.get('b', ['1'])[0], filename)
788 786 self._run_with_debugger(
789 787 code, code_ns, filename, bp_line, bp_file)
790 788 else:
791 789 if 'm' in opts:
792 790 def run():
793 791 self.shell.safe_run_module(modulename, prog_ns)
794 792 else:
795 793 if runner is None:
796 794 runner = self.default_runner
797 795 if runner is None:
798 796 runner = self.shell.safe_execfile
799 797
800 798 def run():
801 799 runner(filename, prog_ns, prog_ns,
802 800 exit_ignore=exit_ignore)
803 801
804 802 if 't' in opts:
805 803 # timed execution
806 804 try:
807 805 nruns = int(opts['N'][0])
808 806 if nruns < 1:
809 807 error('Number of runs must be >=1')
810 808 return
811 809 except (KeyError):
812 810 nruns = 1
813 811 self._run_with_timing(run, nruns)
814 812 else:
815 813 # regular execution
816 814 run()
817 815
818 816 if 'i' in opts:
819 817 self.shell.user_ns['__name__'] = __name__save
820 818 else:
821 819 # update IPython interactive namespace
822 820
823 821 # Some forms of read errors on the file may mean the
824 822 # __name__ key was never set; using pop we don't have to
825 823 # worry about a possible KeyError.
826 824 prog_ns.pop('__name__', None)
827 825
828 826 with preserve_keys(self.shell.user_ns, '__file__'):
829 827 self.shell.user_ns.update(prog_ns)
830 828 finally:
831 829 # It's a bit of a mystery why, but __builtins__ can change from
832 830 # being a module to becoming a dict missing some key data after
833 831 # %run. As best I can see, this is NOT something IPython is doing
834 832 # at all, and similar problems have been reported before:
835 833 # http://coding.derkeiler.com/Archive/Python/comp.lang.python/2004-10/0188.html
836 834 # Since this seems to be done by the interpreter itself, the best
837 835 # we can do is to at least restore __builtins__ for the user on
838 836 # exit.
839 837 self.shell.user_ns['__builtins__'] = builtin_mod
840 838
841 839 # Ensure key global structures are restored
842 840 sys.argv = save_argv
843 841 if restore_main:
844 842 sys.modules['__main__'] = restore_main
845 843 if '__mp_main__' in sys.modules:
846 844 sys.modules['__mp_main__'] = restore_main
847 845 else:
848 846 # Remove from sys.modules the reference to main_mod we'd
849 847 # added. Otherwise it will trap references to objects
850 848 # contained therein.
851 849 del sys.modules[main_mod_name]
852 850
853 851 return stats
854 852
855 853 def _run_with_debugger(self, code, code_ns, filename=None,
856 854 bp_line=None, bp_file=None):
857 855 """
858 856 Run `code` in debugger with a break point.
859 857
860 858 Parameters
861 859 ----------
862 860 code : str
863 861 Code to execute.
864 862 code_ns : dict
865 863 A namespace in which `code` is executed.
866 864 filename : str
867 865 `code` is ran as if it is in `filename`.
868 866 bp_line : int, optional
869 867 Line number of the break point.
870 868 bp_file : str, optional
871 869 Path to the file in which break point is specified.
872 870 `filename` is used if not given.
873 871
874 872 Raises
875 873 ------
876 874 UsageError
877 875 If the break point given by `bp_line` is not valid.
878 876
879 877 """
880 878 deb = self.shell.InteractiveTB.pdb
881 879 if not deb:
882 880 self.shell.InteractiveTB.pdb = self.shell.InteractiveTB.debugger_cls()
883 881 deb = self.shell.InteractiveTB.pdb
884 882
885 883 # deb.checkline() fails if deb.curframe exists but is None; it can
886 884 # handle it not existing. https://github.com/ipython/ipython/issues/10028
887 885 if hasattr(deb, 'curframe'):
888 886 del deb.curframe
889 887
890 888 # reset Breakpoint state, which is moronically kept
891 889 # in a class
892 890 bdb.Breakpoint.next = 1
893 891 bdb.Breakpoint.bplist = {}
894 892 bdb.Breakpoint.bpbynumber = [None]
895 893 deb.clear_all_breaks()
896 894 if bp_line is not None:
897 895 # Set an initial breakpoint to stop execution
898 896 maxtries = 10
899 897 bp_file = bp_file or filename
900 898 checkline = deb.checkline(bp_file, bp_line)
901 899 if not checkline:
902 900 for bp in range(bp_line + 1, bp_line + maxtries + 1):
903 901 if deb.checkline(bp_file, bp):
904 902 break
905 903 else:
906 904 msg = ("\nI failed to find a valid line to set "
907 905 "a breakpoint\n"
908 906 "after trying up to line: %s.\n"
909 907 "Please set a valid breakpoint manually "
910 908 "with the -b option." % bp)
911 909 raise UsageError(msg)
912 910 # if we find a good linenumber, set the breakpoint
913 911 deb.do_break('%s:%s' % (bp_file, bp_line))
914 912
915 913 if filename:
916 914 # Mimic Pdb._runscript(...)
917 915 deb._wait_for_mainpyfile = True
918 916 deb.mainpyfile = deb.canonic(filename)
919 917
920 918 # Start file run
921 919 print("NOTE: Enter 'c' at the %s prompt to continue execution." % deb.prompt)
922 920 try:
923 921 if filename:
924 922 # save filename so it can be used by methods on the deb object
925 923 deb._exec_filename = filename
926 924 while True:
927 925 try:
928 926 trace = sys.gettrace()
929 927 deb.run(code, code_ns)
930 928 except Restart:
931 929 print("Restarting")
932 930 if filename:
933 931 deb._wait_for_mainpyfile = True
934 932 deb.mainpyfile = deb.canonic(filename)
935 933 continue
936 934 else:
937 935 break
938 936 finally:
939 937 sys.settrace(trace)
940 938
941 939
942 940 except:
943 941 etype, value, tb = sys.exc_info()
944 942 # Skip three frames in the traceback: the %run one,
945 943 # one inside bdb.py, and the command-line typed by the
946 944 # user (run by exec in pdb itself).
947 945 self.shell.InteractiveTB(etype, value, tb, tb_offset=3)
948 946
949 947 @staticmethod
950 948 def _run_with_timing(run, nruns):
951 949 """
952 950 Run function `run` and print timing information.
953 951
954 952 Parameters
955 953 ----------
956 954 run : callable
957 955 Any callable object which takes no argument.
958 956 nruns : int
959 957 Number of times to execute `run`.
960 958
961 959 """
962 960 twall0 = time.perf_counter()
963 961 if nruns == 1:
964 962 t0 = clock2()
965 963 run()
966 964 t1 = clock2()
967 965 t_usr = t1[0] - t0[0]
968 966 t_sys = t1[1] - t0[1]
969 967 print("\nIPython CPU timings (estimated):")
970 968 print(" User : %10.2f s." % t_usr)
971 969 print(" System : %10.2f s." % t_sys)
972 970 else:
973 971 runs = range(nruns)
974 972 t0 = clock2()
975 973 for nr in runs:
976 974 run()
977 975 t1 = clock2()
978 976 t_usr = t1[0] - t0[0]
979 977 t_sys = t1[1] - t0[1]
980 978 print("\nIPython CPU timings (estimated):")
981 979 print("Total runs performed:", nruns)
982 980 print(" Times : %10s %10s" % ('Total', 'Per run'))
983 981 print(" User : %10.2f s, %10.2f s." % (t_usr, t_usr / nruns))
984 982 print(" System : %10.2f s, %10.2f s." % (t_sys, t_sys / nruns))
985 983 twall1 = time.perf_counter()
986 984 print("Wall time: %10.2f s." % (twall1 - twall0))
987 985
988 986 @skip_doctest
989 987 @no_var_expand
990 988 @line_cell_magic
991 989 @needs_local_scope
992 990 def timeit(self, line='', cell=None, local_ns=None):
993 991 """Time execution of a Python statement or expression
994 992
995 993 Usage, in line mode:
996 994 %timeit [-n<N> -r<R> [-t|-c] -q -p<P> -o] statement
997 995 or in cell mode:
998 996 %%timeit [-n<N> -r<R> [-t|-c] -q -p<P> -o] setup_code
999 997 code
1000 998 code...
1001 999
1002 1000 Time execution of a Python statement or expression using the timeit
1003 1001 module. This function can be used both as a line and cell magic:
1004 1002
1005 1003 - In line mode you can time a single-line statement (though multiple
1006 1004 ones can be chained with using semicolons).
1007 1005
1008 1006 - In cell mode, the statement in the first line is used as setup code
1009 1007 (executed but not timed) and the body of the cell is timed. The cell
1010 1008 body has access to any variables created in the setup code.
1011 1009
1012 1010 Options:
1013 1011 -n<N>: execute the given statement <N> times in a loop. If <N> is not
1014 1012 provided, <N> is determined so as to get sufficient accuracy.
1015 1013
1016 1014 -r<R>: number of repeats <R>, each consisting of <N> loops, and take the
1017 1015 best result.
1018 1016 Default: 7
1019 1017
1020 1018 -t: use time.time to measure the time, which is the default on Unix.
1021 1019 This function measures wall time.
1022 1020
1023 1021 -c: use time.clock to measure the time, which is the default on
1024 1022 Windows and measures wall time. On Unix, resource.getrusage is used
1025 1023 instead and returns the CPU user time.
1026 1024
1027 1025 -p<P>: use a precision of <P> digits to display the timing result.
1028 1026 Default: 3
1029 1027
1030 1028 -q: Quiet, do not print result.
1031 1029
1032 1030 -o: return a TimeitResult that can be stored in a variable to inspect
1033 1031 the result in more details.
1034 1032
1035 1033 .. versionchanged:: 7.3
1036 1034 User variables are no longer expanded,
1037 1035 the magic line is always left unmodified.
1038 1036
1039 1037 Examples
1040 1038 --------
1041 1039 ::
1042 1040
1043 1041 In [1]: %timeit pass
1044 1042 8.26 ns Β± 0.12 ns per loop (mean Β± std. dev. of 7 runs, 100000000 loops each)
1045 1043
1046 1044 In [2]: u = None
1047 1045
1048 1046 In [3]: %timeit u is None
1049 1047 29.9 ns Β± 0.643 ns per loop (mean Β± std. dev. of 7 runs, 10000000 loops each)
1050 1048
1051 1049 In [4]: %timeit -r 4 u == None
1052 1050
1053 1051 In [5]: import time
1054 1052
1055 1053 In [6]: %timeit -n1 time.sleep(2)
1056 1054
1057 1055
1058 1056 The times reported by %timeit will be slightly higher than those
1059 1057 reported by the timeit.py script when variables are accessed. This is
1060 1058 due to the fact that %timeit executes the statement in the namespace
1061 1059 of the shell, compared with timeit.py, which uses a single setup
1062 1060 statement to import function or create variables. Generally, the bias
1063 1061 does not matter as long as results from timeit.py are not mixed with
1064 1062 those from %timeit."""
1065 1063
1066 1064 opts, stmt = self.parse_options(line,'n:r:tcp:qo',
1067 1065 posix=False, strict=False)
1068 1066 if stmt == "" and cell is None:
1069 1067 return
1070 1068
1071 1069 timefunc = timeit.default_timer
1072 1070 number = int(getattr(opts, "n", 0))
1073 1071 default_repeat = 7 if timeit.default_repeat < 7 else timeit.default_repeat
1074 1072 repeat = int(getattr(opts, "r", default_repeat))
1075 1073 precision = int(getattr(opts, "p", 3))
1076 1074 quiet = 'q' in opts
1077 1075 return_result = 'o' in opts
1078 1076 if hasattr(opts, "t"):
1079 1077 timefunc = time.time
1080 1078 if hasattr(opts, "c"):
1081 1079 timefunc = clock
1082 1080
1083 1081 timer = Timer(timer=timefunc)
1084 1082 # this code has tight coupling to the inner workings of timeit.Timer,
1085 1083 # but is there a better way to achieve that the code stmt has access
1086 1084 # to the shell namespace?
1087 1085 transform = self.shell.transform_cell
1088 1086
1089 1087 if cell is None:
1090 1088 # called as line magic
1091 1089 ast_setup = self.shell.compile.ast_parse("pass")
1092 1090 ast_stmt = self.shell.compile.ast_parse(transform(stmt))
1093 1091 else:
1094 1092 ast_setup = self.shell.compile.ast_parse(transform(stmt))
1095 1093 ast_stmt = self.shell.compile.ast_parse(transform(cell))
1096 1094
1097 1095 ast_setup = self.shell.transform_ast(ast_setup)
1098 1096 ast_stmt = self.shell.transform_ast(ast_stmt)
1099 1097
1100 1098 # Check that these compile to valid Python code *outside* the timer func
1101 1099 # Invalid code may become valid when put inside the function & loop,
1102 1100 # which messes up error messages.
1103 1101 # https://github.com/ipython/ipython/issues/10636
1104 1102 self.shell.compile(ast_setup, "<magic-timeit-setup>", "exec")
1105 1103 self.shell.compile(ast_stmt, "<magic-timeit-stmt>", "exec")
1106 1104
1107 1105 # This codestring is taken from timeit.template - we fill it in as an
1108 1106 # AST, so that we can apply our AST transformations to the user code
1109 1107 # without affecting the timing code.
1110 1108 timeit_ast_template = ast.parse('def inner(_it, _timer):\n'
1111 1109 ' setup\n'
1112 1110 ' _t0 = _timer()\n'
1113 1111 ' for _i in _it:\n'
1114 1112 ' stmt\n'
1115 1113 ' _t1 = _timer()\n'
1116 1114 ' return _t1 - _t0\n')
1117 1115
1118 1116 timeit_ast = TimeitTemplateFiller(ast_setup, ast_stmt).visit(timeit_ast_template)
1119 1117 timeit_ast = ast.fix_missing_locations(timeit_ast)
1120 1118
1121 1119 # Track compilation time so it can be reported if too long
1122 1120 # Minimum time above which compilation time will be reported
1123 1121 tc_min = 0.1
1124 1122
1125 1123 t0 = clock()
1126 1124 code = self.shell.compile(timeit_ast, "<magic-timeit>", "exec")
1127 1125 tc = clock()-t0
1128 1126
1129 1127 ns = {}
1130 1128 glob = self.shell.user_ns
1131 1129 # handles global vars with same name as local vars. We store them in conflict_globs.
1132 1130 conflict_globs = {}
1133 1131 if local_ns and cell is None:
1134 1132 for var_name, var_val in glob.items():
1135 1133 if var_name in local_ns:
1136 1134 conflict_globs[var_name] = var_val
1137 1135 glob.update(local_ns)
1138 1136
1139 1137 exec(code, glob, ns)
1140 1138 timer.inner = ns["inner"]
1141 1139
1142 1140 # This is used to check if there is a huge difference between the
1143 1141 # best and worst timings.
1144 1142 # Issue: https://github.com/ipython/ipython/issues/6471
1145 1143 if number == 0:
1146 1144 # determine number so that 0.2 <= total time < 2.0
1147 1145 for index in range(0, 10):
1148 1146 number = 10 ** index
1149 1147 time_number = timer.timeit(number)
1150 1148 if time_number >= 0.2:
1151 1149 break
1152 1150
1153 1151 all_runs = timer.repeat(repeat, number)
1154 1152 best = min(all_runs) / number
1155 1153 worst = max(all_runs) / number
1156 1154 timeit_result = TimeitResult(number, repeat, best, worst, all_runs, tc, precision)
1157 1155
1158 1156 # Restore global vars from conflict_globs
1159 1157 if conflict_globs:
1160 1158 glob.update(conflict_globs)
1161 1159
1162 1160 if not quiet :
1163 1161 # Check best timing is greater than zero to avoid a
1164 1162 # ZeroDivisionError.
1165 1163 # In cases where the slowest timing is lesser than a microsecond
1166 1164 # we assume that it does not really matter if the fastest
1167 1165 # timing is 4 times faster than the slowest timing or not.
1168 1166 if worst > 4 * best and best > 0 and worst > 1e-6:
1169 1167 print("The slowest run took %0.2f times longer than the "
1170 1168 "fastest. This could mean that an intermediate result "
1171 1169 "is being cached." % (worst / best))
1172 1170
1173 1171 print( timeit_result )
1174 1172
1175 1173 if tc > tc_min:
1176 1174 print("Compiler time: %.2f s" % tc)
1177 1175 if return_result:
1178 1176 return timeit_result
1179 1177
1180 1178 @skip_doctest
1181 1179 @no_var_expand
1182 1180 @needs_local_scope
1183 1181 @line_cell_magic
1184 1182 def time(self,line='', cell=None, local_ns=None):
1185 1183 """Time execution of a Python statement or expression.
1186 1184
1187 1185 The CPU and wall clock times are printed, and the value of the
1188 1186 expression (if any) is returned. Note that under Win32, system time
1189 1187 is always reported as 0, since it can not be measured.
1190 1188
1191 1189 This function can be used both as a line and cell magic:
1192 1190
1193 1191 - In line mode you can time a single-line statement (though multiple
1194 1192 ones can be chained with using semicolons).
1195 1193
1196 1194 - In cell mode, you can time the cell body (a directly
1197 1195 following statement raises an error).
1198 1196
1199 1197 This function provides very basic timing functionality. Use the timeit
1200 1198 magic for more control over the measurement.
1201 1199
1202 1200 .. versionchanged:: 7.3
1203 1201 User variables are no longer expanded,
1204 1202 the magic line is always left unmodified.
1205 1203
1206 1204 Examples
1207 1205 --------
1208 1206 ::
1209 1207
1210 1208 In [1]: %time 2**128
1211 1209 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1212 1210 Wall time: 0.00
1213 1211 Out[1]: 340282366920938463463374607431768211456L
1214 1212
1215 1213 In [2]: n = 1000000
1216 1214
1217 1215 In [3]: %time sum(range(n))
1218 1216 CPU times: user 1.20 s, sys: 0.05 s, total: 1.25 s
1219 1217 Wall time: 1.37
1220 1218 Out[3]: 499999500000L
1221 1219
1222 1220 In [4]: %time print 'hello world'
1223 1221 hello world
1224 1222 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1225 1223 Wall time: 0.00
1226 1224
1227 1225 Note that the time needed by Python to compile the given expression
1228 1226 will be reported if it is more than 0.1s. In this example, the
1229 1227 actual exponentiation is done by Python at compilation time, so while
1230 1228 the expression can take a noticeable amount of time to compute, that
1231 1229 time is purely due to the compilation:
1232 1230
1233 1231 In [5]: %time 3**9999;
1234 1232 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1235 1233 Wall time: 0.00 s
1236 1234
1237 1235 In [6]: %time 3**999999;
1238 1236 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1239 1237 Wall time: 0.00 s
1240 1238 Compiler : 0.78 s
1241 1239 """
1242 1240
1243 1241 # fail immediately if the given expression can't be compiled
1244 1242
1245 1243 if line and cell:
1246 1244 raise UsageError("Can't use statement directly after '%%time'!")
1247 1245
1248 1246 if cell:
1249 1247 expr = self.shell.transform_cell(cell)
1250 1248 else:
1251 1249 expr = self.shell.transform_cell(line)
1252 1250
1253 1251 # Minimum time above which parse time will be reported
1254 1252 tp_min = 0.1
1255 1253
1256 1254 t0 = clock()
1257 1255 expr_ast = self.shell.compile.ast_parse(expr)
1258 1256 tp = clock()-t0
1259 1257
1260 1258 # Apply AST transformations
1261 1259 expr_ast = self.shell.transform_ast(expr_ast)
1262 1260
1263 1261 # Minimum time above which compilation time will be reported
1264 1262 tc_min = 0.1
1265 1263
1266 1264 expr_val=None
1267 1265 if len(expr_ast.body)==1 and isinstance(expr_ast.body[0], ast.Expr):
1268 1266 mode = 'eval'
1269 1267 source = '<timed eval>'
1270 1268 expr_ast = ast.Expression(expr_ast.body[0].value)
1271 1269 else:
1272 1270 mode = 'exec'
1273 1271 source = '<timed exec>'
1274 1272 # multi-line %%time case
1275 1273 if len(expr_ast.body) > 1 and isinstance(expr_ast.body[-1], ast.Expr):
1276 1274 expr_val= expr_ast.body[-1]
1277 1275 expr_ast = expr_ast.body[:-1]
1278 1276 expr_ast = Module(expr_ast, [])
1279 1277 expr_val = ast.Expression(expr_val.value)
1280 1278
1281 1279 t0 = clock()
1282 1280 code = self.shell.compile(expr_ast, source, mode)
1283 1281 tc = clock()-t0
1284 1282
1285 1283 # skew measurement as little as possible
1286 1284 glob = self.shell.user_ns
1287 1285 wtime = time.time
1288 1286 # time execution
1289 1287 wall_st = wtime()
1290 1288 if mode=='eval':
1291 1289 st = clock2()
1292 1290 try:
1293 1291 out = eval(code, glob, local_ns)
1294 1292 except:
1295 1293 self.shell.showtraceback()
1296 1294 return
1297 1295 end = clock2()
1298 1296 else:
1299 1297 st = clock2()
1300 1298 try:
1301 1299 exec(code, glob, local_ns)
1302 1300 out=None
1303 1301 # multi-line %%time case
1304 1302 if expr_val is not None:
1305 1303 code_2 = self.shell.compile(expr_val, source, 'eval')
1306 1304 out = eval(code_2, glob, local_ns)
1307 1305 except:
1308 1306 self.shell.showtraceback()
1309 1307 return
1310 1308 end = clock2()
1311 1309
1312 1310 wall_end = wtime()
1313 1311 # Compute actual times and report
1314 1312 wall_time = wall_end-wall_st
1315 1313 cpu_user = end[0]-st[0]
1316 1314 cpu_sys = end[1]-st[1]
1317 1315 cpu_tot = cpu_user+cpu_sys
1318 1316 # On windows cpu_sys is always zero, so no new information to the next print
1319 1317 if sys.platform != 'win32':
1320 1318 print("CPU times: user %s, sys: %s, total: %s" % \
1321 1319 (_format_time(cpu_user),_format_time(cpu_sys),_format_time(cpu_tot)))
1322 1320 print("Wall time: %s" % _format_time(wall_time))
1323 1321 if tc > tc_min:
1324 1322 print("Compiler : %s" % _format_time(tc))
1325 1323 if tp > tp_min:
1326 1324 print("Parser : %s" % _format_time(tp))
1327 1325 return out
1328 1326
1329 1327 @skip_doctest
1330 1328 @line_magic
1331 1329 def macro(self, parameter_s=''):
1332 1330 """Define a macro for future re-execution. It accepts ranges of history,
1333 1331 filenames or string objects.
1334 1332
1335 1333 Usage:\\
1336 1334 %macro [options] name n1-n2 n3-n4 ... n5 .. n6 ...
1337 1335
1338 1336 Options:
1339 1337
1340 1338 -r: use 'raw' input. By default, the 'processed' history is used,
1341 1339 so that magics are loaded in their transformed version to valid
1342 1340 Python. If this option is given, the raw input as typed at the
1343 1341 command line is used instead.
1344 1342
1345 1343 -q: quiet macro definition. By default, a tag line is printed
1346 1344 to indicate the macro has been created, and then the contents of
1347 1345 the macro are printed. If this option is given, then no printout
1348 1346 is produced once the macro is created.
1349 1347
1350 1348 This will define a global variable called `name` which is a string
1351 1349 made of joining the slices and lines you specify (n1,n2,... numbers
1352 1350 above) from your input history into a single string. This variable
1353 1351 acts like an automatic function which re-executes those lines as if
1354 1352 you had typed them. You just type 'name' at the prompt and the code
1355 1353 executes.
1356 1354
1357 1355 The syntax for indicating input ranges is described in %history.
1358 1356
1359 1357 Note: as a 'hidden' feature, you can also use traditional python slice
1360 1358 notation, where N:M means numbers N through M-1.
1361 1359
1362 1360 For example, if your history contains (print using %hist -n )::
1363 1361
1364 1362 44: x=1
1365 1363 45: y=3
1366 1364 46: z=x+y
1367 1365 47: print x
1368 1366 48: a=5
1369 1367 49: print 'x',x,'y',y
1370 1368
1371 1369 you can create a macro with lines 44 through 47 (included) and line 49
1372 1370 called my_macro with::
1373 1371
1374 1372 In [55]: %macro my_macro 44-47 49
1375 1373
1376 1374 Now, typing `my_macro` (without quotes) will re-execute all this code
1377 1375 in one pass.
1378 1376
1379 1377 You don't need to give the line-numbers in order, and any given line
1380 1378 number can appear multiple times. You can assemble macros with any
1381 1379 lines from your input history in any order.
1382 1380
1383 1381 The macro is a simple object which holds its value in an attribute,
1384 1382 but IPython's display system checks for macros and executes them as
1385 1383 code instead of printing them when you type their name.
1386 1384
1387 1385 You can view a macro's contents by explicitly printing it with::
1388 1386
1389 1387 print macro_name
1390 1388
1391 1389 """
1392 1390 opts,args = self.parse_options(parameter_s,'rq',mode='list')
1393 1391 if not args: # List existing macros
1394 1392 return sorted(k for k,v in self.shell.user_ns.items() if isinstance(v, Macro))
1395 1393 if len(args) == 1:
1396 1394 raise UsageError(
1397 1395 "%macro insufficient args; usage '%macro name n1-n2 n3-4...")
1398 1396 name, codefrom = args[0], " ".join(args[1:])
1399 1397
1400 1398 #print 'rng',ranges # dbg
1401 1399 try:
1402 1400 lines = self.shell.find_user_code(codefrom, 'r' in opts)
1403 1401 except (ValueError, TypeError) as e:
1404 1402 print(e.args[0])
1405 1403 return
1406 1404 macro = Macro(lines)
1407 1405 self.shell.define_macro(name, macro)
1408 1406 if not ( 'q' in opts) :
1409 1407 print('Macro `%s` created. To execute, type its name (without quotes).' % name)
1410 1408 print('=== Macro contents: ===')
1411 1409 print(macro, end=' ')
1412 1410
1413 1411 @magic_arguments.magic_arguments()
1414 1412 @magic_arguments.argument('output', type=str, default='', nargs='?',
1415 1413 help="""The name of the variable in which to store output.
1416 1414 This is a utils.io.CapturedIO object with stdout/err attributes
1417 1415 for the text of the captured output.
1418 1416
1419 1417 CapturedOutput also has a show() method for displaying the output,
1420 1418 and __call__ as well, so you can use that to quickly display the
1421 1419 output.
1422 1420
1423 1421 If unspecified, captured output is discarded.
1424 1422 """
1425 1423 )
1426 1424 @magic_arguments.argument('--no-stderr', action="store_true",
1427 1425 help="""Don't capture stderr."""
1428 1426 )
1429 1427 @magic_arguments.argument('--no-stdout', action="store_true",
1430 1428 help="""Don't capture stdout."""
1431 1429 )
1432 1430 @magic_arguments.argument('--no-display', action="store_true",
1433 1431 help="""Don't capture IPython's rich display."""
1434 1432 )
1435 1433 @cell_magic
1436 1434 def capture(self, line, cell):
1437 1435 """run the cell, capturing stdout, stderr, and IPython's rich display() calls."""
1438 1436 args = magic_arguments.parse_argstring(self.capture, line)
1439 1437 out = not args.no_stdout
1440 1438 err = not args.no_stderr
1441 1439 disp = not args.no_display
1442 1440 with capture_output(out, err, disp) as io:
1443 1441 self.shell.run_cell(cell)
1444 1442 if args.output:
1445 1443 self.shell.user_ns[args.output] = io
1446 1444
1447 1445 def parse_breakpoint(text, current_file):
1448 1446 '''Returns (file, line) for file:line and (current_file, line) for line'''
1449 1447 colon = text.find(':')
1450 1448 if colon == -1:
1451 1449 return current_file, int(text)
1452 1450 else:
1453 1451 return text[:colon], int(text[colon+1:])
1454 1452
1455 1453 def _format_time(timespan, precision=3):
1456 1454 """Formats the timespan in a human readable form"""
1457 1455
1458 1456 if timespan >= 60.0:
1459 1457 # we have more than a minute, format that in a human readable form
1460 1458 # Idea from http://snipplr.com/view/5713/
1461 1459 parts = [("d", 60*60*24),("h", 60*60),("min", 60), ("s", 1)]
1462 1460 time = []
1463 1461 leftover = timespan
1464 1462 for suffix, length in parts:
1465 1463 value = int(leftover / length)
1466 1464 if value > 0:
1467 1465 leftover = leftover % length
1468 1466 time.append(u'%s%s' % (str(value), suffix))
1469 1467 if leftover < 1:
1470 1468 break
1471 1469 return " ".join(time)
1472 1470
1473 1471
1474 1472 # Unfortunately the unicode 'micro' symbol can cause problems in
1475 1473 # certain terminals.
1476 1474 # See bug: https://bugs.launchpad.net/ipython/+bug/348466
1477 1475 # Try to prevent crashes by being more secure than it needs to
1478 1476 # E.g. eclipse is able to print a Β΅, but has no sys.stdout.encoding set.
1479 1477 units = [u"s", u"ms",u'us',"ns"] # the save value
1480 1478 if hasattr(sys.stdout, 'encoding') and sys.stdout.encoding:
1481 1479 try:
1482 1480 u'\xb5'.encode(sys.stdout.encoding)
1483 1481 units = [u"s", u"ms",u'\xb5s',"ns"]
1484 1482 except:
1485 1483 pass
1486 1484 scaling = [1, 1e3, 1e6, 1e9]
1487 1485
1488 1486 if timespan > 0.0:
1489 1487 order = min(-int(math.floor(math.log10(timespan)) // 3), 3)
1490 1488 else:
1491 1489 order = 3
1492 1490 return u"%.*g %s" % (precision, timespan * scaling[order], units[order])
@@ -1,582 +1,601 b''
1 1 # encoding: utf-8
2 2 """Tests for code execution (%run and related), which is particularly tricky.
3 3
4 4 Because of how %run manages namespaces, and the fact that we are trying here to
5 5 verify subtle object deletion and reference counting issues, the %run tests
6 6 will be kept in this separate file. This makes it easier to aggregate in one
7 7 place the tricks needed to handle it; most other magics are much easier to test
8 8 and we do so in a common test_magic file.
9 9
10 10 Note that any test using `run -i` should make sure to do a `reset` afterwards,
11 11 as otherwise it may influence later tests.
12 12 """
13 13
14 14 # Copyright (c) IPython Development Team.
15 15 # Distributed under the terms of the Modified BSD License.
16 16
17 17
18 18
19 19 import functools
20 20 import os
21 21 from os.path import join as pjoin
22 22 import random
23 23 import string
24 24 import sys
25 25 import textwrap
26 26 import unittest
27 27 from unittest.mock import patch
28 28
29 29 import nose.tools as nt
30 30 from nose import SkipTest
31 31
32 32 from IPython.testing import decorators as dec
33 33 from IPython.testing import tools as tt
34 34 from IPython.utils.io import capture_output
35 35 from IPython.utils.tempdir import TemporaryDirectory
36 36 from IPython.core import debugger
37 37
38 38 def doctest_refbug():
39 39 """Very nasty problem with references held by multiple runs of a script.
40 40 See: https://github.com/ipython/ipython/issues/141
41 41
42 42 In [1]: _ip.clear_main_mod_cache()
43 43 # random
44 44
45 45 In [2]: %run refbug
46 46
47 47 In [3]: call_f()
48 48 lowercased: hello
49 49
50 50 In [4]: %run refbug
51 51
52 52 In [5]: call_f()
53 53 lowercased: hello
54 54 lowercased: hello
55 55 """
56 56
57 57
58 58 def doctest_run_builtins():
59 59 r"""Check that %run doesn't damage __builtins__.
60 60
61 61 In [1]: import tempfile
62 62
63 63 In [2]: bid1 = id(__builtins__)
64 64
65 65 In [3]: fname = tempfile.mkstemp('.py')[1]
66 66
67 67 In [3]: f = open(fname,'w')
68 68
69 69 In [4]: dummy= f.write('pass\n')
70 70
71 71 In [5]: f.flush()
72 72
73 73 In [6]: t1 = type(__builtins__)
74 74
75 75 In [7]: %run $fname
76 76
77 77 In [7]: f.close()
78 78
79 79 In [8]: bid2 = id(__builtins__)
80 80
81 81 In [9]: t2 = type(__builtins__)
82 82
83 83 In [10]: t1 == t2
84 84 Out[10]: True
85 85
86 86 In [10]: bid1 == bid2
87 87 Out[10]: True
88 88
89 89 In [12]: try:
90 90 ....: os.unlink(fname)
91 91 ....: except:
92 92 ....: pass
93 93 ....:
94 94 """
95 95
96 96
97 97 def doctest_run_option_parser():
98 98 r"""Test option parser in %run.
99 99
100 100 In [1]: %run print_argv.py
101 101 []
102 102
103 103 In [2]: %run print_argv.py print*.py
104 104 ['print_argv.py']
105 105
106 106 In [3]: %run -G print_argv.py print*.py
107 107 ['print*.py']
108 108
109 109 """
110 110
111 111
112 112 @dec.skip_win32
113 113 def doctest_run_option_parser_for_posix():
114 114 r"""Test option parser in %run (Linux/OSX specific).
115 115
116 116 You need double quote to escape glob in POSIX systems:
117 117
118 118 In [1]: %run print_argv.py print\\*.py
119 119 ['print*.py']
120 120
121 121 You can't use quote to escape glob in POSIX systems:
122 122
123 123 In [2]: %run print_argv.py 'print*.py'
124 124 ['print_argv.py']
125 125
126 126 """
127 127
128 128
129 129 @dec.skip_if_not_win32
130 130 def doctest_run_option_parser_for_windows():
131 131 r"""Test option parser in %run (Windows specific).
132 132
133 133 In Windows, you can't escape ``*` `by backslash:
134 134
135 135 In [1]: %run print_argv.py print\\*.py
136 136 ['print\\*.py']
137 137
138 138 You can use quote to escape glob:
139 139
140 140 In [2]: %run print_argv.py 'print*.py'
141 141 ['print*.py']
142 142
143 143 """
144 144
145 145
146 146 def doctest_reset_del():
147 147 """Test that resetting doesn't cause errors in __del__ methods.
148 148
149 149 In [2]: class A(object):
150 150 ...: def __del__(self):
151 151 ...: print(str("Hi"))
152 152 ...:
153 153
154 154 In [3]: a = A()
155 155
156 156 In [4]: get_ipython().reset()
157 157 Hi
158 158
159 159 In [5]: 1+1
160 160 Out[5]: 2
161 161 """
162 162
163 163 # For some tests, it will be handy to organize them in a class with a common
164 164 # setup that makes a temp file
165 165
166 166 class TestMagicRunPass(tt.TempFileMixin):
167 167
168 168 def setUp(self):
169 169 content = "a = [1,2,3]\nb = 1"
170 170 self.mktmp(content)
171 171
172 172 def run_tmpfile(self):
173 173 _ip = get_ipython()
174 174 # This fails on Windows if self.tmpfile.name has spaces or "~" in it.
175 175 # See below and ticket https://bugs.launchpad.net/bugs/366353
176 176 _ip.magic('run %s' % self.fname)
177 177
178 178 def run_tmpfile_p(self):
179 179 _ip = get_ipython()
180 180 # This fails on Windows if self.tmpfile.name has spaces or "~" in it.
181 181 # See below and ticket https://bugs.launchpad.net/bugs/366353
182 182 _ip.magic('run -p %s' % self.fname)
183 183
184 184 def test_builtins_id(self):
185 185 """Check that %run doesn't damage __builtins__ """
186 186 _ip = get_ipython()
187 187 # Test that the id of __builtins__ is not modified by %run
188 188 bid1 = id(_ip.user_ns['__builtins__'])
189 189 self.run_tmpfile()
190 190 bid2 = id(_ip.user_ns['__builtins__'])
191 191 nt.assert_equal(bid1, bid2)
192 192
193 193 def test_builtins_type(self):
194 194 """Check that the type of __builtins__ doesn't change with %run.
195 195
196 196 However, the above could pass if __builtins__ was already modified to
197 197 be a dict (it should be a module) by a previous use of %run. So we
198 198 also check explicitly that it really is a module:
199 199 """
200 200 _ip = get_ipython()
201 201 self.run_tmpfile()
202 202 nt.assert_equal(type(_ip.user_ns['__builtins__']),type(sys))
203 203
204 204 def test_run_profile( self ):
205 205 """Test that the option -p, which invokes the profiler, do not
206 206 crash by invoking execfile"""
207 207 self.run_tmpfile_p()
208 208
209 209 def test_run_debug_twice(self):
210 210 # https://github.com/ipython/ipython/issues/10028
211 211 _ip = get_ipython()
212 212 with tt.fake_input(['c']):
213 213 _ip.magic('run -d %s' % self.fname)
214 214 with tt.fake_input(['c']):
215 215 _ip.magic('run -d %s' % self.fname)
216 216
217 217 def test_run_debug_twice_with_breakpoint(self):
218 218 """Make a valid python temp file."""
219 219 _ip = get_ipython()
220 220 with tt.fake_input(['b 2', 'c', 'c']):
221 221 _ip.magic('run -d %s' % self.fname)
222 222
223 223 with tt.fake_input(['c']):
224 224 with tt.AssertNotPrints('KeyError'):
225 225 _ip.magic('run -d %s' % self.fname)
226 226
227 227
228 228 class TestMagicRunSimple(tt.TempFileMixin):
229 229
230 230 def test_simpledef(self):
231 231 """Test that simple class definitions work."""
232 232 src = ("class foo: pass\n"
233 233 "def f(): return foo()")
234 234 self.mktmp(src)
235 235 _ip.magic('run %s' % self.fname)
236 236 _ip.run_cell('t = isinstance(f(), foo)')
237 237 nt.assert_true(_ip.user_ns['t'])
238 238
239 239 def test_obj_del(self):
240 240 """Test that object's __del__ methods are called on exit."""
241 241 if sys.platform == 'win32':
242 242 try:
243 243 import win32api
244 244 except ImportError:
245 245 raise SkipTest("Test requires pywin32")
246 246 src = ("class A(object):\n"
247 247 " def __del__(self):\n"
248 248 " print('object A deleted')\n"
249 249 "a = A()\n")
250 250 self.mktmp(src)
251 251 err = None
252 252 tt.ipexec_validate(self.fname, 'object A deleted', err)
253 253
254 254 def test_aggressive_namespace_cleanup(self):
255 255 """Test that namespace cleanup is not too aggressive GH-238
256 256
257 257 Returning from another run magic deletes the namespace"""
258 258 # see ticket https://github.com/ipython/ipython/issues/238
259 259
260 260 with tt.TempFileMixin() as empty:
261 261 empty.mktmp('')
262 262 # On Windows, the filename will have \users in it, so we need to use the
263 263 # repr so that the \u becomes \\u.
264 264 src = ("ip = get_ipython()\n"
265 265 "for i in range(5):\n"
266 266 " try:\n"
267 267 " ip.magic(%r)\n"
268 268 " except NameError as e:\n"
269 269 " print(i)\n"
270 270 " break\n" % ('run ' + empty.fname))
271 271 self.mktmp(src)
272 272 _ip.magic('run %s' % self.fname)
273 273 _ip.run_cell('ip == get_ipython()')
274 274 nt.assert_equal(_ip.user_ns['i'], 4)
275 275
276 276 def test_run_second(self):
277 277 """Test that running a second file doesn't clobber the first, gh-3547
278 278 """
279 279 self.mktmp("avar = 1\n"
280 280 "def afunc():\n"
281 281 " return avar\n")
282 282
283 283 with tt.TempFileMixin() as empty:
284 284 empty.mktmp("")
285 285
286 286 _ip.magic('run %s' % self.fname)
287 287 _ip.magic('run %s' % empty.fname)
288 288 nt.assert_equal(_ip.user_ns['afunc'](), 1)
289 289
290 290 @dec.skip_win32
291 291 def test_tclass(self):
292 292 mydir = os.path.dirname(__file__)
293 293 tc = os.path.join(mydir, 'tclass')
294 294 src = ("%%run '%s' C-first\n"
295 295 "%%run '%s' C-second\n"
296 296 "%%run '%s' C-third\n") % (tc, tc, tc)
297 297 self.mktmp(src, '.ipy')
298 298 out = """\
299 299 ARGV 1-: ['C-first']
300 300 ARGV 1-: ['C-second']
301 301 tclass.py: deleting object: C-first
302 302 ARGV 1-: ['C-third']
303 303 tclass.py: deleting object: C-second
304 304 tclass.py: deleting object: C-third
305 305 """
306 306 err = None
307 307 tt.ipexec_validate(self.fname, out, err)
308 308
309 309 def test_run_i_after_reset(self):
310 310 """Check that %run -i still works after %reset (gh-693)"""
311 311 src = "yy = zz\n"
312 312 self.mktmp(src)
313 313 _ip.run_cell("zz = 23")
314 314 try:
315 315 _ip.magic('run -i %s' % self.fname)
316 316 nt.assert_equal(_ip.user_ns['yy'], 23)
317 317 finally:
318 318 _ip.magic('reset -f')
319 319
320 320 _ip.run_cell("zz = 23")
321 321 try:
322 322 _ip.magic('run -i %s' % self.fname)
323 323 nt.assert_equal(_ip.user_ns['yy'], 23)
324 324 finally:
325 325 _ip.magic('reset -f')
326 326
327 327 def test_unicode(self):
328 328 """Check that files in odd encodings are accepted."""
329 329 mydir = os.path.dirname(__file__)
330 330 na = os.path.join(mydir, 'nonascii.py')
331 331 _ip.magic('run "%s"' % na)
332 332 nt.assert_equal(_ip.user_ns['u'], u'ΠŽΡ‚β„–Π€')
333 333
334 334 def test_run_py_file_attribute(self):
335 335 """Test handling of `__file__` attribute in `%run <file>.py`."""
336 336 src = "t = __file__\n"
337 337 self.mktmp(src)
338 338 _missing = object()
339 339 file1 = _ip.user_ns.get('__file__', _missing)
340 340 _ip.magic('run %s' % self.fname)
341 341 file2 = _ip.user_ns.get('__file__', _missing)
342 342
343 343 # Check that __file__ was equal to the filename in the script's
344 344 # namespace.
345 345 nt.assert_equal(_ip.user_ns['t'], self.fname)
346 346
347 347 # Check that __file__ was not leaked back into user_ns.
348 348 nt.assert_equal(file1, file2)
349 349
350 350 def test_run_ipy_file_attribute(self):
351 351 """Test handling of `__file__` attribute in `%run <file.ipy>`."""
352 352 src = "t = __file__\n"
353 353 self.mktmp(src, ext='.ipy')
354 354 _missing = object()
355 355 file1 = _ip.user_ns.get('__file__', _missing)
356 356 _ip.magic('run %s' % self.fname)
357 357 file2 = _ip.user_ns.get('__file__', _missing)
358 358
359 359 # Check that __file__ was equal to the filename in the script's
360 360 # namespace.
361 361 nt.assert_equal(_ip.user_ns['t'], self.fname)
362 362
363 363 # Check that __file__ was not leaked back into user_ns.
364 364 nt.assert_equal(file1, file2)
365 365
366 366 def test_run_formatting(self):
367 367 """ Test that %run -t -N<N> does not raise a TypeError for N > 1."""
368 368 src = "pass"
369 369 self.mktmp(src)
370 370 _ip.magic('run -t -N 1 %s' % self.fname)
371 371 _ip.magic('run -t -N 10 %s' % self.fname)
372 372
373 373 def test_ignore_sys_exit(self):
374 374 """Test the -e option to ignore sys.exit()"""
375 375 src = "import sys; sys.exit(1)"
376 376 self.mktmp(src)
377 377 with tt.AssertPrints('SystemExit'):
378 378 _ip.magic('run %s' % self.fname)
379 379
380 380 with tt.AssertNotPrints('SystemExit'):
381 381 _ip.magic('run -e %s' % self.fname)
382 382
383 383 def test_run_nb(self):
384 384 """Test %run notebook.ipynb"""
385 385 from nbformat import v4, writes
386 386 nb = v4.new_notebook(
387 387 cells=[
388 388 v4.new_markdown_cell("The Ultimate Question of Everything"),
389 389 v4.new_code_cell("answer=42")
390 390 ]
391 391 )
392 392 src = writes(nb, version=4)
393 393 self.mktmp(src, ext='.ipynb')
394 394
395 395 _ip.magic("run %s" % self.fname)
396 396
397 397 nt.assert_equal(_ip.user_ns['answer'], 42)
398 398
399 def test_run_nb_error(self):
400 """Test %run notebook.ipynb error"""
401 from nbformat import v4, writes
402 # %run when a file name isn't provided
403 nt.assert_raises(Exception, _ip.magic, "run")
404
405 # %run when a file doesn't exist
406 nt.assert_raises(Exception, _ip.magic, "run foobar.ipynb")
407
408 # %run on a notebook with an error
409 nb = v4.new_notebook(
410 cells=[
411 v4.new_code_cell("0/0")
412 ]
413 )
414 src = writes(nb, version=4)
415 self.mktmp(src, ext='.ipynb')
416 nt.assert_raises(Exception, _ip.magic, "run %s" % self.fname)
417
399 418 def test_file_options(self):
400 419 src = ('import sys\n'
401 420 'a = " ".join(sys.argv[1:])\n')
402 421 self.mktmp(src)
403 422 test_opts = '-x 3 --verbose'
404 423 _ip.run_line_magic("run", '{0} {1}'.format(self.fname, test_opts))
405 424 nt.assert_equal(_ip.user_ns['a'], test_opts)
406 425
407 426
408 427 class TestMagicRunWithPackage(unittest.TestCase):
409 428
410 429 def writefile(self, name, content):
411 430 path = os.path.join(self.tempdir.name, name)
412 431 d = os.path.dirname(path)
413 432 if not os.path.isdir(d):
414 433 os.makedirs(d)
415 434 with open(path, 'w') as f:
416 435 f.write(textwrap.dedent(content))
417 436
418 437 def setUp(self):
419 438 self.package = package = 'tmp{0}'.format(''.join([random.choice(string.ascii_letters) for i in range(10)]))
420 439 """Temporary (probably) valid python package name."""
421 440
422 441 self.value = int(random.random() * 10000)
423 442
424 443 self.tempdir = TemporaryDirectory()
425 444 self.__orig_cwd = os.getcwd()
426 445 sys.path.insert(0, self.tempdir.name)
427 446
428 447 self.writefile(os.path.join(package, '__init__.py'), '')
429 448 self.writefile(os.path.join(package, 'sub.py'), """
430 449 x = {0!r}
431 450 """.format(self.value))
432 451 self.writefile(os.path.join(package, 'relative.py'), """
433 452 from .sub import x
434 453 """)
435 454 self.writefile(os.path.join(package, 'absolute.py'), """
436 455 from {0}.sub import x
437 456 """.format(package))
438 457 self.writefile(os.path.join(package, 'args.py'), """
439 458 import sys
440 459 a = " ".join(sys.argv[1:])
441 460 """.format(package))
442 461
443 462 def tearDown(self):
444 463 os.chdir(self.__orig_cwd)
445 464 sys.path[:] = [p for p in sys.path if p != self.tempdir.name]
446 465 self.tempdir.cleanup()
447 466
448 467 def check_run_submodule(self, submodule, opts=''):
449 468 _ip.user_ns.pop('x', None)
450 469 _ip.magic('run {2} -m {0}.{1}'.format(self.package, submodule, opts))
451 470 self.assertEqual(_ip.user_ns['x'], self.value,
452 471 'Variable `x` is not loaded from module `{0}`.'
453 472 .format(submodule))
454 473
455 474 def test_run_submodule_with_absolute_import(self):
456 475 self.check_run_submodule('absolute')
457 476
458 477 def test_run_submodule_with_relative_import(self):
459 478 """Run submodule that has a relative import statement (#2727)."""
460 479 self.check_run_submodule('relative')
461 480
462 481 def test_prun_submodule_with_absolute_import(self):
463 482 self.check_run_submodule('absolute', '-p')
464 483
465 484 def test_prun_submodule_with_relative_import(self):
466 485 self.check_run_submodule('relative', '-p')
467 486
468 487 def with_fake_debugger(func):
469 488 @functools.wraps(func)
470 489 def wrapper(*args, **kwds):
471 490 with patch.object(debugger.Pdb, 'run', staticmethod(eval)):
472 491 return func(*args, **kwds)
473 492 return wrapper
474 493
475 494 @with_fake_debugger
476 495 def test_debug_run_submodule_with_absolute_import(self):
477 496 self.check_run_submodule('absolute', '-d')
478 497
479 498 @with_fake_debugger
480 499 def test_debug_run_submodule_with_relative_import(self):
481 500 self.check_run_submodule('relative', '-d')
482 501
483 502 def test_module_options(self):
484 503 _ip.user_ns.pop('a', None)
485 504 test_opts = '-x abc -m test'
486 505 _ip.run_line_magic('run', '-m {0}.args {1}'.format(self.package, test_opts))
487 506 nt.assert_equal(_ip.user_ns['a'], test_opts)
488 507
489 508 def test_module_options_with_separator(self):
490 509 _ip.user_ns.pop('a', None)
491 510 test_opts = '-x abc -m test'
492 511 _ip.run_line_magic('run', '-m {0}.args -- {1}'.format(self.package, test_opts))
493 512 nt.assert_equal(_ip.user_ns['a'], test_opts)
494 513
495 514 def test_run__name__():
496 515 with TemporaryDirectory() as td:
497 516 path = pjoin(td, 'foo.py')
498 517 with open(path, 'w') as f:
499 518 f.write("q = __name__")
500 519
501 520 _ip.user_ns.pop('q', None)
502 521 _ip.magic('run {}'.format(path))
503 522 nt.assert_equal(_ip.user_ns.pop('q'), '__main__')
504 523
505 524 _ip.magic('run -n {}'.format(path))
506 525 nt.assert_equal(_ip.user_ns.pop('q'), 'foo')
507 526
508 527 try:
509 528 _ip.magic('run -i -n {}'.format(path))
510 529 nt.assert_equal(_ip.user_ns.pop('q'), 'foo')
511 530 finally:
512 531 _ip.magic('reset -f')
513 532
514 533
515 534 def test_run_tb():
516 535 """Test traceback offset in %run"""
517 536 with TemporaryDirectory() as td:
518 537 path = pjoin(td, 'foo.py')
519 538 with open(path, 'w') as f:
520 539 f.write('\n'.join([
521 540 "def foo():",
522 541 " return bar()",
523 542 "def bar():",
524 543 " raise RuntimeError('hello!')",
525 544 "foo()",
526 545 ]))
527 546 with capture_output() as io:
528 547 _ip.magic('run {}'.format(path))
529 548 out = io.stdout
530 549 nt.assert_not_in("execfile", out)
531 550 nt.assert_in("RuntimeError", out)
532 551 nt.assert_equal(out.count("---->"), 3)
533 552 del ip.user_ns['bar']
534 553 del ip.user_ns['foo']
535 554
536 555
537 556 def test_multiprocessing_run():
538 557 """Set we can run mutiprocesgin without messing up up main namespace
539 558
540 559 Note that import `nose.tools as nt` mdify the value s
541 560 sys.module['__mp_main__'] so wee need to temporarily set it to None to test
542 561 the issue.
543 562 """
544 563 with TemporaryDirectory() as td:
545 564 mpm = sys.modules.get('__mp_main__')
546 565 assert mpm is not None
547 566 sys.modules['__mp_main__'] = None
548 567 try:
549 568 path = pjoin(td, 'test.py')
550 569 with open(path, 'w') as f:
551 570 f.write("import multiprocessing\nprint('hoy')")
552 571 with capture_output() as io:
553 572 _ip.run_line_magic('run', path)
554 573 _ip.run_cell("i_m_undefined")
555 574 out = io.stdout
556 575 nt.assert_in("hoy", out)
557 576 nt.assert_not_in("AttributeError", out)
558 577 nt.assert_in("NameError", out)
559 578 nt.assert_equal(out.count("---->"), 1)
560 579 except:
561 580 raise
562 581 finally:
563 582 sys.modules['__mp_main__'] = mpm
564 583
565 584 @dec.knownfailureif(sys.platform == 'win32', "writes to io.stdout aren't captured on Windows")
566 585 def test_script_tb():
567 586 """Test traceback offset in `ipython script.py`"""
568 587 with TemporaryDirectory() as td:
569 588 path = pjoin(td, 'foo.py')
570 589 with open(path, 'w') as f:
571 590 f.write('\n'.join([
572 591 "def foo():",
573 592 " return bar()",
574 593 "def bar():",
575 594 " raise RuntimeError('hello!')",
576 595 "foo()",
577 596 ]))
578 597 out, err = tt.ipexec(path)
579 598 nt.assert_not_in("execfile", out)
580 599 nt.assert_in("RuntimeError", out)
581 600 nt.assert_equal(out.count("---->"), 3)
582 601
General Comments 0
You need to be logged in to leave comments. Login now