##// END OF EJS Templates
Notebook magic used old terminology "input"...
Matthias Bussonnier -
Show More
@@ -1,613 +1,613 b''
1 1 """Implementation of basic magic functions."""
2 2
3 3 from __future__ import print_function
4 4
5 5 import io
6 6 import json
7 7 import sys
8 8 from pprint import pformat
9 9
10 10 from IPython.core import magic_arguments, page
11 11 from IPython.core.error import UsageError
12 12 from IPython.core.magic import Magics, magics_class, line_magic, magic_escapes
13 13 from IPython.utils.text import format_screen, dedent, indent
14 14 from IPython.testing.skipdoctest import skip_doctest
15 15 from IPython.utils.ipstruct import Struct
16 16 from IPython.utils.path import unquote_filename
17 17 from IPython.utils.py3compat import unicode_type
18 18 from IPython.utils.warn import warn, error
19 19
20 20
21 21 class MagicsDisplay(object):
22 22 def __init__(self, magics_manager):
23 23 self.magics_manager = magics_manager
24 24
25 25 def _lsmagic(self):
26 26 """The main implementation of the %lsmagic"""
27 27 mesc = magic_escapes['line']
28 28 cesc = magic_escapes['cell']
29 29 mman = self.magics_manager
30 30 magics = mman.lsmagic()
31 31 out = ['Available line magics:',
32 32 mesc + (' '+mesc).join(sorted(magics['line'])),
33 33 '',
34 34 'Available cell magics:',
35 35 cesc + (' '+cesc).join(sorted(magics['cell'])),
36 36 '',
37 37 mman.auto_status()]
38 38 return '\n'.join(out)
39 39
40 40 def _repr_pretty_(self, p, cycle):
41 41 p.text(self._lsmagic())
42 42
43 43 def __str__(self):
44 44 return self._lsmagic()
45 45
46 46 def _jsonable(self):
47 47 """turn magics dict into jsonable dict of the same structure
48 48
49 49 replaces object instances with their class names as strings
50 50 """
51 51 magic_dict = {}
52 52 mman = self.magics_manager
53 53 magics = mman.lsmagic()
54 54 for key, subdict in magics.items():
55 55 d = {}
56 56 magic_dict[key] = d
57 57 for name, obj in subdict.items():
58 58 try:
59 59 classname = obj.__self__.__class__.__name__
60 60 except AttributeError:
61 61 classname = 'Other'
62 62
63 63 d[name] = classname
64 64 return magic_dict
65 65
66 66 def _repr_json_(self):
67 67 return self._jsonable()
68 68
69 69
70 70 @magics_class
71 71 class BasicMagics(Magics):
72 72 """Magics that provide central IPython functionality.
73 73
74 74 These are various magics that don't fit into specific categories but that
75 75 are all part of the base 'IPython experience'."""
76 76
77 77 @magic_arguments.magic_arguments()
78 78 @magic_arguments.argument(
79 79 '-l', '--line', action='store_true',
80 80 help="""Create a line magic alias."""
81 81 )
82 82 @magic_arguments.argument(
83 83 '-c', '--cell', action='store_true',
84 84 help="""Create a cell magic alias."""
85 85 )
86 86 @magic_arguments.argument(
87 87 'name',
88 88 help="""Name of the magic to be created."""
89 89 )
90 90 @magic_arguments.argument(
91 91 'target',
92 92 help="""Name of the existing line or cell magic."""
93 93 )
94 94 @line_magic
95 95 def alias_magic(self, line=''):
96 96 """Create an alias for an existing line or cell magic.
97 97
98 98 Examples
99 99 --------
100 100 ::
101 101
102 102 In [1]: %alias_magic t timeit
103 103 Created `%t` as an alias for `%timeit`.
104 104 Created `%%t` as an alias for `%%timeit`.
105 105
106 106 In [2]: %t -n1 pass
107 107 1 loops, best of 3: 954 ns per loop
108 108
109 109 In [3]: %%t -n1
110 110 ...: pass
111 111 ...:
112 112 1 loops, best of 3: 954 ns per loop
113 113
114 114 In [4]: %alias_magic --cell whereami pwd
115 115 UsageError: Cell magic function `%%pwd` not found.
116 116 In [5]: %alias_magic --line whereami pwd
117 117 Created `%whereami` as an alias for `%pwd`.
118 118
119 119 In [6]: %whereami
120 120 Out[6]: u'/home/testuser'
121 121 """
122 122 args = magic_arguments.parse_argstring(self.alias_magic, line)
123 123 shell = self.shell
124 124 mman = self.shell.magics_manager
125 125 escs = ''.join(magic_escapes.values())
126 126
127 127 target = args.target.lstrip(escs)
128 128 name = args.name.lstrip(escs)
129 129
130 130 # Find the requested magics.
131 131 m_line = shell.find_magic(target, 'line')
132 132 m_cell = shell.find_magic(target, 'cell')
133 133 if args.line and m_line is None:
134 134 raise UsageError('Line magic function `%s%s` not found.' %
135 135 (magic_escapes['line'], target))
136 136 if args.cell and m_cell is None:
137 137 raise UsageError('Cell magic function `%s%s` not found.' %
138 138 (magic_escapes['cell'], target))
139 139
140 140 # If --line and --cell are not specified, default to the ones
141 141 # that are available.
142 142 if not args.line and not args.cell:
143 143 if not m_line and not m_cell:
144 144 raise UsageError(
145 145 'No line or cell magic with name `%s` found.' % target
146 146 )
147 147 args.line = bool(m_line)
148 148 args.cell = bool(m_cell)
149 149
150 150 if args.line:
151 151 mman.register_alias(name, target, 'line')
152 152 print('Created `%s%s` as an alias for `%s%s`.' % (
153 153 magic_escapes['line'], name,
154 154 magic_escapes['line'], target))
155 155
156 156 if args.cell:
157 157 mman.register_alias(name, target, 'cell')
158 158 print('Created `%s%s` as an alias for `%s%s`.' % (
159 159 magic_escapes['cell'], name,
160 160 magic_escapes['cell'], target))
161 161
162 162 @line_magic
163 163 def lsmagic(self, parameter_s=''):
164 164 """List currently available magic functions."""
165 165 return MagicsDisplay(self.shell.magics_manager)
166 166
167 167 def _magic_docs(self, brief=False, rest=False):
168 168 """Return docstrings from magic functions."""
169 169 mman = self.shell.magics_manager
170 170 docs = mman.lsmagic_docs(brief, missing='No documentation')
171 171
172 172 if rest:
173 173 format_string = '**%s%s**::\n\n%s\n\n'
174 174 else:
175 175 format_string = '%s%s:\n%s\n'
176 176
177 177 return ''.join(
178 178 [format_string % (magic_escapes['line'], fname,
179 179 indent(dedent(fndoc)))
180 180 for fname, fndoc in sorted(docs['line'].items())]
181 181 +
182 182 [format_string % (magic_escapes['cell'], fname,
183 183 indent(dedent(fndoc)))
184 184 for fname, fndoc in sorted(docs['cell'].items())]
185 185 )
186 186
187 187 @line_magic
188 188 def magic(self, parameter_s=''):
189 189 """Print information about the magic function system.
190 190
191 191 Supported formats: -latex, -brief, -rest
192 192 """
193 193
194 194 mode = ''
195 195 try:
196 196 mode = parameter_s.split()[0][1:]
197 197 if mode == 'rest':
198 198 rest_docs = []
199 199 except IndexError:
200 200 pass
201 201
202 202 brief = (mode == 'brief')
203 203 rest = (mode == 'rest')
204 204 magic_docs = self._magic_docs(brief, rest)
205 205
206 206 if mode == 'latex':
207 207 print(self.format_latex(magic_docs))
208 208 return
209 209 else:
210 210 magic_docs = format_screen(magic_docs)
211 211
212 212 out = ["""
213 213 IPython's 'magic' functions
214 214 ===========================
215 215
216 216 The magic function system provides a series of functions which allow you to
217 217 control the behavior of IPython itself, plus a lot of system-type
218 218 features. There are two kinds of magics, line-oriented and cell-oriented.
219 219
220 220 Line magics are prefixed with the % character and work much like OS
221 221 command-line calls: they get as an argument the rest of the line, where
222 222 arguments are passed without parentheses or quotes. For example, this will
223 223 time the given statement::
224 224
225 225 %timeit range(1000)
226 226
227 227 Cell magics are prefixed with a double %%, and they are functions that get as
228 228 an argument not only the rest of the line, but also the lines below it in a
229 229 separate argument. These magics are called with two arguments: the rest of the
230 230 call line and the body of the cell, consisting of the lines below the first.
231 231 For example::
232 232
233 233 %%timeit x = numpy.random.randn((100, 100))
234 234 numpy.linalg.svd(x)
235 235
236 236 will time the execution of the numpy svd routine, running the assignment of x
237 237 as part of the setup phase, which is not timed.
238 238
239 239 In a line-oriented client (the terminal or Qt console IPython), starting a new
240 240 input with %% will automatically enter cell mode, and IPython will continue
241 241 reading input until a blank line is given. In the notebook, simply type the
242 242 whole cell as one entity, but keep in mind that the %% escape can only be at
243 243 the very start of the cell.
244 244
245 245 NOTE: If you have 'automagic' enabled (via the command line option or with the
246 246 %automagic function), you don't need to type in the % explicitly for line
247 247 magics; cell magics always require an explicit '%%' escape. By default,
248 248 IPython ships with automagic on, so you should only rarely need the % escape.
249 249
250 250 Example: typing '%cd mydir' (without the quotes) changes you working directory
251 251 to 'mydir', if it exists.
252 252
253 253 For a list of the available magic functions, use %lsmagic. For a description
254 254 of any of them, type %magic_name?, e.g. '%cd?'.
255 255
256 256 Currently the magic system has the following functions:""",
257 257 magic_docs,
258 258 "Summary of magic functions (from %slsmagic):" % magic_escapes['line'],
259 259 str(self.lsmagic()),
260 260 ]
261 261 page.page('\n'.join(out))
262 262
263 263
264 264 @line_magic
265 265 def page(self, parameter_s=''):
266 266 """Pretty print the object and display it through a pager.
267 267
268 268 %page [options] OBJECT
269 269
270 270 If no object is given, use _ (last output).
271 271
272 272 Options:
273 273
274 274 -r: page str(object), don't pretty-print it."""
275 275
276 276 # After a function contributed by Olivier Aubert, slightly modified.
277 277
278 278 # Process options/args
279 279 opts, args = self.parse_options(parameter_s, 'r')
280 280 raw = 'r' in opts
281 281
282 282 oname = args and args or '_'
283 283 info = self.shell._ofind(oname)
284 284 if info['found']:
285 285 txt = (raw and str or pformat)( info['obj'] )
286 286 page.page(txt)
287 287 else:
288 288 print('Object `%s` not found' % oname)
289 289
290 290 @line_magic
291 291 def profile(self, parameter_s=''):
292 292 """Print your currently active IPython profile.
293 293
294 294 See Also
295 295 --------
296 296 prun : run code using the Python profiler
297 297 (:meth:`~IPython.core.magics.execution.ExecutionMagics.prun`)
298 298 """
299 299 warn("%profile is now deprecated. Please use get_ipython().profile instead.")
300 300 from IPython.core.application import BaseIPythonApplication
301 301 if BaseIPythonApplication.initialized():
302 302 print(BaseIPythonApplication.instance().profile)
303 303 else:
304 304 error("profile is an application-level value, but you don't appear to be in an IPython application")
305 305
306 306 @line_magic
307 307 def pprint(self, parameter_s=''):
308 308 """Toggle pretty printing on/off."""
309 309 ptformatter = self.shell.display_formatter.formatters['text/plain']
310 310 ptformatter.pprint = bool(1 - ptformatter.pprint)
311 311 print('Pretty printing has been turned',
312 312 ['OFF','ON'][ptformatter.pprint])
313 313
314 314 @line_magic
315 315 def colors(self, parameter_s=''):
316 316 """Switch color scheme for prompts, info system and exception handlers.
317 317
318 318 Currently implemented schemes: NoColor, Linux, LightBG.
319 319
320 320 Color scheme names are not case-sensitive.
321 321
322 322 Examples
323 323 --------
324 324 To get a plain black and white terminal::
325 325
326 326 %colors nocolor
327 327 """
328 328 def color_switch_err(name):
329 329 warn('Error changing %s color schemes.\n%s' %
330 330 (name, sys.exc_info()[1]))
331 331
332 332
333 333 new_scheme = parameter_s.strip()
334 334 if not new_scheme:
335 335 raise UsageError(
336 336 "%colors: you must specify a color scheme. See '%colors?'")
337 337 # local shortcut
338 338 shell = self.shell
339 339
340 340 import IPython.utils.rlineimpl as readline
341 341
342 342 if not shell.colors_force and \
343 343 not readline.have_readline and \
344 344 (sys.platform == "win32" or sys.platform == "cli"):
345 345 msg = """\
346 346 Proper color support under MS Windows requires the pyreadline library.
347 347 You can find it at:
348 348 http://ipython.org/pyreadline.html
349 349
350 350 Defaulting color scheme to 'NoColor'"""
351 351 new_scheme = 'NoColor'
352 352 warn(msg)
353 353
354 354 # readline option is 0
355 355 if not shell.colors_force and not shell.has_readline:
356 356 new_scheme = 'NoColor'
357 357
358 358 # Set prompt colors
359 359 try:
360 360 shell.prompt_manager.color_scheme = new_scheme
361 361 except:
362 362 color_switch_err('prompt')
363 363 else:
364 364 shell.colors = \
365 365 shell.prompt_manager.color_scheme_table.active_scheme_name
366 366 # Set exception colors
367 367 try:
368 368 shell.InteractiveTB.set_colors(scheme = new_scheme)
369 369 shell.SyntaxTB.set_colors(scheme = new_scheme)
370 370 except:
371 371 color_switch_err('exception')
372 372
373 373 # Set info (for 'object?') colors
374 374 if shell.color_info:
375 375 try:
376 376 shell.inspector.set_active_scheme(new_scheme)
377 377 except:
378 378 color_switch_err('object inspector')
379 379 else:
380 380 shell.inspector.set_active_scheme('NoColor')
381 381
382 382 @line_magic
383 383 def xmode(self, parameter_s=''):
384 384 """Switch modes for the exception handlers.
385 385
386 386 Valid modes: Plain, Context and Verbose.
387 387
388 388 If called without arguments, acts as a toggle."""
389 389
390 390 def xmode_switch_err(name):
391 391 warn('Error changing %s exception modes.\n%s' %
392 392 (name,sys.exc_info()[1]))
393 393
394 394 shell = self.shell
395 395 new_mode = parameter_s.strip().capitalize()
396 396 try:
397 397 shell.InteractiveTB.set_mode(mode=new_mode)
398 398 print('Exception reporting mode:',shell.InteractiveTB.mode)
399 399 except:
400 400 xmode_switch_err('user')
401 401
402 402 @line_magic
403 403 def quickref(self,arg):
404 404 """ Show a quick reference sheet """
405 405 from IPython.core.usage import quick_reference
406 406 qr = quick_reference + self._magic_docs(brief=True)
407 407 page.page(qr)
408 408
409 409 @line_magic
410 410 def doctest_mode(self, parameter_s=''):
411 411 """Toggle doctest mode on and off.
412 412
413 413 This mode is intended to make IPython behave as much as possible like a
414 414 plain Python shell, from the perspective of how its prompts, exceptions
415 415 and output look. This makes it easy to copy and paste parts of a
416 416 session into doctests. It does so by:
417 417
418 418 - Changing the prompts to the classic ``>>>`` ones.
419 419 - Changing the exception reporting mode to 'Plain'.
420 420 - Disabling pretty-printing of output.
421 421
422 422 Note that IPython also supports the pasting of code snippets that have
423 423 leading '>>>' and '...' prompts in them. This means that you can paste
424 424 doctests from files or docstrings (even if they have leading
425 425 whitespace), and the code will execute correctly. You can then use
426 426 '%history -t' to see the translated history; this will give you the
427 427 input after removal of all the leading prompts and whitespace, which
428 428 can be pasted back into an editor.
429 429
430 430 With these features, you can switch into this mode easily whenever you
431 431 need to do testing and changes to doctests, without having to leave
432 432 your existing IPython session.
433 433 """
434 434
435 435 # Shorthands
436 436 shell = self.shell
437 437 pm = shell.prompt_manager
438 438 meta = shell.meta
439 439 disp_formatter = self.shell.display_formatter
440 440 ptformatter = disp_formatter.formatters['text/plain']
441 441 # dstore is a data store kept in the instance metadata bag to track any
442 442 # changes we make, so we can undo them later.
443 443 dstore = meta.setdefault('doctest_mode',Struct())
444 444 save_dstore = dstore.setdefault
445 445
446 446 # save a few values we'll need to recover later
447 447 mode = save_dstore('mode',False)
448 448 save_dstore('rc_pprint',ptformatter.pprint)
449 449 save_dstore('xmode',shell.InteractiveTB.mode)
450 450 save_dstore('rc_separate_out',shell.separate_out)
451 451 save_dstore('rc_separate_out2',shell.separate_out2)
452 452 save_dstore('rc_prompts_pad_left',pm.justify)
453 453 save_dstore('rc_separate_in',shell.separate_in)
454 454 save_dstore('rc_active_types',disp_formatter.active_types)
455 455 save_dstore('prompt_templates',(pm.in_template, pm.in2_template, pm.out_template))
456 456
457 457 if mode == False:
458 458 # turn on
459 459 pm.in_template = '>>> '
460 460 pm.in2_template = '... '
461 461 pm.out_template = ''
462 462
463 463 # Prompt separators like plain python
464 464 shell.separate_in = ''
465 465 shell.separate_out = ''
466 466 shell.separate_out2 = ''
467 467
468 468 pm.justify = False
469 469
470 470 ptformatter.pprint = False
471 471 disp_formatter.active_types = ['text/plain']
472 472
473 473 shell.magic('xmode Plain')
474 474 else:
475 475 # turn off
476 476 pm.in_template, pm.in2_template, pm.out_template = dstore.prompt_templates
477 477
478 478 shell.separate_in = dstore.rc_separate_in
479 479
480 480 shell.separate_out = dstore.rc_separate_out
481 481 shell.separate_out2 = dstore.rc_separate_out2
482 482
483 483 pm.justify = dstore.rc_prompts_pad_left
484 484
485 485 ptformatter.pprint = dstore.rc_pprint
486 486 disp_formatter.active_types = dstore.rc_active_types
487 487
488 488 shell.magic('xmode ' + dstore.xmode)
489 489
490 490 # Store new mode and inform
491 491 dstore.mode = bool(1-int(mode))
492 492 mode_label = ['OFF','ON'][dstore.mode]
493 493 print('Doctest mode is:', mode_label)
494 494
495 495 @line_magic
496 496 def gui(self, parameter_s=''):
497 497 """Enable or disable IPython GUI event loop integration.
498 498
499 499 %gui [GUINAME]
500 500
501 501 This magic replaces IPython's threaded shells that were activated
502 502 using the (pylab/wthread/etc.) command line flags. GUI toolkits
503 503 can now be enabled at runtime and keyboard
504 504 interrupts should work without any problems. The following toolkits
505 505 are supported: wxPython, PyQt4, PyGTK, Tk and Cocoa (OSX)::
506 506
507 507 %gui wx # enable wxPython event loop integration
508 508 %gui qt4|qt # enable PyQt4 event loop integration
509 509 %gui qt5 # enable PyQt5 event loop integration
510 510 %gui gtk # enable PyGTK event loop integration
511 511 %gui gtk3 # enable Gtk3 event loop integration
512 512 %gui tk # enable Tk event loop integration
513 513 %gui osx # enable Cocoa event loop integration
514 514 # (requires %matplotlib 1.1)
515 515 %gui # disable all event loop integration
516 516
517 517 WARNING: after any of these has been called you can simply create
518 518 an application object, but DO NOT start the event loop yourself, as
519 519 we have already handled that.
520 520 """
521 521 opts, arg = self.parse_options(parameter_s, '')
522 522 if arg=='': arg = None
523 523 try:
524 524 return self.shell.enable_gui(arg)
525 525 except Exception as e:
526 526 # print simple error message, rather than traceback if we can't
527 527 # hook up the GUI
528 528 error(str(e))
529 529
530 530 @skip_doctest
531 531 @line_magic
532 532 def precision(self, s=''):
533 533 """Set floating point precision for pretty printing.
534 534
535 535 Can set either integer precision or a format string.
536 536
537 537 If numpy has been imported and precision is an int,
538 538 numpy display precision will also be set, via ``numpy.set_printoptions``.
539 539
540 540 If no argument is given, defaults will be restored.
541 541
542 542 Examples
543 543 --------
544 544 ::
545 545
546 546 In [1]: from math import pi
547 547
548 548 In [2]: %precision 3
549 549 Out[2]: u'%.3f'
550 550
551 551 In [3]: pi
552 552 Out[3]: 3.142
553 553
554 554 In [4]: %precision %i
555 555 Out[4]: u'%i'
556 556
557 557 In [5]: pi
558 558 Out[5]: 3
559 559
560 560 In [6]: %precision %e
561 561 Out[6]: u'%e'
562 562
563 563 In [7]: pi**10
564 564 Out[7]: 9.364805e+04
565 565
566 566 In [8]: %precision
567 567 Out[8]: u'%r'
568 568
569 569 In [9]: pi**10
570 570 Out[9]: 93648.047476082982
571 571 """
572 572 ptformatter = self.shell.display_formatter.formatters['text/plain']
573 573 ptformatter.float_precision = s
574 574 return ptformatter.float_format
575 575
576 576 @magic_arguments.magic_arguments()
577 577 @magic_arguments.argument(
578 578 '-e', '--export', action='store_true', default=False,
579 579 help='Export IPython history as a notebook. The filename argument '
580 580 'is used to specify the notebook name and format. For example '
581 581 'a filename of notebook.ipynb will result in a notebook name '
582 582 'of "notebook" and a format of "json". Likewise using a ".py" '
583 583 'file extension will write the notebook as a Python script'
584 584 )
585 585 @magic_arguments.argument(
586 586 'filename', type=unicode_type,
587 587 help='Notebook name or filename'
588 588 )
589 589 @line_magic
590 590 def notebook(self, s):
591 591 """Export and convert IPython notebooks.
592 592
593 593 This function can export the current IPython history to a notebook file.
594 594 For example, to export the history to "foo.ipynb" do "%notebook -e foo.ipynb".
595 595 To export the history to "foo.py" do "%notebook -e foo.py".
596 596 """
597 597 args = magic_arguments.parse_argstring(self.notebook, s)
598 598
599 599 from IPython.nbformat import write, v4
600 600 args.filename = unquote_filename(args.filename)
601 601 if args.export:
602 602 cells = []
603 603 hist = list(self.shell.history_manager.get_range())
604 604 if(len(hist)<=1):
605 605 raise ValueError('History is empty, cannot export')
606 for session, execution_count, input in hist[:-1]:
606 for session, execution_count, source in hist[:-1]:
607 607 cells.append(v4.new_code_cell(
608 608 execution_count=execution_count,
609 609 source=source
610 610 ))
611 611 nb = v4.new_notebook(cells=cells)
612 612 with io.open(args.filename, 'w', encoding='utf-8') as f:
613 613 write(nb, f, version=4)
@@ -1,998 +1,998 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 from __future__ import absolute_import
7 7
8 8 import io
9 9 import os
10 10 import sys
11 11 import warnings
12 12 from unittest import TestCase, skipIf
13 13
14 14 try:
15 15 from importlib import invalidate_caches # Required from Python 3.3
16 16 except ImportError:
17 17 def invalidate_caches():
18 18 pass
19 19
20 20 import nose.tools as nt
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, line_cell_magic,
27 27 register_line_magic, register_cell_magic,
28 28 register_line_cell_magic)
29 29 from IPython.core.magics import execution, script, code
30 30 from IPython.testing import decorators as dec
31 31 from IPython.testing import tools as tt
32 32 from IPython.utils import py3compat
33 33 from IPython.utils.io import capture_output
34 34 from IPython.utils.tempdir import TemporaryDirectory
35 35 from IPython.utils.process import find_cmd
36 36
37 37 if py3compat.PY3:
38 38 from io import StringIO
39 39 else:
40 40 from StringIO import StringIO
41 41
42 42
43 43 @magic.magics_class
44 44 class DummyMagics(magic.Magics): pass
45 45
46 46 def test_extract_code_ranges():
47 47 instr = "1 3 5-6 7-9 10:15 17: :10 10- -13 :"
48 48 expected = [(0, 1),
49 49 (2, 3),
50 50 (4, 6),
51 51 (6, 9),
52 52 (9, 14),
53 53 (16, None),
54 54 (None, 9),
55 55 (9, None),
56 56 (None, 13),
57 57 (None, None)]
58 58 actual = list(code.extract_code_ranges(instr))
59 59 nt.assert_equal(actual, expected)
60 60
61 61 def test_extract_symbols():
62 62 source = """import foo\na = 10\ndef b():\n return 42\n\n\nclass A: pass\n\n\n"""
63 63 symbols_args = ["a", "b", "A", "A,b", "A,a", "z"]
64 64 expected = [([], ['a']),
65 65 (["def b():\n return 42\n"], []),
66 66 (["class A: pass\n"], []),
67 67 (["class A: pass\n", "def b():\n return 42\n"], []),
68 68 (["class A: pass\n"], ['a']),
69 69 ([], ['z'])]
70 70 for symbols, exp in zip(symbols_args, expected):
71 71 nt.assert_equal(code.extract_symbols(source, symbols), exp)
72 72
73 73
74 74 def test_extract_symbols_raises_exception_with_non_python_code():
75 75 source = ("=begin A Ruby program :)=end\n"
76 76 "def hello\n"
77 77 "puts 'Hello world'\n"
78 78 "end")
79 79 with nt.assert_raises(SyntaxError):
80 80 code.extract_symbols(source, "hello")
81 81
82 82 def test_config():
83 83 """ test that config magic does not raise
84 84 can happen if Configurable init is moved too early into
85 85 Magics.__init__ as then a Config object will be registerd as a
86 86 magic.
87 87 """
88 88 ## should not raise.
89 89 _ip.magic('config')
90 90
91 91 def test_rehashx():
92 92 # clear up everything
93 93 _ip = get_ipython()
94 94 _ip.alias_manager.clear_aliases()
95 95 del _ip.db['syscmdlist']
96 96
97 97 _ip.magic('rehashx')
98 98 # Practically ALL ipython development systems will have more than 10 aliases
99 99
100 100 nt.assert_true(len(_ip.alias_manager.aliases) > 10)
101 101 for name, cmd in _ip.alias_manager.aliases:
102 102 # we must strip dots from alias names
103 103 nt.assert_not_in('.', name)
104 104
105 105 # rehashx must fill up syscmdlist
106 106 scoms = _ip.db['syscmdlist']
107 107 nt.assert_true(len(scoms) > 10)
108 108
109 109
110 110 def test_magic_parse_options():
111 111 """Test that we don't mangle paths when parsing magic options."""
112 112 ip = get_ipython()
113 113 path = 'c:\\x'
114 114 m = DummyMagics(ip)
115 115 opts = m.parse_options('-f %s' % path,'f:')[0]
116 116 # argv splitting is os-dependent
117 117 if os.name == 'posix':
118 118 expected = 'c:x'
119 119 else:
120 120 expected = path
121 121 nt.assert_equal(opts['f'], expected)
122 122
123 123 def test_magic_parse_long_options():
124 124 """Magic.parse_options can handle --foo=bar long options"""
125 125 ip = get_ipython()
126 126 m = DummyMagics(ip)
127 127 opts, _ = m.parse_options('--foo --bar=bubble', 'a', 'foo', 'bar=')
128 128 nt.assert_in('foo', opts)
129 129 nt.assert_in('bar', opts)
130 130 nt.assert_equal(opts['bar'], "bubble")
131 131
132 132
133 133 @dec.skip_without('sqlite3')
134 134 def doctest_hist_f():
135 135 """Test %hist -f with temporary filename.
136 136
137 137 In [9]: import tempfile
138 138
139 139 In [10]: tfile = tempfile.mktemp('.py','tmp-ipython-')
140 140
141 141 In [11]: %hist -nl -f $tfile 3
142 142
143 143 In [13]: import os; os.unlink(tfile)
144 144 """
145 145
146 146
147 147 @dec.skip_without('sqlite3')
148 148 def doctest_hist_r():
149 149 """Test %hist -r
150 150
151 151 XXX - This test is not recording the output correctly. For some reason, in
152 152 testing mode the raw history isn't getting populated. No idea why.
153 153 Disabling the output checking for now, though at least we do run it.
154 154
155 155 In [1]: 'hist' in _ip.lsmagic()
156 156 Out[1]: True
157 157
158 158 In [2]: x=1
159 159
160 160 In [3]: %hist -rl 2
161 161 x=1 # random
162 162 %hist -r 2
163 163 """
164 164
165 165
166 166 @dec.skip_without('sqlite3')
167 167 def doctest_hist_op():
168 168 """Test %hist -op
169 169
170 170 In [1]: class b(float):
171 171 ...: pass
172 172 ...:
173 173
174 174 In [2]: class s(object):
175 175 ...: def __str__(self):
176 176 ...: return 's'
177 177 ...:
178 178
179 179 In [3]:
180 180
181 181 In [4]: class r(b):
182 182 ...: def __repr__(self):
183 183 ...: return 'r'
184 184 ...:
185 185
186 186 In [5]: class sr(s,r): pass
187 187 ...:
188 188
189 189 In [6]:
190 190
191 191 In [7]: bb=b()
192 192
193 193 In [8]: ss=s()
194 194
195 195 In [9]: rr=r()
196 196
197 197 In [10]: ssrr=sr()
198 198
199 199 In [11]: 4.5
200 200 Out[11]: 4.5
201 201
202 202 In [12]: str(ss)
203 203 Out[12]: 's'
204 204
205 205 In [13]:
206 206
207 207 In [14]: %hist -op
208 208 >>> class b:
209 209 ... pass
210 210 ...
211 211 >>> class s(b):
212 212 ... def __str__(self):
213 213 ... return 's'
214 214 ...
215 215 >>>
216 216 >>> class r(b):
217 217 ... def __repr__(self):
218 218 ... return 'r'
219 219 ...
220 220 >>> class sr(s,r): pass
221 221 >>>
222 222 >>> bb=b()
223 223 >>> ss=s()
224 224 >>> rr=r()
225 225 >>> ssrr=sr()
226 226 >>> 4.5
227 227 4.5
228 228 >>> str(ss)
229 229 's'
230 230 >>>
231 231 """
232 232
233 233 def test_hist_pof():
234 234 ip = get_ipython()
235 235 ip.run_cell(u"1+2", store_history=True)
236 236 #raise Exception(ip.history_manager.session_number)
237 237 #raise Exception(list(ip.history_manager._get_range_session()))
238 238 with TemporaryDirectory() as td:
239 239 tf = os.path.join(td, 'hist.py')
240 240 ip.run_line_magic('history', '-pof %s' % tf)
241 241 assert os.path.isfile(tf)
242 242
243 243
244 244 @dec.skip_without('sqlite3')
245 245 def test_macro():
246 246 ip = get_ipython()
247 247 ip.history_manager.reset() # Clear any existing history.
248 248 cmds = ["a=1", "def b():\n return a**2", "print(a,b())"]
249 249 for i, cmd in enumerate(cmds, start=1):
250 250 ip.history_manager.store_inputs(i, cmd)
251 251 ip.magic("macro test 1-3")
252 252 nt.assert_equal(ip.user_ns["test"].value, "\n".join(cmds)+"\n")
253 253
254 254 # List macros
255 255 nt.assert_in("test", ip.magic("macro"))
256 256
257 257
258 258 @dec.skip_without('sqlite3')
259 259 def test_macro_run():
260 260 """Test that we can run a multi-line macro successfully."""
261 261 ip = get_ipython()
262 262 ip.history_manager.reset()
263 263 cmds = ["a=10", "a+=1", py3compat.doctest_refactor_print("print a"),
264 264 "%macro test 2-3"]
265 265 for cmd in cmds:
266 266 ip.run_cell(cmd, store_history=True)
267 267 nt.assert_equal(ip.user_ns["test"].value,
268 268 py3compat.doctest_refactor_print("a+=1\nprint a\n"))
269 269 with tt.AssertPrints("12"):
270 270 ip.run_cell("test")
271 271 with tt.AssertPrints("13"):
272 272 ip.run_cell("test")
273 273
274 274
275 275 def test_magic_magic():
276 276 """Test %magic"""
277 277 ip = get_ipython()
278 278 with capture_output() as captured:
279 279 ip.magic("magic")
280 280
281 281 stdout = captured.stdout
282 282 nt.assert_in('%magic', stdout)
283 283 nt.assert_in('IPython', stdout)
284 284 nt.assert_in('Available', stdout)
285 285
286 286
287 287 @dec.skipif_not_numpy
288 288 def test_numpy_reset_array_undec():
289 289 "Test '%reset array' functionality"
290 290 _ip.ex('import numpy as np')
291 291 _ip.ex('a = np.empty(2)')
292 292 nt.assert_in('a', _ip.user_ns)
293 293 _ip.magic('reset -f array')
294 294 nt.assert_not_in('a', _ip.user_ns)
295 295
296 296 def test_reset_out():
297 297 "Test '%reset out' magic"
298 298 _ip.run_cell("parrot = 'dead'", store_history=True)
299 299 # test '%reset -f out', make an Out prompt
300 300 _ip.run_cell("parrot", store_history=True)
301 301 nt.assert_true('dead' in [_ip.user_ns[x] for x in ('_','__','___')])
302 302 _ip.magic('reset -f out')
303 303 nt.assert_false('dead' in [_ip.user_ns[x] for x in ('_','__','___')])
304 304 nt.assert_equal(len(_ip.user_ns['Out']), 0)
305 305
306 306 def test_reset_in():
307 307 "Test '%reset in' magic"
308 308 # test '%reset -f in'
309 309 _ip.run_cell("parrot", store_history=True)
310 310 nt.assert_true('parrot' in [_ip.user_ns[x] for x in ('_i','_ii','_iii')])
311 311 _ip.magic('%reset -f in')
312 312 nt.assert_false('parrot' in [_ip.user_ns[x] for x in ('_i','_ii','_iii')])
313 313 nt.assert_equal(len(set(_ip.user_ns['In'])), 1)
314 314
315 315 def test_reset_dhist():
316 316 "Test '%reset dhist' magic"
317 317 _ip.run_cell("tmp = [d for d in _dh]") # copy before clearing
318 318 _ip.magic('cd ' + os.path.dirname(nt.__file__))
319 319 _ip.magic('cd -')
320 320 nt.assert_true(len(_ip.user_ns['_dh']) > 0)
321 321 _ip.magic('reset -f dhist')
322 322 nt.assert_equal(len(_ip.user_ns['_dh']), 0)
323 323 _ip.run_cell("_dh = [d for d in tmp]") #restore
324 324
325 325 def test_reset_in_length():
326 326 "Test that '%reset in' preserves In[] length"
327 327 _ip.run_cell("print 'foo'")
328 328 _ip.run_cell("reset -f in")
329 329 nt.assert_equal(len(_ip.user_ns['In']), _ip.displayhook.prompt_count+1)
330 330
331 331 def test_tb_syntaxerror():
332 332 """test %tb after a SyntaxError"""
333 333 ip = get_ipython()
334 334 ip.run_cell("for")
335 335
336 336 # trap and validate stdout
337 337 save_stdout = sys.stdout
338 338 try:
339 339 sys.stdout = StringIO()
340 340 ip.run_cell("%tb")
341 341 out = sys.stdout.getvalue()
342 342 finally:
343 343 sys.stdout = save_stdout
344 344 # trim output, and only check the last line
345 345 last_line = out.rstrip().splitlines()[-1].strip()
346 346 nt.assert_equal(last_line, "SyntaxError: invalid syntax")
347 347
348 348
349 349 def test_time():
350 350 ip = get_ipython()
351 351
352 352 with tt.AssertPrints("Wall time: "):
353 353 ip.run_cell("%time None")
354 354
355 355 ip.run_cell("def f(kmjy):\n"
356 356 " %time print (2*kmjy)")
357 357
358 358 with tt.AssertPrints("Wall time: "):
359 359 with tt.AssertPrints("hihi", suppress=False):
360 360 ip.run_cell("f('hi')")
361 361
362 362
363 363 @dec.skip_win32
364 364 def test_time2():
365 365 ip = get_ipython()
366 366
367 367 with tt.AssertPrints("CPU times: user "):
368 368 ip.run_cell("%time None")
369 369
370 370 def test_time3():
371 371 """Erroneous magic function calls, issue gh-3334"""
372 372 ip = get_ipython()
373 373 ip.user_ns.pop('run', None)
374 374
375 375 with tt.AssertNotPrints("not found", channel='stderr'):
376 376 ip.run_cell("%%time\n"
377 377 "run = 0\n"
378 378 "run += 1")
379 379
380 380 @dec.skipif(sys.version_info[0] >= 3, "no differences with __future__ in py3")
381 381 def test_time_futures():
382 382 "Test %time with __future__ environments"
383 383 ip = get_ipython()
384 384 ip.autocall = 0
385 385 ip.run_cell("from __future__ import division")
386 386 with tt.AssertPrints('0.25'):
387 387 ip.run_line_magic('time', 'print(1/4)')
388 388 ip.compile.reset_compiler_flags()
389 389 with tt.AssertNotPrints('0.25'):
390 390 ip.run_line_magic('time', 'print(1/4)')
391 391
392 392 def test_doctest_mode():
393 393 "Toggle doctest_mode twice, it should be a no-op and run without error"
394 394 _ip.magic('doctest_mode')
395 395 _ip.magic('doctest_mode')
396 396
397 397
398 398 def test_parse_options():
399 399 """Tests for basic options parsing in magics."""
400 400 # These are only the most minimal of tests, more should be added later. At
401 401 # the very least we check that basic text/unicode calls work OK.
402 402 m = DummyMagics(_ip)
403 403 nt.assert_equal(m.parse_options('foo', '')[1], 'foo')
404 404 nt.assert_equal(m.parse_options(u'foo', '')[1], u'foo')
405 405
406 406
407 407 def test_dirops():
408 408 """Test various directory handling operations."""
409 409 # curpath = lambda :os.path.splitdrive(py3compat.getcwd())[1].replace('\\','/')
410 410 curpath = py3compat.getcwd
411 411 startdir = py3compat.getcwd()
412 412 ipdir = os.path.realpath(_ip.ipython_dir)
413 413 try:
414 414 _ip.magic('cd "%s"' % ipdir)
415 415 nt.assert_equal(curpath(), ipdir)
416 416 _ip.magic('cd -')
417 417 nt.assert_equal(curpath(), startdir)
418 418 _ip.magic('pushd "%s"' % ipdir)
419 419 nt.assert_equal(curpath(), ipdir)
420 420 _ip.magic('popd')
421 421 nt.assert_equal(curpath(), startdir)
422 422 finally:
423 423 os.chdir(startdir)
424 424
425 425
426 426 def test_xmode():
427 427 # Calling xmode three times should be a no-op
428 428 xmode = _ip.InteractiveTB.mode
429 429 for i in range(3):
430 430 _ip.magic("xmode")
431 431 nt.assert_equal(_ip.InteractiveTB.mode, xmode)
432 432
433 433 def test_reset_hard():
434 434 monitor = []
435 435 class A(object):
436 436 def __del__(self):
437 437 monitor.append(1)
438 438 def __repr__(self):
439 439 return "<A instance>"
440 440
441 441 _ip.user_ns["a"] = A()
442 442 _ip.run_cell("a")
443 443
444 444 nt.assert_equal(monitor, [])
445 445 _ip.magic("reset -f")
446 446 nt.assert_equal(monitor, [1])
447 447
448 448 class TestXdel(tt.TempFileMixin):
449 449 def test_xdel(self):
450 450 """Test that references from %run are cleared by xdel."""
451 451 src = ("class A(object):\n"
452 452 " monitor = []\n"
453 453 " def __del__(self):\n"
454 454 " self.monitor.append(1)\n"
455 455 "a = A()\n")
456 456 self.mktmp(src)
457 457 # %run creates some hidden references...
458 458 _ip.magic("run %s" % self.fname)
459 459 # ... as does the displayhook.
460 460 _ip.run_cell("a")
461 461
462 462 monitor = _ip.user_ns["A"].monitor
463 463 nt.assert_equal(monitor, [])
464 464
465 465 _ip.magic("xdel a")
466 466
467 467 # Check that a's __del__ method has been called.
468 468 nt.assert_equal(monitor, [1])
469 469
470 470 def doctest_who():
471 471 """doctest for %who
472 472
473 473 In [1]: %reset -f
474 474
475 475 In [2]: alpha = 123
476 476
477 477 In [3]: beta = 'beta'
478 478
479 479 In [4]: %who int
480 480 alpha
481 481
482 482 In [5]: %who str
483 483 beta
484 484
485 485 In [6]: %whos
486 486 Variable Type Data/Info
487 487 ----------------------------
488 488 alpha int 123
489 489 beta str beta
490 490
491 491 In [7]: %who_ls
492 492 Out[7]: ['alpha', 'beta']
493 493 """
494 494
495 495 def test_whos():
496 496 """Check that whos is protected against objects where repr() fails."""
497 497 class A(object):
498 498 def __repr__(self):
499 499 raise Exception()
500 500 _ip.user_ns['a'] = A()
501 501 _ip.magic("whos")
502 502
503 503 @py3compat.u_format
504 504 def doctest_precision():
505 505 """doctest for %precision
506 506
507 507 In [1]: f = get_ipython().display_formatter.formatters['text/plain']
508 508
509 509 In [2]: %precision 5
510 510 Out[2]: {u}'%.5f'
511 511
512 512 In [3]: f.float_format
513 513 Out[3]: {u}'%.5f'
514 514
515 515 In [4]: %precision %e
516 516 Out[4]: {u}'%e'
517 517
518 518 In [5]: f(3.1415927)
519 519 Out[5]: {u}'3.141593e+00'
520 520 """
521 521
522 522 def test_psearch():
523 523 with tt.AssertPrints("dict.fromkeys"):
524 524 _ip.run_cell("dict.fr*?")
525 525
526 526 def test_timeit_shlex():
527 527 """test shlex issues with timeit (#1109)"""
528 528 _ip.ex("def f(*a,**kw): pass")
529 529 _ip.magic('timeit -n1 "this is a bug".count(" ")')
530 530 _ip.magic('timeit -r1 -n1 f(" ", 1)')
531 531 _ip.magic('timeit -r1 -n1 f(" ", 1, " ", 2, " ")')
532 532 _ip.magic('timeit -r1 -n1 ("a " + "b")')
533 533 _ip.magic('timeit -r1 -n1 f("a " + "b")')
534 534 _ip.magic('timeit -r1 -n1 f("a " + "b ")')
535 535
536 536
537 537 def test_timeit_arguments():
538 538 "Test valid timeit arguments, should not cause SyntaxError (GH #1269)"
539 539 _ip.magic("timeit ('#')")
540 540
541 541
542 542 def test_timeit_special_syntax():
543 543 "Test %%timeit with IPython special syntax"
544 544 @register_line_magic
545 545 def lmagic(line):
546 546 ip = get_ipython()
547 547 ip.user_ns['lmagic_out'] = line
548 548
549 549 # line mode test
550 550 _ip.run_line_magic('timeit', '-n1 -r1 %lmagic my line')
551 551 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line')
552 552 # cell mode test
553 553 _ip.run_cell_magic('timeit', '-n1 -r1', '%lmagic my line2')
554 554 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line2')
555 555
556 556 def test_timeit_return():
557 557 """
558 558 test wether timeit -o return object
559 559 """
560 560
561 561 res = _ip.run_line_magic('timeit','-n10 -r10 -o 1')
562 562 assert(res is not None)
563 563
564 564 def test_timeit_quiet():
565 565 """
566 566 test quiet option of timeit magic
567 567 """
568 568 with tt.AssertNotPrints("loops"):
569 569 _ip.run_cell("%timeit -n1 -r1 -q 1")
570 570
571 571 @dec.skipif(sys.version_info[0] >= 3, "no differences with __future__ in py3")
572 572 def test_timeit_futures():
573 573 "Test %timeit with __future__ environments"
574 574 ip = get_ipython()
575 575 ip.run_cell("from __future__ import division")
576 576 with tt.AssertPrints('0.25'):
577 577 ip.run_line_magic('timeit', '-n1 -r1 print(1/4)')
578 578 ip.compile.reset_compiler_flags()
579 579 with tt.AssertNotPrints('0.25'):
580 580 ip.run_line_magic('timeit', '-n1 -r1 print(1/4)')
581 581
582 582 @dec.skipif(execution.profile is None)
583 583 def test_prun_special_syntax():
584 584 "Test %%prun with IPython special syntax"
585 585 @register_line_magic
586 586 def lmagic(line):
587 587 ip = get_ipython()
588 588 ip.user_ns['lmagic_out'] = line
589 589
590 590 # line mode test
591 591 _ip.run_line_magic('prun', '-q %lmagic my line')
592 592 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line')
593 593 # cell mode test
594 594 _ip.run_cell_magic('prun', '-q', '%lmagic my line2')
595 595 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line2')
596 596
597 597 @dec.skipif(execution.profile is None)
598 598 def test_prun_quotes():
599 599 "Test that prun does not clobber string escapes (GH #1302)"
600 600 _ip.magic(r"prun -q x = '\t'")
601 601 nt.assert_equal(_ip.user_ns['x'], '\t')
602 602
603 603 def test_extension():
604 604 tmpdir = TemporaryDirectory()
605 605 orig_ipython_dir = _ip.ipython_dir
606 606 try:
607 607 _ip.ipython_dir = tmpdir.name
608 608 nt.assert_raises(ImportError, _ip.magic, "load_ext daft_extension")
609 609 url = os.path.join(os.path.dirname(__file__), "daft_extension.py")
610 610 _ip.magic("install_ext %s" % url)
611 611 _ip.user_ns.pop('arq', None)
612 612 invalidate_caches() # Clear import caches
613 613 _ip.magic("load_ext daft_extension")
614 614 nt.assert_equal(_ip.user_ns['arq'], 185)
615 615 _ip.magic("unload_ext daft_extension")
616 616 assert 'arq' not in _ip.user_ns
617 617 finally:
618 618 _ip.ipython_dir = orig_ipython_dir
619 619 tmpdir.cleanup()
620 620
621 621
622 622 # The nose skip decorator doesn't work on classes, so this uses unittest's skipIf
623 623 @skipIf(dec.module_not_available('IPython.nbformat'), 'nbformat not importable')
624 624 class NotebookExportMagicTests(TestCase):
625 625 def test_notebook_export_json(self):
626 626 _ip = get_ipython()
627 627 _ip.history_manager.reset() # Clear any existing history.
628 cmds = [u"a=1", u"def b():\n return a**2", u"print(a, b())"]
628 cmds = [u"a=1", u"def b():\n return a**2", u"print('noΓ«l, Γ©tΓ©', b())"]
629 629 for i, cmd in enumerate(cmds, start=1):
630 630 _ip.history_manager.store_inputs(i, cmd)
631 631 with TemporaryDirectory() as td:
632 632 outfile = os.path.join(td, "nb.ipynb")
633 633 _ip.magic("notebook -e %s" % outfile)
634 634
635 635
636 636 class TestEnv(TestCase):
637 637
638 638 def test_env(self):
639 639 env = _ip.magic("env")
640 640 self.assertTrue(isinstance(env, dict))
641 641
642 642 def test_env_get_set_simple(self):
643 643 env = _ip.magic("env var val1")
644 644 self.assertEqual(env, None)
645 645 self.assertEqual(os.environ['var'], 'val1')
646 646 self.assertEqual(_ip.magic("env var"), 'val1')
647 647 env = _ip.magic("env var=val2")
648 648 self.assertEqual(env, None)
649 649 self.assertEqual(os.environ['var'], 'val2')
650 650
651 651 def test_env_get_set_complex(self):
652 652 env = _ip.magic("env var 'val1 '' 'val2")
653 653 self.assertEqual(env, None)
654 654 self.assertEqual(os.environ['var'], "'val1 '' 'val2")
655 655 self.assertEqual(_ip.magic("env var"), "'val1 '' 'val2")
656 656 env = _ip.magic('env var=val2 val3="val4')
657 657 self.assertEqual(env, None)
658 658 self.assertEqual(os.environ['var'], 'val2 val3="val4')
659 659
660 660 def test_env_set_bad_input(self):
661 661 self.assertRaises(UsageError, lambda: _ip.magic("set_env var"))
662 662
663 663 def test_env_set_whitespace(self):
664 664 self.assertRaises(UsageError, lambda: _ip.magic("env var A=B"))
665 665
666 666
667 667 class CellMagicTestCase(TestCase):
668 668
669 669 def check_ident(self, magic):
670 670 # Manually called, we get the result
671 671 out = _ip.run_cell_magic(magic, 'a', 'b')
672 672 nt.assert_equal(out, ('a','b'))
673 673 # Via run_cell, it goes into the user's namespace via displayhook
674 674 _ip.run_cell('%%' + magic +' c\nd')
675 675 nt.assert_equal(_ip.user_ns['_'], ('c','d'))
676 676
677 677 def test_cell_magic_func_deco(self):
678 678 "Cell magic using simple decorator"
679 679 @register_cell_magic
680 680 def cellm(line, cell):
681 681 return line, cell
682 682
683 683 self.check_ident('cellm')
684 684
685 685 def test_cell_magic_reg(self):
686 686 "Cell magic manually registered"
687 687 def cellm(line, cell):
688 688 return line, cell
689 689
690 690 _ip.register_magic_function(cellm, 'cell', 'cellm2')
691 691 self.check_ident('cellm2')
692 692
693 693 def test_cell_magic_class(self):
694 694 "Cell magics declared via a class"
695 695 @magics_class
696 696 class MyMagics(Magics):
697 697
698 698 @cell_magic
699 699 def cellm3(self, line, cell):
700 700 return line, cell
701 701
702 702 _ip.register_magics(MyMagics)
703 703 self.check_ident('cellm3')
704 704
705 705 def test_cell_magic_class2(self):
706 706 "Cell magics declared via a class, #2"
707 707 @magics_class
708 708 class MyMagics2(Magics):
709 709
710 710 @cell_magic('cellm4')
711 711 def cellm33(self, line, cell):
712 712 return line, cell
713 713
714 714 _ip.register_magics(MyMagics2)
715 715 self.check_ident('cellm4')
716 716 # Check that nothing is registered as 'cellm33'
717 717 c33 = _ip.find_cell_magic('cellm33')
718 718 nt.assert_equal(c33, None)
719 719
720 720 def test_file():
721 721 """Basic %%file"""
722 722 ip = get_ipython()
723 723 with TemporaryDirectory() as td:
724 724 fname = os.path.join(td, 'file1')
725 725 ip.run_cell_magic("file", fname, u'\n'.join([
726 726 'line1',
727 727 'line2',
728 728 ]))
729 729 with open(fname) as f:
730 730 s = f.read()
731 731 nt.assert_in('line1\n', s)
732 732 nt.assert_in('line2', s)
733 733
734 734 def test_file_var_expand():
735 735 """%%file $filename"""
736 736 ip = get_ipython()
737 737 with TemporaryDirectory() as td:
738 738 fname = os.path.join(td, 'file1')
739 739 ip.user_ns['filename'] = fname
740 740 ip.run_cell_magic("file", '$filename', u'\n'.join([
741 741 'line1',
742 742 'line2',
743 743 ]))
744 744 with open(fname) as f:
745 745 s = f.read()
746 746 nt.assert_in('line1\n', s)
747 747 nt.assert_in('line2', s)
748 748
749 749 def test_file_unicode():
750 750 """%%file with unicode cell"""
751 751 ip = get_ipython()
752 752 with TemporaryDirectory() as td:
753 753 fname = os.path.join(td, 'file1')
754 754 ip.run_cell_magic("file", fname, u'\n'.join([
755 755 u'linΓ©1',
756 756 u'linΓ©2',
757 757 ]))
758 758 with io.open(fname, encoding='utf-8') as f:
759 759 s = f.read()
760 760 nt.assert_in(u'linΓ©1\n', s)
761 761 nt.assert_in(u'linΓ©2', s)
762 762
763 763 def test_file_amend():
764 764 """%%file -a amends files"""
765 765 ip = get_ipython()
766 766 with TemporaryDirectory() as td:
767 767 fname = os.path.join(td, 'file2')
768 768 ip.run_cell_magic("file", fname, u'\n'.join([
769 769 'line1',
770 770 'line2',
771 771 ]))
772 772 ip.run_cell_magic("file", "-a %s" % fname, u'\n'.join([
773 773 'line3',
774 774 'line4',
775 775 ]))
776 776 with open(fname) as f:
777 777 s = f.read()
778 778 nt.assert_in('line1\n', s)
779 779 nt.assert_in('line3\n', s)
780 780
781 781
782 782 def test_script_config():
783 783 ip = get_ipython()
784 784 ip.config.ScriptMagics.script_magics = ['whoda']
785 785 sm = script.ScriptMagics(shell=ip)
786 786 nt.assert_in('whoda', sm.magics['cell'])
787 787
788 788 @dec.skip_win32
789 789 def test_script_out():
790 790 ip = get_ipython()
791 791 ip.run_cell_magic("script", "--out output sh", "echo 'hi'")
792 792 nt.assert_equal(ip.user_ns['output'], 'hi\n')
793 793
794 794 @dec.skip_win32
795 795 def test_script_err():
796 796 ip = get_ipython()
797 797 ip.run_cell_magic("script", "--err error sh", "echo 'hello' >&2")
798 798 nt.assert_equal(ip.user_ns['error'], 'hello\n')
799 799
800 800 @dec.skip_win32
801 801 def test_script_out_err():
802 802 ip = get_ipython()
803 803 ip.run_cell_magic("script", "--out output --err error sh", "echo 'hi'\necho 'hello' >&2")
804 804 nt.assert_equal(ip.user_ns['output'], 'hi\n')
805 805 nt.assert_equal(ip.user_ns['error'], 'hello\n')
806 806
807 807 @dec.skip_win32
808 808 def test_script_bg_out():
809 809 ip = get_ipython()
810 810 ip.run_cell_magic("script", "--bg --out output sh", "echo 'hi'")
811 811 nt.assert_equal(ip.user_ns['output'].read(), b'hi\n')
812 812
813 813 @dec.skip_win32
814 814 def test_script_bg_err():
815 815 ip = get_ipython()
816 816 ip.run_cell_magic("script", "--bg --err error sh", "echo 'hello' >&2")
817 817 nt.assert_equal(ip.user_ns['error'].read(), b'hello\n')
818 818
819 819 @dec.skip_win32
820 820 def test_script_bg_out_err():
821 821 ip = get_ipython()
822 822 ip.run_cell_magic("script", "--bg --out output --err error sh", "echo 'hi'\necho 'hello' >&2")
823 823 nt.assert_equal(ip.user_ns['output'].read(), b'hi\n')
824 824 nt.assert_equal(ip.user_ns['error'].read(), b'hello\n')
825 825
826 826 def test_script_defaults():
827 827 ip = get_ipython()
828 828 for cmd in ['sh', 'bash', 'perl', 'ruby']:
829 829 try:
830 830 find_cmd(cmd)
831 831 except Exception:
832 832 pass
833 833 else:
834 834 nt.assert_in(cmd, ip.magics_manager.magics['cell'])
835 835
836 836
837 837 @magics_class
838 838 class FooFoo(Magics):
839 839 """class with both %foo and %%foo magics"""
840 840 @line_magic('foo')
841 841 def line_foo(self, line):
842 842 "I am line foo"
843 843 pass
844 844
845 845 @cell_magic("foo")
846 846 def cell_foo(self, line, cell):
847 847 "I am cell foo, not line foo"
848 848 pass
849 849
850 850 def test_line_cell_info():
851 851 """%%foo and %foo magics are distinguishable to inspect"""
852 852 ip = get_ipython()
853 853 ip.magics_manager.register(FooFoo)
854 854 oinfo = ip.object_inspect('foo')
855 855 nt.assert_true(oinfo['found'])
856 856 nt.assert_true(oinfo['ismagic'])
857 857
858 858 oinfo = ip.object_inspect('%%foo')
859 859 nt.assert_true(oinfo['found'])
860 860 nt.assert_true(oinfo['ismagic'])
861 861 nt.assert_equal(oinfo['docstring'], FooFoo.cell_foo.__doc__)
862 862
863 863 oinfo = ip.object_inspect('%foo')
864 864 nt.assert_true(oinfo['found'])
865 865 nt.assert_true(oinfo['ismagic'])
866 866 nt.assert_equal(oinfo['docstring'], FooFoo.line_foo.__doc__)
867 867
868 868 def test_multiple_magics():
869 869 ip = get_ipython()
870 870 foo1 = FooFoo(ip)
871 871 foo2 = FooFoo(ip)
872 872 mm = ip.magics_manager
873 873 mm.register(foo1)
874 874 nt.assert_true(mm.magics['line']['foo'].__self__ is foo1)
875 875 mm.register(foo2)
876 876 nt.assert_true(mm.magics['line']['foo'].__self__ is foo2)
877 877
878 878 def test_alias_magic():
879 879 """Test %alias_magic."""
880 880 ip = get_ipython()
881 881 mm = ip.magics_manager
882 882
883 883 # Basic operation: both cell and line magics are created, if possible.
884 884 ip.run_line_magic('alias_magic', 'timeit_alias timeit')
885 885 nt.assert_in('timeit_alias', mm.magics['line'])
886 886 nt.assert_in('timeit_alias', mm.magics['cell'])
887 887
888 888 # --cell is specified, line magic not created.
889 889 ip.run_line_magic('alias_magic', '--cell timeit_cell_alias timeit')
890 890 nt.assert_not_in('timeit_cell_alias', mm.magics['line'])
891 891 nt.assert_in('timeit_cell_alias', mm.magics['cell'])
892 892
893 893 # Test that line alias is created successfully.
894 894 ip.run_line_magic('alias_magic', '--line env_alias env')
895 895 nt.assert_equal(ip.run_line_magic('env', ''),
896 896 ip.run_line_magic('env_alias', ''))
897 897
898 898 def test_save():
899 899 """Test %save."""
900 900 ip = get_ipython()
901 901 ip.history_manager.reset() # Clear any existing history.
902 902 cmds = [u"a=1", u"def b():\n return a**2", u"print(a, b())"]
903 903 for i, cmd in enumerate(cmds, start=1):
904 904 ip.history_manager.store_inputs(i, cmd)
905 905 with TemporaryDirectory() as tmpdir:
906 906 file = os.path.join(tmpdir, "testsave.py")
907 907 ip.run_line_magic("save", "%s 1-10" % file)
908 908 with open(file) as f:
909 909 content = f.read()
910 910 nt.assert_equal(content.count(cmds[0]), 1)
911 911 nt.assert_in('coding: utf-8', content)
912 912 ip.run_line_magic("save", "-a %s 1-10" % file)
913 913 with open(file) as f:
914 914 content = f.read()
915 915 nt.assert_equal(content.count(cmds[0]), 2)
916 916 nt.assert_in('coding: utf-8', content)
917 917
918 918
919 919 def test_store():
920 920 """Test %store."""
921 921 ip = get_ipython()
922 922 ip.run_line_magic('load_ext', 'storemagic')
923 923
924 924 # make sure the storage is empty
925 925 ip.run_line_magic('store', '-z')
926 926 ip.user_ns['var'] = 42
927 927 ip.run_line_magic('store', 'var')
928 928 ip.user_ns['var'] = 39
929 929 ip.run_line_magic('store', '-r')
930 930 nt.assert_equal(ip.user_ns['var'], 42)
931 931
932 932 ip.run_line_magic('store', '-d var')
933 933 ip.user_ns['var'] = 39
934 934 ip.run_line_magic('store' , '-r')
935 935 nt.assert_equal(ip.user_ns['var'], 39)
936 936
937 937
938 938 def _run_edit_test(arg_s, exp_filename=None,
939 939 exp_lineno=-1,
940 940 exp_contents=None,
941 941 exp_is_temp=None):
942 942 ip = get_ipython()
943 943 M = code.CodeMagics(ip)
944 944 last_call = ['','']
945 945 opts,args = M.parse_options(arg_s,'prxn:')
946 946 filename, lineno, is_temp = M._find_edit_target(ip, args, opts, last_call)
947 947
948 948 if exp_filename is not None:
949 949 nt.assert_equal(exp_filename, filename)
950 950 if exp_contents is not None:
951 951 with io.open(filename, 'r', encoding='utf-8') as f:
952 952 contents = f.read()
953 953 nt.assert_equal(exp_contents, contents)
954 954 if exp_lineno != -1:
955 955 nt.assert_equal(exp_lineno, lineno)
956 956 if exp_is_temp is not None:
957 957 nt.assert_equal(exp_is_temp, is_temp)
958 958
959 959
960 960 def test_edit_interactive():
961 961 """%edit on interactively defined objects"""
962 962 ip = get_ipython()
963 963 n = ip.execution_count
964 964 ip.run_cell(u"def foo(): return 1", store_history=True)
965 965
966 966 try:
967 967 _run_edit_test("foo")
968 968 except code.InteractivelyDefined as e:
969 969 nt.assert_equal(e.index, n)
970 970 else:
971 971 raise AssertionError("Should have raised InteractivelyDefined")
972 972
973 973
974 974 def test_edit_cell():
975 975 """%edit [cell id]"""
976 976 ip = get_ipython()
977 977
978 978 ip.run_cell(u"def foo(): return 1", store_history=True)
979 979
980 980 # test
981 981 _run_edit_test("1", exp_contents=ip.user_ns['In'][1], exp_is_temp=True)
982 982
983 983 def test_bookmark():
984 984 ip = get_ipython()
985 985 ip.run_line_magic('bookmark', 'bmname')
986 986 with tt.AssertPrints('bmname'):
987 987 ip.run_line_magic('bookmark', '-l')
988 988 ip.run_line_magic('bookmark', '-d bmname')
989 989
990 990 def test_ls_magic():
991 991 ip = get_ipython()
992 992 json_formatter = ip.display_formatter.formatters['application/json']
993 993 json_formatter.enabled = True
994 994 lsmagic = ip.magic('lsmagic')
995 995 with warnings.catch_warnings(record=True) as w:
996 996 j = json_formatter(lsmagic)
997 997 nt.assert_equal(sorted(j), ['cell', 'line'])
998 998 nt.assert_equal(w, []) # no warnings
General Comments 0
You need to be logged in to leave comments. Login now