##// END OF EJS Templates
By default, Magics inherit from Configurable
Matthias BUSSONNIER -
Show More
@@ -1,676 +1,694 b''
1 1 # encoding: utf-8
2 2 """Magic functions for InteractiveShell.
3 3 """
4 4
5 5 #-----------------------------------------------------------------------------
6 6 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de> and
7 7 # Copyright (C) 2001 Fernando Perez <fperez@colorado.edu>
8 8 # Copyright (C) 2008 The IPython Development Team
9 9
10 10 # Distributed under the terms of the BSD License. The full license is in
11 11 # the file COPYING, distributed as part of this software.
12 12 #-----------------------------------------------------------------------------
13 13
14 14 #-----------------------------------------------------------------------------
15 15 # Imports
16 16 #-----------------------------------------------------------------------------
17 17 # Stdlib
18 18 import os
19 19 import re
20 20 import sys
21 21 import types
22 22 from getopt import getopt, GetoptError
23 23
24 24 # Our own
25 25 from IPython.config.configurable import Configurable
26 26 from IPython.core import oinspect
27 27 from IPython.core.error import UsageError
28 28 from IPython.core.inputsplitter import ESC_MAGIC, ESC_MAGIC2
29 29 from IPython.external.decorator import decorator
30 30 from IPython.utils.ipstruct import Struct
31 31 from IPython.utils.process import arg_split
32 32 from IPython.utils.text import dedent
33 33 from IPython.utils.traitlets import Bool, Dict, Instance, MetaHasTraits
34 34 from IPython.utils.warn import error
35 35
36 36 #-----------------------------------------------------------------------------
37 37 # Globals
38 38 #-----------------------------------------------------------------------------
39 39
40 40 # A dict we'll use for each class that has magics, used as temporary storage to
41 41 # pass information between the @line/cell_magic method decorators and the
42 42 # @magics_class class decorator, because the method decorators have no
43 43 # access to the class when they run. See for more details:
44 44 # http://stackoverflow.com/questions/2366713/can-a-python-decorator-of-an-instance-method-access-the-class
45 45
46 46 magics = dict(line={}, cell={})
47 47
48 48 magic_kinds = ('line', 'cell')
49 49 magic_spec = ('line', 'cell', 'line_cell')
50 50 magic_escapes = dict(line=ESC_MAGIC, cell=ESC_MAGIC2)
51 51
52 52 #-----------------------------------------------------------------------------
53 53 # Utility classes and functions
54 54 #-----------------------------------------------------------------------------
55 55
56 56 class Bunch: pass
57 57
58 58
59 59 def on_off(tag):
60 60 """Return an ON/OFF string for a 1/0 input. Simple utility function."""
61 61 return ['OFF','ON'][tag]
62 62
63 63
64 64 def compress_dhist(dh):
65 65 """Compress a directory history into a new one with at most 20 entries.
66 66
67 67 Return a new list made from the first and last 10 elements of dhist after
68 68 removal of duplicates.
69 69 """
70 70 head, tail = dh[:-10], dh[-10:]
71 71
72 72 newhead = []
73 73 done = set()
74 74 for h in head:
75 75 if h in done:
76 76 continue
77 77 newhead.append(h)
78 78 done.add(h)
79 79
80 80 return newhead + tail
81 81
82 82
83 83 def needs_local_scope(func):
84 84 """Decorator to mark magic functions which need to local scope to run."""
85 85 func.needs_local_scope = True
86 86 return func
87 87
88 88 #-----------------------------------------------------------------------------
89 89 # Class and method decorators for registering magics
90 90 #-----------------------------------------------------------------------------
91 91
92 92 def magics_class(cls):
93 93 """Class decorator for all subclasses of the main Magics class.
94 94
95 95 Any class that subclasses Magics *must* also apply this decorator, to
96 96 ensure that all the methods that have been decorated as line/cell magics
97 97 get correctly registered in the class instance. This is necessary because
98 98 when method decorators run, the class does not exist yet, so they
99 99 temporarily store their information into a module global. Application of
100 100 this class decorator copies that global data to the class instance and
101 101 clears the global.
102 102
103 103 Obviously, this mechanism is not thread-safe, which means that the
104 104 *creation* of subclasses of Magic should only be done in a single-thread
105 105 context. Instantiation of the classes has no restrictions. Given that
106 106 these classes are typically created at IPython startup time and before user
107 107 application code becomes active, in practice this should not pose any
108 108 problems.
109 109 """
110 110 cls.registered = True
111 111 cls.magics = dict(line = magics['line'],
112 112 cell = magics['cell'])
113 113 magics['line'] = {}
114 114 magics['cell'] = {}
115 115 return cls
116 116
117 117
118 118 def record_magic(dct, magic_kind, magic_name, func):
119 119 """Utility function to store a function as a magic of a specific kind.
120 120
121 121 Parameters
122 122 ----------
123 123 dct : dict
124 124 A dictionary with 'line' and 'cell' subdicts.
125 125
126 126 magic_kind : str
127 127 Kind of magic to be stored.
128 128
129 129 magic_name : str
130 130 Key to store the magic as.
131 131
132 132 func : function
133 133 Callable object to store.
134 134 """
135 135 if magic_kind == 'line_cell':
136 136 dct['line'][magic_name] = dct['cell'][magic_name] = func
137 137 else:
138 138 dct[magic_kind][magic_name] = func
139 139
140 140
141 141 def validate_type(magic_kind):
142 142 """Ensure that the given magic_kind is valid.
143 143
144 144 Check that the given magic_kind is one of the accepted spec types (stored
145 145 in the global `magic_spec`), raise ValueError otherwise.
146 146 """
147 147 if magic_kind not in magic_spec:
148 148 raise ValueError('magic_kind must be one of %s, %s given' %
149 149 magic_kinds, magic_kind)
150 150
151 151
152 152 # The docstrings for the decorator below will be fairly similar for the two
153 153 # types (method and function), so we generate them here once and reuse the
154 154 # templates below.
155 155 _docstring_template = \
156 156 """Decorate the given {0} as {1} magic.
157 157
158 158 The decorator can be used with or without arguments, as follows.
159 159
160 160 i) without arguments: it will create a {1} magic named as the {0} being
161 161 decorated::
162 162
163 163 @deco
164 164 def foo(...)
165 165
166 166 will create a {1} magic named `foo`.
167 167
168 168 ii) with one string argument: which will be used as the actual name of the
169 169 resulting magic::
170 170
171 171 @deco('bar')
172 172 def foo(...)
173 173
174 174 will create a {1} magic named `bar`.
175 175 """
176 176
177 177 # These two are decorator factories. While they are conceptually very similar,
178 178 # there are enough differences in the details that it's simpler to have them
179 179 # written as completely standalone functions rather than trying to share code
180 180 # and make a single one with convoluted logic.
181 181
182 182 def _method_magic_marker(magic_kind):
183 183 """Decorator factory for methods in Magics subclasses.
184 184 """
185 185
186 186 validate_type(magic_kind)
187 187
188 188 # This is a closure to capture the magic_kind. We could also use a class,
189 189 # but it's overkill for just that one bit of state.
190 190 def magic_deco(arg):
191 191 call = lambda f, *a, **k: f(*a, **k)
192 192
193 193 if callable(arg):
194 194 # "Naked" decorator call (just @foo, no args)
195 195 func = arg
196 196 name = func.func_name
197 197 retval = decorator(call, func)
198 198 record_magic(magics, magic_kind, name, name)
199 199 elif isinstance(arg, basestring):
200 200 # Decorator called with arguments (@foo('bar'))
201 201 name = arg
202 202 def mark(func, *a, **kw):
203 203 record_magic(magics, magic_kind, name, func.func_name)
204 204 return decorator(call, func)
205 205 retval = mark
206 206 else:
207 207 raise TypeError("Decorator can only be called with "
208 208 "string or function")
209 209 return retval
210 210
211 211 # Ensure the resulting decorator has a usable docstring
212 212 magic_deco.__doc__ = _docstring_template.format('method', magic_kind)
213 213 return magic_deco
214 214
215 215
216 216 def _function_magic_marker(magic_kind):
217 217 """Decorator factory for standalone functions.
218 218 """
219 219 validate_type(magic_kind)
220 220
221 221 # This is a closure to capture the magic_kind. We could also use a class,
222 222 # but it's overkill for just that one bit of state.
223 223 def magic_deco(arg):
224 224 call = lambda f, *a, **k: f(*a, **k)
225 225
226 226 # Find get_ipython() in the caller's namespace
227 227 caller = sys._getframe(1)
228 228 for ns in ['f_locals', 'f_globals', 'f_builtins']:
229 229 get_ipython = getattr(caller, ns).get('get_ipython')
230 230 if get_ipython is not None:
231 231 break
232 232 else:
233 233 raise NameError('Decorator can only run in context where '
234 234 '`get_ipython` exists')
235 235
236 236 ip = get_ipython()
237 237
238 238 if callable(arg):
239 239 # "Naked" decorator call (just @foo, no args)
240 240 func = arg
241 241 name = func.func_name
242 242 ip.register_magic_function(func, magic_kind, name)
243 243 retval = decorator(call, func)
244 244 elif isinstance(arg, basestring):
245 245 # Decorator called with arguments (@foo('bar'))
246 246 name = arg
247 247 def mark(func, *a, **kw):
248 248 ip.register_magic_function(func, magic_kind, name)
249 249 return decorator(call, func)
250 250 retval = mark
251 251 else:
252 252 raise TypeError("Decorator can only be called with "
253 253 "string or function")
254 254 return retval
255 255
256 256 # Ensure the resulting decorator has a usable docstring
257 257 ds = _docstring_template.format('function', magic_kind)
258 258
259 259 ds += dedent("""
260 260 Note: this decorator can only be used in a context where IPython is already
261 261 active, so that the `get_ipython()` call succeeds. You can therefore use
262 262 it in your startup files loaded after IPython initializes, but *not* in the
263 263 IPython configuration file itself, which is executed before IPython is
264 264 fully up and running. Any file located in the `startup` subdirectory of
265 265 your configuration profile will be OK in this sense.
266 266 """)
267 267
268 268 magic_deco.__doc__ = ds
269 269 return magic_deco
270 270
271 271
272 272 # Create the actual decorators for public use
273 273
274 274 # These three are used to decorate methods in class definitions
275 275 line_magic = _method_magic_marker('line')
276 276 cell_magic = _method_magic_marker('cell')
277 277 line_cell_magic = _method_magic_marker('line_cell')
278 278
279 279 # These three decorate standalone functions and perform the decoration
280 280 # immediately. They can only run where get_ipython() works
281 281 register_line_magic = _function_magic_marker('line')
282 282 register_cell_magic = _function_magic_marker('cell')
283 283 register_line_cell_magic = _function_magic_marker('line_cell')
284 284
285 285 #-----------------------------------------------------------------------------
286 286 # Core Magic classes
287 287 #-----------------------------------------------------------------------------
288 288
289 289 class MagicsManager(Configurable):
290 290 """Object that handles all magic-related functionality for IPython.
291 291 """
292 292 # Non-configurable class attributes
293 293
294 294 # A two-level dict, first keyed by magic type, then by magic function, and
295 295 # holding the actual callable object as value. This is the dict used for
296 296 # magic function dispatch
297 297 magics = Dict
298 298
299 299 # A registry of the original objects that we've been given holding magics.
300 300 registry = Dict
301 301
302 302 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
303 303
304 304 auto_magic = Bool(True, config=True, help=
305 305 "Automatically call line magics without requiring explicit % prefix")
306 306
307 307 def _auto_magic_changed(self, name, value):
308 308 self.shell.automagic = value
309 309
310 310 _auto_status = [
311 311 'Automagic is OFF, % prefix IS needed for line magics.',
312 312 'Automagic is ON, % prefix IS NOT needed for line magics.']
313 313
314 314 user_magics = Instance('IPython.core.magics.UserMagics')
315 315
316 316 def __init__(self, shell=None, config=None, user_magics=None, **traits):
317 317
318 318 super(MagicsManager, self).__init__(shell=shell, config=config,
319 319 user_magics=user_magics, **traits)
320 320 self.magics = dict(line={}, cell={})
321 321 # Let's add the user_magics to the registry for uniformity, so *all*
322 322 # registered magic containers can be found there.
323 323 self.registry[user_magics.__class__.__name__] = user_magics
324 324
325 325 def auto_status(self):
326 326 """Return descriptive string with automagic status."""
327 327 return self._auto_status[self.auto_magic]
328 328
329 329 def lsmagic(self):
330 330 """Return a dict of currently available magic functions.
331 331
332 332 The return dict has the keys 'line' and 'cell', corresponding to the
333 333 two types of magics we support. Each value is a list of names.
334 334 """
335 335 return self.magics
336 336
337 337 def lsmagic_docs(self, brief=False, missing=''):
338 338 """Return dict of documentation of magic functions.
339 339
340 340 The return dict has the keys 'line' and 'cell', corresponding to the
341 341 two types of magics we support. Each value is a dict keyed by magic
342 342 name whose value is the function docstring. If a docstring is
343 343 unavailable, the value of `missing` is used instead.
344 344
345 345 If brief is True, only the first line of each docstring will be returned.
346 346 """
347 347 docs = {}
348 348 for m_type in self.magics:
349 349 m_docs = {}
350 350 for m_name, m_func in self.magics[m_type].iteritems():
351 351 if m_func.__doc__:
352 352 if brief:
353 353 m_docs[m_name] = m_func.__doc__.split('\n', 1)[0]
354 354 else:
355 355 m_docs[m_name] = m_func.__doc__.rstrip()
356 356 else:
357 357 m_docs[m_name] = missing
358 358 docs[m_type] = m_docs
359 359 return docs
360 360
361 361 def register(self, *magic_objects):
362 362 """Register one or more instances of Magics.
363 363
364 364 Take one or more classes or instances of classes that subclass the main
365 365 `core.Magic` class, and register them with IPython to use the magic
366 366 functions they provide. The registration process will then ensure that
367 367 any methods that have decorated to provide line and/or cell magics will
368 368 be recognized with the `%x`/`%%x` syntax as a line/cell magic
369 369 respectively.
370 370
371 371 If classes are given, they will be instantiated with the default
372 372 constructor. If your classes need a custom constructor, you should
373 373 instanitate them first and pass the instance.
374 374
375 375 The provided arguments can be an arbitrary mix of classes and instances.
376 376
377 377 Parameters
378 378 ----------
379 379 magic_objects : one or more classes or instances
380 380 """
381 381 # Start by validating them to ensure they have all had their magic
382 382 # methods registered at the instance level
383 383 for m in magic_objects:
384 384 if not m.registered:
385 385 raise ValueError("Class of magics %r was constructed without "
386 386 "the @register_magics class decorator")
387 387 if type(m) in (type, MetaHasTraits):
388 388 # If we're given an uninstantiated class
389 389 m = m(shell=self.shell)
390 390
391 391 # Now that we have an instance, we can register it and update the
392 392 # table of callables
393 393 self.registry[m.__class__.__name__] = m
394 394 for mtype in magic_kinds:
395 395 self.magics[mtype].update(m.magics[mtype])
396 396
397 397 def register_function(self, func, magic_kind='line', magic_name=None):
398 398 """Expose a standalone function as magic function for IPython.
399 399
400 400 This will create an IPython magic (line, cell or both) from a
401 401 standalone function. The functions should have the following
402 402 signatures:
403 403
404 404 * For line magics: `def f(line)`
405 405 * For cell magics: `def f(line, cell)`
406 406 * For a function that does both: `def f(line, cell=None)`
407 407
408 408 In the latter case, the function will be called with `cell==None` when
409 409 invoked as `%f`, and with cell as a string when invoked as `%%f`.
410 410
411 411 Parameters
412 412 ----------
413 413 func : callable
414 414 Function to be registered as a magic.
415 415
416 416 magic_kind : str
417 417 Kind of magic, one of 'line', 'cell' or 'line_cell'
418 418
419 419 magic_name : optional str
420 420 If given, the name the magic will have in the IPython namespace. By
421 421 default, the name of the function itself is used.
422 422 """
423 423
424 424 # Create the new method in the user_magics and register it in the
425 425 # global table
426 426 validate_type(magic_kind)
427 427 magic_name = func.func_name if magic_name is None else magic_name
428 428 setattr(self.user_magics, magic_name, func)
429 429 record_magic(self.magics, magic_kind, magic_name, func)
430 430
431 431 def define_magic(self, name, func):
432 432 """[Deprecated] Expose own function as magic function for IPython.
433 433
434 434 Example::
435 435
436 436 def foo_impl(self, parameter_s=''):
437 437 'My very own magic!. (Use docstrings, IPython reads them).'
438 438 print 'Magic function. Passed parameter is between < >:'
439 439 print '<%s>' % parameter_s
440 440 print 'The self object is:', self
441 441
442 442 ip.define_magic('foo',foo_impl)
443 443 """
444 444 meth = types.MethodType(func, self.user_magics)
445 445 setattr(self.user_magics, name, meth)
446 446 record_magic(self.magics, 'line', name, meth)
447 447
448 448 def register_alias(self, alias_name, magic_name, magic_kind='line'):
449 449 """Register an alias to a magic function.
450 450
451 451 The alias is an instance of :class:`MagicAlias`, which holds the
452 452 name and kind of the magic it should call. Binding is done at
453 453 call time, so if the underlying magic function is changed the alias
454 454 will call the new function.
455 455
456 456 Parameters
457 457 ----------
458 458 alias_name : str
459 459 The name of the magic to be registered.
460 460
461 461 magic_name : str
462 462 The name of an existing magic.
463 463
464 464 magic_kind : str
465 465 Kind of magic, one of 'line' or 'cell'
466 466 """
467 467
468 468 # `validate_type` is too permissive, as it allows 'line_cell'
469 469 # which we do not handle.
470 470 if magic_kind not in magic_kinds:
471 471 raise ValueError('magic_kind must be one of %s, %s given' %
472 472 magic_kinds, magic_kind)
473 473
474 474 alias = MagicAlias(self.shell, magic_name, magic_kind)
475 475 setattr(self.user_magics, alias_name, alias)
476 476 record_magic(self.magics, magic_kind, alias_name, alias)
477 477
478 478 # Key base class that provides the central functionality for magics.
479 479
480 class Magics(object):
480
481 class Magics(Configurable):
481 482 """Base class for implementing magic functions.
482 483
483 484 Shell functions which can be reached as %function_name. All magic
484 485 functions should accept a string, which they can parse for their own
485 486 needs. This can make some functions easier to type, eg `%cd ../`
486 487 vs. `%cd("../")`
487 488
488 489 Classes providing magic functions need to subclass this class, and they
489 490 MUST:
490 491
491 492 - Use the method decorators `@line_magic` and `@cell_magic` to decorate
492 493 individual methods as magic functions, AND
493 494
494 495 - Use the class decorator `@magics_class` to ensure that the magic
495 496 methods are properly registered at the instance level upon instance
496 497 initialization.
497 498
498 499 See :mod:`magic_functions` for examples of actual implementation classes.
499 500 """
500 501 # Dict holding all command-line options for each magic.
501 502 options_table = None
502 503 # Dict for the mapping of magic names to methods, set by class decorator
503 504 magics = None
504 505 # Flag to check that the class decorator was properly applied
505 506 registered = False
506 507 # Instance of IPython shell
507 508 shell = None
508 509
509 def __init__(self, shell):
510 def __init__(self, shell=None, **kwargs):
511 if shell is not None:
512 kwargs['shell'] = shell
513 kwargs.setdefault('parent', shell)
514 super(Magics, self).__init__(**kwargs)
515
516 def __init__(self, shell=None, **kwargs):
510 517 if not(self.__class__.registered):
511 518 raise ValueError('Magics subclass without registration - '
512 519 'did you forget to apply @magics_class?')
520 if shell is not None:
521 if hasattr( shell, 'configurables'):
522 shell.configurables.append(self)
523 if hasattr( shell, 'config'):
524 kwargs.setdefault('parent', shell)
525 kwargs['shell'] = shell
526
513 527 self.shell = shell
514 528 self.options_table = {}
515 529 # The method decorators are run when the instance doesn't exist yet, so
516 530 # they can only record the names of the methods they are supposed to
517 531 # grab. Only now, that the instance exists, can we create the proper
518 532 # mapping to bound methods. So we read the info off the original names
519 533 # table and replace each method name by the actual bound method.
520 534 # But we mustn't clobber the *class* mapping, in case of multiple instances.
521 535 class_magics = self.magics
522 536 self.magics = {}
523 537 for mtype in magic_kinds:
524 538 tab = self.magics[mtype] = {}
525 539 cls_tab = class_magics[mtype]
526 540 for magic_name, meth_name in cls_tab.iteritems():
527 541 if isinstance(meth_name, basestring):
528 542 # it's a method name, grab it
529 543 tab[magic_name] = getattr(self, meth_name)
530 544 else:
531 545 # it's the real thing
532 546 tab[magic_name] = meth_name
547 # Configurable **need** to be initiated at the end or the config
548 # magics get screwed up.
549 super(Magics, self).__init__(**kwargs)
533 550
534 551 def arg_err(self,func):
535 552 """Print docstring if incorrect arguments were passed"""
536 553 print 'Error in arguments:'
537 554 print oinspect.getdoc(func)
538 555
539 556 def format_latex(self, strng):
540 557 """Format a string for latex inclusion."""
541 558
542 559 # Characters that need to be escaped for latex:
543 560 escape_re = re.compile(r'(%|_|\$|#|&)',re.MULTILINE)
544 561 # Magic command names as headers:
545 562 cmd_name_re = re.compile(r'^(%s.*?):' % ESC_MAGIC,
546 563 re.MULTILINE)
547 564 # Magic commands
548 565 cmd_re = re.compile(r'(?P<cmd>%s.+?\b)(?!\}\}:)' % ESC_MAGIC,
549 566 re.MULTILINE)
550 567 # Paragraph continue
551 568 par_re = re.compile(r'\\$',re.MULTILINE)
552 569
553 570 # The "\n" symbol
554 571 newline_re = re.compile(r'\\n')
555 572
556 573 # Now build the string for output:
557 574 #strng = cmd_name_re.sub(r'\n\\texttt{\\textsl{\\large \1}}:',strng)
558 575 strng = cmd_name_re.sub(r'\n\\bigskip\n\\texttt{\\textbf{ \1}}:',
559 576 strng)
560 577 strng = cmd_re.sub(r'\\texttt{\g<cmd>}',strng)
561 578 strng = par_re.sub(r'\\\\',strng)
562 579 strng = escape_re.sub(r'\\\1',strng)
563 580 strng = newline_re.sub(r'\\textbackslash{}n',strng)
564 581 return strng
565 582
566 583 def parse_options(self, arg_str, opt_str, *long_opts, **kw):
567 584 """Parse options passed to an argument string.
568 585
569 586 The interface is similar to that of getopt(), but it returns back a
570 587 Struct with the options as keys and the stripped argument string still
571 588 as a string.
572 589
573 590 arg_str is quoted as a true sys.argv vector by using shlex.split.
574 591 This allows us to easily expand variables, glob files, quote
575 592 arguments, etc.
576 593
577 594 Options:
578 595 -mode: default 'string'. If given as 'list', the argument string is
579 596 returned as a list (split on whitespace) instead of a string.
580 597
581 598 -list_all: put all option values in lists. Normally only options
582 599 appearing more than once are put in a list.
583 600
584 601 -posix (True): whether to split the input line in POSIX mode or not,
585 602 as per the conventions outlined in the shlex module from the
586 603 standard library."""
587 604
588 605 # inject default options at the beginning of the input line
589 606 caller = sys._getframe(1).f_code.co_name
590 607 arg_str = '%s %s' % (self.options_table.get(caller,''),arg_str)
591 608
592 609 mode = kw.get('mode','string')
593 610 if mode not in ['string','list']:
594 611 raise ValueError('incorrect mode given: %s' % mode)
595 612 # Get options
596 613 list_all = kw.get('list_all',0)
597 614 posix = kw.get('posix', os.name == 'posix')
598 615 strict = kw.get('strict', True)
599 616
600 617 # Check if we have more than one argument to warrant extra processing:
601 618 odict = {} # Dictionary with options
602 619 args = arg_str.split()
603 620 if len(args) >= 1:
604 621 # If the list of inputs only has 0 or 1 thing in it, there's no
605 622 # need to look for options
606 623 argv = arg_split(arg_str, posix, strict)
607 624 # Do regular option processing
608 625 try:
609 626 opts,args = getopt(argv, opt_str, long_opts)
610 627 except GetoptError as e:
611 628 raise UsageError('%s ( allowed: "%s" %s)' % (e.msg,opt_str,
612 629 " ".join(long_opts)))
613 630 for o,a in opts:
614 631 if o.startswith('--'):
615 632 o = o[2:]
616 633 else:
617 634 o = o[1:]
618 635 try:
619 636 odict[o].append(a)
620 637 except AttributeError:
621 638 odict[o] = [odict[o],a]
622 639 except KeyError:
623 640 if list_all:
624 641 odict[o] = [a]
625 642 else:
626 643 odict[o] = a
627 644
628 645 # Prepare opts,args for return
629 646 opts = Struct(odict)
630 647 if mode == 'string':
631 648 args = ' '.join(args)
632 649
633 650 return opts,args
634 651
635 652 def default_option(self, fn, optstr):
636 653 """Make an entry in the options_table for fn, with value optstr"""
637 654
638 655 if fn not in self.lsmagic():
639 656 error("%s is not a magic function" % fn)
640 657 self.options_table[fn] = optstr
641 658
659
642 660 class MagicAlias(object):
643 661 """An alias to another magic function.
644 662
645 663 An alias is determined by its magic name and magic kind. Lookup
646 664 is done at call time, so if the underlying magic changes the alias
647 665 will call the new function.
648 666
649 667 Use the :meth:`MagicsManager.register_alias` method or the
650 668 `%alias_magic` magic function to create and register a new alias.
651 669 """
652 670 def __init__(self, shell, magic_name, magic_kind):
653 671 self.shell = shell
654 672 self.magic_name = magic_name
655 673 self.magic_kind = magic_kind
656 674
657 675 self.pretty_target = '%s%s' % (magic_escapes[self.magic_kind], self.magic_name)
658 676 self.__doc__ = "Alias for `%s`." % self.pretty_target
659 677
660 678 self._in_call = False
661 679
662 680 def __call__(self, *args, **kwargs):
663 681 """Call the magic alias."""
664 682 fn = self.shell.find_magic(self.magic_name, self.magic_kind)
665 683 if fn is None:
666 684 raise UsageError("Magic `%s` not found." % self.pretty_target)
667 685
668 686 # Protect against infinite recursion.
669 687 if self._in_call:
670 688 raise UsageError("Infinite recursion detected; "
671 689 "magic aliases cannot call themselves.")
672 690 self._in_call = True
673 691 try:
674 692 return fn(*args, **kwargs)
675 693 finally:
676 694 self._in_call = False
@@ -1,280 +1,279 b''
1 1 """Magic functions for running cells in various scripts."""
2 2 #-----------------------------------------------------------------------------
3 3 # Copyright (c) 2012 The IPython Development Team.
4 4 #
5 5 # Distributed under the terms of the Modified BSD License.
6 6 #
7 7 # The full license is in the file COPYING.txt, distributed with this software.
8 8 #-----------------------------------------------------------------------------
9 9
10 10 #-----------------------------------------------------------------------------
11 11 # Imports
12 12 #-----------------------------------------------------------------------------
13 13
14 14 # Stdlib
15 15 import errno
16 16 import os
17 17 import sys
18 18 import signal
19 19 import time
20 20 from subprocess import Popen, PIPE
21 21 import atexit
22 22
23 23 # Our own packages
24 24 from IPython.config.configurable import Configurable
25 25 from IPython.core import magic_arguments
26 26 from IPython.core.magic import (
27 27 Magics, magics_class, line_magic, cell_magic
28 28 )
29 29 from IPython.lib.backgroundjobs import BackgroundJobManager
30 30 from IPython.utils import py3compat
31 31 from IPython.utils.process import arg_split
32 32 from IPython.utils.traitlets import List, Dict
33 33
34 34 #-----------------------------------------------------------------------------
35 35 # Magic implementation classes
36 36 #-----------------------------------------------------------------------------
37 37
38 38 def script_args(f):
39 39 """single decorator for adding script args"""
40 40 args = [
41 41 magic_arguments.argument(
42 42 '--out', type=str,
43 43 help="""The variable in which to store stdout from the script.
44 44 If the script is backgrounded, this will be the stdout *pipe*,
45 45 instead of the stderr text itself.
46 46 """
47 47 ),
48 48 magic_arguments.argument(
49 49 '--err', type=str,
50 50 help="""The variable in which to store stderr from the script.
51 51 If the script is backgrounded, this will be the stderr *pipe*,
52 52 instead of the stderr text itself.
53 53 """
54 54 ),
55 55 magic_arguments.argument(
56 56 '--bg', action="store_true",
57 57 help="""Whether to run the script in the background.
58 58 If given, the only way to see the output of the command is
59 59 with --out/err.
60 60 """
61 61 ),
62 62 magic_arguments.argument(
63 63 '--proc', type=str,
64 64 help="""The variable in which to store Popen instance.
65 65 This is used only when --bg option is given.
66 66 """
67 67 ),
68 68 ]
69 69 for arg in args:
70 70 f = arg(f)
71 71 return f
72 72
73 73 @magics_class
74 class ScriptMagics(Magics, Configurable):
74 class ScriptMagics(Magics):
75 75 """Magics for talking to scripts
76 76
77 77 This defines a base `%%script` cell magic for running a cell
78 78 with a program in a subprocess, and registers a few top-level
79 79 magics that call %%script with common interpreters.
80 80 """
81 81 script_magics = List(config=True,
82 82 help="""Extra script cell magics to define
83 83
84 84 This generates simple wrappers of `%%script foo` as `%%foo`.
85 85
86 86 If you want to add script magics that aren't on your path,
87 87 specify them in script_paths
88 88 """,
89 89 )
90 90 def _script_magics_default(self):
91 91 """default to a common list of programs"""
92 92
93 93 defaults = [
94 94 'sh',
95 95 'bash',
96 96 'perl',
97 97 'ruby',
98 98 'python',
99 99 'python3',
100 100 'pypy',
101 101 ]
102 102 if os.name == 'nt':
103 103 defaults.extend([
104 104 'cmd',
105 105 'powershell',
106 106 ])
107 107
108 108 return defaults
109 109
110 110 script_paths = Dict(config=True,
111 111 help="""Dict mapping short 'ruby' names to full paths, such as '/opt/secret/bin/ruby'
112 112
113 113 Only necessary for items in script_magics where the default path will not
114 114 find the right interpreter.
115 115 """
116 116 )
117 117
118 118 def __init__(self, shell=None):
119 Configurable.__init__(self, config=shell.config)
119 super(ScriptMagics, self).__init__(shell=shell)
120 120 self._generate_script_magics()
121 Magics.__init__(self, shell=shell)
122 121 self.job_manager = BackgroundJobManager()
123 122 self.bg_processes = []
124 123 atexit.register(self.kill_bg_processes)
125 124
126 125 def __del__(self):
127 126 self.kill_bg_processes()
128 127
129 128 def _generate_script_magics(self):
130 129 cell_magics = self.magics['cell']
131 130 for name in self.script_magics:
132 131 cell_magics[name] = self._make_script_magic(name)
133 132
134 133 def _make_script_magic(self, name):
135 134 """make a named magic, that calls %%script with a particular program"""
136 135 # expand to explicit path if necessary:
137 136 script = self.script_paths.get(name, name)
138 137
139 138 @magic_arguments.magic_arguments()
140 139 @script_args
141 140 def named_script_magic(line, cell):
142 141 # if line, add it as cl-flags
143 142 if line:
144 143 line = "%s %s" % (script, line)
145 144 else:
146 145 line = script
147 146 return self.shebang(line, cell)
148 147
149 148 # write a basic docstring:
150 149 named_script_magic.__doc__ = \
151 150 """%%{name} script magic
152 151
153 152 Run cells with {script} in a subprocess.
154 153
155 154 This is a shortcut for `%%script {script}`
156 155 """.format(**locals())
157 156
158 157 return named_script_magic
159 158
160 159 @magic_arguments.magic_arguments()
161 160 @script_args
162 161 @cell_magic("script")
163 162 def shebang(self, line, cell):
164 163 """Run a cell via a shell command
165 164
166 165 The `%%script` line is like the #! line of script,
167 166 specifying a program (bash, perl, ruby, etc.) with which to run.
168 167
169 168 The rest of the cell is run by that program.
170 169
171 170 Examples
172 171 --------
173 172 ::
174 173
175 174 In [1]: %%script bash
176 175 ...: for i in 1 2 3; do
177 176 ...: echo $i
178 177 ...: done
179 178 1
180 179 2
181 180 3
182 181 """
183 182 argv = arg_split(line, posix = not sys.platform.startswith('win'))
184 183 args, cmd = self.shebang.parser.parse_known_args(argv)
185 184
186 185 try:
187 186 p = Popen(cmd, stdout=PIPE, stderr=PIPE, stdin=PIPE)
188 187 except OSError as e:
189 188 if e.errno == errno.ENOENT:
190 189 print "Couldn't find program: %r" % cmd[0]
191 190 return
192 191 else:
193 192 raise
194 193
195 194 cell = cell.encode('utf8', 'replace')
196 195 if args.bg:
197 196 self.bg_processes.append(p)
198 197 self._gc_bg_processes()
199 198 if args.out:
200 199 self.shell.user_ns[args.out] = p.stdout
201 200 if args.err:
202 201 self.shell.user_ns[args.err] = p.stderr
203 202 self.job_manager.new(self._run_script, p, cell, daemon=True)
204 203 if args.proc:
205 204 self.shell.user_ns[args.proc] = p
206 205 return
207 206
208 207 try:
209 208 out, err = p.communicate(cell)
210 209 except KeyboardInterrupt:
211 210 try:
212 211 p.send_signal(signal.SIGINT)
213 212 time.sleep(0.1)
214 213 if p.poll() is not None:
215 214 print "Process is interrupted."
216 215 return
217 216 p.terminate()
218 217 time.sleep(0.1)
219 218 if p.poll() is not None:
220 219 print "Process is terminated."
221 220 return
222 221 p.kill()
223 222 print "Process is killed."
224 223 except OSError:
225 224 pass
226 225 except Exception as e:
227 226 print "Error while terminating subprocess (pid=%i): %s" \
228 227 % (p.pid, e)
229 228 return
230 229 out = py3compat.bytes_to_str(out)
231 230 err = py3compat.bytes_to_str(err)
232 231 if args.out:
233 232 self.shell.user_ns[args.out] = out
234 233 else:
235 234 sys.stdout.write(out)
236 235 sys.stdout.flush()
237 236 if args.err:
238 237 self.shell.user_ns[args.err] = err
239 238 else:
240 239 sys.stderr.write(err)
241 240 sys.stderr.flush()
242 241
243 242 def _run_script(self, p, cell):
244 243 """callback for running the script in the background"""
245 244 p.stdin.write(cell)
246 245 p.stdin.close()
247 246 p.wait()
248 247
249 248 @line_magic("killbgscripts")
250 249 def killbgscripts(self, _nouse_=''):
251 250 """Kill all BG processes started by %%script and its family."""
252 251 self.kill_bg_processes()
253 252 print "All background processes were killed."
254 253
255 254 def kill_bg_processes(self):
256 255 """Kill all BG processes which are still running."""
257 256 for p in self.bg_processes:
258 257 if p.poll() is None:
259 258 try:
260 259 p.send_signal(signal.SIGINT)
261 260 except:
262 261 pass
263 262 time.sleep(0.1)
264 263 for p in self.bg_processes:
265 264 if p.poll() is None:
266 265 try:
267 266 p.terminate()
268 267 except:
269 268 pass
270 269 time.sleep(0.1)
271 270 for p in self.bg_processes:
272 271 if p.poll() is None:
273 272 try:
274 273 p.kill()
275 274 except:
276 275 pass
277 276 self._gc_bg_processes()
278 277
279 278 def _gc_bg_processes(self):
280 279 self.bg_processes = [p for p in self.bg_processes if p.poll() is None]
@@ -1,933 +1,940 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 #-----------------------------------------------------------------------------
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 48 def test_extract_code_ranges():
49 49 instr = "1 3 5-6 7-9 10:15 17: :10 10- -13 :"
50 50 expected = [(0, 1),
51 51 (2, 3),
52 52 (4, 6),
53 53 (6, 9),
54 54 (9, 14),
55 55 (16, None),
56 56 (None, 9),
57 57 (9, None),
58 58 (None, 13),
59 59 (None, None)]
60 60 actual = list(code.extract_code_ranges(instr))
61 61 nt.assert_equal(actual, expected)
62 62
63
64 63 def test_extract_symbols():
65 64 source = """import foo\na = 10\ndef b():\n return 42\n\n\nclass A: pass\n\n\n"""
66 65 symbols_args = ["a", "b", "A", "A,b", "A,a", "z"]
67 66 expected = [([], ['a']),
68 67 (["def b():\n return 42\n"], []),
69 68 (["class A: pass\n"], []),
70 69 (["class A: pass\n", "def b():\n return 42\n"], []),
71 70 (["class A: pass\n"], ['a']),
72 71 ([], ['z'])]
73 72 for symbols, exp in zip(symbols_args, expected):
74 73 nt.assert_equal(code.extract_symbols(source, symbols), exp)
75 74
76 75
77 76 def test_extract_symbols_raises_exception_with_non_python_code():
78 77 source = ("=begin A Ruby program :)=end\n"
79 78 "def hello\n"
80 79 "puts 'Hello world'\n"
81 80 "end")
82 81 with nt.assert_raises(SyntaxError):
83 82 code.extract_symbols(source, "hello")
84 83
84 def test_config():
85 """ test that config magic does not raise
86 can happen if Configurable init is moved too early into
87 Magics.__init__ as then a Config object will be registerd as a
88 magic.
89 """
90 ## should not raise.
91 _ip.magic('config')
85 92
86 93 def test_rehashx():
87 94 # clear up everything
88 95 _ip = get_ipython()
89 96 _ip.alias_manager.clear_aliases()
90 97 del _ip.db['syscmdlist']
91 98
92 99 _ip.magic('rehashx')
93 100 # Practically ALL ipython development systems will have more than 10 aliases
94 101
95 102 nt.assert_true(len(_ip.alias_manager.aliases) > 10)
96 103 for name, cmd in _ip.alias_manager.aliases:
97 104 # we must strip dots from alias names
98 105 nt.assert_not_in('.', name)
99 106
100 107 # rehashx must fill up syscmdlist
101 108 scoms = _ip.db['syscmdlist']
102 109 nt.assert_true(len(scoms) > 10)
103 110
104 111
105 112 def test_magic_parse_options():
106 113 """Test that we don't mangle paths when parsing magic options."""
107 114 ip = get_ipython()
108 115 path = 'c:\\x'
109 116 m = DummyMagics(ip)
110 117 opts = m.parse_options('-f %s' % path,'f:')[0]
111 118 # argv splitting is os-dependent
112 119 if os.name == 'posix':
113 120 expected = 'c:x'
114 121 else:
115 122 expected = path
116 123 nt.assert_equal(opts['f'], expected)
117 124
118 125 def test_magic_parse_long_options():
119 126 """Magic.parse_options can handle --foo=bar long options"""
120 127 ip = get_ipython()
121 128 m = DummyMagics(ip)
122 129 opts, _ = m.parse_options('--foo --bar=bubble', 'a', 'foo', 'bar=')
123 130 nt.assert_in('foo', opts)
124 131 nt.assert_in('bar', opts)
125 132 nt.assert_equal(opts['bar'], "bubble")
126 133
127 134
128 135 @dec.skip_without('sqlite3')
129 136 def doctest_hist_f():
130 137 """Test %hist -f with temporary filename.
131 138
132 139 In [9]: import tempfile
133 140
134 141 In [10]: tfile = tempfile.mktemp('.py','tmp-ipython-')
135 142
136 143 In [11]: %hist -nl -f $tfile 3
137 144
138 145 In [13]: import os; os.unlink(tfile)
139 146 """
140 147
141 148
142 149 @dec.skip_without('sqlite3')
143 150 def doctest_hist_r():
144 151 """Test %hist -r
145 152
146 153 XXX - This test is not recording the output correctly. For some reason, in
147 154 testing mode the raw history isn't getting populated. No idea why.
148 155 Disabling the output checking for now, though at least we do run it.
149 156
150 157 In [1]: 'hist' in _ip.lsmagic()
151 158 Out[1]: True
152 159
153 160 In [2]: x=1
154 161
155 162 In [3]: %hist -rl 2
156 163 x=1 # random
157 164 %hist -r 2
158 165 """
159 166
160 167
161 168 @dec.skip_without('sqlite3')
162 169 def doctest_hist_op():
163 170 """Test %hist -op
164 171
165 172 In [1]: class b(float):
166 173 ...: pass
167 174 ...:
168 175
169 176 In [2]: class s(object):
170 177 ...: def __str__(self):
171 178 ...: return 's'
172 179 ...:
173 180
174 181 In [3]:
175 182
176 183 In [4]: class r(b):
177 184 ...: def __repr__(self):
178 185 ...: return 'r'
179 186 ...:
180 187
181 188 In [5]: class sr(s,r): pass
182 189 ...:
183 190
184 191 In [6]:
185 192
186 193 In [7]: bb=b()
187 194
188 195 In [8]: ss=s()
189 196
190 197 In [9]: rr=r()
191 198
192 199 In [10]: ssrr=sr()
193 200
194 201 In [11]: 4.5
195 202 Out[11]: 4.5
196 203
197 204 In [12]: str(ss)
198 205 Out[12]: 's'
199 206
200 207 In [13]:
201 208
202 209 In [14]: %hist -op
203 210 >>> class b:
204 211 ... pass
205 212 ...
206 213 >>> class s(b):
207 214 ... def __str__(self):
208 215 ... return 's'
209 216 ...
210 217 >>>
211 218 >>> class r(b):
212 219 ... def __repr__(self):
213 220 ... return 'r'
214 221 ...
215 222 >>> class sr(s,r): pass
216 223 >>>
217 224 >>> bb=b()
218 225 >>> ss=s()
219 226 >>> rr=r()
220 227 >>> ssrr=sr()
221 228 >>> 4.5
222 229 4.5
223 230 >>> str(ss)
224 231 's'
225 232 >>>
226 233 """
227 234
228 235
229 236 @dec.skip_without('sqlite3')
230 237 def test_macro():
231 238 ip = get_ipython()
232 239 ip.history_manager.reset() # Clear any existing history.
233 240 cmds = ["a=1", "def b():\n return a**2", "print(a,b())"]
234 241 for i, cmd in enumerate(cmds, start=1):
235 242 ip.history_manager.store_inputs(i, cmd)
236 243 ip.magic("macro test 1-3")
237 244 nt.assert_equal(ip.user_ns["test"].value, "\n".join(cmds)+"\n")
238 245
239 246 # List macros
240 247 nt.assert_in("test", ip.magic("macro"))
241 248
242 249
243 250 @dec.skip_without('sqlite3')
244 251 def test_macro_run():
245 252 """Test that we can run a multi-line macro successfully."""
246 253 ip = get_ipython()
247 254 ip.history_manager.reset()
248 255 cmds = ["a=10", "a+=1", py3compat.doctest_refactor_print("print a"),
249 256 "%macro test 2-3"]
250 257 for cmd in cmds:
251 258 ip.run_cell(cmd, store_history=True)
252 259 nt.assert_equal(ip.user_ns["test"].value,
253 260 py3compat.doctest_refactor_print("a+=1\nprint a\n"))
254 261 with tt.AssertPrints("12"):
255 262 ip.run_cell("test")
256 263 with tt.AssertPrints("13"):
257 264 ip.run_cell("test")
258 265
259 266
260 267 def test_magic_magic():
261 268 """Test %magic"""
262 269 ip = get_ipython()
263 270 with capture_output() as captured:
264 271 ip.magic("magic")
265 272
266 273 stdout = captured.stdout
267 274 nt.assert_in('%magic', stdout)
268 275 nt.assert_in('IPython', stdout)
269 276 nt.assert_in('Available', stdout)
270 277
271 278
272 279 @dec.skipif_not_numpy
273 280 def test_numpy_reset_array_undec():
274 281 "Test '%reset array' functionality"
275 282 _ip.ex('import numpy as np')
276 283 _ip.ex('a = np.empty(2)')
277 284 nt.assert_in('a', _ip.user_ns)
278 285 _ip.magic('reset -f array')
279 286 nt.assert_not_in('a', _ip.user_ns)
280 287
281 288 def test_reset_out():
282 289 "Test '%reset out' magic"
283 290 _ip.run_cell("parrot = 'dead'", store_history=True)
284 291 # test '%reset -f out', make an Out prompt
285 292 _ip.run_cell("parrot", store_history=True)
286 293 nt.assert_true('dead' in [_ip.user_ns[x] for x in '_','__','___'])
287 294 _ip.magic('reset -f out')
288 295 nt.assert_false('dead' in [_ip.user_ns[x] for x in '_','__','___'])
289 296 nt.assert_equal(len(_ip.user_ns['Out']), 0)
290 297
291 298 def test_reset_in():
292 299 "Test '%reset in' magic"
293 300 # test '%reset -f in'
294 301 _ip.run_cell("parrot", store_history=True)
295 302 nt.assert_true('parrot' in [_ip.user_ns[x] for x in '_i','_ii','_iii'])
296 303 _ip.magic('%reset -f in')
297 304 nt.assert_false('parrot' in [_ip.user_ns[x] for x in '_i','_ii','_iii'])
298 305 nt.assert_equal(len(set(_ip.user_ns['In'])), 1)
299 306
300 307 def test_reset_dhist():
301 308 "Test '%reset dhist' magic"
302 309 _ip.run_cell("tmp = [d for d in _dh]") # copy before clearing
303 310 _ip.magic('cd ' + os.path.dirname(nt.__file__))
304 311 _ip.magic('cd -')
305 312 nt.assert_true(len(_ip.user_ns['_dh']) > 0)
306 313 _ip.magic('reset -f dhist')
307 314 nt.assert_equal(len(_ip.user_ns['_dh']), 0)
308 315 _ip.run_cell("_dh = [d for d in tmp]") #restore
309 316
310 317 def test_reset_in_length():
311 318 "Test that '%reset in' preserves In[] length"
312 319 _ip.run_cell("print 'foo'")
313 320 _ip.run_cell("reset -f in")
314 321 nt.assert_equal(len(_ip.user_ns['In']), _ip.displayhook.prompt_count+1)
315 322
316 323 def test_tb_syntaxerror():
317 324 """test %tb after a SyntaxError"""
318 325 ip = get_ipython()
319 326 ip.run_cell("for")
320 327
321 328 # trap and validate stdout
322 329 save_stdout = sys.stdout
323 330 try:
324 331 sys.stdout = StringIO()
325 332 ip.run_cell("%tb")
326 333 out = sys.stdout.getvalue()
327 334 finally:
328 335 sys.stdout = save_stdout
329 336 # trim output, and only check the last line
330 337 last_line = out.rstrip().splitlines()[-1].strip()
331 338 nt.assert_equal(last_line, "SyntaxError: invalid syntax")
332 339
333 340
334 341 def test_time():
335 342 ip = get_ipython()
336 343
337 344 with tt.AssertPrints("Wall time: "):
338 345 ip.run_cell("%time None")
339 346
340 347 ip.run_cell("def f(kmjy):\n"
341 348 " %time print (2*kmjy)")
342 349
343 350 with tt.AssertPrints("Wall time: "):
344 351 with tt.AssertPrints("hihi", suppress=False):
345 352 ip.run_cell("f('hi')")
346 353
347 354
348 355 @dec.skip_win32
349 356 def test_time2():
350 357 ip = get_ipython()
351 358
352 359 with tt.AssertPrints("CPU times: user "):
353 360 ip.run_cell("%time None")
354 361
355 362 def test_time3():
356 363 """Erroneous magic function calls, issue gh-3334"""
357 364 ip = get_ipython()
358 365 ip.user_ns.pop('run', None)
359 366
360 367 with tt.AssertNotPrints("not found", channel='stderr'):
361 368 ip.run_cell("%%time\n"
362 369 "run = 0\n"
363 370 "run += 1")
364 371
365 372 def test_doctest_mode():
366 373 "Toggle doctest_mode twice, it should be a no-op and run without error"
367 374 _ip.magic('doctest_mode')
368 375 _ip.magic('doctest_mode')
369 376
370 377
371 378 def test_parse_options():
372 379 """Tests for basic options parsing in magics."""
373 380 # These are only the most minimal of tests, more should be added later. At
374 381 # the very least we check that basic text/unicode calls work OK.
375 382 m = DummyMagics(_ip)
376 383 nt.assert_equal(m.parse_options('foo', '')[1], 'foo')
377 384 nt.assert_equal(m.parse_options(u'foo', '')[1], u'foo')
378 385
379 386
380 387 def test_dirops():
381 388 """Test various directory handling operations."""
382 389 # curpath = lambda :os.path.splitdrive(os.getcwdu())[1].replace('\\','/')
383 390 curpath = os.getcwdu
384 391 startdir = os.getcwdu()
385 392 ipdir = os.path.realpath(_ip.ipython_dir)
386 393 try:
387 394 _ip.magic('cd "%s"' % ipdir)
388 395 nt.assert_equal(curpath(), ipdir)
389 396 _ip.magic('cd -')
390 397 nt.assert_equal(curpath(), startdir)
391 398 _ip.magic('pushd "%s"' % ipdir)
392 399 nt.assert_equal(curpath(), ipdir)
393 400 _ip.magic('popd')
394 401 nt.assert_equal(curpath(), startdir)
395 402 finally:
396 403 os.chdir(startdir)
397 404
398 405
399 406 def test_xmode():
400 407 # Calling xmode three times should be a no-op
401 408 xmode = _ip.InteractiveTB.mode
402 409 for i in range(3):
403 410 _ip.magic("xmode")
404 411 nt.assert_equal(_ip.InteractiveTB.mode, xmode)
405 412
406 413 def test_reset_hard():
407 414 monitor = []
408 415 class A(object):
409 416 def __del__(self):
410 417 monitor.append(1)
411 418 def __repr__(self):
412 419 return "<A instance>"
413 420
414 421 _ip.user_ns["a"] = A()
415 422 _ip.run_cell("a")
416 423
417 424 nt.assert_equal(monitor, [])
418 425 _ip.magic("reset -f")
419 426 nt.assert_equal(monitor, [1])
420 427
421 428 class TestXdel(tt.TempFileMixin):
422 429 def test_xdel(self):
423 430 """Test that references from %run are cleared by xdel."""
424 431 src = ("class A(object):\n"
425 432 " monitor = []\n"
426 433 " def __del__(self):\n"
427 434 " self.monitor.append(1)\n"
428 435 "a = A()\n")
429 436 self.mktmp(src)
430 437 # %run creates some hidden references...
431 438 _ip.magic("run %s" % self.fname)
432 439 # ... as does the displayhook.
433 440 _ip.run_cell("a")
434 441
435 442 monitor = _ip.user_ns["A"].monitor
436 443 nt.assert_equal(monitor, [])
437 444
438 445 _ip.magic("xdel a")
439 446
440 447 # Check that a's __del__ method has been called.
441 448 nt.assert_equal(monitor, [1])
442 449
443 450 def doctest_who():
444 451 """doctest for %who
445 452
446 453 In [1]: %reset -f
447 454
448 455 In [2]: alpha = 123
449 456
450 457 In [3]: beta = 'beta'
451 458
452 459 In [4]: %who int
453 460 alpha
454 461
455 462 In [5]: %who str
456 463 beta
457 464
458 465 In [6]: %whos
459 466 Variable Type Data/Info
460 467 ----------------------------
461 468 alpha int 123
462 469 beta str beta
463 470
464 471 In [7]: %who_ls
465 472 Out[7]: ['alpha', 'beta']
466 473 """
467 474
468 475 def test_whos():
469 476 """Check that whos is protected against objects where repr() fails."""
470 477 class A(object):
471 478 def __repr__(self):
472 479 raise Exception()
473 480 _ip.user_ns['a'] = A()
474 481 _ip.magic("whos")
475 482
476 483 @py3compat.u_format
477 484 def doctest_precision():
478 485 """doctest for %precision
479 486
480 487 In [1]: f = get_ipython().display_formatter.formatters['text/plain']
481 488
482 489 In [2]: %precision 5
483 490 Out[2]: {u}'%.5f'
484 491
485 492 In [3]: f.float_format
486 493 Out[3]: {u}'%.5f'
487 494
488 495 In [4]: %precision %e
489 496 Out[4]: {u}'%e'
490 497
491 498 In [5]: f(3.1415927)
492 499 Out[5]: {u}'3.141593e+00'
493 500 """
494 501
495 502 def test_psearch():
496 503 with tt.AssertPrints("dict.fromkeys"):
497 504 _ip.run_cell("dict.fr*?")
498 505
499 506 def test_timeit_shlex():
500 507 """test shlex issues with timeit (#1109)"""
501 508 _ip.ex("def f(*a,**kw): pass")
502 509 _ip.magic('timeit -n1 "this is a bug".count(" ")')
503 510 _ip.magic('timeit -r1 -n1 f(" ", 1)')
504 511 _ip.magic('timeit -r1 -n1 f(" ", 1, " ", 2, " ")')
505 512 _ip.magic('timeit -r1 -n1 ("a " + "b")')
506 513 _ip.magic('timeit -r1 -n1 f("a " + "b")')
507 514 _ip.magic('timeit -r1 -n1 f("a " + "b ")')
508 515
509 516
510 517 def test_timeit_arguments():
511 518 "Test valid timeit arguments, should not cause SyntaxError (GH #1269)"
512 519 _ip.magic("timeit ('#')")
513 520
514 521
515 522 def test_timeit_special_syntax():
516 523 "Test %%timeit with IPython special syntax"
517 524 @register_line_magic
518 525 def lmagic(line):
519 526 ip = get_ipython()
520 527 ip.user_ns['lmagic_out'] = line
521 528
522 529 # line mode test
523 530 _ip.run_line_magic('timeit', '-n1 -r1 %lmagic my line')
524 531 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line')
525 532 # cell mode test
526 533 _ip.run_cell_magic('timeit', '-n1 -r1', '%lmagic my line2')
527 534 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line2')
528 535
529 536 def test_timeit_return():
530 537 """
531 538 test wether timeit -o return object
532 539 """
533 540
534 541 res = _ip.run_line_magic('timeit','-n10 -r10 -o 1')
535 542 assert(res is not None)
536 543
537 544 def test_timeit_quiet():
538 545 """
539 546 test quiet option of timeit magic
540 547 """
541 548 with tt.AssertNotPrints("loops"):
542 549 _ip.run_cell("%timeit -n1 -r1 -q 1")
543 550
544 551 @dec.skipif(execution.profile is None)
545 552 def test_prun_special_syntax():
546 553 "Test %%prun with IPython special syntax"
547 554 @register_line_magic
548 555 def lmagic(line):
549 556 ip = get_ipython()
550 557 ip.user_ns['lmagic_out'] = line
551 558
552 559 # line mode test
553 560 _ip.run_line_magic('prun', '-q %lmagic my line')
554 561 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line')
555 562 # cell mode test
556 563 _ip.run_cell_magic('prun', '-q', '%lmagic my line2')
557 564 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line2')
558 565
559 566 @dec.skipif(execution.profile is None)
560 567 def test_prun_quotes():
561 568 "Test that prun does not clobber string escapes (GH #1302)"
562 569 _ip.magic(r"prun -q x = '\t'")
563 570 nt.assert_equal(_ip.user_ns['x'], '\t')
564 571
565 572 def test_extension():
566 573 tmpdir = TemporaryDirectory()
567 574 orig_ipython_dir = _ip.ipython_dir
568 575 try:
569 576 _ip.ipython_dir = tmpdir.name
570 577 nt.assert_raises(ImportError, _ip.magic, "load_ext daft_extension")
571 578 url = os.path.join(os.path.dirname(__file__), "daft_extension.py")
572 579 _ip.magic("install_ext %s" % url)
573 580 _ip.user_ns.pop('arq', None)
574 581 invalidate_caches() # Clear import caches
575 582 _ip.magic("load_ext daft_extension")
576 583 nt.assert_equal(_ip.user_ns['arq'], 185)
577 584 _ip.magic("unload_ext daft_extension")
578 585 assert 'arq' not in _ip.user_ns
579 586 finally:
580 587 _ip.ipython_dir = orig_ipython_dir
581 588 tmpdir.cleanup()
582 589
583 590 def test_notebook_export_json():
584 591 with TemporaryDirectory() as td:
585 592 outfile = os.path.join(td, "nb.ipynb")
586 593 _ip.ex(py3compat.u_format(u"u = {u}'hΓ©llo'"))
587 594 _ip.magic("notebook -e %s" % outfile)
588 595
589 596 def test_notebook_export_py():
590 597 with TemporaryDirectory() as td:
591 598 outfile = os.path.join(td, "nb.py")
592 599 _ip.ex(py3compat.u_format(u"u = {u}'hΓ©llo'"))
593 600 _ip.magic("notebook -e %s" % outfile)
594 601
595 602 def test_notebook_reformat_py():
596 603 with TemporaryDirectory() as td:
597 604 infile = os.path.join(td, "nb.ipynb")
598 605 with io.open(infile, 'w', encoding='utf-8') as f:
599 606 current.write(nb0, f, 'json')
600 607
601 608 _ip.ex(py3compat.u_format(u"u = {u}'hΓ©llo'"))
602 609 _ip.magic("notebook -f py %s" % infile)
603 610
604 611 def test_notebook_reformat_json():
605 612 with TemporaryDirectory() as td:
606 613 infile = os.path.join(td, "nb.py")
607 614 with io.open(infile, 'w', encoding='utf-8') as f:
608 615 current.write(nb0, f, 'py')
609 616
610 617 _ip.ex(py3compat.u_format(u"u = {u}'hΓ©llo'"))
611 618 _ip.magic("notebook -f ipynb %s" % infile)
612 619 _ip.magic("notebook -f json %s" % infile)
613 620
614 621 def test_env():
615 622 env = _ip.magic("env")
616 623 assert isinstance(env, dict), type(env)
617 624
618 625
619 626 class CellMagicTestCase(TestCase):
620 627
621 628 def check_ident(self, magic):
622 629 # Manually called, we get the result
623 630 out = _ip.run_cell_magic(magic, 'a', 'b')
624 631 nt.assert_equal(out, ('a','b'))
625 632 # Via run_cell, it goes into the user's namespace via displayhook
626 633 _ip.run_cell('%%' + magic +' c\nd')
627 634 nt.assert_equal(_ip.user_ns['_'], ('c','d'))
628 635
629 636 def test_cell_magic_func_deco(self):
630 637 "Cell magic using simple decorator"
631 638 @register_cell_magic
632 639 def cellm(line, cell):
633 640 return line, cell
634 641
635 642 self.check_ident('cellm')
636 643
637 644 def test_cell_magic_reg(self):
638 645 "Cell magic manually registered"
639 646 def cellm(line, cell):
640 647 return line, cell
641 648
642 649 _ip.register_magic_function(cellm, 'cell', 'cellm2')
643 650 self.check_ident('cellm2')
644 651
645 652 def test_cell_magic_class(self):
646 653 "Cell magics declared via a class"
647 654 @magics_class
648 655 class MyMagics(Magics):
649 656
650 657 @cell_magic
651 658 def cellm3(self, line, cell):
652 659 return line, cell
653 660
654 661 _ip.register_magics(MyMagics)
655 662 self.check_ident('cellm3')
656 663
657 664 def test_cell_magic_class2(self):
658 665 "Cell magics declared via a class, #2"
659 666 @magics_class
660 667 class MyMagics2(Magics):
661 668
662 669 @cell_magic('cellm4')
663 670 def cellm33(self, line, cell):
664 671 return line, cell
665 672
666 673 _ip.register_magics(MyMagics2)
667 674 self.check_ident('cellm4')
668 675 # Check that nothing is registered as 'cellm33'
669 676 c33 = _ip.find_cell_magic('cellm33')
670 677 nt.assert_equal(c33, None)
671 678
672 679 def test_file():
673 680 """Basic %%file"""
674 681 ip = get_ipython()
675 682 with TemporaryDirectory() as td:
676 683 fname = os.path.join(td, 'file1')
677 684 ip.run_cell_magic("file", fname, u'\n'.join([
678 685 'line1',
679 686 'line2',
680 687 ]))
681 688 with open(fname) as f:
682 689 s = f.read()
683 690 nt.assert_in('line1\n', s)
684 691 nt.assert_in('line2', s)
685 692
686 693 def test_file_var_expand():
687 694 """%%file $filename"""
688 695 ip = get_ipython()
689 696 with TemporaryDirectory() as td:
690 697 fname = os.path.join(td, 'file1')
691 698 ip.user_ns['filename'] = fname
692 699 ip.run_cell_magic("file", '$filename', u'\n'.join([
693 700 'line1',
694 701 'line2',
695 702 ]))
696 703 with open(fname) as f:
697 704 s = f.read()
698 705 nt.assert_in('line1\n', s)
699 706 nt.assert_in('line2', s)
700 707
701 708 def test_file_unicode():
702 709 """%%file with unicode cell"""
703 710 ip = get_ipython()
704 711 with TemporaryDirectory() as td:
705 712 fname = os.path.join(td, 'file1')
706 713 ip.run_cell_magic("file", fname, u'\n'.join([
707 714 u'linΓ©1',
708 715 u'linΓ©2',
709 716 ]))
710 717 with io.open(fname, encoding='utf-8') as f:
711 718 s = f.read()
712 719 nt.assert_in(u'linΓ©1\n', s)
713 720 nt.assert_in(u'linΓ©2', s)
714 721
715 722 def test_file_amend():
716 723 """%%file -a amends files"""
717 724 ip = get_ipython()
718 725 with TemporaryDirectory() as td:
719 726 fname = os.path.join(td, 'file2')
720 727 ip.run_cell_magic("file", fname, u'\n'.join([
721 728 'line1',
722 729 'line2',
723 730 ]))
724 731 ip.run_cell_magic("file", "-a %s" % fname, u'\n'.join([
725 732 'line3',
726 733 'line4',
727 734 ]))
728 735 with open(fname) as f:
729 736 s = f.read()
730 737 nt.assert_in('line1\n', s)
731 738 nt.assert_in('line3\n', s)
732 739
733 740
734 741 def test_script_config():
735 742 ip = get_ipython()
736 743 ip.config.ScriptMagics.script_magics = ['whoda']
737 744 sm = script.ScriptMagics(shell=ip)
738 745 nt.assert_in('whoda', sm.magics['cell'])
739 746
740 747 @dec.skip_win32
741 748 def test_script_out():
742 749 ip = get_ipython()
743 750 ip.run_cell_magic("script", "--out output sh", "echo 'hi'")
744 751 nt.assert_equal(ip.user_ns['output'], 'hi\n')
745 752
746 753 @dec.skip_win32
747 754 def test_script_err():
748 755 ip = get_ipython()
749 756 ip.run_cell_magic("script", "--err error sh", "echo 'hello' >&2")
750 757 nt.assert_equal(ip.user_ns['error'], 'hello\n')
751 758
752 759 @dec.skip_win32
753 760 def test_script_out_err():
754 761 ip = get_ipython()
755 762 ip.run_cell_magic("script", "--out output --err error sh", "echo 'hi'\necho 'hello' >&2")
756 763 nt.assert_equal(ip.user_ns['output'], 'hi\n')
757 764 nt.assert_equal(ip.user_ns['error'], 'hello\n')
758 765
759 766 @dec.skip_win32
760 767 def test_script_bg_out():
761 768 ip = get_ipython()
762 769 ip.run_cell_magic("script", "--bg --out output sh", "echo 'hi'")
763 770 nt.assert_equal(ip.user_ns['output'].read(), b'hi\n')
764 771
765 772 @dec.skip_win32
766 773 def test_script_bg_err():
767 774 ip = get_ipython()
768 775 ip.run_cell_magic("script", "--bg --err error sh", "echo 'hello' >&2")
769 776 nt.assert_equal(ip.user_ns['error'].read(), b'hello\n')
770 777
771 778 @dec.skip_win32
772 779 def test_script_bg_out_err():
773 780 ip = get_ipython()
774 781 ip.run_cell_magic("script", "--bg --out output --err error sh", "echo 'hi'\necho 'hello' >&2")
775 782 nt.assert_equal(ip.user_ns['output'].read(), b'hi\n')
776 783 nt.assert_equal(ip.user_ns['error'].read(), b'hello\n')
777 784
778 785 def test_script_defaults():
779 786 ip = get_ipython()
780 787 for cmd in ['sh', 'bash', 'perl', 'ruby']:
781 788 try:
782 789 find_cmd(cmd)
783 790 except Exception:
784 791 pass
785 792 else:
786 793 nt.assert_in(cmd, ip.magics_manager.magics['cell'])
787 794
788 795
789 796 @magics_class
790 797 class FooFoo(Magics):
791 798 """class with both %foo and %%foo magics"""
792 799 @line_magic('foo')
793 800 def line_foo(self, line):
794 801 "I am line foo"
795 802 pass
796 803
797 804 @cell_magic("foo")
798 805 def cell_foo(self, line, cell):
799 806 "I am cell foo, not line foo"
800 807 pass
801 808
802 809 def test_line_cell_info():
803 810 """%%foo and %foo magics are distinguishable to inspect"""
804 811 ip = get_ipython()
805 812 ip.magics_manager.register(FooFoo)
806 813 oinfo = ip.object_inspect('foo')
807 814 nt.assert_true(oinfo['found'])
808 815 nt.assert_true(oinfo['ismagic'])
809 816
810 817 oinfo = ip.object_inspect('%%foo')
811 818 nt.assert_true(oinfo['found'])
812 819 nt.assert_true(oinfo['ismagic'])
813 820 nt.assert_equal(oinfo['docstring'], FooFoo.cell_foo.__doc__)
814 821
815 822 oinfo = ip.object_inspect('%foo')
816 823 nt.assert_true(oinfo['found'])
817 824 nt.assert_true(oinfo['ismagic'])
818 825 nt.assert_equal(oinfo['docstring'], FooFoo.line_foo.__doc__)
819 826
820 827 def test_multiple_magics():
821 828 ip = get_ipython()
822 829 foo1 = FooFoo(ip)
823 830 foo2 = FooFoo(ip)
824 831 mm = ip.magics_manager
825 832 mm.register(foo1)
826 833 nt.assert_true(mm.magics['line']['foo'].im_self is foo1)
827 834 mm.register(foo2)
828 835 nt.assert_true(mm.magics['line']['foo'].im_self is foo2)
829 836
830 837 def test_alias_magic():
831 838 """Test %alias_magic."""
832 839 ip = get_ipython()
833 840 mm = ip.magics_manager
834 841
835 842 # Basic operation: both cell and line magics are created, if possible.
836 843 ip.run_line_magic('alias_magic', 'timeit_alias timeit')
837 844 nt.assert_in('timeit_alias', mm.magics['line'])
838 845 nt.assert_in('timeit_alias', mm.magics['cell'])
839 846
840 847 # --cell is specified, line magic not created.
841 848 ip.run_line_magic('alias_magic', '--cell timeit_cell_alias timeit')
842 849 nt.assert_not_in('timeit_cell_alias', mm.magics['line'])
843 850 nt.assert_in('timeit_cell_alias', mm.magics['cell'])
844 851
845 852 # Test that line alias is created successfully.
846 853 ip.run_line_magic('alias_magic', '--line env_alias env')
847 854 nt.assert_equal(ip.run_line_magic('env', ''),
848 855 ip.run_line_magic('env_alias', ''))
849 856
850 857 def test_save():
851 858 """Test %save."""
852 859 ip = get_ipython()
853 860 ip.history_manager.reset() # Clear any existing history.
854 861 cmds = [u"a=1", u"def b():\n return a**2", u"print(a, b())"]
855 862 for i, cmd in enumerate(cmds, start=1):
856 863 ip.history_manager.store_inputs(i, cmd)
857 864 with TemporaryDirectory() as tmpdir:
858 865 file = os.path.join(tmpdir, "testsave.py")
859 866 ip.run_line_magic("save", "%s 1-10" % file)
860 867 with open(file) as f:
861 868 content = f.read()
862 869 nt.assert_equal(content.count(cmds[0]), 1)
863 870 nt.assert_in('coding: utf-8', content)
864 871 ip.run_line_magic("save", "-a %s 1-10" % file)
865 872 with open(file) as f:
866 873 content = f.read()
867 874 nt.assert_equal(content.count(cmds[0]), 2)
868 875 nt.assert_in('coding: utf-8', content)
869 876
870 877
871 878 def test_store():
872 879 """Test %store."""
873 880 ip = get_ipython()
874 881 ip.run_line_magic('load_ext', 'storemagic')
875 882
876 883 # make sure the storage is empty
877 884 ip.run_line_magic('store', '-z')
878 885 ip.user_ns['var'] = 42
879 886 ip.run_line_magic('store', 'var')
880 887 ip.user_ns['var'] = 39
881 888 ip.run_line_magic('store', '-r')
882 889 nt.assert_equal(ip.user_ns['var'], 42)
883 890
884 891 ip.run_line_magic('store', '-d var')
885 892 ip.user_ns['var'] = 39
886 893 ip.run_line_magic('store' , '-r')
887 894 nt.assert_equal(ip.user_ns['var'], 39)
888 895
889 896
890 897 def _run_edit_test(arg_s, exp_filename=None,
891 898 exp_lineno=-1,
892 899 exp_contents=None,
893 900 exp_is_temp=None):
894 901 ip = get_ipython()
895 902 M = code.CodeMagics(ip)
896 903 last_call = ['','']
897 904 opts,args = M.parse_options(arg_s,'prxn:')
898 905 filename, lineno, is_temp = M._find_edit_target(ip, args, opts, last_call)
899 906
900 907 if exp_filename is not None:
901 908 nt.assert_equal(exp_filename, filename)
902 909 if exp_contents is not None:
903 910 with io.open(filename, 'r') as f:
904 911 contents = f.read()
905 912 nt.assert_equal(exp_contents, contents)
906 913 if exp_lineno != -1:
907 914 nt.assert_equal(exp_lineno, lineno)
908 915 if exp_is_temp is not None:
909 916 nt.assert_equal(exp_is_temp, is_temp)
910 917
911 918
912 919 def test_edit_interactive():
913 920 """%edit on interactively defined objects"""
914 921 ip = get_ipython()
915 922 n = ip.execution_count
916 923 ip.run_cell(u"def foo(): return 1", store_history=True)
917 924
918 925 try:
919 926 _run_edit_test("foo")
920 927 except code.InteractivelyDefined as e:
921 928 nt.assert_equal(e.index, n)
922 929 else:
923 930 raise AssertionError("Should have raised InteractivelyDefined")
924 931
925 932
926 933 def test_edit_cell():
927 934 """%edit [cell id]"""
928 935 ip = get_ipython()
929 936
930 937 ip.run_cell(u"def foo(): return 1", store_history=True)
931 938
932 939 # test
933 940 _run_edit_test("1", exp_contents=ip.user_ns['In'][1], exp_is_temp=True)
@@ -1,243 +1,241 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 %store magic for lightweight persistence.
4 4
5 5 Stores variables, aliases and macros in IPython's database.
6 6
7 7 To automatically restore stored variables at startup, add this to your
8 8 :file:`ipython_config.py` file::
9 9
10 10 c.StoreMagic.autorestore = True
11 11 """
12 12 #-----------------------------------------------------------------------------
13 13 # Copyright (c) 2012, The IPython Development Team.
14 14 #
15 15 # Distributed under the terms of the Modified BSD License.
16 16 #
17 17 # The full license is in the file COPYING.txt, distributed with this software.
18 18 #-----------------------------------------------------------------------------
19 19
20 20 #-----------------------------------------------------------------------------
21 21 # Imports
22 22 #-----------------------------------------------------------------------------
23 23
24 24 # Stdlib
25 25 import inspect, os, sys, textwrap
26 26
27 27 # Our own
28 from IPython.config.configurable import Configurable
29 28 from IPython.core.error import UsageError
30 29 from IPython.core.magic import Magics, magics_class, line_magic
31 30 from IPython.testing.skipdoctest import skip_doctest
32 31 from IPython.utils.traitlets import Bool
33 32
34 33 #-----------------------------------------------------------------------------
35 34 # Functions and classes
36 35 #-----------------------------------------------------------------------------
37 36
38 37 def restore_aliases(ip):
39 38 staliases = ip.db.get('stored_aliases', {})
40 39 for k,v in staliases.items():
41 40 #print "restore alias",k,v # dbg
42 41 #self.alias_table[k] = v
43 42 ip.alias_manager.define_alias(k,v)
44 43
45 44
46 45 def refresh_variables(ip):
47 46 db = ip.db
48 47 for key in db.keys('autorestore/*'):
49 48 # strip autorestore
50 49 justkey = os.path.basename(key)
51 50 try:
52 51 obj = db[key]
53 52 except KeyError:
54 53 print "Unable to restore variable '%s', ignoring (use %%store -d to forget!)" % justkey
55 54 print "The error was:", sys.exc_info()[0]
56 55 else:
57 56 #print "restored",justkey,"=",obj #dbg
58 57 ip.user_ns[justkey] = obj
59 58
60 59
61 60 def restore_dhist(ip):
62 61 ip.user_ns['_dh'] = ip.db.get('dhist',[])
63 62
64 63
65 64 def restore_data(ip):
66 65 refresh_variables(ip)
67 66 restore_aliases(ip)
68 67 restore_dhist(ip)
69 68
70 69
71 70 @magics_class
72 class StoreMagics(Magics, Configurable):
71 class StoreMagics(Magics):
73 72 """Lightweight persistence for python variables.
74 73
75 74 Provides the %store magic."""
76 75
77 76 autorestore = Bool(False, config=True, help=
78 77 """If True, any %store-d variables will be automatically restored
79 78 when IPython starts.
80 79 """
81 80 )
82 81
83 82 def __init__(self, shell):
84 Configurable.__init__(self, config=shell.config)
85 Magics.__init__(self, shell=shell)
83 super(StoreMagics, self).__init__(shell=shell)
86 84 self.shell.configurables.append(self)
87 85 if self.autorestore:
88 86 restore_data(self.shell)
89 87
90 88 @skip_doctest
91 89 @line_magic
92 90 def store(self, parameter_s=''):
93 91 """Lightweight persistence for python variables.
94 92
95 93 Example::
96 94
97 95 In [1]: l = ['hello',10,'world']
98 96 In [2]: %store l
99 97 In [3]: exit
100 98
101 99 (IPython session is closed and started again...)
102 100
103 101 ville@badger:~$ ipython
104 102 In [1]: l
105 103 NameError: name 'l' is not defined
106 104 In [2]: %store -r
107 105 In [3]: l
108 106 Out[3]: ['hello', 10, 'world']
109 107
110 108 Usage:
111 109
112 110 * ``%store`` - Show list of all variables and their current
113 111 values
114 112 * ``%store spam`` - Store the *current* value of the variable spam
115 113 to disk
116 114 * ``%store -d spam`` - Remove the variable and its value from storage
117 115 * ``%store -z`` - Remove all variables from storage
118 116 * ``%store -r`` - Refresh all variables from store (overwrite
119 117 current vals)
120 118 * ``%store -r spam bar`` - Refresh specified variables from store
121 119 (delete current val)
122 120 * ``%store foo >a.txt`` - Store value of foo to new file a.txt
123 121 * ``%store foo >>a.txt`` - Append value of foo to file a.txt
124 122
125 123 It should be noted that if you change the value of a variable, you
126 124 need to %store it again if you want to persist the new value.
127 125
128 126 Note also that the variables will need to be pickleable; most basic
129 127 python types can be safely %store'd.
130 128
131 129 Also aliases can be %store'd across sessions.
132 130 """
133 131
134 132 opts,argsl = self.parse_options(parameter_s,'drz',mode='string')
135 133 args = argsl.split(None,1)
136 134 ip = self.shell
137 135 db = ip.db
138 136 # delete
139 137 if 'd' in opts:
140 138 try:
141 139 todel = args[0]
142 140 except IndexError:
143 141 raise UsageError('You must provide the variable to forget')
144 142 else:
145 143 try:
146 144 del db['autorestore/' + todel]
147 145 except:
148 146 raise UsageError("Can't delete variable '%s'" % todel)
149 147 # reset
150 148 elif 'z' in opts:
151 149 for k in db.keys('autorestore/*'):
152 150 del db[k]
153 151
154 152 elif 'r' in opts:
155 153 if args:
156 154 for arg in args:
157 155 try:
158 156 obj = db['autorestore/' + arg]
159 157 except KeyError:
160 158 print "no stored variable %s" % arg
161 159 else:
162 160 ip.user_ns[arg] = obj
163 161 else:
164 162 restore_data(ip)
165 163
166 164 # run without arguments -> list variables & values
167 165 elif not args:
168 166 vars = db.keys('autorestore/*')
169 167 vars.sort()
170 168 if vars:
171 169 size = max(map(len, vars))
172 170 else:
173 171 size = 0
174 172
175 173 print 'Stored variables and their in-db values:'
176 174 fmt = '%-'+str(size)+'s -> %s'
177 175 get = db.get
178 176 for var in vars:
179 177 justkey = os.path.basename(var)
180 178 # print 30 first characters from every var
181 179 print fmt % (justkey, repr(get(var, '<unavailable>'))[:50])
182 180
183 181 # default action - store the variable
184 182 else:
185 183 # %store foo >file.txt or >>file.txt
186 184 if len(args) > 1 and args[1].startswith('>'):
187 185 fnam = os.path.expanduser(args[1].lstrip('>').lstrip())
188 186 if args[1].startswith('>>'):
189 187 fil = open(fnam, 'a')
190 188 else:
191 189 fil = open(fnam, 'w')
192 190 obj = ip.ev(args[0])
193 191 print "Writing '%s' (%s) to file '%s'." % (args[0],
194 192 obj.__class__.__name__, fnam)
195 193
196 194
197 195 if not isinstance (obj, basestring):
198 196 from pprint import pprint
199 197 pprint(obj, fil)
200 198 else:
201 199 fil.write(obj)
202 200 if not obj.endswith('\n'):
203 201 fil.write('\n')
204 202
205 203 fil.close()
206 204 return
207 205
208 206 # %store foo
209 207 try:
210 208 obj = ip.user_ns[args[0]]
211 209 except KeyError:
212 210 # it might be an alias
213 211 name = args[0]
214 212 try:
215 213 cmd = ip.alias_manager.retrieve_alias(name)
216 214 except ValueError:
217 215 raise UsageError("Unknown variable '%s'" % name)
218 216
219 217 staliases = db.get('stored_aliases',{})
220 218 staliases[name] = cmd
221 219 db['stored_aliases'] = staliases
222 220 print "Alias stored: %s (%s)" % (name, cmd)
223 221 return
224 222
225 223 else:
226 224 modname = getattr(inspect.getmodule(obj), '__name__', '')
227 225 if modname == '__main__':
228 226 print textwrap.dedent("""\
229 227 Warning:%s is %s
230 228 Proper storage of interactively declared classes (or instances
231 229 of those classes) is not possible! Only instances
232 230 of classes in real modules on file system can be %%store'd.
233 231 """ % (args[0], obj) )
234 232 return
235 233 #pickled = pickle.dumps(obj)
236 234 db[ 'autorestore/' + args[0] ] = obj
237 235 print "Stored '%s' (%s)" % (args[0], obj.__class__.__name__)
238 236
239 237
240 238 def load_ipython_extension(ip):
241 239 """Load the extension in IPython."""
242 240 ip.register_magics(StoreMagics)
243 241
@@ -1,316 +1,317 b''
1 1 """Tests for autoreload extension.
2 2 """
3 3 #-----------------------------------------------------------------------------
4 4 # Copyright (c) 2012 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 import os
16 16 import sys
17 17 import tempfile
18 18 import shutil
19 19 import random
20 20 import time
21 21 from StringIO import StringIO
22 22
23 23 import nose.tools as nt
24 24 import IPython.testing.tools as tt
25 25
26 26 from IPython.extensions.autoreload import AutoreloadMagics
27 27 from IPython.core.hooks import TryNext
28 28
29 29 #-----------------------------------------------------------------------------
30 30 # Test fixture
31 31 #-----------------------------------------------------------------------------
32 32
33 33 noop = lambda *a, **kw: None
34 34
35 35 class FakeShell(object):
36
36 37 def __init__(self):
37 38 self.ns = {}
38 39 self.auto_magics = AutoreloadMagics(shell=self)
39 40
40 41 register_magics = set_hook = noop
41 42
42 43 def run_code(self, code):
43 44 try:
44 45 self.auto_magics.pre_run_code_hook(self)
45 46 except TryNext:
46 47 pass
47 48 exec code in self.ns
48 49
49 50 def push(self, items):
50 51 self.ns.update(items)
51 52
52 53 def magic_autoreload(self, parameter):
53 54 self.auto_magics.autoreload(parameter)
54 55
55 56 def magic_aimport(self, parameter, stream=None):
56 57 self.auto_magics.aimport(parameter, stream=stream)
57 58
58 59
59 60 class Fixture(object):
60 61 """Fixture for creating test module files"""
61 62
62 63 test_dir = None
63 64 old_sys_path = None
64 65 filename_chars = "abcdefghijklmopqrstuvwxyz0123456789"
65 66
66 67 def setUp(self):
67 68 self.test_dir = tempfile.mkdtemp()
68 69 self.old_sys_path = list(sys.path)
69 70 sys.path.insert(0, self.test_dir)
70 71 self.shell = FakeShell()
71 72
72 73 def tearDown(self):
73 74 shutil.rmtree(self.test_dir)
74 75 sys.path = self.old_sys_path
75 76
76 77 self.test_dir = None
77 78 self.old_sys_path = None
78 79 self.shell = None
79 80
80 81 def get_module(self):
81 82 module_name = "tmpmod_" + "".join(random.sample(self.filename_chars,20))
82 83 if module_name in sys.modules:
83 84 del sys.modules[module_name]
84 85 file_name = os.path.join(self.test_dir, module_name + ".py")
85 86 return module_name, file_name
86 87
87 88 def write_file(self, filename, content):
88 89 """
89 90 Write a file, and force a timestamp difference of at least one second
90 91
91 92 Notes
92 93 -----
93 94 Python's .pyc files record the timestamp of their compilation
94 95 with a time resolution of one second.
95 96
96 97 Therefore, we need to force a timestamp difference between .py
97 98 and .pyc, without having the .py file be timestamped in the
98 99 future, and without changing the timestamp of the .pyc file
99 100 (because that is stored in the file). The only reliable way
100 101 to achieve this seems to be to sleep.
101 102 """
102 103
103 104 # Sleep one second + eps
104 105 time.sleep(1.05)
105 106
106 107 # Write
107 108 f = open(filename, 'w')
108 109 try:
109 110 f.write(content)
110 111 finally:
111 112 f.close()
112 113
113 114 def new_module(self, code):
114 115 mod_name, mod_fn = self.get_module()
115 116 f = open(mod_fn, 'w')
116 117 try:
117 118 f.write(code)
118 119 finally:
119 120 f.close()
120 121 return mod_name, mod_fn
121 122
122 123 #-----------------------------------------------------------------------------
123 124 # Test automatic reloading
124 125 #-----------------------------------------------------------------------------
125 126
126 127 class TestAutoreload(Fixture):
127 128 def _check_smoketest(self, use_aimport=True):
128 129 """
129 130 Functional test for the automatic reloader using either
130 131 '%autoreload 1' or '%autoreload 2'
131 132 """
132 133
133 134 mod_name, mod_fn = self.new_module("""
134 135 x = 9
135 136
136 137 z = 123 # this item will be deleted
137 138
138 139 def foo(y):
139 140 return y + 3
140 141
141 142 class Baz(object):
142 143 def __init__(self, x):
143 144 self.x = x
144 145 def bar(self, y):
145 146 return self.x + y
146 147 @property
147 148 def quux(self):
148 149 return 42
149 150 def zzz(self):
150 151 '''This method will be deleted below'''
151 152 return 99
152 153
153 154 class Bar: # old-style class: weakref doesn't work for it on Python < 2.7
154 155 def foo(self):
155 156 return 1
156 157 """)
157 158
158 159 #
159 160 # Import module, and mark for reloading
160 161 #
161 162 if use_aimport:
162 163 self.shell.magic_autoreload("1")
163 164 self.shell.magic_aimport(mod_name)
164 165 stream = StringIO()
165 166 self.shell.magic_aimport("", stream=stream)
166 167 nt.assert_true(("Modules to reload:\n%s" % mod_name) in
167 168 stream.getvalue())
168 169
169 170 nt.assert_raises(
170 171 ImportError,
171 172 self.shell.magic_aimport, "tmpmod_as318989e89ds")
172 173 else:
173 174 self.shell.magic_autoreload("2")
174 175 self.shell.run_code("import %s" % mod_name)
175 176 stream = StringIO()
176 177 self.shell.magic_aimport("", stream=stream)
177 178 nt.assert_true("Modules to reload:\nall-except-skipped" in
178 179 stream.getvalue())
179 180 nt.assert_in(mod_name, self.shell.ns)
180 181
181 182 mod = sys.modules[mod_name]
182 183
183 184 #
184 185 # Test module contents
185 186 #
186 187 old_foo = mod.foo
187 188 old_obj = mod.Baz(9)
188 189 old_obj2 = mod.Bar()
189 190
190 191 def check_module_contents():
191 192 nt.assert_equal(mod.x, 9)
192 193 nt.assert_equal(mod.z, 123)
193 194
194 195 nt.assert_equal(old_foo(0), 3)
195 196 nt.assert_equal(mod.foo(0), 3)
196 197
197 198 obj = mod.Baz(9)
198 199 nt.assert_equal(old_obj.bar(1), 10)
199 200 nt.assert_equal(obj.bar(1), 10)
200 201 nt.assert_equal(obj.quux, 42)
201 202 nt.assert_equal(obj.zzz(), 99)
202 203
203 204 obj2 = mod.Bar()
204 205 nt.assert_equal(old_obj2.foo(), 1)
205 206 nt.assert_equal(obj2.foo(), 1)
206 207
207 208 check_module_contents()
208 209
209 210 #
210 211 # Simulate a failed reload: no reload should occur and exactly
211 212 # one error message should be printed
212 213 #
213 214 self.write_file(mod_fn, """
214 215 a syntax error
215 216 """)
216 217
217 218 with tt.AssertPrints(('[autoreload of %s failed:' % mod_name), channel='stderr'):
218 219 self.shell.run_code("pass") # trigger reload
219 220 with tt.AssertNotPrints(('[autoreload of %s failed:' % mod_name), channel='stderr'):
220 221 self.shell.run_code("pass") # trigger another reload
221 222 check_module_contents()
222 223
223 224 #
224 225 # Rewrite module (this time reload should succeed)
225 226 #
226 227 self.write_file(mod_fn, """
227 228 x = 10
228 229
229 230 def foo(y):
230 231 return y + 4
231 232
232 233 class Baz(object):
233 234 def __init__(self, x):
234 235 self.x = x
235 236 def bar(self, y):
236 237 return self.x + y + 1
237 238 @property
238 239 def quux(self):
239 240 return 43
240 241
241 242 class Bar: # old-style class
242 243 def foo(self):
243 244 return 2
244 245 """)
245 246
246 247 def check_module_contents():
247 248 nt.assert_equal(mod.x, 10)
248 249 nt.assert_false(hasattr(mod, 'z'))
249 250
250 251 nt.assert_equal(old_foo(0), 4) # superreload magic!
251 252 nt.assert_equal(mod.foo(0), 4)
252 253
253 254 obj = mod.Baz(9)
254 255 nt.assert_equal(old_obj.bar(1), 11) # superreload magic!
255 256 nt.assert_equal(obj.bar(1), 11)
256 257
257 258 nt.assert_equal(old_obj.quux, 43)
258 259 nt.assert_equal(obj.quux, 43)
259 260
260 261 nt.assert_false(hasattr(old_obj, 'zzz'))
261 262 nt.assert_false(hasattr(obj, 'zzz'))
262 263
263 264 obj2 = mod.Bar()
264 265 nt.assert_equal(old_obj2.foo(), 2)
265 266 nt.assert_equal(obj2.foo(), 2)
266 267
267 268 self.shell.run_code("pass") # trigger reload
268 269 check_module_contents()
269 270
270 271 #
271 272 # Another failure case: deleted file (shouldn't reload)
272 273 #
273 274 os.unlink(mod_fn)
274 275
275 276 self.shell.run_code("pass") # trigger reload
276 277 check_module_contents()
277 278
278 279 #
279 280 # Disable autoreload and rewrite module: no reload should occur
280 281 #
281 282 if use_aimport:
282 283 self.shell.magic_aimport("-" + mod_name)
283 284 stream = StringIO()
284 285 self.shell.magic_aimport("", stream=stream)
285 286 nt.assert_true(("Modules to skip:\n%s" % mod_name) in
286 287 stream.getvalue())
287 288
288 289 # This should succeed, although no such module exists
289 290 self.shell.magic_aimport("-tmpmod_as318989e89ds")
290 291 else:
291 292 self.shell.magic_autoreload("0")
292 293
293 294 self.write_file(mod_fn, """
294 295 x = -99
295 296 """)
296 297
297 298 self.shell.run_code("pass") # trigger reload
298 299 self.shell.run_code("pass")
299 300 check_module_contents()
300 301
301 302 #
302 303 # Re-enable autoreload: reload should now occur
303 304 #
304 305 if use_aimport:
305 306 self.shell.magic_aimport(mod_name)
306 307 else:
307 308 self.shell.magic_autoreload("")
308 309
309 310 self.shell.run_code("pass") # trigger reload
310 311 nt.assert_equal(mod.x, -99)
311 312
312 313 def test_smoketest_aimport(self):
313 314 self._check_smoketest(use_aimport=True)
314 315
315 316 def test_smoketest_autoreload(self):
316 317 self._check_smoketest(use_aimport=False)
General Comments 0
You need to be logged in to leave comments. Login now