##// END OF EJS Templates
Preserve function/method identity in magic decorators...
Nikita Kniazev -
Show More
@@ -1,717 +1,712
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 import os
15 15 import re
16 16 import sys
17 17 from getopt import getopt, GetoptError
18 18
19 19 from traitlets.config.configurable import Configurable
20 20 from . import oinspect
21 21 from .error import UsageError
22 22 from .inputtransformer2 import ESC_MAGIC, ESC_MAGIC2
23 from decorator import decorator
24 23 from ..utils.ipstruct import Struct
25 24 from ..utils.process import arg_split
26 25 from ..utils.text import dedent
27 26 from traitlets import Bool, Dict, Instance, observe
28 27 from logging import error
29 28
30 29 #-----------------------------------------------------------------------------
31 30 # Globals
32 31 #-----------------------------------------------------------------------------
33 32
34 33 # A dict we'll use for each class that has magics, used as temporary storage to
35 34 # pass information between the @line/cell_magic method decorators and the
36 35 # @magics_class class decorator, because the method decorators have no
37 36 # access to the class when they run. See for more details:
38 37 # http://stackoverflow.com/questions/2366713/can-a-python-decorator-of-an-instance-method-access-the-class
39 38
40 39 magics = dict(line={}, cell={})
41 40
42 41 magic_kinds = ('line', 'cell')
43 42 magic_spec = ('line', 'cell', 'line_cell')
44 43 magic_escapes = dict(line=ESC_MAGIC, cell=ESC_MAGIC2)
45 44
46 45 #-----------------------------------------------------------------------------
47 46 # Utility classes and functions
48 47 #-----------------------------------------------------------------------------
49 48
50 49 class Bunch: pass
51 50
52 51
53 52 def on_off(tag):
54 53 """Return an ON/OFF string for a 1/0 input. Simple utility function."""
55 54 return ['OFF','ON'][tag]
56 55
57 56
58 57 def compress_dhist(dh):
59 58 """Compress a directory history into a new one with at most 20 entries.
60 59
61 60 Return a new list made from the first and last 10 elements of dhist after
62 61 removal of duplicates.
63 62 """
64 63 head, tail = dh[:-10], dh[-10:]
65 64
66 65 newhead = []
67 66 done = set()
68 67 for h in head:
69 68 if h in done:
70 69 continue
71 70 newhead.append(h)
72 71 done.add(h)
73 72
74 73 return newhead + tail
75 74
76 75
77 76 def needs_local_scope(func):
78 77 """Decorator to mark magic functions which need to local scope to run."""
79 78 func.needs_local_scope = True
80 79 return func
81 80
82 81 #-----------------------------------------------------------------------------
83 82 # Class and method decorators for registering magics
84 83 #-----------------------------------------------------------------------------
85 84
86 85 def magics_class(cls):
87 86 """Class decorator for all subclasses of the main Magics class.
88 87
89 88 Any class that subclasses Magics *must* also apply this decorator, to
90 89 ensure that all the methods that have been decorated as line/cell magics
91 90 get correctly registered in the class instance. This is necessary because
92 91 when method decorators run, the class does not exist yet, so they
93 92 temporarily store their information into a module global. Application of
94 93 this class decorator copies that global data to the class instance and
95 94 clears the global.
96 95
97 96 Obviously, this mechanism is not thread-safe, which means that the
98 97 *creation* of subclasses of Magic should only be done in a single-thread
99 98 context. Instantiation of the classes has no restrictions. Given that
100 99 these classes are typically created at IPython startup time and before user
101 100 application code becomes active, in practice this should not pose any
102 101 problems.
103 102 """
104 103 cls.registered = True
105 104 cls.magics = dict(line = magics['line'],
106 105 cell = magics['cell'])
107 106 magics['line'] = {}
108 107 magics['cell'] = {}
109 108 return cls
110 109
111 110
112 111 def record_magic(dct, magic_kind, magic_name, func):
113 112 """Utility function to store a function as a magic of a specific kind.
114 113
115 114 Parameters
116 115 ----------
117 116 dct : dict
118 117 A dictionary with 'line' and 'cell' subdicts.
119 118
120 119 magic_kind : str
121 120 Kind of magic to be stored.
122 121
123 122 magic_name : str
124 123 Key to store the magic as.
125 124
126 125 func : function
127 126 Callable object to store.
128 127 """
129 128 if magic_kind == 'line_cell':
130 129 dct['line'][magic_name] = dct['cell'][magic_name] = func
131 130 else:
132 131 dct[magic_kind][magic_name] = func
133 132
134 133
135 134 def validate_type(magic_kind):
136 135 """Ensure that the given magic_kind is valid.
137 136
138 137 Check that the given magic_kind is one of the accepted spec types (stored
139 138 in the global `magic_spec`), raise ValueError otherwise.
140 139 """
141 140 if magic_kind not in magic_spec:
142 141 raise ValueError('magic_kind must be one of %s, %s given' %
143 142 magic_kinds, magic_kind)
144 143
145 144
146 145 # The docstrings for the decorator below will be fairly similar for the two
147 146 # types (method and function), so we generate them here once and reuse the
148 147 # templates below.
149 148 _docstring_template = \
150 149 """Decorate the given {0} as {1} magic.
151 150
152 151 The decorator can be used with or without arguments, as follows.
153 152
154 153 i) without arguments: it will create a {1} magic named as the {0} being
155 154 decorated::
156 155
157 156 @deco
158 157 def foo(...)
159 158
160 159 will create a {1} magic named `foo`.
161 160
162 161 ii) with one string argument: which will be used as the actual name of the
163 162 resulting magic::
164 163
165 164 @deco('bar')
166 165 def foo(...)
167 166
168 167 will create a {1} magic named `bar`.
169 168
170 169 To register a class magic use ``Interactiveshell.register_magic(class or instance)``.
171 170 """
172 171
173 172 # These two are decorator factories. While they are conceptually very similar,
174 173 # there are enough differences in the details that it's simpler to have them
175 174 # written as completely standalone functions rather than trying to share code
176 175 # and make a single one with convoluted logic.
177 176
178 177 def _method_magic_marker(magic_kind):
179 178 """Decorator factory for methods in Magics subclasses.
180 179 """
181 180
182 181 validate_type(magic_kind)
183 182
184 183 # This is a closure to capture the magic_kind. We could also use a class,
185 184 # but it's overkill for just that one bit of state.
186 185 def magic_deco(arg):
187 call = lambda f, *a, **k: f(*a, **k)
188
189 186 if callable(arg):
190 187 # "Naked" decorator call (just @foo, no args)
191 188 func = arg
192 189 name = func.__name__
193 retval = decorator(call, func)
190 retval = arg
194 191 record_magic(magics, magic_kind, name, name)
195 192 elif isinstance(arg, str):
196 193 # Decorator called with arguments (@foo('bar'))
197 194 name = arg
198 195 def mark(func, *a, **kw):
199 196 record_magic(magics, magic_kind, name, func.__name__)
200 return decorator(call, func)
197 return func
201 198 retval = mark
202 199 else:
203 200 raise TypeError("Decorator can only be called with "
204 201 "string or function")
205 202 return retval
206 203
207 204 # Ensure the resulting decorator has a usable docstring
208 205 magic_deco.__doc__ = _docstring_template.format('method', magic_kind)
209 206 return magic_deco
210 207
211 208
212 209 def _function_magic_marker(magic_kind):
213 210 """Decorator factory for standalone functions.
214 211 """
215 212 validate_type(magic_kind)
216 213
217 214 # This is a closure to capture the magic_kind. We could also use a class,
218 215 # but it's overkill for just that one bit of state.
219 216 def magic_deco(arg):
220 call = lambda f, *a, **k: f(*a, **k)
221
222 217 # Find get_ipython() in the caller's namespace
223 218 caller = sys._getframe(1)
224 219 for ns in ['f_locals', 'f_globals', 'f_builtins']:
225 220 get_ipython = getattr(caller, ns).get('get_ipython')
226 221 if get_ipython is not None:
227 222 break
228 223 else:
229 224 raise NameError('Decorator can only run in context where '
230 225 '`get_ipython` exists')
231 226
232 227 ip = get_ipython()
233 228
234 229 if callable(arg):
235 230 # "Naked" decorator call (just @foo, no args)
236 231 func = arg
237 232 name = func.__name__
238 233 ip.register_magic_function(func, magic_kind, name)
239 retval = decorator(call, func)
234 retval = arg
240 235 elif isinstance(arg, str):
241 236 # Decorator called with arguments (@foo('bar'))
242 237 name = arg
243 238 def mark(func, *a, **kw):
244 239 ip.register_magic_function(func, magic_kind, name)
245 return decorator(call, func)
240 return func
246 241 retval = mark
247 242 else:
248 243 raise TypeError("Decorator can only be called with "
249 244 "string or function")
250 245 return retval
251 246
252 247 # Ensure the resulting decorator has a usable docstring
253 248 ds = _docstring_template.format('function', magic_kind)
254 249
255 250 ds += dedent("""
256 251 Note: this decorator can only be used in a context where IPython is already
257 252 active, so that the `get_ipython()` call succeeds. You can therefore use
258 253 it in your startup files loaded after IPython initializes, but *not* in the
259 254 IPython configuration file itself, which is executed before IPython is
260 255 fully up and running. Any file located in the `startup` subdirectory of
261 256 your configuration profile will be OK in this sense.
262 257 """)
263 258
264 259 magic_deco.__doc__ = ds
265 260 return magic_deco
266 261
267 262
268 263 MAGIC_NO_VAR_EXPAND_ATTR = '_ipython_magic_no_var_expand'
269 264
270 265
271 266 def no_var_expand(magic_func):
272 267 """Mark a magic function as not needing variable expansion
273 268
274 269 By default, IPython interprets `{a}` or `$a` in the line passed to magics
275 270 as variables that should be interpolated from the interactive namespace
276 271 before passing the line to the magic function.
277 272 This is not always desirable, e.g. when the magic executes Python code
278 273 (%timeit, %time, etc.).
279 274 Decorate magics with `@no_var_expand` to opt-out of variable expansion.
280 275
281 276 .. versionadded:: 7.3
282 277 """
283 278 setattr(magic_func, MAGIC_NO_VAR_EXPAND_ATTR, True)
284 279 return magic_func
285 280
286 281
287 282 # Create the actual decorators for public use
288 283
289 284 # These three are used to decorate methods in class definitions
290 285 line_magic = _method_magic_marker('line')
291 286 cell_magic = _method_magic_marker('cell')
292 287 line_cell_magic = _method_magic_marker('line_cell')
293 288
294 289 # These three decorate standalone functions and perform the decoration
295 290 # immediately. They can only run where get_ipython() works
296 291 register_line_magic = _function_magic_marker('line')
297 292 register_cell_magic = _function_magic_marker('cell')
298 293 register_line_cell_magic = _function_magic_marker('line_cell')
299 294
300 295 #-----------------------------------------------------------------------------
301 296 # Core Magic classes
302 297 #-----------------------------------------------------------------------------
303 298
304 299 class MagicsManager(Configurable):
305 300 """Object that handles all magic-related functionality for IPython.
306 301 """
307 302 # Non-configurable class attributes
308 303
309 304 # A two-level dict, first keyed by magic type, then by magic function, and
310 305 # holding the actual callable object as value. This is the dict used for
311 306 # magic function dispatch
312 307 magics = Dict()
313 308
314 309 # A registry of the original objects that we've been given holding magics.
315 310 registry = Dict()
316 311
317 312 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
318 313
319 314 auto_magic = Bool(True, help=
320 315 "Automatically call line magics without requiring explicit % prefix"
321 316 ).tag(config=True)
322 317 @observe('auto_magic')
323 318 def _auto_magic_changed(self, change):
324 319 self.shell.automagic = change['new']
325 320
326 321 _auto_status = [
327 322 'Automagic is OFF, % prefix IS needed for line magics.',
328 323 'Automagic is ON, % prefix IS NOT needed for line magics.']
329 324
330 325 user_magics = Instance('IPython.core.magics.UserMagics', allow_none=True)
331 326
332 327 def __init__(self, shell=None, config=None, user_magics=None, **traits):
333 328
334 329 super(MagicsManager, self).__init__(shell=shell, config=config,
335 330 user_magics=user_magics, **traits)
336 331 self.magics = dict(line={}, cell={})
337 332 # Let's add the user_magics to the registry for uniformity, so *all*
338 333 # registered magic containers can be found there.
339 334 self.registry[user_magics.__class__.__name__] = user_magics
340 335
341 336 def auto_status(self):
342 337 """Return descriptive string with automagic status."""
343 338 return self._auto_status[self.auto_magic]
344 339
345 340 def lsmagic(self):
346 341 """Return a dict of currently available magic functions.
347 342
348 343 The return dict has the keys 'line' and 'cell', corresponding to the
349 344 two types of magics we support. Each value is a list of names.
350 345 """
351 346 return self.magics
352 347
353 348 def lsmagic_docs(self, brief=False, missing=''):
354 349 """Return dict of documentation of magic functions.
355 350
356 351 The return dict has the keys 'line' and 'cell', corresponding to the
357 352 two types of magics we support. Each value is a dict keyed by magic
358 353 name whose value is the function docstring. If a docstring is
359 354 unavailable, the value of `missing` is used instead.
360 355
361 356 If brief is True, only the first line of each docstring will be returned.
362 357 """
363 358 docs = {}
364 359 for m_type in self.magics:
365 360 m_docs = {}
366 361 for m_name, m_func in self.magics[m_type].items():
367 362 if m_func.__doc__:
368 363 if brief:
369 364 m_docs[m_name] = m_func.__doc__.split('\n', 1)[0]
370 365 else:
371 366 m_docs[m_name] = m_func.__doc__.rstrip()
372 367 else:
373 368 m_docs[m_name] = missing
374 369 docs[m_type] = m_docs
375 370 return docs
376 371
377 372 def register(self, *magic_objects):
378 373 """Register one or more instances of Magics.
379 374
380 375 Take one or more classes or instances of classes that subclass the main
381 376 `core.Magic` class, and register them with IPython to use the magic
382 377 functions they provide. The registration process will then ensure that
383 378 any methods that have decorated to provide line and/or cell magics will
384 379 be recognized with the `%x`/`%%x` syntax as a line/cell magic
385 380 respectively.
386 381
387 382 If classes are given, they will be instantiated with the default
388 383 constructor. If your classes need a custom constructor, you should
389 384 instanitate them first and pass the instance.
390 385
391 386 The provided arguments can be an arbitrary mix of classes and instances.
392 387
393 388 Parameters
394 389 ----------
395 390 magic_objects : one or more classes or instances
396 391 """
397 392 # Start by validating them to ensure they have all had their magic
398 393 # methods registered at the instance level
399 394 for m in magic_objects:
400 395 if not m.registered:
401 396 raise ValueError("Class of magics %r was constructed without "
402 397 "the @register_magics class decorator")
403 398 if isinstance(m, type):
404 399 # If we're given an uninstantiated class
405 400 m = m(shell=self.shell)
406 401
407 402 # Now that we have an instance, we can register it and update the
408 403 # table of callables
409 404 self.registry[m.__class__.__name__] = m
410 405 for mtype in magic_kinds:
411 406 self.magics[mtype].update(m.magics[mtype])
412 407
413 408 def register_function(self, func, magic_kind='line', magic_name=None):
414 409 """Expose a standalone function as magic function for IPython.
415 410
416 411 This will create an IPython magic (line, cell or both) from a
417 412 standalone function. The functions should have the following
418 413 signatures:
419 414
420 415 * For line magics: `def f(line)`
421 416 * For cell magics: `def f(line, cell)`
422 417 * For a function that does both: `def f(line, cell=None)`
423 418
424 419 In the latter case, the function will be called with `cell==None` when
425 420 invoked as `%f`, and with cell as a string when invoked as `%%f`.
426 421
427 422 Parameters
428 423 ----------
429 424 func : callable
430 425 Function to be registered as a magic.
431 426
432 427 magic_kind : str
433 428 Kind of magic, one of 'line', 'cell' or 'line_cell'
434 429
435 430 magic_name : optional str
436 431 If given, the name the magic will have in the IPython namespace. By
437 432 default, the name of the function itself is used.
438 433 """
439 434
440 435 # Create the new method in the user_magics and register it in the
441 436 # global table
442 437 validate_type(magic_kind)
443 438 magic_name = func.__name__ if magic_name is None else magic_name
444 439 setattr(self.user_magics, magic_name, func)
445 440 record_magic(self.magics, magic_kind, magic_name, func)
446 441
447 442 def register_alias(self, alias_name, magic_name, magic_kind='line', magic_params=None):
448 443 """Register an alias to a magic function.
449 444
450 445 The alias is an instance of :class:`MagicAlias`, which holds the
451 446 name and kind of the magic it should call. Binding is done at
452 447 call time, so if the underlying magic function is changed the alias
453 448 will call the new function.
454 449
455 450 Parameters
456 451 ----------
457 452 alias_name : str
458 453 The name of the magic to be registered.
459 454
460 455 magic_name : str
461 456 The name of an existing magic.
462 457
463 458 magic_kind : str
464 459 Kind of magic, one of 'line' or 'cell'
465 460 """
466 461
467 462 # `validate_type` is too permissive, as it allows 'line_cell'
468 463 # which we do not handle.
469 464 if magic_kind not in magic_kinds:
470 465 raise ValueError('magic_kind must be one of %s, %s given' %
471 466 magic_kinds, magic_kind)
472 467
473 468 alias = MagicAlias(self.shell, magic_name, magic_kind, magic_params)
474 469 setattr(self.user_magics, alias_name, alias)
475 470 record_magic(self.magics, magic_kind, alias_name, alias)
476 471
477 472 # Key base class that provides the central functionality for magics.
478 473
479 474
480 475 class Magics(Configurable):
481 476 """Base class for implementing magic functions.
482 477
483 478 Shell functions which can be reached as %function_name. All magic
484 479 functions should accept a string, which they can parse for their own
485 480 needs. This can make some functions easier to type, eg `%cd ../`
486 481 vs. `%cd("../")`
487 482
488 483 Classes providing magic functions need to subclass this class, and they
489 484 MUST:
490 485
491 486 - Use the method decorators `@line_magic` and `@cell_magic` to decorate
492 487 individual methods as magic functions, AND
493 488
494 489 - Use the class decorator `@magics_class` to ensure that the magic
495 490 methods are properly registered at the instance level upon instance
496 491 initialization.
497 492
498 493 See :mod:`magic_functions` for examples of actual implementation classes.
499 494 """
500 495 # Dict holding all command-line options for each magic.
501 496 options_table = None
502 497 # Dict for the mapping of magic names to methods, set by class decorator
503 498 magics = None
504 499 # Flag to check that the class decorator was properly applied
505 500 registered = False
506 501 # Instance of IPython shell
507 502 shell = None
508 503
509 504 def __init__(self, shell=None, **kwargs):
510 505 if not(self.__class__.registered):
511 506 raise ValueError('Magics subclass without registration - '
512 507 'did you forget to apply @magics_class?')
513 508 if shell is not None:
514 509 if hasattr(shell, 'configurables'):
515 510 shell.configurables.append(self)
516 511 if hasattr(shell, 'config'):
517 512 kwargs.setdefault('parent', shell)
518 513
519 514 self.shell = shell
520 515 self.options_table = {}
521 516 # The method decorators are run when the instance doesn't exist yet, so
522 517 # they can only record the names of the methods they are supposed to
523 518 # grab. Only now, that the instance exists, can we create the proper
524 519 # mapping to bound methods. So we read the info off the original names
525 520 # table and replace each method name by the actual bound method.
526 521 # But we mustn't clobber the *class* mapping, in case of multiple instances.
527 522 class_magics = self.magics
528 523 self.magics = {}
529 524 for mtype in magic_kinds:
530 525 tab = self.magics[mtype] = {}
531 526 cls_tab = class_magics[mtype]
532 527 for magic_name, meth_name in cls_tab.items():
533 528 if isinstance(meth_name, str):
534 529 # it's a method name, grab it
535 530 tab[magic_name] = getattr(self, meth_name)
536 531 else:
537 532 # it's the real thing
538 533 tab[magic_name] = meth_name
539 534 # Configurable **needs** to be initiated at the end or the config
540 535 # magics get screwed up.
541 536 super(Magics, self).__init__(**kwargs)
542 537
543 538 def arg_err(self,func):
544 539 """Print docstring if incorrect arguments were passed"""
545 540 print('Error in arguments:')
546 541 print(oinspect.getdoc(func))
547 542
548 543 def format_latex(self, strng):
549 544 """Format a string for latex inclusion."""
550 545
551 546 # Characters that need to be escaped for latex:
552 547 escape_re = re.compile(r'(%|_|\$|#|&)',re.MULTILINE)
553 548 # Magic command names as headers:
554 549 cmd_name_re = re.compile(r'^(%s.*?):' % ESC_MAGIC,
555 550 re.MULTILINE)
556 551 # Magic commands
557 552 cmd_re = re.compile(r'(?P<cmd>%s.+?\b)(?!\}\}:)' % ESC_MAGIC,
558 553 re.MULTILINE)
559 554 # Paragraph continue
560 555 par_re = re.compile(r'\\$',re.MULTILINE)
561 556
562 557 # The "\n" symbol
563 558 newline_re = re.compile(r'\\n')
564 559
565 560 # Now build the string for output:
566 561 #strng = cmd_name_re.sub(r'\n\\texttt{\\textsl{\\large \1}}:',strng)
567 562 strng = cmd_name_re.sub(r'\n\\bigskip\n\\texttt{\\textbf{ \1}}:',
568 563 strng)
569 564 strng = cmd_re.sub(r'\\texttt{\g<cmd>}',strng)
570 565 strng = par_re.sub(r'\\\\',strng)
571 566 strng = escape_re.sub(r'\\\1',strng)
572 567 strng = newline_re.sub(r'\\textbackslash{}n',strng)
573 568 return strng
574 569
575 570 def parse_options(self, arg_str, opt_str, *long_opts, **kw):
576 571 """Parse options passed to an argument string.
577 572
578 573 The interface is similar to that of :func:`getopt.getopt`, but it
579 574 returns a :class:`~IPython.utils.struct.Struct` with the options as keys
580 575 and the stripped argument string still as a string.
581 576
582 577 arg_str is quoted as a true sys.argv vector by using shlex.split.
583 578 This allows us to easily expand variables, glob files, quote
584 579 arguments, etc.
585 580
586 581 Parameters
587 582 ----------
588 583
589 584 arg_str : str
590 585 The arguments to parse.
591 586
592 587 opt_str : str
593 588 The options specification.
594 589
595 590 mode : str, default 'string'
596 591 If given as 'list', the argument string is returned as a list (split
597 592 on whitespace) instead of a string.
598 593
599 594 list_all : bool, default False
600 595 Put all option values in lists. Normally only options
601 596 appearing more than once are put in a list.
602 597
603 598 posix : bool, default True
604 599 Whether to split the input line in POSIX mode or not, as per the
605 600 conventions outlined in the :mod:`shlex` module from the standard
606 601 library.
607 602 """
608 603
609 604 # inject default options at the beginning of the input line
610 605 caller = sys._getframe(1).f_code.co_name
611 606 arg_str = '%s %s' % (self.options_table.get(caller,''),arg_str)
612 607
613 608 mode = kw.get('mode','string')
614 609 if mode not in ['string','list']:
615 610 raise ValueError('incorrect mode given: %s' % mode)
616 611 # Get options
617 612 list_all = kw.get('list_all',0)
618 613 posix = kw.get('posix', os.name == 'posix')
619 614 strict = kw.get('strict', True)
620 615
621 616 preserve_non_opts = kw.get("preserve_non_opts", False)
622 617 remainder_arg_str = arg_str
623 618
624 619 # Check if we have more than one argument to warrant extra processing:
625 620 odict = {} # Dictionary with options
626 621 args = arg_str.split()
627 622 if len(args) >= 1:
628 623 # If the list of inputs only has 0 or 1 thing in it, there's no
629 624 # need to look for options
630 625 argv = arg_split(arg_str, posix, strict)
631 626 # Do regular option processing
632 627 try:
633 628 opts,args = getopt(argv, opt_str, long_opts)
634 629 except GetoptError as e:
635 630 raise UsageError(
636 631 '%s ( allowed: "%s" %s)' % (e.msg, opt_str, " ".join(long_opts))
637 632 ) from e
638 633 for o, a in opts:
639 634 if mode == "string" and preserve_non_opts:
640 635 # remove option-parts from the original args-string and preserve remaining-part.
641 636 # This relies on the arg_split(...) and getopt(...)'s impl spec, that the parsed options are
642 637 # returned in the original order.
643 638 remainder_arg_str = remainder_arg_str.replace(o, "", 1).replace(
644 639 a, "", 1
645 640 )
646 641 if o.startswith("--"):
647 642 o = o[2:]
648 643 else:
649 644 o = o[1:]
650 645 try:
651 646 odict[o].append(a)
652 647 except AttributeError:
653 648 odict[o] = [odict[o],a]
654 649 except KeyError:
655 650 if list_all:
656 651 odict[o] = [a]
657 652 else:
658 653 odict[o] = a
659 654
660 655 # Prepare opts,args for return
661 656 opts = Struct(odict)
662 657 if mode == 'string':
663 658 if preserve_non_opts:
664 659 args = remainder_arg_str.lstrip()
665 660 else:
666 661 args = " ".join(args)
667 662
668 663 return opts,args
669 664
670 665 def default_option(self, fn, optstr):
671 666 """Make an entry in the options_table for fn, with value optstr"""
672 667
673 668 if fn not in self.lsmagic():
674 669 error("%s is not a magic function" % fn)
675 670 self.options_table[fn] = optstr
676 671
677 672
678 673 class MagicAlias(object):
679 674 """An alias to another magic function.
680 675
681 676 An alias is determined by its magic name and magic kind. Lookup
682 677 is done at call time, so if the underlying magic changes the alias
683 678 will call the new function.
684 679
685 680 Use the :meth:`MagicsManager.register_alias` method or the
686 681 `%alias_magic` magic function to create and register a new alias.
687 682 """
688 683 def __init__(self, shell, magic_name, magic_kind, magic_params=None):
689 684 self.shell = shell
690 685 self.magic_name = magic_name
691 686 self.magic_params = magic_params
692 687 self.magic_kind = magic_kind
693 688
694 689 self.pretty_target = '%s%s' % (magic_escapes[self.magic_kind], self.magic_name)
695 690 self.__doc__ = "Alias for `%s`." % self.pretty_target
696 691
697 692 self._in_call = False
698 693
699 694 def __call__(self, *args, **kwargs):
700 695 """Call the magic alias."""
701 696 fn = self.shell.find_magic(self.magic_name, self.magic_kind)
702 697 if fn is None:
703 698 raise UsageError("Magic `%s` not found." % self.pretty_target)
704 699
705 700 # Protect against infinite recursion.
706 701 if self._in_call:
707 702 raise UsageError("Infinite recursion detected; "
708 703 "magic aliases cannot call themselves.")
709 704 self._in_call = True
710 705 try:
711 706 if self.magic_params:
712 707 args_list = list(args)
713 708 args_list[0] = self.magic_params + " " + args[0]
714 709 args = tuple(args_list)
715 710 return fn(*args, **kwargs)
716 711 finally:
717 712 self._in_call = False
@@ -1,664 +1,665
1 1 """Implementation of basic magic functions."""
2 2
3 3
4 4 import argparse
5 5 from logging import error
6 6 import io
7 7 from pprint import pformat
8 8 import sys
9 9 from warnings import warn
10 10
11 11 from traitlets.utils.importstring import import_item
12 12 from IPython.core import magic_arguments, page
13 13 from IPython.core.error import UsageError
14 14 from IPython.core.magic import Magics, magics_class, line_magic, magic_escapes
15 15 from IPython.utils.text import format_screen, dedent, indent
16 16 from IPython.testing.skipdoctest import skip_doctest
17 17 from IPython.utils.ipstruct import Struct
18 18
19 19
20 20 class MagicsDisplay(object):
21 21 def __init__(self, magics_manager, ignore=None):
22 22 self.ignore = ignore if ignore else []
23 23 self.magics_manager = magics_manager
24 24
25 25 def _lsmagic(self):
26 26 """The main implementation of the %lsmagic"""
27 27 mesc = magic_escapes['line']
28 28 cesc = magic_escapes['cell']
29 29 mman = self.magics_manager
30 30 magics = mman.lsmagic()
31 31 out = ['Available line magics:',
32 32 mesc + (' '+mesc).join(sorted([m for m,v in magics['line'].items() if (v not in self.ignore)])),
33 33 '',
34 34 'Available cell magics:',
35 35 cesc + (' '+cesc).join(sorted([m for m,v in magics['cell'].items() if (v not in self.ignore)])),
36 36 '',
37 37 mman.auto_status()]
38 38 return '\n'.join(out)
39 39
40 40 def _repr_pretty_(self, p, cycle):
41 41 p.text(self._lsmagic())
42 42
43 43 def __str__(self):
44 44 return self._lsmagic()
45 45
46 46 def _jsonable(self):
47 47 """turn magics dict into jsonable dict of the same structure
48 48
49 49 replaces object instances with their class names as strings
50 50 """
51 51 magic_dict = {}
52 52 mman = self.magics_manager
53 53 magics = mman.lsmagic()
54 54 for key, subdict in magics.items():
55 55 d = {}
56 56 magic_dict[key] = d
57 57 for name, obj in subdict.items():
58 58 try:
59 59 classname = obj.__self__.__class__.__name__
60 60 except AttributeError:
61 61 classname = 'Other'
62 62
63 63 d[name] = classname
64 64 return magic_dict
65 65
66 66 def _repr_json_(self):
67 67 return self._jsonable()
68 68
69 69
70 70 @magics_class
71 71 class BasicMagics(Magics):
72 72 """Magics that provide central IPython functionality.
73 73
74 74 These are various magics that don't fit into specific categories but that
75 75 are all part of the base 'IPython experience'."""
76 76
77 @skip_doctest
77 78 @magic_arguments.magic_arguments()
78 79 @magic_arguments.argument(
79 80 '-l', '--line', action='store_true',
80 81 help="""Create a line magic alias."""
81 82 )
82 83 @magic_arguments.argument(
83 84 '-c', '--cell', action='store_true',
84 85 help="""Create a cell magic alias."""
85 86 )
86 87 @magic_arguments.argument(
87 88 'name',
88 89 help="""Name of the magic to be created."""
89 90 )
90 91 @magic_arguments.argument(
91 92 'target',
92 93 help="""Name of the existing line or cell magic."""
93 94 )
94 95 @magic_arguments.argument(
95 96 '-p', '--params', default=None,
96 97 help="""Parameters passed to the magic function."""
97 98 )
98 99 @line_magic
99 100 def alias_magic(self, line=''):
100 101 """Create an alias for an existing line or cell magic.
101 102
102 103 Examples
103 104 --------
104 105 ::
105 106
106 107 In [1]: %alias_magic t timeit
107 108 Created `%t` as an alias for `%timeit`.
108 109 Created `%%t` as an alias for `%%timeit`.
109 110
110 111 In [2]: %t -n1 pass
111 112 1 loops, best of 3: 954 ns per loop
112 113
113 114 In [3]: %%t -n1
114 115 ...: pass
115 116 ...:
116 117 1 loops, best of 3: 954 ns per loop
117 118
118 119 In [4]: %alias_magic --cell whereami pwd
119 120 UsageError: Cell magic function `%%pwd` not found.
120 121 In [5]: %alias_magic --line whereami pwd
121 122 Created `%whereami` as an alias for `%pwd`.
122 123
123 124 In [6]: %whereami
124 125 Out[6]: u'/home/testuser'
125 126
126 127 In [7]: %alias_magic h history "-p -l 30" --line
127 128 Created `%h` as an alias for `%history -l 30`.
128 129 """
129 130
130 131 args = magic_arguments.parse_argstring(self.alias_magic, line)
131 132 shell = self.shell
132 133 mman = self.shell.magics_manager
133 134 escs = ''.join(magic_escapes.values())
134 135
135 136 target = args.target.lstrip(escs)
136 137 name = args.name.lstrip(escs)
137 138
138 139 params = args.params
139 140 if (params and
140 141 ((params.startswith('"') and params.endswith('"'))
141 142 or (params.startswith("'") and params.endswith("'")))):
142 143 params = params[1:-1]
143 144
144 145 # Find the requested magics.
145 146 m_line = shell.find_magic(target, 'line')
146 147 m_cell = shell.find_magic(target, 'cell')
147 148 if args.line and m_line is None:
148 149 raise UsageError('Line magic function `%s%s` not found.' %
149 150 (magic_escapes['line'], target))
150 151 if args.cell and m_cell is None:
151 152 raise UsageError('Cell magic function `%s%s` not found.' %
152 153 (magic_escapes['cell'], target))
153 154
154 155 # If --line and --cell are not specified, default to the ones
155 156 # that are available.
156 157 if not args.line and not args.cell:
157 158 if not m_line and not m_cell:
158 159 raise UsageError(
159 160 'No line or cell magic with name `%s` found.' % target
160 161 )
161 162 args.line = bool(m_line)
162 163 args.cell = bool(m_cell)
163 164
164 165 params_str = "" if params is None else " " + params
165 166
166 167 if args.line:
167 168 mman.register_alias(name, target, 'line', params)
168 169 print('Created `%s%s` as an alias for `%s%s%s`.' % (
169 170 magic_escapes['line'], name,
170 171 magic_escapes['line'], target, params_str))
171 172
172 173 if args.cell:
173 174 mman.register_alias(name, target, 'cell', params)
174 175 print('Created `%s%s` as an alias for `%s%s%s`.' % (
175 176 magic_escapes['cell'], name,
176 177 magic_escapes['cell'], target, params_str))
177 178
178 179 @line_magic
179 180 def lsmagic(self, parameter_s=''):
180 181 """List currently available magic functions."""
181 182 return MagicsDisplay(self.shell.magics_manager, ignore=[])
182 183
183 184 def _magic_docs(self, brief=False, rest=False):
184 185 """Return docstrings from magic functions."""
185 186 mman = self.shell.magics_manager
186 187 docs = mman.lsmagic_docs(brief, missing='No documentation')
187 188
188 189 if rest:
189 190 format_string = '**%s%s**::\n\n%s\n\n'
190 191 else:
191 192 format_string = '%s%s:\n%s\n'
192 193
193 194 return ''.join(
194 195 [format_string % (magic_escapes['line'], fname,
195 196 indent(dedent(fndoc)))
196 197 for fname, fndoc in sorted(docs['line'].items())]
197 198 +
198 199 [format_string % (magic_escapes['cell'], fname,
199 200 indent(dedent(fndoc)))
200 201 for fname, fndoc in sorted(docs['cell'].items())]
201 202 )
202 203
203 204 @line_magic
204 205 def magic(self, parameter_s=''):
205 206 """Print information about the magic function system.
206 207
207 208 Supported formats: -latex, -brief, -rest
208 209 """
209 210
210 211 mode = ''
211 212 try:
212 213 mode = parameter_s.split()[0][1:]
213 214 except IndexError:
214 215 pass
215 216
216 217 brief = (mode == 'brief')
217 218 rest = (mode == 'rest')
218 219 magic_docs = self._magic_docs(brief, rest)
219 220
220 221 if mode == 'latex':
221 222 print(self.format_latex(magic_docs))
222 223 return
223 224 else:
224 225 magic_docs = format_screen(magic_docs)
225 226
226 227 out = ["""
227 228 IPython's 'magic' functions
228 229 ===========================
229 230
230 231 The magic function system provides a series of functions which allow you to
231 232 control the behavior of IPython itself, plus a lot of system-type
232 233 features. There are two kinds of magics, line-oriented and cell-oriented.
233 234
234 235 Line magics are prefixed with the % character and work much like OS
235 236 command-line calls: they get as an argument the rest of the line, where
236 237 arguments are passed without parentheses or quotes. For example, this will
237 238 time the given statement::
238 239
239 240 %timeit range(1000)
240 241
241 242 Cell magics are prefixed with a double %%, and they are functions that get as
242 243 an argument not only the rest of the line, but also the lines below it in a
243 244 separate argument. These magics are called with two arguments: the rest of the
244 245 call line and the body of the cell, consisting of the lines below the first.
245 246 For example::
246 247
247 248 %%timeit x = numpy.random.randn((100, 100))
248 249 numpy.linalg.svd(x)
249 250
250 251 will time the execution of the numpy svd routine, running the assignment of x
251 252 as part of the setup phase, which is not timed.
252 253
253 254 In a line-oriented client (the terminal or Qt console IPython), starting a new
254 255 input with %% will automatically enter cell mode, and IPython will continue
255 256 reading input until a blank line is given. In the notebook, simply type the
256 257 whole cell as one entity, but keep in mind that the %% escape can only be at
257 258 the very start of the cell.
258 259
259 260 NOTE: If you have 'automagic' enabled (via the command line option or with the
260 261 %automagic function), you don't need to type in the % explicitly for line
261 262 magics; cell magics always require an explicit '%%' escape. By default,
262 263 IPython ships with automagic on, so you should only rarely need the % escape.
263 264
264 265 Example: typing '%cd mydir' (without the quotes) changes your working directory
265 266 to 'mydir', if it exists.
266 267
267 268 For a list of the available magic functions, use %lsmagic. For a description
268 269 of any of them, type %magic_name?, e.g. '%cd?'.
269 270
270 271 Currently the magic system has the following functions:""",
271 272 magic_docs,
272 273 "Summary of magic functions (from %slsmagic):" % magic_escapes['line'],
273 274 str(self.lsmagic()),
274 275 ]
275 276 page.page('\n'.join(out))
276 277
277 278
278 279 @line_magic
279 280 def page(self, parameter_s=''):
280 281 """Pretty print the object and display it through a pager.
281 282
282 283 %page [options] OBJECT
283 284
284 285 If no object is given, use _ (last output).
285 286
286 287 Options:
287 288
288 289 -r: page str(object), don't pretty-print it."""
289 290
290 291 # After a function contributed by Olivier Aubert, slightly modified.
291 292
292 293 # Process options/args
293 294 opts, args = self.parse_options(parameter_s, 'r')
294 295 raw = 'r' in opts
295 296
296 297 oname = args and args or '_'
297 298 info = self.shell._ofind(oname)
298 299 if info['found']:
299 300 txt = (raw and str or pformat)( info['obj'] )
300 301 page.page(txt)
301 302 else:
302 303 print('Object `%s` not found' % oname)
303 304
304 305 @line_magic
305 306 def pprint(self, parameter_s=''):
306 307 """Toggle pretty printing on/off."""
307 308 ptformatter = self.shell.display_formatter.formatters['text/plain']
308 309 ptformatter.pprint = bool(1 - ptformatter.pprint)
309 310 print('Pretty printing has been turned',
310 311 ['OFF','ON'][ptformatter.pprint])
311 312
312 313 @line_magic
313 314 def colors(self, parameter_s=''):
314 315 """Switch color scheme for prompts, info system and exception handlers.
315 316
316 317 Currently implemented schemes: NoColor, Linux, LightBG.
317 318
318 319 Color scheme names are not case-sensitive.
319 320
320 321 Examples
321 322 --------
322 323 To get a plain black and white terminal::
323 324
324 325 %colors nocolor
325 326 """
326 327 def color_switch_err(name):
327 328 warn('Error changing %s color schemes.\n%s' %
328 329 (name, sys.exc_info()[1]), stacklevel=2)
329 330
330 331
331 332 new_scheme = parameter_s.strip()
332 333 if not new_scheme:
333 334 raise UsageError(
334 335 "%colors: you must specify a color scheme. See '%colors?'")
335 336 # local shortcut
336 337 shell = self.shell
337 338
338 339 # Set shell colour scheme
339 340 try:
340 341 shell.colors = new_scheme
341 342 shell.refresh_style()
342 343 except:
343 344 color_switch_err('shell')
344 345
345 346 # Set exception colors
346 347 try:
347 348 shell.InteractiveTB.set_colors(scheme = new_scheme)
348 349 shell.SyntaxTB.set_colors(scheme = new_scheme)
349 350 except:
350 351 color_switch_err('exception')
351 352
352 353 # Set info (for 'object?') colors
353 354 if shell.color_info:
354 355 try:
355 356 shell.inspector.set_active_scheme(new_scheme)
356 357 except:
357 358 color_switch_err('object inspector')
358 359 else:
359 360 shell.inspector.set_active_scheme('NoColor')
360 361
361 362 @line_magic
362 363 def xmode(self, parameter_s=''):
363 364 """Switch modes for the exception handlers.
364 365
365 366 Valid modes: Plain, Context, Verbose, and Minimal.
366 367
367 368 If called without arguments, acts as a toggle.
368 369
369 370 When in verbose mode the value --show (and --hide)
370 371 will respectively show (or hide) frames with ``__tracebackhide__ =
371 372 True`` value set.
372 373 """
373 374
374 375 def xmode_switch_err(name):
375 376 warn('Error changing %s exception modes.\n%s' %
376 377 (name,sys.exc_info()[1]))
377 378
378 379 shell = self.shell
379 380 if parameter_s.strip() == "--show":
380 381 shell.InteractiveTB.skip_hidden = False
381 382 return
382 383 if parameter_s.strip() == "--hide":
383 384 shell.InteractiveTB.skip_hidden = True
384 385 return
385 386
386 387 new_mode = parameter_s.strip().capitalize()
387 388 try:
388 389 shell.InteractiveTB.set_mode(mode=new_mode)
389 390 print('Exception reporting mode:',shell.InteractiveTB.mode)
390 391 except:
391 392 xmode_switch_err('user')
392 393
393 394 @line_magic
394 395 def quickref(self, arg):
395 396 """ Show a quick reference sheet """
396 397 from IPython.core.usage import quick_reference
397 398 qr = quick_reference + self._magic_docs(brief=True)
398 399 page.page(qr)
399 400
400 401 @line_magic
401 402 def doctest_mode(self, parameter_s=''):
402 403 """Toggle doctest mode on and off.
403 404
404 405 This mode is intended to make IPython behave as much as possible like a
405 406 plain Python shell, from the perspective of how its prompts, exceptions
406 407 and output look. This makes it easy to copy and paste parts of a
407 408 session into doctests. It does so by:
408 409
409 410 - Changing the prompts to the classic ``>>>`` ones.
410 411 - Changing the exception reporting mode to 'Plain'.
411 412 - Disabling pretty-printing of output.
412 413
413 414 Note that IPython also supports the pasting of code snippets that have
414 415 leading '>>>' and '...' prompts in them. This means that you can paste
415 416 doctests from files or docstrings (even if they have leading
416 417 whitespace), and the code will execute correctly. You can then use
417 418 '%history -t' to see the translated history; this will give you the
418 419 input after removal of all the leading prompts and whitespace, which
419 420 can be pasted back into an editor.
420 421
421 422 With these features, you can switch into this mode easily whenever you
422 423 need to do testing and changes to doctests, without having to leave
423 424 your existing IPython session.
424 425 """
425 426
426 427 # Shorthands
427 428 shell = self.shell
428 429 meta = shell.meta
429 430 disp_formatter = self.shell.display_formatter
430 431 ptformatter = disp_formatter.formatters['text/plain']
431 432 # dstore is a data store kept in the instance metadata bag to track any
432 433 # changes we make, so we can undo them later.
433 434 dstore = meta.setdefault('doctest_mode',Struct())
434 435 save_dstore = dstore.setdefault
435 436
436 437 # save a few values we'll need to recover later
437 438 mode = save_dstore('mode',False)
438 439 save_dstore('rc_pprint',ptformatter.pprint)
439 440 save_dstore('xmode',shell.InteractiveTB.mode)
440 441 save_dstore('rc_separate_out',shell.separate_out)
441 442 save_dstore('rc_separate_out2',shell.separate_out2)
442 443 save_dstore('rc_separate_in',shell.separate_in)
443 444 save_dstore('rc_active_types',disp_formatter.active_types)
444 445
445 446 if not mode:
446 447 # turn on
447 448
448 449 # Prompt separators like plain python
449 450 shell.separate_in = ''
450 451 shell.separate_out = ''
451 452 shell.separate_out2 = ''
452 453
453 454
454 455 ptformatter.pprint = False
455 456 disp_formatter.active_types = ['text/plain']
456 457
457 458 shell.magic('xmode Plain')
458 459 else:
459 460 # turn off
460 461 shell.separate_in = dstore.rc_separate_in
461 462
462 463 shell.separate_out = dstore.rc_separate_out
463 464 shell.separate_out2 = dstore.rc_separate_out2
464 465
465 466 ptformatter.pprint = dstore.rc_pprint
466 467 disp_formatter.active_types = dstore.rc_active_types
467 468
468 469 shell.magic('xmode ' + dstore.xmode)
469 470
470 471 # mode here is the state before we switch; switch_doctest_mode takes
471 472 # the mode we're switching to.
472 473 shell.switch_doctest_mode(not mode)
473 474
474 475 # Store new mode and inform
475 476 dstore.mode = bool(not mode)
476 477 mode_label = ['OFF','ON'][dstore.mode]
477 478 print('Doctest mode is:', mode_label)
478 479
479 480 @line_magic
480 481 def gui(self, parameter_s=''):
481 482 """Enable or disable IPython GUI event loop integration.
482 483
483 484 %gui [GUINAME]
484 485
485 486 This magic replaces IPython's threaded shells that were activated
486 487 using the (pylab/wthread/etc.) command line flags. GUI toolkits
487 488 can now be enabled at runtime and keyboard
488 489 interrupts should work without any problems. The following toolkits
489 490 are supported: wxPython, PyQt4, PyGTK, Tk and Cocoa (OSX)::
490 491
491 492 %gui wx # enable wxPython event loop integration
492 493 %gui qt4|qt # enable PyQt4 event loop integration
493 494 %gui qt5 # enable PyQt5 event loop integration
494 495 %gui gtk # enable PyGTK event loop integration
495 496 %gui gtk3 # enable Gtk3 event loop integration
496 497 %gui gtk4 # enable Gtk4 event loop integration
497 498 %gui tk # enable Tk event loop integration
498 499 %gui osx # enable Cocoa event loop integration
499 500 # (requires %matplotlib 1.1)
500 501 %gui # disable all event loop integration
501 502
502 503 WARNING: after any of these has been called you can simply create
503 504 an application object, but DO NOT start the event loop yourself, as
504 505 we have already handled that.
505 506 """
506 507 opts, arg = self.parse_options(parameter_s, '')
507 508 if arg=='': arg = None
508 509 try:
509 510 return self.shell.enable_gui(arg)
510 511 except Exception as e:
511 512 # print simple error message, rather than traceback if we can't
512 513 # hook up the GUI
513 514 error(str(e))
514 515
515 516 @skip_doctest
516 517 @line_magic
517 518 def precision(self, s=''):
518 519 """Set floating point precision for pretty printing.
519 520
520 521 Can set either integer precision or a format string.
521 522
522 523 If numpy has been imported and precision is an int,
523 524 numpy display precision will also be set, via ``numpy.set_printoptions``.
524 525
525 526 If no argument is given, defaults will be restored.
526 527
527 528 Examples
528 529 --------
529 530 ::
530 531
531 532 In [1]: from math import pi
532 533
533 534 In [2]: %precision 3
534 535 Out[2]: u'%.3f'
535 536
536 537 In [3]: pi
537 538 Out[3]: 3.142
538 539
539 540 In [4]: %precision %i
540 541 Out[4]: u'%i'
541 542
542 543 In [5]: pi
543 544 Out[5]: 3
544 545
545 546 In [6]: %precision %e
546 547 Out[6]: u'%e'
547 548
548 549 In [7]: pi**10
549 550 Out[7]: 9.364805e+04
550 551
551 552 In [8]: %precision
552 553 Out[8]: u'%r'
553 554
554 555 In [9]: pi**10
555 556 Out[9]: 93648.047476082982
556 557 """
557 558 ptformatter = self.shell.display_formatter.formatters['text/plain']
558 559 ptformatter.float_precision = s
559 560 return ptformatter.float_format
560 561
561 562 @magic_arguments.magic_arguments()
562 563 @magic_arguments.argument(
563 564 '-e', '--export', action='store_true', default=False,
564 565 help=argparse.SUPPRESS
565 566 )
566 567 @magic_arguments.argument(
567 568 'filename', type=str,
568 569 help='Notebook name or filename'
569 570 )
570 571 @line_magic
571 572 def notebook(self, s):
572 573 """Export and convert IPython notebooks.
573 574
574 575 This function can export the current IPython history to a notebook file.
575 576 For example, to export the history to "foo.ipynb" do "%notebook foo.ipynb".
576 577
577 578 The -e or --export flag is deprecated in IPython 5.2, and will be
578 579 removed in the future.
579 580 """
580 581 args = magic_arguments.parse_argstring(self.notebook, s)
581 582
582 583 from nbformat import write, v4
583 584
584 585 cells = []
585 586 hist = list(self.shell.history_manager.get_range())
586 587 if(len(hist)<=1):
587 588 raise ValueError('History is empty, cannot export')
588 589 for session, execution_count, source in hist[:-1]:
589 590 cells.append(v4.new_code_cell(
590 591 execution_count=execution_count,
591 592 source=source
592 593 ))
593 594 nb = v4.new_notebook(cells=cells)
594 595 with io.open(args.filename, 'w', encoding='utf-8') as f:
595 596 write(nb, f, version=4)
596 597
597 598 @magics_class
598 599 class AsyncMagics(BasicMagics):
599 600
600 601 @line_magic
601 602 def autoawait(self, parameter_s):
602 603 """
603 604 Allow to change the status of the autoawait option.
604 605
605 606 This allow you to set a specific asynchronous code runner.
606 607
607 608 If no value is passed, print the currently used asynchronous integration
608 609 and whether it is activated.
609 610
610 611 It can take a number of value evaluated in the following order:
611 612
612 613 - False/false/off deactivate autoawait integration
613 614 - True/true/on activate autoawait integration using configured default
614 615 loop
615 616 - asyncio/curio/trio activate autoawait integration and use integration
616 617 with said library.
617 618
618 619 - `sync` turn on the pseudo-sync integration (mostly used for
619 620 `IPython.embed()` which does not run IPython with a real eventloop and
620 621 deactivate running asynchronous code. Turning on Asynchronous code with
621 622 the pseudo sync loop is undefined behavior and may lead IPython to crash.
622 623
623 624 If the passed parameter does not match any of the above and is a python
624 625 identifier, get said object from user namespace and set it as the
625 626 runner, and activate autoawait.
626 627
627 628 If the object is a fully qualified object name, attempt to import it and
628 629 set it as the runner, and activate autoawait.
629 630
630 631
631 632 The exact behavior of autoawait is experimental and subject to change
632 633 across version of IPython and Python.
633 634 """
634 635
635 636 param = parameter_s.strip()
636 637 d = {True: "on", False: "off"}
637 638
638 639 if not param:
639 640 print("IPython autoawait is `{}`, and set to use `{}`".format(
640 641 d[self.shell.autoawait],
641 642 self.shell.loop_runner
642 643 ))
643 644 return None
644 645
645 646 if param.lower() in ('false', 'off'):
646 647 self.shell.autoawait = False
647 648 return None
648 649 if param.lower() in ('true', 'on'):
649 650 self.shell.autoawait = True
650 651 return None
651 652
652 653 if param in self.shell.loop_runner_map:
653 654 self.shell.loop_runner, self.shell.autoawait = self.shell.loop_runner_map[param]
654 655 return None
655 656
656 657 if param in self.shell.user_ns :
657 658 self.shell.loop_runner = self.shell.user_ns[param]
658 659 self.shell.autoawait = True
659 660 return None
660 661
661 662 runner = import_item(param)
662 663
663 664 self.shell.loop_runner = runner
664 665 self.shell.autoawait = True
@@ -1,158 +1,187
1 1 """Implementation of configuration-related 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 re
17 17
18 18 # Our own packages
19 19 from IPython.core.error import UsageError
20 20 from IPython.core.magic import Magics, magics_class, line_magic
21 21 from logging import error
22 22
23 23 #-----------------------------------------------------------------------------
24 24 # Magic implementation classes
25 25 #-----------------------------------------------------------------------------
26 26
27 27 reg = re.compile(r'^\w+\.\w+$')
28 28 @magics_class
29 29 class ConfigMagics(Magics):
30 30
31 31 def __init__(self, shell):
32 32 super(ConfigMagics, self).__init__(shell)
33 33 self.configurables = []
34 34
35 35 @line_magic
36 36 def config(self, s):
37 37 """configure IPython
38 38
39 39 %config Class[.trait=value]
40 40
41 41 This magic exposes most of the IPython config system. Any
42 42 Configurable class should be able to be configured with the simple
43 43 line::
44 44
45 45 %config Class.trait=value
46 46
47 47 Where `value` will be resolved in the user's namespace, if it is an
48 48 expression or variable name.
49 49
50 50 Examples
51 51 --------
52 52
53 53 To see what classes are available for config, pass no arguments::
54 54
55 55 In [1]: %config
56 56 Available objects for config:
57 TerminalInteractiveShell
58 HistoryManager
59 PrefilterManager
60 57 AliasManager
61 IPCompleter
62 58 DisplayFormatter
59 HistoryManager
60 IPCompleter
61 LoggingMagics
62 MagicsManager
63 OSMagics
64 PrefilterManager
65 ScriptMagics
66 TerminalInteractiveShell
63 67
64 68 To view what is configurable on a given class, just pass the class
65 69 name::
66 70
67 71 In [2]: %config IPCompleter
68 IPCompleter options
69 -----------------
70 IPCompleter.omit__names=<Enum>
71 Current: 2
72 Choices: (0, 1, 2)
73 Instruct the completer to omit private method names
74 Specifically, when completing on ``object.<tab>``.
75 When 2 [default]: all names that start with '_' will be excluded.
76 When 1: all 'magic' names (``__foo__``) will be excluded.
77 When 0: nothing will be excluded.
78 IPCompleter.merge_completions=<CBool>
72 IPCompleter(Completer) options
73 ----------------------------
74 IPCompleter.backslash_combining_completions=<Bool>
75 Enable unicode completions, e.g. \\alpha<tab> . Includes completion of latex
76 commands, unicode names, and expanding unicode characters back to latex
77 commands.
79 78 Current: True
80 Whether to merge completion results into a single list
81 If False, only the completion results from the first non-empty
82 completer will be returned.
83 IPCompleter.limit_to__all__=<CBool>
79 IPCompleter.debug=<Bool>
80 Enable debug for the Completer. Mostly print extra information for
81 experimental jedi integration.
82 Current: False
83 IPCompleter.greedy=<Bool>
84 Activate greedy completion
85 PENDING DEPRECTION. this is now mostly taken care of with Jedi.
86 This will enable completion on elements of lists, results of function calls, etc.,
87 but can be unsafe because the code is actually evaluated on TAB.
84 88 Current: False
89 IPCompleter.jedi_compute_type_timeout=<Int>
90 Experimental: restrict time (in milliseconds) during which Jedi can compute types.
91 Set to 0 to stop computing types. Non-zero value lower than 100ms may hurt
92 performance by preventing jedi to build its cache.
93 Current: 400
94 IPCompleter.limit_to__all__=<Bool>
95 DEPRECATED as of version 5.0.
85 96 Instruct the completer to use __all__ for the completion
86 97 Specifically, when completing on ``object.<tab>``.
87 98 When True: only those names in obj.__all__ will be included.
88 99 When False [default]: the __all__ attribute is ignored
89 IPCompleter.greedy=<CBool>
90 100 Current: False
91 Activate greedy completion
92 This will enable completion on elements of lists, results of
93 function calls, etc., but can be unsafe because the code is
94 actually evaluated on TAB.
101 IPCompleter.merge_completions=<Bool>
102 Whether to merge completion results into a single list
103 If False, only the completion results from the first non-empty
104 completer will be returned.
105 Current: True
106 IPCompleter.omit__names=<Enum>
107 Instruct the completer to omit private method names
108 Specifically, when completing on ``object.<tab>``.
109 When 2 [default]: all names that start with '_' will be excluded.
110 When 1: all 'magic' names (``__foo__``) will be excluded.
111 When 0: nothing will be excluded.
112 Choices: any of [0, 1, 2]
113 Current: 2
114 IPCompleter.profile_completions=<Bool>
115 If True, emit profiling data for completion subsystem using cProfile.
116 Current: False
117 IPCompleter.profiler_output_dir=<Unicode>
118 Template for path at which to output profile data for completions.
119 Current: '.completion_profiles'
120 IPCompleter.use_jedi=<Bool>
121 Experimental: Use Jedi to generate autocompletions. Default to True if jedi
122 is installed.
123 Current: True
95 124
96 125 but the real use is in setting values::
97 126
98 127 In [3]: %config IPCompleter.greedy = True
99 128
100 129 and these values are read from the user_ns if they are variables::
101 130
102 131 In [4]: feeling_greedy=False
103 132
104 133 In [5]: %config IPCompleter.greedy = feeling_greedy
105 134
106 135 """
107 136 from traitlets.config.loader import Config
108 137 # some IPython objects are Configurable, but do not yet have
109 138 # any configurable traits. Exclude them from the effects of
110 139 # this magic, as their presence is just noise:
111 140 configurables = sorted(set([ c for c in self.shell.configurables
112 141 if c.__class__.class_traits(config=True)
113 142 ]), key=lambda x: x.__class__.__name__)
114 143 classnames = [ c.__class__.__name__ for c in configurables ]
115 144
116 145 line = s.strip()
117 146 if not line:
118 147 # print available configurable names
119 148 print("Available objects for config:")
120 149 for name in classnames:
121 print(" ", name)
150 print(" ", name)
122 151 return
123 152 elif line in classnames:
124 153 # `%config TerminalInteractiveShell` will print trait info for
125 154 # TerminalInteractiveShell
126 155 c = configurables[classnames.index(line)]
127 156 cls = c.__class__
128 157 help = cls.class_get_help(c)
129 158 # strip leading '--' from cl-args:
130 159 help = re.sub(re.compile(r'^--', re.MULTILINE), '', help)
131 160 print(help)
132 161 return
133 162 elif reg.match(line):
134 163 cls, attr = line.split('.')
135 164 return getattr(configurables[classnames.index(cls)],attr)
136 165 elif '=' not in line:
137 166 msg = "Invalid config statement: %r, "\
138 167 "should be `Class.trait = value`."
139 168
140 169 ll = line.lower()
141 170 for classname in classnames:
142 171 if ll == classname.lower():
143 172 msg = msg + '\nDid you mean %s (note the case)?' % classname
144 173 break
145 174
146 175 raise UsageError( msg % line)
147 176
148 177 # otherwise, assume we are setting configurables.
149 178 # leave quotes on args when splitting, because we want
150 179 # unquoted args to eval in user_ns
151 180 cfg = Config()
152 181 exec("cfg."+line, self.shell.user_ns, locals())
153 182
154 183 for configurable in configurables:
155 184 try:
156 185 configurable.update_config(cfg)
157 186 except Exception as e:
158 187 error(e)
@@ -1,355 +1,357
1 1 """Magic functions for running cells in various scripts."""
2 2
3 3 # Copyright (c) IPython Development Team.
4 4 # Distributed under the terms of the Modified BSD License.
5 5
6 6 import asyncio
7 7 import atexit
8 8 import errno
9 9 import functools
10 10 import os
11 11 import signal
12 12 import sys
13 13 import time
14 14 from contextlib import contextmanager
15 15 from subprocess import CalledProcessError
16 16
17 17 from traitlets import Dict, List, default
18 18
19 19 from IPython.core import magic_arguments
20 20 from IPython.core.magic import Magics, cell_magic, line_magic, magics_class
21 21 from IPython.lib.backgroundjobs import BackgroundJobManager
22 22 from IPython.utils.process import arg_split
23 23
24 24 #-----------------------------------------------------------------------------
25 25 # Magic implementation classes
26 26 #-----------------------------------------------------------------------------
27 27
28 28 def script_args(f):
29 29 """single decorator for adding script args"""
30 30 args = [
31 31 magic_arguments.argument(
32 32 '--out', type=str,
33 33 help="""The variable in which to store stdout from the script.
34 34 If the script is backgrounded, this will be the stdout *pipe*,
35 35 instead of the stderr text itself and will not be auto closed.
36 36 """
37 37 ),
38 38 magic_arguments.argument(
39 39 '--err', type=str,
40 40 help="""The variable in which to store stderr from the script.
41 41 If the script is backgrounded, this will be the stderr *pipe*,
42 42 instead of the stderr text itself and will not be autoclosed.
43 43 """
44 44 ),
45 45 magic_arguments.argument(
46 46 '--bg', action="store_true",
47 47 help="""Whether to run the script in the background.
48 48 If given, the only way to see the output of the command is
49 49 with --out/err.
50 50 """
51 51 ),
52 52 magic_arguments.argument(
53 53 '--proc', type=str,
54 54 help="""The variable in which to store Popen instance.
55 55 This is used only when --bg option is given.
56 56 """
57 57 ),
58 58 magic_arguments.argument(
59 59 '--no-raise-error', action="store_false", dest='raise_error',
60 60 help="""Whether you should raise an error message in addition to
61 61 a stream on stderr if you get a nonzero exit code.
62 62 """
63 63 )
64 64 ]
65 65 for arg in args:
66 66 f = arg(f)
67 67 return f
68 68
69 69
70 70 @contextmanager
71 71 def safe_watcher():
72 72 if sys.platform == "win32":
73 73 yield
74 74 return
75 75
76 76 from asyncio import SafeChildWatcher
77 77
78 78 policy = asyncio.get_event_loop_policy()
79 79 old_watcher = policy.get_child_watcher()
80 80 if isinstance(old_watcher, SafeChildWatcher):
81 81 yield
82 82 return
83 83
84 84 loop = policy.get_event_loop()
85 85 try:
86 86 watcher = asyncio.SafeChildWatcher()
87 87 watcher.attach_loop(loop)
88 88 policy.set_child_watcher(watcher)
89 89 yield
90 90 finally:
91 91 watcher.close()
92 92 policy.set_child_watcher(old_watcher)
93 93
94 94
95 95 def dec_safe_watcher(fun):
96 96 @functools.wraps(fun)
97 97 def _inner(*args, **kwargs):
98 98 with safe_watcher():
99 99 return fun(*args, **kwargs)
100 100
101 101 return _inner
102 102
103 103
104 104 @magics_class
105 105 class ScriptMagics(Magics):
106 106 """Magics for talking to scripts
107 107
108 108 This defines a base `%%script` cell magic for running a cell
109 109 with a program in a subprocess, and registers a few top-level
110 110 magics that call %%script with common interpreters.
111 111 """
112 112 script_magics = List(
113 113 help="""Extra script cell magics to define
114 114
115 115 This generates simple wrappers of `%%script foo` as `%%foo`.
116 116
117 117 If you want to add script magics that aren't on your path,
118 118 specify them in script_paths
119 119 """,
120 120 ).tag(config=True)
121 121 @default('script_magics')
122 122 def _script_magics_default(self):
123 123 """default to a common list of programs"""
124 124
125 125 defaults = [
126 126 'sh',
127 127 'bash',
128 128 'perl',
129 129 'ruby',
130 130 'python',
131 131 'python2',
132 132 'python3',
133 133 'pypy',
134 134 ]
135 135 if os.name == 'nt':
136 136 defaults.extend([
137 137 'cmd',
138 138 ])
139 139
140 140 return defaults
141 141
142 142 script_paths = Dict(
143 143 help="""Dict mapping short 'ruby' names to full paths, such as '/opt/secret/bin/ruby'
144 144
145 145 Only necessary for items in script_magics where the default path will not
146 146 find the right interpreter.
147 147 """
148 148 ).tag(config=True)
149 149
150 150 def __init__(self, shell=None):
151 151 super(ScriptMagics, self).__init__(shell=shell)
152 152 self._generate_script_magics()
153 153 self.job_manager = BackgroundJobManager()
154 154 self.bg_processes = []
155 155 atexit.register(self.kill_bg_processes)
156 156
157 157 def __del__(self):
158 158 self.kill_bg_processes()
159 159
160 160 def _generate_script_magics(self):
161 161 cell_magics = self.magics['cell']
162 162 for name in self.script_magics:
163 163 cell_magics[name] = self._make_script_magic(name)
164 164
165 165 def _make_script_magic(self, name):
166 166 """make a named magic, that calls %%script with a particular program"""
167 167 # expand to explicit path if necessary:
168 168 script = self.script_paths.get(name, name)
169 169
170 170 @magic_arguments.magic_arguments()
171 171 @script_args
172 172 def named_script_magic(line, cell):
173 173 # if line, add it as cl-flags
174 174 if line:
175 175 line = "%s %s" % (script, line)
176 176 else:
177 177 line = script
178 178 return self.shebang(line, cell)
179 179
180 180 # write a basic docstring:
181 181 named_script_magic.__doc__ = \
182 182 """%%{name} script magic
183 183
184 184 Run cells with {script} in a subprocess.
185 185
186 186 This is a shortcut for `%%script {script}`
187 187 """.format(**locals())
188 188
189 189 return named_script_magic
190 190
191 191 @magic_arguments.magic_arguments()
192 192 @script_args
193 193 @cell_magic("script")
194 194 @dec_safe_watcher
195 195 def shebang(self, line, cell):
196 196 """Run a cell via a shell command
197 197
198 198 The `%%script` line is like the #! line of script,
199 199 specifying a program (bash, perl, ruby, etc.) with which to run.
200 200
201 201 The rest of the cell is run by that program.
202 202
203 203 Examples
204 204 --------
205 205 ::
206 206
207 207 In [1]: %%script bash
208 208 ...: for i in 1 2 3; do
209 209 ...: echo $i
210 210 ...: done
211 211 1
212 212 2
213 213 3
214 214 """
215 215
216 216 async def _handle_stream(stream, stream_arg, file_object):
217 217 while True:
218 218 line = (await stream.readline()).decode("utf8")
219 219 if not line:
220 220 break
221 221 if stream_arg:
222 222 self.shell.user_ns[stream_arg] = line
223 223 else:
224 224 file_object.write(line)
225 225 file_object.flush()
226 226
227 227 async def _stream_communicate(process, cell):
228 228 process.stdin.write(cell)
229 229 process.stdin.close()
230 230 stdout_task = asyncio.create_task(
231 231 _handle_stream(process.stdout, args.out, sys.stdout)
232 232 )
233 233 stderr_task = asyncio.create_task(
234 234 _handle_stream(process.stderr, args.err, sys.stderr)
235 235 )
236 236 await asyncio.wait([stdout_task, stderr_task])
237 237 await process.wait()
238 238
239 239 if sys.platform.startswith("win"):
240 240 asyncio.set_event_loop_policy(asyncio.WindowsProactorEventLoopPolicy())
241 241 loop = asyncio.get_event_loop_policy().get_event_loop()
242 242 argv = arg_split(line, posix=not sys.platform.startswith("win"))
243 243 args, cmd = self.shebang.parser.parse_known_args(argv)
244 244 try:
245 245 p = loop.run_until_complete(
246 246 asyncio.create_subprocess_exec(
247 247 *cmd,
248 248 stdout=asyncio.subprocess.PIPE,
249 249 stderr=asyncio.subprocess.PIPE,
250 250 stdin=asyncio.subprocess.PIPE,
251 251 )
252 252 )
253 253 except OSError as e:
254 254 if e.errno == errno.ENOENT:
255 255 print("Couldn't find program: %r" % cmd[0])
256 256 return
257 257 else:
258 258 raise
259 259
260 260 if not cell.endswith('\n'):
261 261 cell += '\n'
262 262 cell = cell.encode('utf8', 'replace')
263 263 if args.bg:
264 264 self.bg_processes.append(p)
265 265 self._gc_bg_processes()
266 266 to_close = []
267 267 if args.out:
268 268 self.shell.user_ns[args.out] = p.stdout
269 269 else:
270 270 to_close.append(p.stdout)
271 271 if args.err:
272 272 self.shell.user_ns[args.err] = p.stderr
273 273 else:
274 274 to_close.append(p.stderr)
275 275 self.job_manager.new(self._run_script, p, cell, to_close, daemon=True)
276 276 if args.proc:
277 277 self.shell.user_ns[args.proc] = p
278 278 return
279 279
280 280 try:
281 281 loop.run_until_complete(_stream_communicate(p, cell))
282 282 except KeyboardInterrupt:
283 283 try:
284 284 p.send_signal(signal.SIGINT)
285 285 time.sleep(0.1)
286 286 if p.returncode is not None:
287 287 print("Process is interrupted.")
288 288 return
289 289 p.terminate()
290 290 time.sleep(0.1)
291 291 if p.returncode is not None:
292 292 print("Process is terminated.")
293 293 return
294 294 p.kill()
295 295 print("Process is killed.")
296 296 except OSError:
297 297 pass
298 298 except Exception as e:
299 299 print("Error while terminating subprocess (pid=%i): %s" % (p.pid, e))
300 300 return
301 301 if args.raise_error and p.returncode!=0:
302 302 # If we get here and p.returncode is still None, we must have
303 303 # killed it but not yet seen its return code. We don't wait for it,
304 304 # in case it's stuck in uninterruptible sleep. -9 = SIGKILL
305 305 rc = p.returncode or -9
306 306 raise CalledProcessError(rc, cell)
307
308 shebang.__skip_doctest__ = os.name != "posix"
307 309
308 310 def _run_script(self, p, cell, to_close):
309 311 """callback for running the script in the background"""
310 312 p.stdin.write(cell)
311 313 p.stdin.close()
312 314 for s in to_close:
313 315 s.close()
314 316 p.wait()
315 317
316 318 @line_magic("killbgscripts")
317 319 def killbgscripts(self, _nouse_=''):
318 320 """Kill all BG processes started by %%script and its family."""
319 321 self.kill_bg_processes()
320 322 print("All background processes were killed.")
321 323
322 324 def kill_bg_processes(self):
323 325 """Kill all BG processes which are still running."""
324 326 if not self.bg_processes:
325 327 return
326 328 for p in self.bg_processes:
327 329 if p.returncode is None:
328 330 try:
329 331 p.send_signal(signal.SIGINT)
330 332 except:
331 333 pass
332 334 time.sleep(0.1)
333 335 self._gc_bg_processes()
334 336 if not self.bg_processes:
335 337 return
336 338 for p in self.bg_processes:
337 339 if p.returncode is None:
338 340 try:
339 341 p.terminate()
340 342 except:
341 343 pass
342 344 time.sleep(0.1)
343 345 self._gc_bg_processes()
344 346 if not self.bg_processes:
345 347 return
346 348 for p in self.bg_processes:
347 349 if p.returncode is None:
348 350 try:
349 351 p.kill()
350 352 except:
351 353 pass
352 354 self._gc_bg_processes()
353 355
354 356 def _gc_bg_processes(self):
355 357 self.bg_processes = [p for p in self.bg_processes if p.returncode is None]
@@ -1,1072 +1,1082
1 1 # -*- coding: utf-8 -*-
2 2 """Tests for the key interactiveshell module.
3 3
4 4 Historically the main classes in interactiveshell have been under-tested. This
5 5 module should grow as many single-method tests as possible to trap many of the
6 6 recurring bugs we seem to encounter with high-level interaction.
7 7 """
8 8
9 9 # Copyright (c) IPython Development Team.
10 10 # Distributed under the terms of the Modified BSD License.
11 11
12 12 import asyncio
13 13 import ast
14 14 import os
15 15 import signal
16 16 import shutil
17 17 import sys
18 18 import tempfile
19 19 import unittest
20 20 from unittest import mock
21 21
22 22 from os.path import join
23 23
24 24 from IPython.core.error import InputRejected
25 25 from IPython.core.inputtransformer import InputTransformer
26 26 from IPython.core import interactiveshell
27 27 from IPython.testing.decorators import (
28 28 skipif, skip_win32, onlyif_unicode_paths, onlyif_cmds_exist,
29 29 )
30 30 from IPython.testing import tools as tt
31 31 from IPython.utils.process import find_cmd
32 32
33 33 #-----------------------------------------------------------------------------
34 34 # Globals
35 35 #-----------------------------------------------------------------------------
36 36 # This is used by every single test, no point repeating it ad nauseam
37 37
38 38 #-----------------------------------------------------------------------------
39 39 # Tests
40 40 #-----------------------------------------------------------------------------
41 41
42 42 class DerivedInterrupt(KeyboardInterrupt):
43 43 pass
44 44
45 45 class InteractiveShellTestCase(unittest.TestCase):
46 46 def test_naked_string_cells(self):
47 47 """Test that cells with only naked strings are fully executed"""
48 48 # First, single-line inputs
49 49 ip.run_cell('"a"\n')
50 50 self.assertEqual(ip.user_ns['_'], 'a')
51 51 # And also multi-line cells
52 52 ip.run_cell('"""a\nb"""\n')
53 53 self.assertEqual(ip.user_ns['_'], 'a\nb')
54 54
55 55 def test_run_empty_cell(self):
56 56 """Just make sure we don't get a horrible error with a blank
57 57 cell of input. Yes, I did overlook that."""
58 58 old_xc = ip.execution_count
59 59 res = ip.run_cell('')
60 60 self.assertEqual(ip.execution_count, old_xc)
61 61 self.assertEqual(res.execution_count, None)
62 62
63 63 def test_run_cell_multiline(self):
64 64 """Multi-block, multi-line cells must execute correctly.
65 65 """
66 66 src = '\n'.join(["x=1",
67 67 "y=2",
68 68 "if 1:",
69 69 " x += 1",
70 70 " y += 1",])
71 71 res = ip.run_cell(src)
72 72 self.assertEqual(ip.user_ns['x'], 2)
73 73 self.assertEqual(ip.user_ns['y'], 3)
74 74 self.assertEqual(res.success, True)
75 75 self.assertEqual(res.result, None)
76 76
77 77 def test_multiline_string_cells(self):
78 78 "Code sprinkled with multiline strings should execute (GH-306)"
79 79 ip.run_cell('tmp=0')
80 80 self.assertEqual(ip.user_ns['tmp'], 0)
81 81 res = ip.run_cell('tmp=1;"""a\nb"""\n')
82 82 self.assertEqual(ip.user_ns['tmp'], 1)
83 83 self.assertEqual(res.success, True)
84 84 self.assertEqual(res.result, "a\nb")
85 85
86 86 def test_dont_cache_with_semicolon(self):
87 87 "Ending a line with semicolon should not cache the returned object (GH-307)"
88 88 oldlen = len(ip.user_ns['Out'])
89 89 for cell in ['1;', '1;1;']:
90 90 res = ip.run_cell(cell, store_history=True)
91 91 newlen = len(ip.user_ns['Out'])
92 92 self.assertEqual(oldlen, newlen)
93 93 self.assertIsNone(res.result)
94 94 i = 0
95 95 #also test the default caching behavior
96 96 for cell in ['1', '1;1']:
97 97 ip.run_cell(cell, store_history=True)
98 98 newlen = len(ip.user_ns['Out'])
99 99 i += 1
100 100 self.assertEqual(oldlen+i, newlen)
101 101
102 102 def test_syntax_error(self):
103 103 res = ip.run_cell("raise = 3")
104 104 self.assertIsInstance(res.error_before_exec, SyntaxError)
105 105
106 106 def test_In_variable(self):
107 107 "Verify that In variable grows with user input (GH-284)"
108 108 oldlen = len(ip.user_ns['In'])
109 109 ip.run_cell('1;', store_history=True)
110 110 newlen = len(ip.user_ns['In'])
111 111 self.assertEqual(oldlen+1, newlen)
112 112 self.assertEqual(ip.user_ns['In'][-1],'1;')
113 113
114 114 def test_magic_names_in_string(self):
115 115 ip.run_cell('a = """\n%exit\n"""')
116 116 self.assertEqual(ip.user_ns['a'], '\n%exit\n')
117 117
118 118 def test_trailing_newline(self):
119 119 """test that running !(command) does not raise a SyntaxError"""
120 120 ip.run_cell('!(true)\n', False)
121 121 ip.run_cell('!(true)\n\n\n', False)
122 122
123 123 def test_gh_597(self):
124 124 """Pretty-printing lists of objects with non-ascii reprs may cause
125 125 problems."""
126 126 class Spam(object):
127 127 def __repr__(self):
128 128 return "\xe9"*50
129 129 import IPython.core.formatters
130 130 f = IPython.core.formatters.PlainTextFormatter()
131 131 f([Spam(),Spam()])
132 132
133 133
134 134 def test_future_flags(self):
135 135 """Check that future flags are used for parsing code (gh-777)"""
136 136 ip.run_cell('from __future__ import barry_as_FLUFL')
137 137 try:
138 138 ip.run_cell('prfunc_return_val = 1 <> 2')
139 139 assert 'prfunc_return_val' in ip.user_ns
140 140 finally:
141 141 # Reset compiler flags so we don't mess up other tests.
142 142 ip.compile.reset_compiler_flags()
143 143
144 144 def test_can_pickle(self):
145 145 "Can we pickle objects defined interactively (GH-29)"
146 146 ip = get_ipython()
147 147 ip.reset()
148 148 ip.run_cell(("class Mylist(list):\n"
149 149 " def __init__(self,x=[]):\n"
150 150 " list.__init__(self,x)"))
151 151 ip.run_cell("w=Mylist([1,2,3])")
152 152
153 153 from pickle import dumps
154 154
155 155 # We need to swap in our main module - this is only necessary
156 156 # inside the test framework, because IPython puts the interactive module
157 157 # in place (but the test framework undoes this).
158 158 _main = sys.modules['__main__']
159 159 sys.modules['__main__'] = ip.user_module
160 160 try:
161 161 res = dumps(ip.user_ns["w"])
162 162 finally:
163 163 sys.modules['__main__'] = _main
164 164 self.assertTrue(isinstance(res, bytes))
165 165
166 166 def test_global_ns(self):
167 167 "Code in functions must be able to access variables outside them."
168 168 ip = get_ipython()
169 169 ip.run_cell("a = 10")
170 170 ip.run_cell(("def f(x):\n"
171 171 " return x + a"))
172 172 ip.run_cell("b = f(12)")
173 173 self.assertEqual(ip.user_ns["b"], 22)
174 174
175 175 def test_bad_custom_tb(self):
176 176 """Check that InteractiveShell is protected from bad custom exception handlers"""
177 177 ip.set_custom_exc((IOError,), lambda etype,value,tb: 1/0)
178 178 self.assertEqual(ip.custom_exceptions, (IOError,))
179 179 with tt.AssertPrints("Custom TB Handler failed", channel='stderr'):
180 180 ip.run_cell(u'raise IOError("foo")')
181 181 self.assertEqual(ip.custom_exceptions, ())
182 182
183 183 def test_bad_custom_tb_return(self):
184 184 """Check that InteractiveShell is protected from bad return types in custom exception handlers"""
185 185 ip.set_custom_exc((NameError,),lambda etype,value,tb, tb_offset=None: 1)
186 186 self.assertEqual(ip.custom_exceptions, (NameError,))
187 187 with tt.AssertPrints("Custom TB Handler failed", channel='stderr'):
188 188 ip.run_cell(u'a=abracadabra')
189 189 self.assertEqual(ip.custom_exceptions, ())
190 190
191 191 def test_drop_by_id(self):
192 192 myvars = {"a":object(), "b":object(), "c": object()}
193 193 ip.push(myvars, interactive=False)
194 194 for name in myvars:
195 195 assert name in ip.user_ns, name
196 196 assert name in ip.user_ns_hidden, name
197 197 ip.user_ns['b'] = 12
198 198 ip.drop_by_id(myvars)
199 199 for name in ["a", "c"]:
200 200 assert name not in ip.user_ns, name
201 201 assert name not in ip.user_ns_hidden, name
202 202 assert ip.user_ns['b'] == 12
203 203 ip.reset()
204 204
205 205 def test_var_expand(self):
206 206 ip.user_ns['f'] = u'Ca\xf1o'
207 207 self.assertEqual(ip.var_expand(u'echo $f'), u'echo Ca\xf1o')
208 208 self.assertEqual(ip.var_expand(u'echo {f}'), u'echo Ca\xf1o')
209 209 self.assertEqual(ip.var_expand(u'echo {f[:-1]}'), u'echo Ca\xf1')
210 210 self.assertEqual(ip.var_expand(u'echo {1*2}'), u'echo 2')
211 211
212 212 self.assertEqual(ip.var_expand(u"grep x | awk '{print $1}'"), u"grep x | awk '{print $1}'")
213 213
214 214 ip.user_ns['f'] = b'Ca\xc3\xb1o'
215 215 # This should not raise any exception:
216 216 ip.var_expand(u'echo $f')
217 217
218 218 def test_var_expand_local(self):
219 219 """Test local variable expansion in !system and %magic calls"""
220 220 # !system
221 221 ip.run_cell(
222 222 "def test():\n"
223 223 ' lvar = "ttt"\n'
224 224 " ret = !echo {lvar}\n"
225 225 " return ret[0]\n"
226 226 )
227 227 res = ip.user_ns["test"]()
228 228 self.assertIn("ttt", res)
229 229
230 230 # %magic
231 231 ip.run_cell(
232 232 "def makemacro():\n"
233 233 ' macroname = "macro_var_expand_locals"\n'
234 234 " %macro {macroname} codestr\n"
235 235 )
236 236 ip.user_ns["codestr"] = "str(12)"
237 237 ip.run_cell("makemacro()")
238 238 self.assertIn("macro_var_expand_locals", ip.user_ns)
239 239
240 240 def test_var_expand_self(self):
241 241 """Test variable expansion with the name 'self', which was failing.
242 242
243 243 See https://github.com/ipython/ipython/issues/1878#issuecomment-7698218
244 244 """
245 245 ip.run_cell(
246 246 "class cTest:\n"
247 247 ' classvar="see me"\n'
248 248 " def test(self):\n"
249 249 " res = !echo Variable: {self.classvar}\n"
250 250 " return res[0]\n"
251 251 )
252 252 self.assertIn("see me", ip.user_ns["cTest"]().test())
253 253
254 254 def test_bad_var_expand(self):
255 255 """var_expand on invalid formats shouldn't raise"""
256 256 # SyntaxError
257 257 self.assertEqual(ip.var_expand(u"{'a':5}"), u"{'a':5}")
258 258 # NameError
259 259 self.assertEqual(ip.var_expand(u"{asdf}"), u"{asdf}")
260 260 # ZeroDivisionError
261 261 self.assertEqual(ip.var_expand(u"{1/0}"), u"{1/0}")
262 262
263 263 def test_silent_postexec(self):
264 264 """run_cell(silent=True) doesn't invoke pre/post_run_cell callbacks"""
265 265 pre_explicit = mock.Mock()
266 266 pre_always = mock.Mock()
267 267 post_explicit = mock.Mock()
268 268 post_always = mock.Mock()
269 269 all_mocks = [pre_explicit, pre_always, post_explicit, post_always]
270 270
271 271 ip.events.register('pre_run_cell', pre_explicit)
272 272 ip.events.register('pre_execute', pre_always)
273 273 ip.events.register('post_run_cell', post_explicit)
274 274 ip.events.register('post_execute', post_always)
275 275
276 276 try:
277 277 ip.run_cell("1", silent=True)
278 278 assert pre_always.called
279 279 assert not pre_explicit.called
280 280 assert post_always.called
281 281 assert not post_explicit.called
282 282 # double-check that non-silent exec did what we expected
283 283 # silent to avoid
284 284 ip.run_cell("1")
285 285 assert pre_explicit.called
286 286 assert post_explicit.called
287 287 info, = pre_explicit.call_args[0]
288 288 result, = post_explicit.call_args[0]
289 289 self.assertEqual(info, result.info)
290 290 # check that post hooks are always called
291 291 [m.reset_mock() for m in all_mocks]
292 292 ip.run_cell("syntax error")
293 293 assert pre_always.called
294 294 assert pre_explicit.called
295 295 assert post_always.called
296 296 assert post_explicit.called
297 297 info, = pre_explicit.call_args[0]
298 298 result, = post_explicit.call_args[0]
299 299 self.assertEqual(info, result.info)
300 300 finally:
301 301 # remove post-exec
302 302 ip.events.unregister('pre_run_cell', pre_explicit)
303 303 ip.events.unregister('pre_execute', pre_always)
304 304 ip.events.unregister('post_run_cell', post_explicit)
305 305 ip.events.unregister('post_execute', post_always)
306 306
307 307 def test_silent_noadvance(self):
308 308 """run_cell(silent=True) doesn't advance execution_count"""
309 309 ec = ip.execution_count
310 310 # silent should force store_history=False
311 311 ip.run_cell("1", store_history=True, silent=True)
312 312
313 313 self.assertEqual(ec, ip.execution_count)
314 314 # double-check that non-silent exec did what we expected
315 315 # silent to avoid
316 316 ip.run_cell("1", store_history=True)
317 317 self.assertEqual(ec+1, ip.execution_count)
318 318
319 319 def test_silent_nodisplayhook(self):
320 320 """run_cell(silent=True) doesn't trigger displayhook"""
321 321 d = dict(called=False)
322 322
323 323 trap = ip.display_trap
324 324 save_hook = trap.hook
325 325
326 326 def failing_hook(*args, **kwargs):
327 327 d['called'] = True
328 328
329 329 try:
330 330 trap.hook = failing_hook
331 331 res = ip.run_cell("1", silent=True)
332 332 self.assertFalse(d['called'])
333 333 self.assertIsNone(res.result)
334 334 # double-check that non-silent exec did what we expected
335 335 # silent to avoid
336 336 ip.run_cell("1")
337 337 self.assertTrue(d['called'])
338 338 finally:
339 339 trap.hook = save_hook
340 340
341 341 def test_ofind_line_magic(self):
342 342 from IPython.core.magic import register_line_magic
343 343
344 344 @register_line_magic
345 345 def lmagic(line):
346 346 "A line magic"
347 347
348 348 # Get info on line magic
349 lfind = ip._ofind('lmagic')
350 info = dict(found=True, isalias=False, ismagic=True,
351 namespace = 'IPython internal', obj= lmagic.__wrapped__,
352 parent = None)
349 lfind = ip._ofind("lmagic")
350 info = dict(
351 found=True,
352 isalias=False,
353 ismagic=True,
354 namespace="IPython internal",
355 obj=lmagic,
356 parent=None,
357 )
353 358 self.assertEqual(lfind, info)
354 359
355 360 def test_ofind_cell_magic(self):
356 361 from IPython.core.magic import register_cell_magic
357 362
358 363 @register_cell_magic
359 364 def cmagic(line, cell):
360 365 "A cell magic"
361 366
362 367 # Get info on cell magic
363 find = ip._ofind('cmagic')
364 info = dict(found=True, isalias=False, ismagic=True,
365 namespace = 'IPython internal', obj= cmagic.__wrapped__,
366 parent = None)
368 find = ip._ofind("cmagic")
369 info = dict(
370 found=True,
371 isalias=False,
372 ismagic=True,
373 namespace="IPython internal",
374 obj=cmagic,
375 parent=None,
376 )
367 377 self.assertEqual(find, info)
368 378
369 379 def test_ofind_property_with_error(self):
370 380 class A(object):
371 381 @property
372 382 def foo(self):
373 383 raise NotImplementedError()
374 384 a = A()
375 385
376 386 found = ip._ofind('a.foo', [('locals', locals())])
377 387 info = dict(found=True, isalias=False, ismagic=False,
378 388 namespace='locals', obj=A.foo, parent=a)
379 389 self.assertEqual(found, info)
380 390
381 391 def test_ofind_multiple_attribute_lookups(self):
382 392 class A(object):
383 393 @property
384 394 def foo(self):
385 395 raise NotImplementedError()
386 396
387 397 a = A()
388 398 a.a = A()
389 399 a.a.a = A()
390 400
391 401 found = ip._ofind('a.a.a.foo', [('locals', locals())])
392 402 info = dict(found=True, isalias=False, ismagic=False,
393 403 namespace='locals', obj=A.foo, parent=a.a.a)
394 404 self.assertEqual(found, info)
395 405
396 406 def test_ofind_slotted_attributes(self):
397 407 class A(object):
398 408 __slots__ = ['foo']
399 409 def __init__(self):
400 410 self.foo = 'bar'
401 411
402 412 a = A()
403 413 found = ip._ofind('a.foo', [('locals', locals())])
404 414 info = dict(found=True, isalias=False, ismagic=False,
405 415 namespace='locals', obj=a.foo, parent=a)
406 416 self.assertEqual(found, info)
407 417
408 418 found = ip._ofind('a.bar', [('locals', locals())])
409 419 info = dict(found=False, isalias=False, ismagic=False,
410 420 namespace=None, obj=None, parent=a)
411 421 self.assertEqual(found, info)
412 422
413 423 def test_ofind_prefers_property_to_instance_level_attribute(self):
414 424 class A(object):
415 425 @property
416 426 def foo(self):
417 427 return 'bar'
418 428 a = A()
419 429 a.__dict__["foo"] = "baz"
420 430 self.assertEqual(a.foo, "bar")
421 431 found = ip._ofind("a.foo", [("locals", locals())])
422 432 self.assertIs(found["obj"], A.foo)
423 433
424 434 def test_custom_syntaxerror_exception(self):
425 435 called = []
426 436 def my_handler(shell, etype, value, tb, tb_offset=None):
427 437 called.append(etype)
428 438 shell.showtraceback((etype, value, tb), tb_offset=tb_offset)
429 439
430 440 ip.set_custom_exc((SyntaxError,), my_handler)
431 441 try:
432 442 ip.run_cell("1f")
433 443 # Check that this was called, and only once.
434 444 self.assertEqual(called, [SyntaxError])
435 445 finally:
436 446 # Reset the custom exception hook
437 447 ip.set_custom_exc((), None)
438 448
439 449 def test_custom_exception(self):
440 450 called = []
441 451 def my_handler(shell, etype, value, tb, tb_offset=None):
442 452 called.append(etype)
443 453 shell.showtraceback((etype, value, tb), tb_offset=tb_offset)
444 454
445 455 ip.set_custom_exc((ValueError,), my_handler)
446 456 try:
447 457 res = ip.run_cell("raise ValueError('test')")
448 458 # Check that this was called, and only once.
449 459 self.assertEqual(called, [ValueError])
450 460 # Check that the error is on the result object
451 461 self.assertIsInstance(res.error_in_exec, ValueError)
452 462 finally:
453 463 # Reset the custom exception hook
454 464 ip.set_custom_exc((), None)
455 465
456 466 @mock.patch("builtins.print")
457 467 def test_showtraceback_with_surrogates(self, mocked_print):
458 468 values = []
459 469
460 470 def mock_print_func(value, sep=" ", end="\n", file=sys.stdout, flush=False):
461 471 values.append(value)
462 472 if value == chr(0xD8FF):
463 473 raise UnicodeEncodeError("utf-8", chr(0xD8FF), 0, 1, "")
464 474
465 475 # mock builtins.print
466 476 mocked_print.side_effect = mock_print_func
467 477
468 478 # ip._showtraceback() is replaced in globalipapp.py.
469 479 # Call original method to test.
470 480 interactiveshell.InteractiveShell._showtraceback(ip, None, None, chr(0xD8FF))
471 481
472 482 self.assertEqual(mocked_print.call_count, 2)
473 483 self.assertEqual(values, [chr(0xD8FF), "\\ud8ff"])
474 484
475 485 def test_mktempfile(self):
476 486 filename = ip.mktempfile()
477 487 # Check that we can open the file again on Windows
478 488 with open(filename, 'w') as f:
479 489 f.write('abc')
480 490
481 491 filename = ip.mktempfile(data='blah')
482 492 with open(filename, 'r') as f:
483 493 self.assertEqual(f.read(), 'blah')
484 494
485 495 def test_new_main_mod(self):
486 496 # Smoketest to check that this accepts a unicode module name
487 497 name = u'jiefmw'
488 498 mod = ip.new_main_mod(u'%s.py' % name, name)
489 499 self.assertEqual(mod.__name__, name)
490 500
491 501 def test_get_exception_only(self):
492 502 try:
493 503 raise KeyboardInterrupt
494 504 except KeyboardInterrupt:
495 505 msg = ip.get_exception_only()
496 506 self.assertEqual(msg, 'KeyboardInterrupt\n')
497 507
498 508 try:
499 509 raise DerivedInterrupt("foo")
500 510 except KeyboardInterrupt:
501 511 msg = ip.get_exception_only()
502 512 self.assertEqual(msg, 'IPython.core.tests.test_interactiveshell.DerivedInterrupt: foo\n')
503 513
504 514 def test_inspect_text(self):
505 515 ip.run_cell('a = 5')
506 516 text = ip.object_inspect_text('a')
507 517 self.assertIsInstance(text, str)
508 518
509 519 def test_last_execution_result(self):
510 520 """ Check that last execution result gets set correctly (GH-10702) """
511 521 result = ip.run_cell('a = 5; a')
512 522 self.assertTrue(ip.last_execution_succeeded)
513 523 self.assertEqual(ip.last_execution_result.result, 5)
514 524
515 525 result = ip.run_cell('a = x_invalid_id_x')
516 526 self.assertFalse(ip.last_execution_succeeded)
517 527 self.assertFalse(ip.last_execution_result.success)
518 528 self.assertIsInstance(ip.last_execution_result.error_in_exec, NameError)
519 529
520 530 def test_reset_aliasing(self):
521 531 """ Check that standard posix aliases work after %reset. """
522 532 if os.name != 'posix':
523 533 return
524 534
525 535 ip.reset()
526 536 for cmd in ('clear', 'more', 'less', 'man'):
527 537 res = ip.run_cell('%' + cmd)
528 538 self.assertEqual(res.success, True)
529 539
530 540
531 541 class TestSafeExecfileNonAsciiPath(unittest.TestCase):
532 542
533 543 @onlyif_unicode_paths
534 544 def setUp(self):
535 545 self.BASETESTDIR = tempfile.mkdtemp()
536 546 self.TESTDIR = join(self.BASETESTDIR, u"åäö")
537 547 os.mkdir(self.TESTDIR)
538 548 with open(join(self.TESTDIR, u"åäötestscript.py"), "w") as sfile:
539 549 sfile.write("pass\n")
540 550 self.oldpath = os.getcwd()
541 551 os.chdir(self.TESTDIR)
542 552 self.fname = u"åäötestscript.py"
543 553
544 554 def tearDown(self):
545 555 os.chdir(self.oldpath)
546 556 shutil.rmtree(self.BASETESTDIR)
547 557
548 558 @onlyif_unicode_paths
549 559 def test_1(self):
550 560 """Test safe_execfile with non-ascii path
551 561 """
552 562 ip.safe_execfile(self.fname, {}, raise_exceptions=True)
553 563
554 564 class ExitCodeChecks(tt.TempFileMixin):
555 565
556 566 def setUp(self):
557 567 self.system = ip.system_raw
558 568
559 569 def test_exit_code_ok(self):
560 570 self.system('exit 0')
561 571 self.assertEqual(ip.user_ns['_exit_code'], 0)
562 572
563 573 def test_exit_code_error(self):
564 574 self.system('exit 1')
565 575 self.assertEqual(ip.user_ns['_exit_code'], 1)
566 576
567 577 @skipif(not hasattr(signal, 'SIGALRM'))
568 578 def test_exit_code_signal(self):
569 579 self.mktmp("import signal, time\n"
570 580 "signal.setitimer(signal.ITIMER_REAL, 0.1)\n"
571 581 "time.sleep(1)\n")
572 582 self.system("%s %s" % (sys.executable, self.fname))
573 583 self.assertEqual(ip.user_ns['_exit_code'], -signal.SIGALRM)
574 584
575 585 @onlyif_cmds_exist("csh")
576 586 def test_exit_code_signal_csh(self):
577 587 SHELL = os.environ.get('SHELL', None)
578 588 os.environ['SHELL'] = find_cmd("csh")
579 589 try:
580 590 self.test_exit_code_signal()
581 591 finally:
582 592 if SHELL is not None:
583 593 os.environ['SHELL'] = SHELL
584 594 else:
585 595 del os.environ['SHELL']
586 596
587 597
588 598 class TestSystemRaw(ExitCodeChecks):
589 599
590 600 def setUp(self):
591 601 super().setUp()
592 602 self.system = ip.system_raw
593 603
594 604 @onlyif_unicode_paths
595 605 def test_1(self):
596 606 """Test system_raw with non-ascii cmd
597 607 """
598 608 cmd = u'''python -c "'åäö'" '''
599 609 ip.system_raw(cmd)
600 610
601 611 @mock.patch('subprocess.call', side_effect=KeyboardInterrupt)
602 612 @mock.patch('os.system', side_effect=KeyboardInterrupt)
603 613 def test_control_c(self, *mocks):
604 614 try:
605 615 self.system("sleep 1 # wont happen")
606 616 except KeyboardInterrupt:
607 617 self.fail(
608 618 "system call should intercept "
609 619 "keyboard interrupt from subprocess.call"
610 620 )
611 621 self.assertEqual(ip.user_ns["_exit_code"], -signal.SIGINT)
612 622
613 623 def test_magic_warnings(self):
614 624 for magic_cmd in ("ls", "pip", "conda", "cd"):
615 625 with self.assertWarnsRegex(Warning, "You executed the system command"):
616 626 ip.system_raw(magic_cmd)
617 627
618 628 # TODO: Exit codes are currently ignored on Windows.
619 629 class TestSystemPipedExitCode(ExitCodeChecks):
620 630
621 631 def setUp(self):
622 632 super().setUp()
623 633 self.system = ip.system_piped
624 634
625 635 @skip_win32
626 636 def test_exit_code_ok(self):
627 637 ExitCodeChecks.test_exit_code_ok(self)
628 638
629 639 @skip_win32
630 640 def test_exit_code_error(self):
631 641 ExitCodeChecks.test_exit_code_error(self)
632 642
633 643 @skip_win32
634 644 def test_exit_code_signal(self):
635 645 ExitCodeChecks.test_exit_code_signal(self)
636 646
637 647 class TestModules(tt.TempFileMixin):
638 648 def test_extraneous_loads(self):
639 649 """Test we're not loading modules on startup that we shouldn't.
640 650 """
641 651 self.mktmp("import sys\n"
642 652 "print('numpy' in sys.modules)\n"
643 653 "print('ipyparallel' in sys.modules)\n"
644 654 "print('ipykernel' in sys.modules)\n"
645 655 )
646 656 out = "False\nFalse\nFalse\n"
647 657 tt.ipexec_validate(self.fname, out)
648 658
649 659 class Negator(ast.NodeTransformer):
650 660 """Negates all number literals in an AST."""
651 661
652 662 # for python 3.7 and earlier
653 663 def visit_Num(self, node):
654 664 node.n = -node.n
655 665 return node
656 666
657 667 # for python 3.8+
658 668 def visit_Constant(self, node):
659 669 if isinstance(node.value, int):
660 670 return self.visit_Num(node)
661 671 return node
662 672
663 673 class TestAstTransform(unittest.TestCase):
664 674 def setUp(self):
665 675 self.negator = Negator()
666 676 ip.ast_transformers.append(self.negator)
667 677
668 678 def tearDown(self):
669 679 ip.ast_transformers.remove(self.negator)
670 680
671 681 def test_run_cell(self):
672 682 with tt.AssertPrints('-34'):
673 683 ip.run_cell('print (12 + 22)')
674 684
675 685 # A named reference to a number shouldn't be transformed.
676 686 ip.user_ns['n'] = 55
677 687 with tt.AssertNotPrints('-55'):
678 688 ip.run_cell('print (n)')
679 689
680 690 def test_timeit(self):
681 691 called = set()
682 692 def f(x):
683 693 called.add(x)
684 694 ip.push({'f':f})
685 695
686 696 with tt.AssertPrints("std. dev. of"):
687 697 ip.run_line_magic("timeit", "-n1 f(1)")
688 698 self.assertEqual(called, {-1})
689 699 called.clear()
690 700
691 701 with tt.AssertPrints("std. dev. of"):
692 702 ip.run_cell_magic("timeit", "-n1 f(2)", "f(3)")
693 703 self.assertEqual(called, {-2, -3})
694 704
695 705 def test_time(self):
696 706 called = []
697 707 def f(x):
698 708 called.append(x)
699 709 ip.push({'f':f})
700 710
701 711 # Test with an expression
702 712 with tt.AssertPrints("Wall time: "):
703 713 ip.run_line_magic("time", "f(5+9)")
704 714 self.assertEqual(called, [-14])
705 715 called[:] = []
706 716
707 717 # Test with a statement (different code path)
708 718 with tt.AssertPrints("Wall time: "):
709 719 ip.run_line_magic("time", "a = f(-3 + -2)")
710 720 self.assertEqual(called, [5])
711 721
712 722 def test_macro(self):
713 723 ip.push({'a':10})
714 724 # The AST transformation makes this do a+=-1
715 725 ip.define_macro("amacro", "a+=1\nprint(a)")
716 726
717 727 with tt.AssertPrints("9"):
718 728 ip.run_cell("amacro")
719 729 with tt.AssertPrints("8"):
720 730 ip.run_cell("amacro")
721 731
722 732 class TestMiscTransform(unittest.TestCase):
723 733
724 734
725 735 def test_transform_only_once(self):
726 736 cleanup = 0
727 737 line_t = 0
728 738 def count_cleanup(lines):
729 739 nonlocal cleanup
730 740 cleanup += 1
731 741 return lines
732 742
733 743 def count_line_t(lines):
734 744 nonlocal line_t
735 745 line_t += 1
736 746 return lines
737 747
738 748 ip.input_transformer_manager.cleanup_transforms.append(count_cleanup)
739 749 ip.input_transformer_manager.line_transforms.append(count_line_t)
740 750
741 751 ip.run_cell('1')
742 752
743 753 assert cleanup == 1
744 754 assert line_t == 1
745 755
746 756 class IntegerWrapper(ast.NodeTransformer):
747 757 """Wraps all integers in a call to Integer()"""
748 758
749 759 # for Python 3.7 and earlier
750 760
751 761 # for Python 3.7 and earlier
752 762 def visit_Num(self, node):
753 763 if isinstance(node.n, int):
754 764 return ast.Call(func=ast.Name(id='Integer', ctx=ast.Load()),
755 765 args=[node], keywords=[])
756 766 return node
757 767
758 768 # For Python 3.8+
759 769 def visit_Constant(self, node):
760 770 if isinstance(node.value, int):
761 771 return self.visit_Num(node)
762 772 return node
763 773
764 774
765 775 class TestAstTransform2(unittest.TestCase):
766 776 def setUp(self):
767 777 self.intwrapper = IntegerWrapper()
768 778 ip.ast_transformers.append(self.intwrapper)
769 779
770 780 self.calls = []
771 781 def Integer(*args):
772 782 self.calls.append(args)
773 783 return args
774 784 ip.push({"Integer": Integer})
775 785
776 786 def tearDown(self):
777 787 ip.ast_transformers.remove(self.intwrapper)
778 788 del ip.user_ns['Integer']
779 789
780 790 def test_run_cell(self):
781 791 ip.run_cell("n = 2")
782 792 self.assertEqual(self.calls, [(2,)])
783 793
784 794 # This shouldn't throw an error
785 795 ip.run_cell("o = 2.0")
786 796 self.assertEqual(ip.user_ns['o'], 2.0)
787 797
788 798 def test_timeit(self):
789 799 called = set()
790 800 def f(x):
791 801 called.add(x)
792 802 ip.push({'f':f})
793 803
794 804 with tt.AssertPrints("std. dev. of"):
795 805 ip.run_line_magic("timeit", "-n1 f(1)")
796 806 self.assertEqual(called, {(1,)})
797 807 called.clear()
798 808
799 809 with tt.AssertPrints("std. dev. of"):
800 810 ip.run_cell_magic("timeit", "-n1 f(2)", "f(3)")
801 811 self.assertEqual(called, {(2,), (3,)})
802 812
803 813 class ErrorTransformer(ast.NodeTransformer):
804 814 """Throws an error when it sees a number."""
805 815
806 816 # for Python 3.7 and earlier
807 817 def visit_Num(self, node):
808 818 raise ValueError("test")
809 819
810 820 # for Python 3.8+
811 821 def visit_Constant(self, node):
812 822 if isinstance(node.value, int):
813 823 return self.visit_Num(node)
814 824 return node
815 825
816 826
817 827 class TestAstTransformError(unittest.TestCase):
818 828 def test_unregistering(self):
819 829 err_transformer = ErrorTransformer()
820 830 ip.ast_transformers.append(err_transformer)
821 831
822 832 with self.assertWarnsRegex(UserWarning, "It will be unregistered"):
823 833 ip.run_cell("1 + 2")
824 834
825 835 # This should have been removed.
826 836 self.assertNotIn(err_transformer, ip.ast_transformers)
827 837
828 838
829 839 class StringRejector(ast.NodeTransformer):
830 840 """Throws an InputRejected when it sees a string literal.
831 841
832 842 Used to verify that NodeTransformers can signal that a piece of code should
833 843 not be executed by throwing an InputRejected.
834 844 """
835 845
836 846 #for python 3.7 and earlier
837 847 def visit_Str(self, node):
838 848 raise InputRejected("test")
839 849
840 850 # 3.8 only
841 851 def visit_Constant(self, node):
842 852 if isinstance(node.value, str):
843 853 raise InputRejected("test")
844 854 return node
845 855
846 856
847 857 class TestAstTransformInputRejection(unittest.TestCase):
848 858
849 859 def setUp(self):
850 860 self.transformer = StringRejector()
851 861 ip.ast_transformers.append(self.transformer)
852 862
853 863 def tearDown(self):
854 864 ip.ast_transformers.remove(self.transformer)
855 865
856 866 def test_input_rejection(self):
857 867 """Check that NodeTransformers can reject input."""
858 868
859 869 expect_exception_tb = tt.AssertPrints("InputRejected: test")
860 870 expect_no_cell_output = tt.AssertNotPrints("'unsafe'", suppress=False)
861 871
862 872 # Run the same check twice to verify that the transformer is not
863 873 # disabled after raising.
864 874 with expect_exception_tb, expect_no_cell_output:
865 875 ip.run_cell("'unsafe'")
866 876
867 877 with expect_exception_tb, expect_no_cell_output:
868 878 res = ip.run_cell("'unsafe'")
869 879
870 880 self.assertIsInstance(res.error_before_exec, InputRejected)
871 881
872 882 def test__IPYTHON__():
873 883 # This shouldn't raise a NameError, that's all
874 884 __IPYTHON__
875 885
876 886
877 887 class DummyRepr(object):
878 888 def __repr__(self):
879 889 return "DummyRepr"
880 890
881 891 def _repr_html_(self):
882 892 return "<b>dummy</b>"
883 893
884 894 def _repr_javascript_(self):
885 895 return "console.log('hi');", {'key': 'value'}
886 896
887 897
888 898 def test_user_variables():
889 899 # enable all formatters
890 900 ip.display_formatter.active_types = ip.display_formatter.format_types
891 901
892 902 ip.user_ns['dummy'] = d = DummyRepr()
893 903 keys = {'dummy', 'doesnotexist'}
894 904 r = ip.user_expressions({ key:key for key in keys})
895 905
896 906 assert keys == set(r.keys())
897 907 dummy = r["dummy"]
898 908 assert {"status", "data", "metadata"} == set(dummy.keys())
899 909 assert dummy["status"] == "ok"
900 910 data = dummy["data"]
901 911 metadata = dummy["metadata"]
902 912 assert data.get("text/html") == d._repr_html_()
903 913 js, jsmd = d._repr_javascript_()
904 914 assert data.get("application/javascript") == js
905 915 assert metadata.get("application/javascript") == jsmd
906 916
907 917 dne = r["doesnotexist"]
908 918 assert dne["status"] == "error"
909 919 assert dne["ename"] == "NameError"
910 920
911 921 # back to text only
912 922 ip.display_formatter.active_types = ['text/plain']
913 923
914 924 def test_user_expression():
915 925 # enable all formatters
916 926 ip.display_formatter.active_types = ip.display_formatter.format_types
917 927 query = {
918 928 'a' : '1 + 2',
919 929 'b' : '1/0',
920 930 }
921 931 r = ip.user_expressions(query)
922 932 import pprint
923 933 pprint.pprint(r)
924 934 assert set(r.keys()) == set(query.keys())
925 935 a = r["a"]
926 936 assert {"status", "data", "metadata"} == set(a.keys())
927 937 assert a["status"] == "ok"
928 938 data = a["data"]
929 939 metadata = a["metadata"]
930 940 assert data.get("text/plain") == "3"
931 941
932 942 b = r["b"]
933 943 assert b["status"] == "error"
934 944 assert b["ename"] == "ZeroDivisionError"
935 945
936 946 # back to text only
937 947 ip.display_formatter.active_types = ['text/plain']
938 948
939 949
940 950 class TestSyntaxErrorTransformer(unittest.TestCase):
941 951 """Check that SyntaxError raised by an input transformer is handled by run_cell()"""
942 952
943 953 @staticmethod
944 954 def transformer(lines):
945 955 for line in lines:
946 956 pos = line.find('syntaxerror')
947 957 if pos >= 0:
948 958 e = SyntaxError('input contains "syntaxerror"')
949 959 e.text = line
950 960 e.offset = pos + 1
951 961 raise e
952 962 return lines
953 963
954 964 def setUp(self):
955 965 ip.input_transformers_post.append(self.transformer)
956 966
957 967 def tearDown(self):
958 968 ip.input_transformers_post.remove(self.transformer)
959 969
960 970 def test_syntaxerror_input_transformer(self):
961 971 with tt.AssertPrints('1234'):
962 972 ip.run_cell('1234')
963 973 with tt.AssertPrints('SyntaxError: invalid syntax'):
964 974 ip.run_cell('1 2 3') # plain python syntax error
965 975 with tt.AssertPrints('SyntaxError: input contains "syntaxerror"'):
966 976 ip.run_cell('2345 # syntaxerror') # input transformer syntax error
967 977 with tt.AssertPrints('3456'):
968 978 ip.run_cell('3456')
969 979
970 980
971 981 class TestWarningSuppression(unittest.TestCase):
972 982 def test_warning_suppression(self):
973 983 ip.run_cell("import warnings")
974 984 try:
975 985 with self.assertWarnsRegex(UserWarning, "asdf"):
976 986 ip.run_cell("warnings.warn('asdf')")
977 987 # Here's the real test -- if we run that again, we should get the
978 988 # warning again. Traditionally, each warning was only issued once per
979 989 # IPython session (approximately), even if the user typed in new and
980 990 # different code that should have also triggered the warning, leading
981 991 # to much confusion.
982 992 with self.assertWarnsRegex(UserWarning, "asdf"):
983 993 ip.run_cell("warnings.warn('asdf')")
984 994 finally:
985 995 ip.run_cell("del warnings")
986 996
987 997
988 998 def test_deprecation_warning(self):
989 999 ip.run_cell("""
990 1000 import warnings
991 1001 def wrn():
992 1002 warnings.warn(
993 1003 "I AM A WARNING",
994 1004 DeprecationWarning
995 1005 )
996 1006 """)
997 1007 try:
998 1008 with self.assertWarnsRegex(DeprecationWarning, "I AM A WARNING"):
999 1009 ip.run_cell("wrn()")
1000 1010 finally:
1001 1011 ip.run_cell("del warnings")
1002 1012 ip.run_cell("del wrn")
1003 1013
1004 1014
1005 1015 class TestImportNoDeprecate(tt.TempFileMixin):
1006 1016
1007 1017 def setUp(self):
1008 1018 """Make a valid python temp file."""
1009 1019 self.mktmp("""
1010 1020 import warnings
1011 1021 def wrn():
1012 1022 warnings.warn(
1013 1023 "I AM A WARNING",
1014 1024 DeprecationWarning
1015 1025 )
1016 1026 """)
1017 1027 super().setUp()
1018 1028
1019 1029 def test_no_dep(self):
1020 1030 """
1021 1031 No deprecation warning should be raised from imported functions
1022 1032 """
1023 1033 ip.run_cell("from {} import wrn".format(self.fname))
1024 1034
1025 1035 with tt.AssertNotPrints("I AM A WARNING"):
1026 1036 ip.run_cell("wrn()")
1027 1037 ip.run_cell("del wrn")
1028 1038
1029 1039
1030 1040 def test_custom_exc_count():
1031 1041 hook = mock.Mock(return_value=None)
1032 1042 ip.set_custom_exc((SyntaxError,), hook)
1033 1043 before = ip.execution_count
1034 1044 ip.run_cell("def foo()", store_history=True)
1035 1045 # restore default excepthook
1036 1046 ip.set_custom_exc((), None)
1037 1047 assert hook.call_count == 1
1038 1048 assert ip.execution_count == before + 1
1039 1049
1040 1050
1041 1051 def test_run_cell_async():
1042 1052 loop = asyncio.get_event_loop_policy().get_event_loop()
1043 1053 ip.run_cell("import asyncio")
1044 1054 coro = ip.run_cell_async("await asyncio.sleep(0.01)\n5")
1045 1055 assert asyncio.iscoroutine(coro)
1046 1056 result = loop.run_until_complete(coro)
1047 1057 assert isinstance(result, interactiveshell.ExecutionResult)
1048 1058 assert result.result == 5
1049 1059
1050 1060
1051 1061 def test_should_run_async():
1052 1062 assert not ip.should_run_async("a = 5")
1053 1063 assert ip.should_run_async("await x")
1054 1064 assert ip.should_run_async("import asyncio; await asyncio.sleep(1)")
1055 1065
1056 1066
1057 1067 def test_set_custom_completer():
1058 1068 num_completers = len(ip.Completer.matchers)
1059 1069
1060 1070 def foo(*args, **kwargs):
1061 1071 return "I'm a completer!"
1062 1072
1063 1073 ip.set_custom_completer(foo, 0)
1064 1074
1065 1075 # check that we've really added a new completer
1066 1076 assert len(ip.Completer.matchers) == num_completers + 1
1067 1077
1068 1078 # check that the first completer is the function we defined
1069 1079 assert ip.Completer.matchers[0]() == "I'm a completer!"
1070 1080
1071 1081 # clean up
1072 1082 ip.Completer.custom_matchers.pop()
@@ -1,233 +1,236
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.StoreMagics.autorestore = True
11 11 """
12 12
13 13 # Copyright (c) IPython Development Team.
14 14 # Distributed under the terms of the Modified BSD License.
15 15
16 16 import inspect, os, sys, textwrap
17 17
18 18 from IPython.core.error import UsageError
19 19 from IPython.core.magic import Magics, magics_class, line_magic
20 from IPython.testing.skipdoctest import skip_doctest
20 21 from traitlets import Bool
21 22
22 23
23 24 def restore_aliases(ip, alias=None):
24 25 staliases = ip.db.get('stored_aliases', {})
25 26 if alias is None:
26 27 for k,v in staliases.items():
27 28 #print "restore alias",k,v # dbg
28 29 #self.alias_table[k] = v
29 30 ip.alias_manager.define_alias(k,v)
30 31 else:
31 32 ip.alias_manager.define_alias(alias, staliases[alias])
32 33
33 34
34 35 def refresh_variables(ip):
35 36 db = ip.db
36 37 for key in db.keys('autorestore/*'):
37 38 # strip autorestore
38 39 justkey = os.path.basename(key)
39 40 try:
40 41 obj = db[key]
41 42 except KeyError:
42 43 print("Unable to restore variable '%s', ignoring (use %%store -d to forget!)" % justkey)
43 44 print("The error was:", sys.exc_info()[0])
44 45 else:
45 46 #print "restored",justkey,"=",obj #dbg
46 47 ip.user_ns[justkey] = obj
47 48
48 49
49 50 def restore_dhist(ip):
50 51 ip.user_ns['_dh'] = ip.db.get('dhist',[])
51 52
52 53
53 54 def restore_data(ip):
54 55 refresh_variables(ip)
55 56 restore_aliases(ip)
56 57 restore_dhist(ip)
57 58
58 59
59 60 @magics_class
60 61 class StoreMagics(Magics):
61 62 """Lightweight persistence for python variables.
62 63
63 64 Provides the %store magic."""
64 65
65 66 autorestore = Bool(False, help=
66 67 """If True, any %store-d variables will be automatically restored
67 68 when IPython starts.
68 69 """
69 70 ).tag(config=True)
70 71
71 72 def __init__(self, shell):
72 73 super(StoreMagics, self).__init__(shell=shell)
73 74 self.shell.configurables.append(self)
74 75 if self.autorestore:
75 76 restore_data(self.shell)
76 77
78 @skip_doctest
77 79 @line_magic
78 80 def store(self, parameter_s=''):
79 81 """Lightweight persistence for python variables.
80 82
81 83 Example::
82 84
83 85 In [1]: l = ['hello',10,'world']
84 86 In [2]: %store l
87 Stored 'l' (list)
85 88 In [3]: exit
86 89
87 90 (IPython session is closed and started again...)
88 91
89 92 ville@badger:~$ ipython
90 93 In [1]: l
91 94 NameError: name 'l' is not defined
92 95 In [2]: %store -r
93 96 In [3]: l
94 97 Out[3]: ['hello', 10, 'world']
95 98
96 99 Usage:
97 100
98 101 * ``%store`` - Show list of all variables and their current
99 102 values
100 103 * ``%store spam bar`` - Store the *current* value of the variables spam
101 104 and bar to disk
102 105 * ``%store -d spam`` - Remove the variable and its value from storage
103 106 * ``%store -z`` - Remove all variables from storage
104 107 * ``%store -r`` - Refresh all variables, aliases and directory history
105 108 from store (overwrite current vals)
106 109 * ``%store -r spam bar`` - Refresh specified variables and aliases from store
107 110 (delete current val)
108 111 * ``%store foo >a.txt`` - Store value of foo to new file a.txt
109 112 * ``%store foo >>a.txt`` - Append value of foo to file a.txt
110 113
111 114 It should be noted that if you change the value of a variable, you
112 115 need to %store it again if you want to persist the new value.
113 116
114 117 Note also that the variables will need to be pickleable; most basic
115 118 python types can be safely %store'd.
116 119
117 120 Also aliases can be %store'd across sessions.
118 121 To remove an alias from the storage, use the %unalias magic.
119 122 """
120 123
121 124 opts,argsl = self.parse_options(parameter_s,'drz',mode='string')
122 125 args = argsl.split()
123 126 ip = self.shell
124 127 db = ip.db
125 128 # delete
126 129 if 'd' in opts:
127 130 try:
128 131 todel = args[0]
129 132 except IndexError as e:
130 133 raise UsageError('You must provide the variable to forget') from e
131 134 else:
132 135 try:
133 136 del db['autorestore/' + todel]
134 137 except BaseException as e:
135 138 raise UsageError("Can't delete variable '%s'" % todel) from e
136 139 # reset
137 140 elif 'z' in opts:
138 141 for k in db.keys('autorestore/*'):
139 142 del db[k]
140 143
141 144 elif 'r' in opts:
142 145 if args:
143 146 for arg in args:
144 147 try:
145 148 obj = db['autorestore/' + arg]
146 149 except KeyError:
147 150 try:
148 151 restore_aliases(ip, alias=arg)
149 152 except KeyError:
150 153 print("no stored variable or alias %s" % arg)
151 154 else:
152 155 ip.user_ns[arg] = obj
153 156 else:
154 157 restore_data(ip)
155 158
156 159 # run without arguments -> list variables & values
157 160 elif not args:
158 161 vars = db.keys('autorestore/*')
159 162 vars.sort()
160 163 if vars:
161 164 size = max(map(len, vars))
162 165 else:
163 166 size = 0
164 167
165 168 print('Stored variables and their in-db values:')
166 169 fmt = '%-'+str(size)+'s -> %s'
167 170 get = db.get
168 171 for var in vars:
169 172 justkey = os.path.basename(var)
170 173 # print 30 first characters from every var
171 174 print(fmt % (justkey, repr(get(var, '<unavailable>'))[:50]))
172 175
173 176 # default action - store the variable
174 177 else:
175 178 # %store foo >file.txt or >>file.txt
176 179 if len(args) > 1 and args[1].startswith('>'):
177 180 fnam = os.path.expanduser(args[1].lstrip('>').lstrip())
178 181 if args[1].startswith('>>'):
179 182 fil = open(fnam, 'a')
180 183 else:
181 184 fil = open(fnam, 'w')
182 185 with fil:
183 186 obj = ip.ev(args[0])
184 187 print("Writing '%s' (%s) to file '%s'." % (args[0],
185 188 obj.__class__.__name__, fnam))
186 189
187 190 if not isinstance (obj, str):
188 191 from pprint import pprint
189 192 pprint(obj, fil)
190 193 else:
191 194 fil.write(obj)
192 195 if not obj.endswith('\n'):
193 196 fil.write('\n')
194 197
195 198 return
196 199
197 200 # %store foo
198 201 for arg in args:
199 202 try:
200 203 obj = ip.user_ns[arg]
201 204 except KeyError:
202 205 # it might be an alias
203 206 name = arg
204 207 try:
205 208 cmd = ip.alias_manager.retrieve_alias(name)
206 209 except ValueError as e:
207 210 raise UsageError("Unknown variable '%s'" % name) from e
208 211
209 212 staliases = db.get('stored_aliases',{})
210 213 staliases[name] = cmd
211 214 db['stored_aliases'] = staliases
212 215 print("Alias stored: %s (%s)" % (name, cmd))
213 216 return
214 217
215 218 else:
216 219 modname = getattr(inspect.getmodule(obj), '__name__', '')
217 220 if modname == '__main__':
218 221 print(textwrap.dedent("""\
219 222 Warning:%s is %s
220 223 Proper storage of interactively declared classes (or instances
221 224 of those classes) is not possible! Only instances
222 225 of classes in real modules on file system can be %%store'd.
223 226 """ % (arg, obj) ))
224 227 return
225 228 #pickled = pickle.dumps(obj)
226 229 db[ 'autorestore/' + arg ] = obj
227 230 print("Stored '%s' (%s)" % (arg, obj.__class__.__name__))
228 231
229 232
230 233 def load_ipython_extension(ip):
231 234 """Load the extension in IPython."""
232 235 ip.register_magics(StoreMagics)
233 236
@@ -1,213 +1,215
1 1 """Extra magics for terminal use."""
2 2
3 3 # Copyright (c) IPython Development Team.
4 4 # Distributed under the terms of the Modified BSD License.
5 5
6 6
7 7 from logging import error
8 8 import os
9 9 import sys
10 10
11 11 from IPython.core.error import TryNext, UsageError
12 12 from IPython.core.magic import Magics, magics_class, line_magic
13 13 from IPython.lib.clipboard import ClipboardEmpty
14 from IPython.testing.skipdoctest import skip_doctest
14 15 from IPython.utils.text import SList, strip_email_quotes
15 16 from IPython.utils import py3compat
16 17
17 18 def get_pasted_lines(sentinel, l_input=py3compat.input, quiet=False):
18 19 """ Yield pasted lines until the user enters the given sentinel value.
19 20 """
20 21 if not quiet:
21 22 print("Pasting code; enter '%s' alone on the line to stop or use Ctrl-D." \
22 23 % sentinel)
23 24 prompt = ":"
24 25 else:
25 26 prompt = ""
26 27 while True:
27 28 try:
28 29 l = l_input(prompt)
29 30 if l == sentinel:
30 31 return
31 32 else:
32 33 yield l
33 34 except EOFError:
34 35 print('<EOF>')
35 36 return
36 37
37 38
38 39 @magics_class
39 40 class TerminalMagics(Magics):
40 41 def __init__(self, shell):
41 42 super(TerminalMagics, self).__init__(shell)
42 43
43 44 def store_or_execute(self, block, name):
44 45 """ Execute a block, or store it in a variable, per the user's request.
45 46 """
46 47 if name:
47 48 # If storing it for further editing
48 49 self.shell.user_ns[name] = SList(block.splitlines())
49 50 print("Block assigned to '%s'" % name)
50 51 else:
51 52 b = self.preclean_input(block)
52 53 self.shell.user_ns['pasted_block'] = b
53 54 self.shell.using_paste_magics = True
54 55 try:
55 56 self.shell.run_cell(b)
56 57 finally:
57 58 self.shell.using_paste_magics = False
58 59
59 60 def preclean_input(self, block):
60 61 lines = block.splitlines()
61 62 while lines and not lines[0].strip():
62 63 lines = lines[1:]
63 64 return strip_email_quotes('\n'.join(lines))
64 65
65 66 def rerun_pasted(self, name='pasted_block'):
66 67 """ Rerun a previously pasted command.
67 68 """
68 69 b = self.shell.user_ns.get(name)
69 70
70 71 # Sanity checks
71 72 if b is None:
72 73 raise UsageError('No previous pasted block available')
73 74 if not isinstance(b, str):
74 75 raise UsageError(
75 76 "Variable 'pasted_block' is not a string, can't execute")
76 77
77 78 print("Re-executing '%s...' (%d chars)"% (b.split('\n',1)[0], len(b)))
78 79 self.shell.run_cell(b)
79 80
80 81 @line_magic
81 82 def autoindent(self, parameter_s = ''):
82 83 """Toggle autoindent on/off (deprecated)"""
83 84 self.shell.set_autoindent()
84 85 print("Automatic indentation is:",['OFF','ON'][self.shell.autoindent])
85 86
87 @skip_doctest
86 88 @line_magic
87 89 def cpaste(self, parameter_s=''):
88 90 """Paste & execute a pre-formatted code block from clipboard.
89 91
90 92 You must terminate the block with '--' (two minus-signs) or Ctrl-D
91 93 alone on the line. You can also provide your own sentinel with '%paste
92 94 -s %%' ('%%' is the new sentinel for this operation).
93 95
94 96 The block is dedented prior to execution to enable execution of method
95 97 definitions. '>' and '+' characters at the beginning of a line are
96 98 ignored, to allow pasting directly from e-mails, diff files and
97 99 doctests (the '...' continuation prompt is also stripped). The
98 100 executed block is also assigned to variable named 'pasted_block' for
99 101 later editing with '%edit pasted_block'.
100 102
101 103 You can also pass a variable name as an argument, e.g. '%cpaste foo'.
102 104 This assigns the pasted block to variable 'foo' as string, without
103 105 dedenting or executing it (preceding >>> and + is still stripped)
104 106
105 107 '%cpaste -r' re-executes the block previously entered by cpaste.
106 108 '%cpaste -q' suppresses any additional output messages.
107 109
108 110 Do not be alarmed by garbled output on Windows (it's a readline bug).
109 111 Just press enter and type -- (and press enter again) and the block
110 112 will be what was just pasted.
111 113
112 114 Shell escapes are not supported (yet).
113 115
114 116 See also
115 117 --------
116 118 paste: automatically pull code from clipboard.
117 119
118 120 Examples
119 121 --------
120 122 ::
121 123
122 124 In [8]: %cpaste
123 125 Pasting code; enter '--' alone on the line to stop.
124 126 :>>> a = ["world!", "Hello"]
125 127 :>>> print(" ".join(sorted(a)))
126 128 :--
127 129 Hello world!
128 130
129 131 ::
130 132 In [8]: %cpaste
131 133 Pasting code; enter '--' alone on the line to stop.
132 134 :>>> %alias_magic t timeit
133 135 :>>> %t -n1 pass
134 136 :--
135 137 Created `%t` as an alias for `%timeit`.
136 138 Created `%%t` as an alias for `%%timeit`.
137 139 354 ns ± 224 ns per loop (mean ± std. dev. of 7 runs, 1 loop each)
138 140 """
139 141 opts, name = self.parse_options(parameter_s, 'rqs:', mode='string')
140 142 if 'r' in opts:
141 143 self.rerun_pasted()
142 144 return
143 145
144 146 quiet = ('q' in opts)
145 147
146 148 sentinel = opts.get('s', u'--')
147 149 block = '\n'.join(get_pasted_lines(sentinel, quiet=quiet))
148 150 self.store_or_execute(block, name)
149 151
150 152 @line_magic
151 153 def paste(self, parameter_s=''):
152 154 """Paste & execute a pre-formatted code block from clipboard.
153 155
154 156 The text is pulled directly from the clipboard without user
155 157 intervention and printed back on the screen before execution (unless
156 158 the -q flag is given to force quiet mode).
157 159
158 160 The block is dedented prior to execution to enable execution of method
159 161 definitions. '>' and '+' characters at the beginning of a line are
160 162 ignored, to allow pasting directly from e-mails, diff files and
161 163 doctests (the '...' continuation prompt is also stripped). The
162 164 executed block is also assigned to variable named 'pasted_block' for
163 165 later editing with '%edit pasted_block'.
164 166
165 167 You can also pass a variable name as an argument, e.g. '%paste foo'.
166 168 This assigns the pasted block to variable 'foo' as string, without
167 169 executing it (preceding >>> and + is still stripped).
168 170
169 171 Options:
170 172
171 173 -r: re-executes the block previously entered by cpaste.
172 174
173 175 -q: quiet mode: do not echo the pasted text back to the terminal.
174 176
175 177 IPython statements (magics, shell escapes) are not supported (yet).
176 178
177 179 See also
178 180 --------
179 181 cpaste: manually paste code into terminal until you mark its end.
180 182 """
181 183 opts, name = self.parse_options(parameter_s, 'rq', mode='string')
182 184 if 'r' in opts:
183 185 self.rerun_pasted()
184 186 return
185 187 try:
186 188 block = self.shell.hooks.clipboard_get()
187 189 except TryNext as clipboard_exc:
188 190 message = getattr(clipboard_exc, 'args')
189 191 if message:
190 192 error(message[0])
191 193 else:
192 194 error('Could not get text from the clipboard.')
193 195 return
194 196 except ClipboardEmpty as e:
195 197 raise UsageError("The clipboard appears to be empty") from e
196 198
197 199 # By default, echo back to terminal unless quiet mode is requested
198 200 if 'q' not in opts:
199 201 write = self.shell.write
200 202 write(self.shell.pycolorize(block))
201 203 if not block.endswith('\n'):
202 204 write('\n')
203 205 write("## -- End pasted text --\n")
204 206
205 207 self.store_or_execute(block, name)
206 208
207 209 # Class-level: add a '%cls' magic only on Windows
208 210 if sys.platform == 'win32':
209 211 @line_magic
210 212 def cls(self, s):
211 213 """Clear screen.
212 214 """
213 215 os.system("cls")
General Comments 0
You need to be logged in to leave comments. Login now