##// END OF EJS Templates
Merge pull request #4295 from mgaitan/1093_boundary_load_magic...
Min RK -
r12838:9bfd8553 merge
parent child Browse files
Show More
@@ -1,559 +1,614
1 1 """Implementation of code management magic functions.
2 2 """
3 3 #-----------------------------------------------------------------------------
4 4 # Copyright (c) 2012 The IPython Development Team.
5 5 #
6 6 # Distributed under the terms of the Modified BSD License.
7 7 #
8 8 # The full license is in the file COPYING.txt, distributed with this software.
9 9 #-----------------------------------------------------------------------------
10 10
11 11 #-----------------------------------------------------------------------------
12 12 # Imports
13 13 #-----------------------------------------------------------------------------
14 14
15 15 # Stdlib
16 16 import inspect
17 17 import io
18 18 import os
19 19 import re
20 20 import sys
21 from itertools import chain
21 22
22 23 # Our own packages
23 24 from IPython.core.error import TryNext, StdinNotImplementedError, UsageError
24 25 from IPython.core.macro import Macro
25 26 from IPython.core.magic import Magics, magics_class, line_magic
26 27 from IPython.core.oinspect import find_file, find_source_lines
27 28 from IPython.testing.skipdoctest import skip_doctest
28 29 from IPython.utils import py3compat
29 30 from IPython.utils.contexts import preserve_keys
30 31 from IPython.utils.path import get_py_filename, unquote_filename
31 32 from IPython.utils.warn import warn
32 33
33 34 #-----------------------------------------------------------------------------
34 35 # Magic implementation classes
35 36 #-----------------------------------------------------------------------------
36 37
37 38 # Used for exception handling in magic_edit
38 39 class MacroToEdit(ValueError): pass
39 40
40 41 ipython_input_pat = re.compile(r"<ipython\-input\-(\d+)-[a-z\d]+>$")
41 42
43 # To match, e.g. 8-10 1:5 :10 3-
44 range_re = re.compile(r"""
45 (?P<start>\d+)?
46 ((?P<sep>[\-:])
47 (?P<end>\d+)?)?
48 $""", re.VERBOSE)
49
50
51 def extract_code_ranges(ranges_str):
52 """Turn a string of range for %%load into 2-tuples of (start, stop)
53 ready to use as a slice of the content splitted by lines.
54
55 Examples
56 --------
57 list(extract_input_ranges("5-10 2"))
58 [(4, 10), (1, 2)]
59 """
60 for range_str in ranges_str.split():
61 rmatch = range_re.match(range_str)
62 if not rmatch:
63 continue
64 sep = rmatch.group("sep")
65 start = rmatch.group("start")
66 end = rmatch.group("end")
67
68 if sep == '-':
69 start = int(start) - 1 if start else None
70 end = int(end) if end else None
71 elif sep == ':':
72 start = int(start) - 1 if start else None
73 end = int(end) - 1 if end else None
74 else:
75 end = int(start)
76 start = int(start) - 1
77 yield (start, end)
78
79
42 80 class InteractivelyDefined(Exception):
43 81 """Exception for interactively defined variable in magic_edit"""
44 82 def __init__(self, index):
45 83 self.index = index
46 84
47 85
48 86 @magics_class
49 87 class CodeMagics(Magics):
50 88 """Magics related to code management (loading, saving, editing, ...)."""
51 89
52 90 @line_magic
53 91 def save(self, parameter_s=''):
54 92 """Save a set of lines or a macro to a given filename.
55 93
56 94 Usage:\\
57 95 %save [options] filename n1-n2 n3-n4 ... n5 .. n6 ...
58 96
59 97 Options:
60 98
61 99 -r: use 'raw' input. By default, the 'processed' history is used,
62 100 so that magics are loaded in their transformed version to valid
63 101 Python. If this option is given, the raw input as typed as the
64 102 command line is used instead.
65 103
66 104 -f: force overwrite. If file exists, %save will prompt for overwrite
67 105 unless -f is given.
68 106
69 107 -a: append to the file instead of overwriting it.
70 108
71 109 This function uses the same syntax as %history for input ranges,
72 110 then saves the lines to the filename you specify.
73 111
74 112 It adds a '.py' extension to the file if you don't do so yourself, and
75 113 it asks for confirmation before overwriting existing files.
76 114
77 115 If `-r` option is used, the default extension is `.ipy`.
78 116 """
79 117
80 118 opts,args = self.parse_options(parameter_s,'fra',mode='list')
81 119 if not args:
82 120 raise UsageError('Missing filename.')
83 121 raw = 'r' in opts
84 122 force = 'f' in opts
85 123 append = 'a' in opts
86 124 mode = 'a' if append else 'w'
87 125 ext = u'.ipy' if raw else u'.py'
88 126 fname, codefrom = unquote_filename(args[0]), " ".join(args[1:])
89 127 if not fname.endswith((u'.py',u'.ipy')):
90 128 fname += ext
91 129 file_exists = os.path.isfile(fname)
92 130 if file_exists and not force and not append:
93 131 try:
94 132 overwrite = self.shell.ask_yes_no('File `%s` exists. Overwrite (y/[N])? ' % fname, default='n')
95 133 except StdinNotImplementedError:
96 134 print "File `%s` exists. Use `%%save -f %s` to force overwrite" % (fname, parameter_s)
97 135 return
98 136 if not overwrite :
99 137 print 'Operation cancelled.'
100 138 return
101 139 try:
102 140 cmds = self.shell.find_user_code(codefrom,raw)
103 141 except (TypeError, ValueError) as e:
104 142 print e.args[0]
105 143 return
106 144 out = py3compat.cast_unicode(cmds)
107 145 with io.open(fname, mode, encoding="utf-8") as f:
108 146 if not file_exists or not append:
109 147 f.write(u"# coding: utf-8\n")
110 148 f.write(out)
111 149 # make sure we end on a newline
112 150 if not out.endswith(u'\n'):
113 151 f.write(u'\n')
114 152 print 'The following commands were written to file `%s`:' % fname
115 153 print cmds
116 154
117 155 @line_magic
118 156 def pastebin(self, parameter_s=''):
119 157 """Upload code to Github's Gist paste bin, returning the URL.
120 158
121 159 Usage:\\
122 160 %pastebin [-d "Custom description"] 1-7
123 161
124 162 The argument can be an input history range, a filename, or the name of a
125 163 string or macro.
126 164
127 165 Options:
128 166
129 167 -d: Pass a custom description for the gist. The default will say
130 168 "Pasted from IPython".
131 169 """
132 170 opts, args = self.parse_options(parameter_s, 'd:')
133 171
134 172 try:
135 173 code = self.shell.find_user_code(args)
136 174 except (ValueError, TypeError) as e:
137 175 print e.args[0]
138 176 return
139 177
140 178 from urllib2 import urlopen # Deferred import
141 179 import json
142 180 post_data = json.dumps({
143 181 "description": opts.get('d', "Pasted from IPython"),
144 182 "public": True,
145 183 "files": {
146 184 "file1.py": {
147 185 "content": code
148 186 }
149 187 }
150 188 }).encode('utf-8')
151 189
152 190 response = urlopen("https://api.github.com/gists", post_data)
153 191 response_data = json.loads(response.read().decode('utf-8'))
154 192 return response_data['html_url']
155 193
156 194 @line_magic
157 195 def loadpy(self, arg_s):
158 196 """Alias of `%load`
159 197
160 198 `%loadpy` has gained some flexibility and dropped the requirement of a `.py`
161 199 extension. So it has been renamed simply into %load. You can look at
162 200 `%load`'s docstring for more info.
163 201 """
164 202 self.load(arg_s)
165 203
166 204 @line_magic
167 205 def load(self, arg_s):
168 206 """Load code into the current frontend.
169 207
170 208 Usage:\\
171 209 %load [options] source
172 210
173 211 where source can be a filename, URL, input history range or macro
174 212
175 213 Options:
176 214 --------
215 -r <lines>: Specify lines or ranges of lines to load from the source.
216 Ranges could be specified as x-y (x..y) or in python-style x:y
217 (x..(y-1)). Both limits x and y can be left blank (meaning the
218 beginning and end of the file, respectively).
219
177 220 -y : Don't ask confirmation for loading source above 200 000 characters.
178 221
179 222 This magic command can either take a local filename, a URL, an history
180 223 range (see %history) or a macro as argument, it will prompt for
181 224 confirmation before loading source with more than 200 000 characters, unless
182 225 -y flag is passed or if the frontend does not support raw_input::
183 226
184 227 %load myscript.py
185 228 %load 7-27
186 229 %load myMacro
187 230 %load http://www.example.com/myscript.py
231 %load -r 5-10 myscript.py
232 %load -r 10-20,30,40: foo.py
188 233 """
189 opts,args = self.parse_options(arg_s,'y')
234 opts,args = self.parse_options(arg_s,'yr:')
235
190 236 if not args:
191 237 raise UsageError('Missing filename, URL, input history range, '
192 238 'or macro.')
193 239
194 240 contents = self.shell.find_user_code(args)
241
242 if 'r' in opts:
243 ranges = opts['r'].replace(',', ' ')
244 lines = contents.split('\n')
245 slices = extract_code_ranges(ranges)
246 contents = [lines[slice(*slc)] for slc in slices]
247 contents = '\n'.join(chain.from_iterable(contents))
248
195 249 l = len(contents)
196 250
251
197 252 # 200 000 is ~ 2500 full 80 caracter lines
198 253 # so in average, more than 5000 lines
199 254 if l > 200000 and 'y' not in opts:
200 255 try:
201 256 ans = self.shell.ask_yes_no(("The text you're trying to load seems pretty big"\
202 257 " (%d characters). Continue (y/[N]) ?" % l), default='n' )
203 258 except StdinNotImplementedError:
204 259 #asume yes if raw input not implemented
205 260 ans = True
206 261
207 262 if ans is False :
208 263 print 'Operation cancelled.'
209 264 return
210 265
211 266 self.shell.set_next_input(contents)
212 267
213 268 @staticmethod
214 269 def _find_edit_target(shell, args, opts, last_call):
215 270 """Utility method used by magic_edit to find what to edit."""
216 271
217 272 def make_filename(arg):
218 273 "Make a filename from the given args"
219 274 arg = unquote_filename(arg)
220 275 try:
221 276 filename = get_py_filename(arg)
222 277 except IOError:
223 278 # If it ends with .py but doesn't already exist, assume we want
224 279 # a new file.
225 280 if arg.endswith('.py'):
226 281 filename = arg
227 282 else:
228 283 filename = None
229 284 return filename
230 285
231 286 # Set a few locals from the options for convenience:
232 287 opts_prev = 'p' in opts
233 288 opts_raw = 'r' in opts
234 289
235 290 # custom exceptions
236 291 class DataIsObject(Exception): pass
237 292
238 293 # Default line number value
239 294 lineno = opts.get('n',None)
240 295
241 296 if opts_prev:
242 297 args = '_%s' % last_call[0]
243 298 if args not in shell.user_ns:
244 299 args = last_call[1]
245 300
246 301 # by default this is done with temp files, except when the given
247 302 # arg is a filename
248 303 use_temp = True
249 304
250 305 data = ''
251 306
252 307 # First, see if the arguments should be a filename.
253 308 filename = make_filename(args)
254 309 if filename:
255 310 use_temp = False
256 311 elif args:
257 312 # Mode where user specifies ranges of lines, like in %macro.
258 313 data = shell.extract_input_lines(args, opts_raw)
259 314 if not data:
260 315 try:
261 316 # Load the parameter given as a variable. If not a string,
262 317 # process it as an object instead (below)
263 318
264 319 #print '*** args',args,'type',type(args) # dbg
265 320 data = eval(args, shell.user_ns)
266 321 if not isinstance(data, basestring):
267 322 raise DataIsObject
268 323
269 324 except (NameError,SyntaxError):
270 325 # given argument is not a variable, try as a filename
271 326 filename = make_filename(args)
272 327 if filename is None:
273 328 warn("Argument given (%s) can't be found as a variable "
274 329 "or as a filename." % args)
275 330 return (None, None, None)
276 331 use_temp = False
277 332
278 333 except DataIsObject:
279 334 # macros have a special edit function
280 335 if isinstance(data, Macro):
281 336 raise MacroToEdit(data)
282 337
283 338 # For objects, try to edit the file where they are defined
284 339 filename = find_file(data)
285 340 if filename:
286 341 if 'fakemodule' in filename.lower() and \
287 342 inspect.isclass(data):
288 343 # class created by %edit? Try to find source
289 344 # by looking for method definitions instead, the
290 345 # __module__ in those classes is FakeModule.
291 346 attrs = [getattr(data, aname) for aname in dir(data)]
292 347 for attr in attrs:
293 348 if not inspect.ismethod(attr):
294 349 continue
295 350 filename = find_file(attr)
296 351 if filename and \
297 352 'fakemodule' not in filename.lower():
298 353 # change the attribute to be the edit
299 354 # target instead
300 355 data = attr
301 356 break
302 357
303 358 m = ipython_input_pat.match(os.path.basename(filename))
304 359 if m:
305 360 raise InteractivelyDefined(int(m.groups()[0]))
306 361
307 362 datafile = 1
308 363 if filename is None:
309 364 filename = make_filename(args)
310 365 datafile = 1
311 366 if filename is not None:
312 367 # only warn about this if we get a real name
313 368 warn('Could not find file where `%s` is defined.\n'
314 369 'Opening a file named `%s`' % (args, filename))
315 370 # Now, make sure we can actually read the source (if it was
316 371 # in a temp file it's gone by now).
317 372 if datafile:
318 373 if lineno is None:
319 374 lineno = find_source_lines(data)
320 375 if lineno is None:
321 376 filename = make_filename(args)
322 377 if filename is None:
323 378 warn('The file where `%s` was defined '
324 379 'cannot be read or found.' % data)
325 380 return (None, None, None)
326 381 use_temp = False
327 382
328 383 if use_temp:
329 384 filename = shell.mktempfile(data)
330 385 print 'IPython will make a temporary file named:',filename
331 386
332 387 # use last_call to remember the state of the previous call, but don't
333 388 # let it be clobbered by successive '-p' calls.
334 389 try:
335 390 last_call[0] = shell.displayhook.prompt_count
336 391 if not opts_prev:
337 392 last_call[1] = args
338 393 except:
339 394 pass
340 395
341 396
342 397 return filename, lineno, use_temp
343 398
344 399 def _edit_macro(self,mname,macro):
345 400 """open an editor with the macro data in a file"""
346 401 filename = self.shell.mktempfile(macro.value)
347 402 self.shell.hooks.editor(filename)
348 403
349 404 # and make a new macro object, to replace the old one
350 405 mfile = open(filename)
351 406 mvalue = mfile.read()
352 407 mfile.close()
353 408 self.shell.user_ns[mname] = Macro(mvalue)
354 409
355 410 @skip_doctest
356 411 @line_magic
357 412 def edit(self, parameter_s='',last_call=['','']):
358 413 """Bring up an editor and execute the resulting code.
359 414
360 415 Usage:
361 416 %edit [options] [args]
362 417
363 418 %edit runs IPython's editor hook. The default version of this hook is
364 419 set to call the editor specified by your $EDITOR environment variable.
365 420 If this isn't found, it will default to vi under Linux/Unix and to
366 421 notepad under Windows. See the end of this docstring for how to change
367 422 the editor hook.
368 423
369 424 You can also set the value of this editor via the
370 425 ``TerminalInteractiveShell.editor`` option in your configuration file.
371 426 This is useful if you wish to use a different editor from your typical
372 427 default with IPython (and for Windows users who typically don't set
373 428 environment variables).
374 429
375 430 This command allows you to conveniently edit multi-line code right in
376 431 your IPython session.
377 432
378 433 If called without arguments, %edit opens up an empty editor with a
379 434 temporary file and will execute the contents of this file when you
380 435 close it (don't forget to save it!).
381 436
382 437
383 438 Options:
384 439
385 440 -n <number>: open the editor at a specified line number. By default,
386 441 the IPython editor hook uses the unix syntax 'editor +N filename', but
387 442 you can configure this by providing your own modified hook if your
388 443 favorite editor supports line-number specifications with a different
389 444 syntax.
390 445
391 446 -p: this will call the editor with the same data as the previous time
392 447 it was used, regardless of how long ago (in your current session) it
393 448 was.
394 449
395 450 -r: use 'raw' input. This option only applies to input taken from the
396 451 user's history. By default, the 'processed' history is used, so that
397 452 magics are loaded in their transformed version to valid Python. If
398 453 this option is given, the raw input as typed as the command line is
399 454 used instead. When you exit the editor, it will be executed by
400 455 IPython's own processor.
401 456
402 457 -x: do not execute the edited code immediately upon exit. This is
403 458 mainly useful if you are editing programs which need to be called with
404 459 command line arguments, which you can then do using %run.
405 460
406 461
407 462 Arguments:
408 463
409 464 If arguments are given, the following possibilities exist:
410 465
411 466 - If the argument is a filename, IPython will load that into the
412 467 editor. It will execute its contents with execfile() when you exit,
413 468 loading any code in the file into your interactive namespace.
414 469
415 470 - The arguments are ranges of input history, e.g. "7 ~1/4-6".
416 471 The syntax is the same as in the %history magic.
417 472
418 473 - If the argument is a string variable, its contents are loaded
419 474 into the editor. You can thus edit any string which contains
420 475 python code (including the result of previous edits).
421 476
422 477 - If the argument is the name of an object (other than a string),
423 478 IPython will try to locate the file where it was defined and open the
424 479 editor at the point where it is defined. You can use `%edit function`
425 480 to load an editor exactly at the point where 'function' is defined,
426 481 edit it and have the file be executed automatically.
427 482
428 483 - If the object is a macro (see %macro for details), this opens up your
429 484 specified editor with a temporary file containing the macro's data.
430 485 Upon exit, the macro is reloaded with the contents of the file.
431 486
432 487 Note: opening at an exact line is only supported under Unix, and some
433 488 editors (like kedit and gedit up to Gnome 2.8) do not understand the
434 489 '+NUMBER' parameter necessary for this feature. Good editors like
435 490 (X)Emacs, vi, jed, pico and joe all do.
436 491
437 492 After executing your code, %edit will return as output the code you
438 493 typed in the editor (except when it was an existing file). This way
439 494 you can reload the code in further invocations of %edit as a variable,
440 495 via _<NUMBER> or Out[<NUMBER>], where <NUMBER> is the prompt number of
441 496 the output.
442 497
443 498 Note that %edit is also available through the alias %ed.
444 499
445 500 This is an example of creating a simple function inside the editor and
446 501 then modifying it. First, start up the editor::
447 502
448 503 In [1]: edit
449 504 Editing... done. Executing edited code...
450 505 Out[1]: 'def foo():\\n print "foo() was defined in an editing
451 506 session"\\n'
452 507
453 508 We can then call the function foo()::
454 509
455 510 In [2]: foo()
456 511 foo() was defined in an editing session
457 512
458 513 Now we edit foo. IPython automatically loads the editor with the
459 514 (temporary) file where foo() was previously defined::
460 515
461 516 In [3]: edit foo
462 517 Editing... done. Executing edited code...
463 518
464 519 And if we call foo() again we get the modified version::
465 520
466 521 In [4]: foo()
467 522 foo() has now been changed!
468 523
469 524 Here is an example of how to edit a code snippet successive
470 525 times. First we call the editor::
471 526
472 527 In [5]: edit
473 528 Editing... done. Executing edited code...
474 529 hello
475 530 Out[5]: "print 'hello'\\n"
476 531
477 532 Now we call it again with the previous output (stored in _)::
478 533
479 534 In [6]: edit _
480 535 Editing... done. Executing edited code...
481 536 hello world
482 537 Out[6]: "print 'hello world'\\n"
483 538
484 539 Now we call it with the output #8 (stored in _8, also as Out[8])::
485 540
486 541 In [7]: edit _8
487 542 Editing... done. Executing edited code...
488 543 hello again
489 544 Out[7]: "print 'hello again'\\n"
490 545
491 546
492 547 Changing the default editor hook:
493 548
494 549 If you wish to write your own editor hook, you can put it in a
495 550 configuration file which you load at startup time. The default hook
496 551 is defined in the IPython.core.hooks module, and you can use that as a
497 552 starting example for further modifications. That file also has
498 553 general instructions on how to set a new hook for use once you've
499 554 defined it."""
500 555 opts,args = self.parse_options(parameter_s,'prxn:')
501 556
502 557 try:
503 558 filename, lineno, is_temp = self._find_edit_target(self.shell,
504 559 args, opts, last_call)
505 560 except MacroToEdit as e:
506 561 self._edit_macro(args, e.args[0])
507 562 return
508 563 except InteractivelyDefined as e:
509 564 print "Editing In[%i]" % e.index
510 565 args = str(e.index)
511 566 filename, lineno, is_temp = self._find_edit_target(self.shell,
512 567 args, opts, last_call)
513 568 if filename is None:
514 569 # nothing was found, warnings have already been issued,
515 570 # just give up.
516 571 return
517 572
518 573 # do actual editing here
519 574 print 'Editing...',
520 575 sys.stdout.flush()
521 576 try:
522 577 # Quote filenames that may have spaces in them
523 578 if ' ' in filename:
524 579 filename = "'%s'" % filename
525 580 self.shell.hooks.editor(filename,lineno)
526 581 except TryNext:
527 582 warn('Could not open editor')
528 583 return
529 584
530 585 # XXX TODO: should this be generalized for all string vars?
531 586 # For now, this is special-cased to blocks created by cpaste
532 587 if args.strip() == 'pasted_block':
533 588 with open(filename, 'r') as f:
534 589 self.shell.user_ns['pasted_block'] = f.read()
535 590
536 591 if 'x' in opts: # -x prevents actual execution
537 592 print
538 593 else:
539 594 print 'done. Executing edited code...'
540 595 with preserve_keys(self.shell.user_ns, '__file__'):
541 596 if not is_temp:
542 597 self.shell.user_ns['__file__'] = filename
543 598 if 'r' in opts: # Untranslated IPython code
544 599 with open(filename, 'r') as f:
545 600 source = f.read()
546 601 self.shell.run_cell(source, store_history=False)
547 602 else:
548 603 self.shell.safe_execfile(filename, self.shell.user_ns,
549 604 self.shell.user_ns)
550 605
551 606 if is_temp:
552 607 try:
553 608 return open(filename).read()
554 609 except IOError as msg:
555 610 if msg.filename == filename:
556 611 warn('File not found. Did you forget to save?')
557 612 return
558 613 else:
559 614 self.shell.showtraceback()
@@ -1,895 +1,910
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 #-----------------------------------------------------------------------------
9 9 # Imports
10 10 #-----------------------------------------------------------------------------
11 11
12 12 import io
13 13 import os
14 14 import sys
15 15 from StringIO import StringIO
16 16 from unittest import TestCase
17 17
18 18 try:
19 19 from importlib import invalidate_caches # Required from Python 3.3
20 20 except ImportError:
21 21 def invalidate_caches():
22 22 pass
23 23
24 24 import nose.tools as nt
25 25
26 26 from IPython.core import magic
27 27 from IPython.core.magic import (Magics, magics_class, line_magic,
28 28 cell_magic, line_cell_magic,
29 29 register_line_magic, register_cell_magic,
30 30 register_line_cell_magic)
31 31 from IPython.core.magics import execution, script, code
32 32 from IPython.nbformat.v3.tests.nbexamples import nb0
33 33 from IPython.nbformat import current
34 34 from IPython.testing import decorators as dec
35 35 from IPython.testing import tools as tt
36 36 from IPython.utils import py3compat
37 37 from IPython.utils.io import capture_output
38 38 from IPython.utils.tempdir import TemporaryDirectory
39 39 from IPython.utils.process import find_cmd
40 40
41 41 #-----------------------------------------------------------------------------
42 42 # Test functions begin
43 43 #-----------------------------------------------------------------------------
44 44
45 45 @magic.magics_class
46 46 class DummyMagics(magic.Magics): pass
47 47
48 def test_extract_code_ranges():
49 instr = "1 3 5-6 7-9 10:15 17: :10 10- -13 :"
50 expected = [(0, 1),
51 (2, 3),
52 (4, 6),
53 (6, 9),
54 (9, 14),
55 (16, None),
56 (None, 9),
57 (9, None),
58 (None, 13),
59 (None, None)]
60 actual = list(code.extract_code_ranges(instr))
61 nt.assert_equal(actual, expected)
62
48 63 def test_rehashx():
49 64 # clear up everything
50 65 _ip = get_ipython()
51 66 _ip.alias_manager.clear_aliases()
52 67 del _ip.db['syscmdlist']
53 68
54 69 _ip.magic('rehashx')
55 70 # Practically ALL ipython development systems will have more than 10 aliases
56 71
57 72 nt.assert_true(len(_ip.alias_manager.aliases) > 10)
58 73 for name, cmd in _ip.alias_manager.aliases:
59 74 # we must strip dots from alias names
60 75 nt.assert_not_in('.', name)
61 76
62 77 # rehashx must fill up syscmdlist
63 78 scoms = _ip.db['syscmdlist']
64 79 nt.assert_true(len(scoms) > 10)
65 80
66 81
67 82 def test_magic_parse_options():
68 83 """Test that we don't mangle paths when parsing magic options."""
69 84 ip = get_ipython()
70 85 path = 'c:\\x'
71 86 m = DummyMagics(ip)
72 87 opts = m.parse_options('-f %s' % path,'f:')[0]
73 88 # argv splitting is os-dependent
74 89 if os.name == 'posix':
75 90 expected = 'c:x'
76 91 else:
77 92 expected = path
78 93 nt.assert_equal(opts['f'], expected)
79 94
80 95 def test_magic_parse_long_options():
81 96 """Magic.parse_options can handle --foo=bar long options"""
82 97 ip = get_ipython()
83 98 m = DummyMagics(ip)
84 99 opts, _ = m.parse_options('--foo --bar=bubble', 'a', 'foo', 'bar=')
85 100 nt.assert_in('foo', opts)
86 101 nt.assert_in('bar', opts)
87 102 nt.assert_equal(opts['bar'], "bubble")
88 103
89 104
90 105 @dec.skip_without('sqlite3')
91 106 def doctest_hist_f():
92 107 """Test %hist -f with temporary filename.
93 108
94 109 In [9]: import tempfile
95 110
96 111 In [10]: tfile = tempfile.mktemp('.py','tmp-ipython-')
97 112
98 113 In [11]: %hist -nl -f $tfile 3
99 114
100 115 In [13]: import os; os.unlink(tfile)
101 116 """
102 117
103 118
104 119 @dec.skip_without('sqlite3')
105 120 def doctest_hist_r():
106 121 """Test %hist -r
107 122
108 123 XXX - This test is not recording the output correctly. For some reason, in
109 124 testing mode the raw history isn't getting populated. No idea why.
110 125 Disabling the output checking for now, though at least we do run it.
111 126
112 127 In [1]: 'hist' in _ip.lsmagic()
113 128 Out[1]: True
114 129
115 130 In [2]: x=1
116 131
117 132 In [3]: %hist -rl 2
118 133 x=1 # random
119 134 %hist -r 2
120 135 """
121 136
122 137
123 138 @dec.skip_without('sqlite3')
124 139 def doctest_hist_op():
125 140 """Test %hist -op
126 141
127 142 In [1]: class b(float):
128 143 ...: pass
129 144 ...:
130 145
131 146 In [2]: class s(object):
132 147 ...: def __str__(self):
133 148 ...: return 's'
134 149 ...:
135 150
136 151 In [3]:
137 152
138 153 In [4]: class r(b):
139 154 ...: def __repr__(self):
140 155 ...: return 'r'
141 156 ...:
142 157
143 158 In [5]: class sr(s,r): pass
144 159 ...:
145 160
146 161 In [6]:
147 162
148 163 In [7]: bb=b()
149 164
150 165 In [8]: ss=s()
151 166
152 167 In [9]: rr=r()
153 168
154 169 In [10]: ssrr=sr()
155 170
156 171 In [11]: 4.5
157 172 Out[11]: 4.5
158 173
159 174 In [12]: str(ss)
160 175 Out[12]: 's'
161 176
162 177 In [13]:
163 178
164 179 In [14]: %hist -op
165 180 >>> class b:
166 181 ... pass
167 182 ...
168 183 >>> class s(b):
169 184 ... def __str__(self):
170 185 ... return 's'
171 186 ...
172 187 >>>
173 188 >>> class r(b):
174 189 ... def __repr__(self):
175 190 ... return 'r'
176 191 ...
177 192 >>> class sr(s,r): pass
178 193 >>>
179 194 >>> bb=b()
180 195 >>> ss=s()
181 196 >>> rr=r()
182 197 >>> ssrr=sr()
183 198 >>> 4.5
184 199 4.5
185 200 >>> str(ss)
186 201 's'
187 202 >>>
188 203 """
189 204
190 205
191 206 @dec.skip_without('sqlite3')
192 207 def test_macro():
193 208 ip = get_ipython()
194 209 ip.history_manager.reset() # Clear any existing history.
195 210 cmds = ["a=1", "def b():\n return a**2", "print(a,b())"]
196 211 for i, cmd in enumerate(cmds, start=1):
197 212 ip.history_manager.store_inputs(i, cmd)
198 213 ip.magic("macro test 1-3")
199 214 nt.assert_equal(ip.user_ns["test"].value, "\n".join(cmds)+"\n")
200 215
201 216 # List macros
202 217 nt.assert_in("test", ip.magic("macro"))
203 218
204 219
205 220 @dec.skip_without('sqlite3')
206 221 def test_macro_run():
207 222 """Test that we can run a multi-line macro successfully."""
208 223 ip = get_ipython()
209 224 ip.history_manager.reset()
210 225 cmds = ["a=10", "a+=1", py3compat.doctest_refactor_print("print a"),
211 226 "%macro test 2-3"]
212 227 for cmd in cmds:
213 228 ip.run_cell(cmd, store_history=True)
214 229 nt.assert_equal(ip.user_ns["test"].value,
215 230 py3compat.doctest_refactor_print("a+=1\nprint a\n"))
216 231 with tt.AssertPrints("12"):
217 232 ip.run_cell("test")
218 233 with tt.AssertPrints("13"):
219 234 ip.run_cell("test")
220 235
221 236
222 237 def test_magic_magic():
223 238 """Test %magic"""
224 239 ip = get_ipython()
225 240 with capture_output() as captured:
226 241 ip.magic("magic")
227 242
228 243 stdout = captured.stdout
229 244 nt.assert_in('%magic', stdout)
230 245 nt.assert_in('IPython', stdout)
231 246 nt.assert_in('Available', stdout)
232 247
233 248
234 249 @dec.skipif_not_numpy
235 250 def test_numpy_reset_array_undec():
236 251 "Test '%reset array' functionality"
237 252 _ip.ex('import numpy as np')
238 253 _ip.ex('a = np.empty(2)')
239 254 nt.assert_in('a', _ip.user_ns)
240 255 _ip.magic('reset -f array')
241 256 nt.assert_not_in('a', _ip.user_ns)
242 257
243 258 def test_reset_out():
244 259 "Test '%reset out' magic"
245 260 _ip.run_cell("parrot = 'dead'", store_history=True)
246 261 # test '%reset -f out', make an Out prompt
247 262 _ip.run_cell("parrot", store_history=True)
248 263 nt.assert_true('dead' in [_ip.user_ns[x] for x in '_','__','___'])
249 264 _ip.magic('reset -f out')
250 265 nt.assert_false('dead' in [_ip.user_ns[x] for x in '_','__','___'])
251 266 nt.assert_equal(len(_ip.user_ns['Out']), 0)
252 267
253 268 def test_reset_in():
254 269 "Test '%reset in' magic"
255 270 # test '%reset -f in'
256 271 _ip.run_cell("parrot", store_history=True)
257 272 nt.assert_true('parrot' in [_ip.user_ns[x] for x in '_i','_ii','_iii'])
258 273 _ip.magic('%reset -f in')
259 274 nt.assert_false('parrot' in [_ip.user_ns[x] for x in '_i','_ii','_iii'])
260 275 nt.assert_equal(len(set(_ip.user_ns['In'])), 1)
261 276
262 277 def test_reset_dhist():
263 278 "Test '%reset dhist' magic"
264 279 _ip.run_cell("tmp = [d for d in _dh]") # copy before clearing
265 280 _ip.magic('cd ' + os.path.dirname(nt.__file__))
266 281 _ip.magic('cd -')
267 282 nt.assert_true(len(_ip.user_ns['_dh']) > 0)
268 283 _ip.magic('reset -f dhist')
269 284 nt.assert_equal(len(_ip.user_ns['_dh']), 0)
270 285 _ip.run_cell("_dh = [d for d in tmp]") #restore
271 286
272 287 def test_reset_in_length():
273 288 "Test that '%reset in' preserves In[] length"
274 289 _ip.run_cell("print 'foo'")
275 290 _ip.run_cell("reset -f in")
276 291 nt.assert_equal(len(_ip.user_ns['In']), _ip.displayhook.prompt_count+1)
277 292
278 293 def test_tb_syntaxerror():
279 294 """test %tb after a SyntaxError"""
280 295 ip = get_ipython()
281 296 ip.run_cell("for")
282 297
283 298 # trap and validate stdout
284 299 save_stdout = sys.stdout
285 300 try:
286 301 sys.stdout = StringIO()
287 302 ip.run_cell("%tb")
288 303 out = sys.stdout.getvalue()
289 304 finally:
290 305 sys.stdout = save_stdout
291 306 # trim output, and only check the last line
292 307 last_line = out.rstrip().splitlines()[-1].strip()
293 308 nt.assert_equal(last_line, "SyntaxError: invalid syntax")
294 309
295 310
296 311 def test_time():
297 312 ip = get_ipython()
298 313
299 314 with tt.AssertPrints("Wall time: "):
300 315 ip.run_cell("%time None")
301 316
302 317 ip.run_cell("def f(kmjy):\n"
303 318 " %time print (2*kmjy)")
304 319
305 320 with tt.AssertPrints("Wall time: "):
306 321 with tt.AssertPrints("hihi", suppress=False):
307 322 ip.run_cell("f('hi')")
308 323
309 324
310 325 @dec.skip_win32
311 326 def test_time2():
312 327 ip = get_ipython()
313 328
314 329 with tt.AssertPrints("CPU times: user "):
315 330 ip.run_cell("%time None")
316 331
317 332 def test_time3():
318 333 """Erroneous magic function calls, issue gh-3334"""
319 334 ip = get_ipython()
320 335 ip.user_ns.pop('run', None)
321 336
322 337 with tt.AssertNotPrints("not found", channel='stderr'):
323 338 ip.run_cell("%%time\n"
324 339 "run = 0\n"
325 340 "run += 1")
326 341
327 342 def test_doctest_mode():
328 343 "Toggle doctest_mode twice, it should be a no-op and run without error"
329 344 _ip.magic('doctest_mode')
330 345 _ip.magic('doctest_mode')
331 346
332 347
333 348 def test_parse_options():
334 349 """Tests for basic options parsing in magics."""
335 350 # These are only the most minimal of tests, more should be added later. At
336 351 # the very least we check that basic text/unicode calls work OK.
337 352 m = DummyMagics(_ip)
338 353 nt.assert_equal(m.parse_options('foo', '')[1], 'foo')
339 354 nt.assert_equal(m.parse_options(u'foo', '')[1], u'foo')
340 355
341 356
342 357 def test_dirops():
343 358 """Test various directory handling operations."""
344 359 # curpath = lambda :os.path.splitdrive(os.getcwdu())[1].replace('\\','/')
345 360 curpath = os.getcwdu
346 361 startdir = os.getcwdu()
347 362 ipdir = os.path.realpath(_ip.ipython_dir)
348 363 try:
349 364 _ip.magic('cd "%s"' % ipdir)
350 365 nt.assert_equal(curpath(), ipdir)
351 366 _ip.magic('cd -')
352 367 nt.assert_equal(curpath(), startdir)
353 368 _ip.magic('pushd "%s"' % ipdir)
354 369 nt.assert_equal(curpath(), ipdir)
355 370 _ip.magic('popd')
356 371 nt.assert_equal(curpath(), startdir)
357 372 finally:
358 373 os.chdir(startdir)
359 374
360 375
361 376 def test_xmode():
362 377 # Calling xmode three times should be a no-op
363 378 xmode = _ip.InteractiveTB.mode
364 379 for i in range(3):
365 380 _ip.magic("xmode")
366 381 nt.assert_equal(_ip.InteractiveTB.mode, xmode)
367 382
368 383 def test_reset_hard():
369 384 monitor = []
370 385 class A(object):
371 386 def __del__(self):
372 387 monitor.append(1)
373 388 def __repr__(self):
374 389 return "<A instance>"
375 390
376 391 _ip.user_ns["a"] = A()
377 392 _ip.run_cell("a")
378 393
379 394 nt.assert_equal(monitor, [])
380 395 _ip.magic("reset -f")
381 396 nt.assert_equal(monitor, [1])
382 397
383 398 class TestXdel(tt.TempFileMixin):
384 399 def test_xdel(self):
385 400 """Test that references from %run are cleared by xdel."""
386 401 src = ("class A(object):\n"
387 402 " monitor = []\n"
388 403 " def __del__(self):\n"
389 404 " self.monitor.append(1)\n"
390 405 "a = A()\n")
391 406 self.mktmp(src)
392 407 # %run creates some hidden references...
393 408 _ip.magic("run %s" % self.fname)
394 409 # ... as does the displayhook.
395 410 _ip.run_cell("a")
396 411
397 412 monitor = _ip.user_ns["A"].monitor
398 413 nt.assert_equal(monitor, [])
399 414
400 415 _ip.magic("xdel a")
401 416
402 417 # Check that a's __del__ method has been called.
403 418 nt.assert_equal(monitor, [1])
404 419
405 420 def doctest_who():
406 421 """doctest for %who
407 422
408 423 In [1]: %reset -f
409 424
410 425 In [2]: alpha = 123
411 426
412 427 In [3]: beta = 'beta'
413 428
414 429 In [4]: %who int
415 430 alpha
416 431
417 432 In [5]: %who str
418 433 beta
419 434
420 435 In [6]: %whos
421 436 Variable Type Data/Info
422 437 ----------------------------
423 438 alpha int 123
424 439 beta str beta
425 440
426 441 In [7]: %who_ls
427 442 Out[7]: ['alpha', 'beta']
428 443 """
429 444
430 445 def test_whos():
431 446 """Check that whos is protected against objects where repr() fails."""
432 447 class A(object):
433 448 def __repr__(self):
434 449 raise Exception()
435 450 _ip.user_ns['a'] = A()
436 451 _ip.magic("whos")
437 452
438 453 @py3compat.u_format
439 454 def doctest_precision():
440 455 """doctest for %precision
441 456
442 457 In [1]: f = get_ipython().display_formatter.formatters['text/plain']
443 458
444 459 In [2]: %precision 5
445 460 Out[2]: {u}'%.5f'
446 461
447 462 In [3]: f.float_format
448 463 Out[3]: {u}'%.5f'
449 464
450 465 In [4]: %precision %e
451 466 Out[4]: {u}'%e'
452 467
453 468 In [5]: f(3.1415927)
454 469 Out[5]: {u}'3.141593e+00'
455 470 """
456 471
457 472 def test_psearch():
458 473 with tt.AssertPrints("dict.fromkeys"):
459 474 _ip.run_cell("dict.fr*?")
460 475
461 476 def test_timeit_shlex():
462 477 """test shlex issues with timeit (#1109)"""
463 478 _ip.ex("def f(*a,**kw): pass")
464 479 _ip.magic('timeit -n1 "this is a bug".count(" ")')
465 480 _ip.magic('timeit -r1 -n1 f(" ", 1)')
466 481 _ip.magic('timeit -r1 -n1 f(" ", 1, " ", 2, " ")')
467 482 _ip.magic('timeit -r1 -n1 ("a " + "b")')
468 483 _ip.magic('timeit -r1 -n1 f("a " + "b")')
469 484 _ip.magic('timeit -r1 -n1 f("a " + "b ")')
470 485
471 486
472 487 def test_timeit_arguments():
473 488 "Test valid timeit arguments, should not cause SyntaxError (GH #1269)"
474 489 _ip.magic("timeit ('#')")
475 490
476 491
477 492 def test_timeit_special_syntax():
478 493 "Test %%timeit with IPython special syntax"
479 494 @register_line_magic
480 495 def lmagic(line):
481 496 ip = get_ipython()
482 497 ip.user_ns['lmagic_out'] = line
483 498
484 499 # line mode test
485 500 _ip.run_line_magic('timeit', '-n1 -r1 %lmagic my line')
486 501 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line')
487 502 # cell mode test
488 503 _ip.run_cell_magic('timeit', '-n1 -r1', '%lmagic my line2')
489 504 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line2')
490 505
491 506 def test_timeit_return():
492 507 """
493 508 test wether timeit -o return object
494 509 """
495 510
496 511 res = _ip.run_line_magic('timeit','-n10 -r10 -o 1')
497 512 assert(res is not None)
498 513
499 514 def test_timeit_quiet():
500 515 """
501 516 test quiet option of timeit magic
502 517 """
503 518 with tt.AssertNotPrints("loops"):
504 519 _ip.run_cell("%timeit -n1 -r1 -q 1")
505 520
506 521 @dec.skipif(execution.profile is None)
507 522 def test_prun_special_syntax():
508 523 "Test %%prun with IPython special syntax"
509 524 @register_line_magic
510 525 def lmagic(line):
511 526 ip = get_ipython()
512 527 ip.user_ns['lmagic_out'] = line
513 528
514 529 # line mode test
515 530 _ip.run_line_magic('prun', '-q %lmagic my line')
516 531 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line')
517 532 # cell mode test
518 533 _ip.run_cell_magic('prun', '-q', '%lmagic my line2')
519 534 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line2')
520 535
521 536 @dec.skipif(execution.profile is None)
522 537 def test_prun_quotes():
523 538 "Test that prun does not clobber string escapes (GH #1302)"
524 539 _ip.magic(r"prun -q x = '\t'")
525 540 nt.assert_equal(_ip.user_ns['x'], '\t')
526 541
527 542 def test_extension():
528 543 tmpdir = TemporaryDirectory()
529 544 orig_ipython_dir = _ip.ipython_dir
530 545 try:
531 546 _ip.ipython_dir = tmpdir.name
532 547 nt.assert_raises(ImportError, _ip.magic, "load_ext daft_extension")
533 548 url = os.path.join(os.path.dirname(__file__), "daft_extension.py")
534 549 _ip.magic("install_ext %s" % url)
535 550 _ip.user_ns.pop('arq', None)
536 551 invalidate_caches() # Clear import caches
537 552 _ip.magic("load_ext daft_extension")
538 553 nt.assert_equal(_ip.user_ns['arq'], 185)
539 554 _ip.magic("unload_ext daft_extension")
540 555 assert 'arq' not in _ip.user_ns
541 556 finally:
542 557 _ip.ipython_dir = orig_ipython_dir
543 558 tmpdir.cleanup()
544 559
545 560 def test_notebook_export_json():
546 561 with TemporaryDirectory() as td:
547 562 outfile = os.path.join(td, "nb.ipynb")
548 563 _ip.ex(py3compat.u_format(u"u = {u}'hΓ©llo'"))
549 564 _ip.magic("notebook -e %s" % outfile)
550 565
551 566 def test_notebook_export_py():
552 567 with TemporaryDirectory() as td:
553 568 outfile = os.path.join(td, "nb.py")
554 569 _ip.ex(py3compat.u_format(u"u = {u}'hΓ©llo'"))
555 570 _ip.magic("notebook -e %s" % outfile)
556 571
557 572 def test_notebook_reformat_py():
558 573 with TemporaryDirectory() as td:
559 574 infile = os.path.join(td, "nb.ipynb")
560 575 with io.open(infile, 'w', encoding='utf-8') as f:
561 576 current.write(nb0, f, 'json')
562 577
563 578 _ip.ex(py3compat.u_format(u"u = {u}'hΓ©llo'"))
564 579 _ip.magic("notebook -f py %s" % infile)
565 580
566 581 def test_notebook_reformat_json():
567 582 with TemporaryDirectory() as td:
568 583 infile = os.path.join(td, "nb.py")
569 584 with io.open(infile, 'w', encoding='utf-8') as f:
570 585 current.write(nb0, f, 'py')
571 586
572 587 _ip.ex(py3compat.u_format(u"u = {u}'hΓ©llo'"))
573 588 _ip.magic("notebook -f ipynb %s" % infile)
574 589 _ip.magic("notebook -f json %s" % infile)
575 590
576 591 def test_env():
577 592 env = _ip.magic("env")
578 593 assert isinstance(env, dict), type(env)
579 594
580 595
581 596 class CellMagicTestCase(TestCase):
582 597
583 598 def check_ident(self, magic):
584 599 # Manually called, we get the result
585 600 out = _ip.run_cell_magic(magic, 'a', 'b')
586 601 nt.assert_equal(out, ('a','b'))
587 602 # Via run_cell, it goes into the user's namespace via displayhook
588 603 _ip.run_cell('%%' + magic +' c\nd')
589 604 nt.assert_equal(_ip.user_ns['_'], ('c','d'))
590 605
591 606 def test_cell_magic_func_deco(self):
592 607 "Cell magic using simple decorator"
593 608 @register_cell_magic
594 609 def cellm(line, cell):
595 610 return line, cell
596 611
597 612 self.check_ident('cellm')
598 613
599 614 def test_cell_magic_reg(self):
600 615 "Cell magic manually registered"
601 616 def cellm(line, cell):
602 617 return line, cell
603 618
604 619 _ip.register_magic_function(cellm, 'cell', 'cellm2')
605 620 self.check_ident('cellm2')
606 621
607 622 def test_cell_magic_class(self):
608 623 "Cell magics declared via a class"
609 624 @magics_class
610 625 class MyMagics(Magics):
611 626
612 627 @cell_magic
613 628 def cellm3(self, line, cell):
614 629 return line, cell
615 630
616 631 _ip.register_magics(MyMagics)
617 632 self.check_ident('cellm3')
618 633
619 634 def test_cell_magic_class2(self):
620 635 "Cell magics declared via a class, #2"
621 636 @magics_class
622 637 class MyMagics2(Magics):
623 638
624 639 @cell_magic('cellm4')
625 640 def cellm33(self, line, cell):
626 641 return line, cell
627 642
628 643 _ip.register_magics(MyMagics2)
629 644 self.check_ident('cellm4')
630 645 # Check that nothing is registered as 'cellm33'
631 646 c33 = _ip.find_cell_magic('cellm33')
632 647 nt.assert_equal(c33, None)
633 648
634 649 def test_file():
635 650 """Basic %%file"""
636 651 ip = get_ipython()
637 652 with TemporaryDirectory() as td:
638 653 fname = os.path.join(td, 'file1')
639 654 ip.run_cell_magic("file", fname, u'\n'.join([
640 655 'line1',
641 656 'line2',
642 657 ]))
643 658 with open(fname) as f:
644 659 s = f.read()
645 660 nt.assert_in('line1\n', s)
646 661 nt.assert_in('line2', s)
647 662
648 663 def test_file_var_expand():
649 664 """%%file $filename"""
650 665 ip = get_ipython()
651 666 with TemporaryDirectory() as td:
652 667 fname = os.path.join(td, 'file1')
653 668 ip.user_ns['filename'] = fname
654 669 ip.run_cell_magic("file", '$filename', u'\n'.join([
655 670 'line1',
656 671 'line2',
657 672 ]))
658 673 with open(fname) as f:
659 674 s = f.read()
660 675 nt.assert_in('line1\n', s)
661 676 nt.assert_in('line2', s)
662 677
663 678 def test_file_unicode():
664 679 """%%file with unicode cell"""
665 680 ip = get_ipython()
666 681 with TemporaryDirectory() as td:
667 682 fname = os.path.join(td, 'file1')
668 683 ip.run_cell_magic("file", fname, u'\n'.join([
669 684 u'linΓ©1',
670 685 u'linΓ©2',
671 686 ]))
672 687 with io.open(fname, encoding='utf-8') as f:
673 688 s = f.read()
674 689 nt.assert_in(u'linΓ©1\n', s)
675 690 nt.assert_in(u'linΓ©2', s)
676 691
677 692 def test_file_amend():
678 693 """%%file -a amends files"""
679 694 ip = get_ipython()
680 695 with TemporaryDirectory() as td:
681 696 fname = os.path.join(td, 'file2')
682 697 ip.run_cell_magic("file", fname, u'\n'.join([
683 698 'line1',
684 699 'line2',
685 700 ]))
686 701 ip.run_cell_magic("file", "-a %s" % fname, u'\n'.join([
687 702 'line3',
688 703 'line4',
689 704 ]))
690 705 with open(fname) as f:
691 706 s = f.read()
692 707 nt.assert_in('line1\n', s)
693 708 nt.assert_in('line3\n', s)
694 709
695 710
696 711 def test_script_config():
697 712 ip = get_ipython()
698 713 ip.config.ScriptMagics.script_magics = ['whoda']
699 714 sm = script.ScriptMagics(shell=ip)
700 715 nt.assert_in('whoda', sm.magics['cell'])
701 716
702 717 @dec.skip_win32
703 718 def test_script_out():
704 719 ip = get_ipython()
705 720 ip.run_cell_magic("script", "--out output sh", "echo 'hi'")
706 721 nt.assert_equal(ip.user_ns['output'], 'hi\n')
707 722
708 723 @dec.skip_win32
709 724 def test_script_err():
710 725 ip = get_ipython()
711 726 ip.run_cell_magic("script", "--err error sh", "echo 'hello' >&2")
712 727 nt.assert_equal(ip.user_ns['error'], 'hello\n')
713 728
714 729 @dec.skip_win32
715 730 def test_script_out_err():
716 731 ip = get_ipython()
717 732 ip.run_cell_magic("script", "--out output --err error sh", "echo 'hi'\necho 'hello' >&2")
718 733 nt.assert_equal(ip.user_ns['output'], 'hi\n')
719 734 nt.assert_equal(ip.user_ns['error'], 'hello\n')
720 735
721 736 @dec.skip_win32
722 737 def test_script_bg_out():
723 738 ip = get_ipython()
724 739 ip.run_cell_magic("script", "--bg --out output sh", "echo 'hi'")
725 740 nt.assert_equal(ip.user_ns['output'].read(), b'hi\n')
726 741
727 742 @dec.skip_win32
728 743 def test_script_bg_err():
729 744 ip = get_ipython()
730 745 ip.run_cell_magic("script", "--bg --err error sh", "echo 'hello' >&2")
731 746 nt.assert_equal(ip.user_ns['error'].read(), b'hello\n')
732 747
733 748 @dec.skip_win32
734 749 def test_script_bg_out_err():
735 750 ip = get_ipython()
736 751 ip.run_cell_magic("script", "--bg --out output --err error sh", "echo 'hi'\necho 'hello' >&2")
737 752 nt.assert_equal(ip.user_ns['output'].read(), b'hi\n')
738 753 nt.assert_equal(ip.user_ns['error'].read(), b'hello\n')
739 754
740 755 def test_script_defaults():
741 756 ip = get_ipython()
742 757 for cmd in ['sh', 'bash', 'perl', 'ruby']:
743 758 try:
744 759 find_cmd(cmd)
745 760 except Exception:
746 761 pass
747 762 else:
748 763 nt.assert_in(cmd, ip.magics_manager.magics['cell'])
749 764
750 765
751 766 @magics_class
752 767 class FooFoo(Magics):
753 768 """class with both %foo and %%foo magics"""
754 769 @line_magic('foo')
755 770 def line_foo(self, line):
756 771 "I am line foo"
757 772 pass
758 773
759 774 @cell_magic("foo")
760 775 def cell_foo(self, line, cell):
761 776 "I am cell foo, not line foo"
762 777 pass
763 778
764 779 def test_line_cell_info():
765 780 """%%foo and %foo magics are distinguishable to inspect"""
766 781 ip = get_ipython()
767 782 ip.magics_manager.register(FooFoo)
768 783 oinfo = ip.object_inspect('foo')
769 784 nt.assert_true(oinfo['found'])
770 785 nt.assert_true(oinfo['ismagic'])
771 786
772 787 oinfo = ip.object_inspect('%%foo')
773 788 nt.assert_true(oinfo['found'])
774 789 nt.assert_true(oinfo['ismagic'])
775 790 nt.assert_equal(oinfo['docstring'], FooFoo.cell_foo.__doc__)
776 791
777 792 oinfo = ip.object_inspect('%foo')
778 793 nt.assert_true(oinfo['found'])
779 794 nt.assert_true(oinfo['ismagic'])
780 795 nt.assert_equal(oinfo['docstring'], FooFoo.line_foo.__doc__)
781 796
782 797 def test_multiple_magics():
783 798 ip = get_ipython()
784 799 foo1 = FooFoo(ip)
785 800 foo2 = FooFoo(ip)
786 801 mm = ip.magics_manager
787 802 mm.register(foo1)
788 803 nt.assert_true(mm.magics['line']['foo'].im_self is foo1)
789 804 mm.register(foo2)
790 805 nt.assert_true(mm.magics['line']['foo'].im_self is foo2)
791 806
792 807 def test_alias_magic():
793 808 """Test %alias_magic."""
794 809 ip = get_ipython()
795 810 mm = ip.magics_manager
796 811
797 812 # Basic operation: both cell and line magics are created, if possible.
798 813 ip.run_line_magic('alias_magic', 'timeit_alias timeit')
799 814 nt.assert_in('timeit_alias', mm.magics['line'])
800 815 nt.assert_in('timeit_alias', mm.magics['cell'])
801 816
802 817 # --cell is specified, line magic not created.
803 818 ip.run_line_magic('alias_magic', '--cell timeit_cell_alias timeit')
804 819 nt.assert_not_in('timeit_cell_alias', mm.magics['line'])
805 820 nt.assert_in('timeit_cell_alias', mm.magics['cell'])
806 821
807 822 # Test that line alias is created successfully.
808 823 ip.run_line_magic('alias_magic', '--line env_alias env')
809 824 nt.assert_equal(ip.run_line_magic('env', ''),
810 825 ip.run_line_magic('env_alias', ''))
811 826
812 827 def test_save():
813 828 """Test %save."""
814 829 ip = get_ipython()
815 830 ip.history_manager.reset() # Clear any existing history.
816 831 cmds = [u"a=1", u"def b():\n return a**2", u"print(a, b())"]
817 832 for i, cmd in enumerate(cmds, start=1):
818 833 ip.history_manager.store_inputs(i, cmd)
819 834 with TemporaryDirectory() as tmpdir:
820 835 file = os.path.join(tmpdir, "testsave.py")
821 836 ip.run_line_magic("save", "%s 1-10" % file)
822 837 with open(file) as f:
823 838 content = f.read()
824 839 nt.assert_equal(content.count(cmds[0]), 1)
825 840 nt.assert_in('coding: utf-8', content)
826 841 ip.run_line_magic("save", "-a %s 1-10" % file)
827 842 with open(file) as f:
828 843 content = f.read()
829 844 nt.assert_equal(content.count(cmds[0]), 2)
830 845 nt.assert_in('coding: utf-8', content)
831 846
832 847
833 848 def test_store():
834 849 """Test %store."""
835 850 ip = get_ipython()
836 851 ip.run_line_magic('load_ext', 'storemagic')
837 852
838 853 # make sure the storage is empty
839 854 ip.run_line_magic('store', '-z')
840 855 ip.user_ns['var'] = 42
841 856 ip.run_line_magic('store', 'var')
842 857 ip.user_ns['var'] = 39
843 858 ip.run_line_magic('store', '-r')
844 859 nt.assert_equal(ip.user_ns['var'], 42)
845 860
846 861 ip.run_line_magic('store', '-d var')
847 862 ip.user_ns['var'] = 39
848 863 ip.run_line_magic('store' , '-r')
849 864 nt.assert_equal(ip.user_ns['var'], 39)
850 865
851 866
852 867 def _run_edit_test(arg_s, exp_filename=None,
853 868 exp_lineno=-1,
854 869 exp_contents=None,
855 870 exp_is_temp=None):
856 871 ip = get_ipython()
857 872 M = code.CodeMagics(ip)
858 873 last_call = ['','']
859 874 opts,args = M.parse_options(arg_s,'prxn:')
860 875 filename, lineno, is_temp = M._find_edit_target(ip, args, opts, last_call)
861 876
862 877 if exp_filename is not None:
863 878 nt.assert_equal(exp_filename, filename)
864 879 if exp_contents is not None:
865 880 with io.open(filename, 'r') as f:
866 881 contents = f.read()
867 882 nt.assert_equal(exp_contents, contents)
868 883 if exp_lineno != -1:
869 884 nt.assert_equal(exp_lineno, lineno)
870 885 if exp_is_temp is not None:
871 886 nt.assert_equal(exp_is_temp, is_temp)
872 887
873 888
874 889 def test_edit_interactive():
875 890 """%edit on interactively defined objects"""
876 891 ip = get_ipython()
877 892 n = ip.execution_count
878 893 ip.run_cell(u"def foo(): return 1", store_history=True)
879 894
880 895 try:
881 896 _run_edit_test("foo")
882 897 except code.InteractivelyDefined as e:
883 898 nt.assert_equal(e.index, n)
884 899 else:
885 900 raise AssertionError("Should have raised InteractivelyDefined")
886 901
887 902
888 903 def test_edit_cell():
889 904 """%edit [cell id]"""
890 905 ip = get_ipython()
891 906
892 907 ip.run_cell(u"def foo(): return 1", store_history=True)
893 908
894 909 # test
895 910 _run_edit_test("1", exp_contents=ip.user_ns['In'][1], exp_is_temp=True)
General Comments 0
You need to be logged in to leave comments. Login now