##// END OF EJS Templates
MAINT: refactor/please mypy....
Matthias Bussonnier -
Show More
@@ -1,41 +1,38 b''
1 1 name: Run MyPy
2 2
3 3 on:
4 4 push:
5 5 branches: [ main, 7.x]
6 6 pull_request:
7 7 branches: [ main, 7.x]
8 8
9 9 permissions:
10 10 contents: read
11 11
12 12 jobs:
13 13 build:
14 14
15 15 runs-on: ubuntu-latest
16 16 strategy:
17 17 matrix:
18 18 python-version: ["3.x"]
19 19
20 20 steps:
21 21 - uses: actions/checkout@v3
22 22 - name: Set up Python ${{ matrix.python-version }}
23 23 uses: actions/setup-python@v4
24 24 with:
25 25 python-version: ${{ matrix.python-version }}
26 26 - name: Install dependencies
27 27 run: |
28 28 python -m pip install --upgrade pip
29 pip install mypy pyflakes flake8
29 pip install mypy pyflakes flake8 types-decorator
30 30 - name: Lint with mypy
31 31 run: |
32 32 set -e
33 mypy -p IPython.terminal
34 mypy -p IPython.core.magics
35 mypy -p IPython.core.guarded_eval
36 mypy -p IPython.core.completer
33 mypy IPython
37 34 - name: Lint with pyflakes
38 35 run: |
39 36 set -e
40 37 flake8 IPython/core/magics/script.py
41 38 flake8 IPython/core/magics/packaging.py
@@ -1,1026 +1,1028 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Display formatters.
3 3
4 4 Inheritance diagram:
5 5
6 6 .. inheritance-diagram:: IPython.core.formatters
7 7 :parts: 3
8 8 """
9 9
10 10 # Copyright (c) IPython Development Team.
11 11 # Distributed under the terms of the Modified BSD License.
12 12
13 13 import abc
14 14 import sys
15 15 import traceback
16 16 import warnings
17 17 from io import StringIO
18 18
19 19 from decorator import decorator
20 20
21 21 from traitlets.config.configurable import Configurable
22 22 from .getipython import get_ipython
23 23 from ..utils.sentinel import Sentinel
24 24 from ..utils.dir2 import get_real_method
25 25 from ..lib import pretty
26 26 from traitlets import (
27 27 Bool, Dict, Integer, Unicode, CUnicode, ObjectName, List,
28 28 ForwardDeclaredInstance,
29 29 default, observe,
30 30 )
31 31
32 from typing import Any
33
32 34
33 35 class DisplayFormatter(Configurable):
34 36
35 37 active_types = List(Unicode(),
36 38 help="""List of currently active mime-types to display.
37 39 You can use this to set a white-list for formats to display.
38 40
39 41 Most users will not need to change this value.
40 42 """).tag(config=True)
41 43
42 44 @default('active_types')
43 45 def _active_types_default(self):
44 46 return self.format_types
45 47
46 48 @observe('active_types')
47 49 def _active_types_changed(self, change):
48 50 for key, formatter in self.formatters.items():
49 51 if key in change['new']:
50 52 formatter.enabled = True
51 53 else:
52 54 formatter.enabled = False
53 55
54 56 ipython_display_formatter = ForwardDeclaredInstance('FormatterABC')
55 57 @default('ipython_display_formatter')
56 58 def _default_formatter(self):
57 59 return IPythonDisplayFormatter(parent=self)
58 60
59 61 mimebundle_formatter = ForwardDeclaredInstance('FormatterABC')
60 62 @default('mimebundle_formatter')
61 63 def _default_mime_formatter(self):
62 64 return MimeBundleFormatter(parent=self)
63 65
64 66 # A dict of formatter whose keys are format types (MIME types) and whose
65 67 # values are subclasses of BaseFormatter.
66 68 formatters = Dict()
67 69 @default('formatters')
68 70 def _formatters_default(self):
69 71 """Activate the default formatters."""
70 72 formatter_classes = [
71 73 PlainTextFormatter,
72 74 HTMLFormatter,
73 75 MarkdownFormatter,
74 76 SVGFormatter,
75 77 PNGFormatter,
76 78 PDFFormatter,
77 79 JPEGFormatter,
78 80 LatexFormatter,
79 81 JSONFormatter,
80 82 JavascriptFormatter
81 83 ]
82 84 d = {}
83 85 for cls in formatter_classes:
84 86 f = cls(parent=self)
85 87 d[f.format_type] = f
86 88 return d
87 89
88 90 def format(self, obj, include=None, exclude=None):
89 91 """Return a format data dict for an object.
90 92
91 93 By default all format types will be computed.
92 94
93 95 The following MIME types are usually implemented:
94 96
95 97 * text/plain
96 98 * text/html
97 99 * text/markdown
98 100 * text/latex
99 101 * application/json
100 102 * application/javascript
101 103 * application/pdf
102 104 * image/png
103 105 * image/jpeg
104 106 * image/svg+xml
105 107
106 108 Parameters
107 109 ----------
108 110 obj : object
109 111 The Python object whose format data will be computed.
110 112 include : list, tuple or set; optional
111 113 A list of format type strings (MIME types) to include in the
112 114 format data dict. If this is set *only* the format types included
113 115 in this list will be computed.
114 116 exclude : list, tuple or set; optional
115 117 A list of format type string (MIME types) to exclude in the format
116 118 data dict. If this is set all format types will be computed,
117 119 except for those included in this argument.
118 120 Mimetypes present in exclude will take precedence over the ones in include
119 121
120 122 Returns
121 123 -------
122 124 (format_dict, metadata_dict) : tuple of two dicts
123 125 format_dict is a dictionary of key/value pairs, one of each format that was
124 126 generated for the object. The keys are the format types, which
125 127 will usually be MIME type strings and the values and JSON'able
126 128 data structure containing the raw data for the representation in
127 129 that format.
128 130
129 131 metadata_dict is a dictionary of metadata about each mime-type output.
130 132 Its keys will be a strict subset of the keys in format_dict.
131 133
132 134 Notes
133 135 -----
134 136 If an object implement `_repr_mimebundle_` as well as various
135 137 `_repr_*_`, the data returned by `_repr_mimebundle_` will take
136 138 precedence and the corresponding `_repr_*_` for this mimetype will
137 139 not be called.
138 140
139 141 """
140 142 format_dict = {}
141 143 md_dict = {}
142 144
143 145 if self.ipython_display_formatter(obj):
144 146 # object handled itself, don't proceed
145 147 return {}, {}
146 148
147 149 format_dict, md_dict = self.mimebundle_formatter(obj, include=include, exclude=exclude)
148 150
149 151 if format_dict or md_dict:
150 152 if include:
151 153 format_dict = {k:v for k,v in format_dict.items() if k in include}
152 154 md_dict = {k:v for k,v in md_dict.items() if k in include}
153 155 if exclude:
154 156 format_dict = {k:v for k,v in format_dict.items() if k not in exclude}
155 157 md_dict = {k:v for k,v in md_dict.items() if k not in exclude}
156 158
157 159 for format_type, formatter in self.formatters.items():
158 160 if format_type in format_dict:
159 161 # already got it from mimebundle, maybe don't render again.
160 162 # exception: manually registered per-mime renderer
161 163 # check priority:
162 164 # 1. user-registered per-mime formatter
163 165 # 2. mime-bundle (user-registered or repr method)
164 166 # 3. default per-mime formatter (e.g. repr method)
165 167 try:
166 168 formatter.lookup(obj)
167 169 except KeyError:
168 170 # no special formatter, use mime-bundle-provided value
169 171 continue
170 172 if include and format_type not in include:
171 173 continue
172 174 if exclude and format_type in exclude:
173 175 continue
174 176
175 177 md = None
176 178 try:
177 179 data = formatter(obj)
178 180 except:
179 181 # FIXME: log the exception
180 182 raise
181 183
182 184 # formatters can return raw data or (data, metadata)
183 185 if isinstance(data, tuple) and len(data) == 2:
184 186 data, md = data
185 187
186 188 if data is not None:
187 189 format_dict[format_type] = data
188 190 if md is not None:
189 191 md_dict[format_type] = md
190 192 return format_dict, md_dict
191 193
192 194 @property
193 195 def format_types(self):
194 196 """Return the format types (MIME types) of the active formatters."""
195 197 return list(self.formatters.keys())
196 198
197 199
198 200 #-----------------------------------------------------------------------------
199 201 # Formatters for specific format types (text, html, svg, etc.)
200 202 #-----------------------------------------------------------------------------
201 203
202 204
203 205 def _safe_repr(obj):
204 206 """Try to return a repr of an object
205 207
206 208 always returns a string, at least.
207 209 """
208 210 try:
209 211 return repr(obj)
210 212 except Exception as e:
211 213 return "un-repr-able object (%r)" % e
212 214
213 215
214 216 class FormatterWarning(UserWarning):
215 217 """Warning class for errors in formatters"""
216 218
217 219 @decorator
218 220 def catch_format_error(method, self, *args, **kwargs):
219 221 """show traceback on failed format call"""
220 222 try:
221 223 r = method(self, *args, **kwargs)
222 224 except NotImplementedError:
223 225 # don't warn on NotImplementedErrors
224 226 return self._check_return(None, args[0])
225 227 except Exception:
226 228 exc_info = sys.exc_info()
227 229 ip = get_ipython()
228 230 if ip is not None:
229 231 ip.showtraceback(exc_info)
230 232 else:
231 233 traceback.print_exception(*exc_info)
232 234 return self._check_return(None, args[0])
233 235 return self._check_return(r, args[0])
234 236
235 237
236 238 class FormatterABC(metaclass=abc.ABCMeta):
237 239 """ Abstract base class for Formatters.
238 240
239 241 A formatter is a callable class that is responsible for computing the
240 242 raw format data for a particular format type (MIME type). For example,
241 243 an HTML formatter would have a format type of `text/html` and would return
242 244 the HTML representation of the object when called.
243 245 """
244 246
245 247 # The format type of the data returned, usually a MIME type.
246 248 format_type = 'text/plain'
247 249
248 250 # Is the formatter enabled...
249 251 enabled = True
250 252
251 253 @abc.abstractmethod
252 254 def __call__(self, obj):
253 255 """Return a JSON'able representation of the object.
254 256
255 257 If the object cannot be formatted by this formatter,
256 258 warn and return None.
257 259 """
258 260 return repr(obj)
259 261
260 262
261 263 def _mod_name_key(typ):
262 264 """Return a (__module__, __name__) tuple for a type.
263 265
264 266 Used as key in Formatter.deferred_printers.
265 267 """
266 268 module = getattr(typ, '__module__', None)
267 269 name = getattr(typ, '__name__', None)
268 270 return (module, name)
269 271
270 272
271 273 def _get_type(obj):
272 274 """Return the type of an instance (old and new-style)"""
273 275 return getattr(obj, '__class__', None) or type(obj)
274 276
275 277
276 278 _raise_key_error = Sentinel('_raise_key_error', __name__,
277 279 """
278 280 Special value to raise a KeyError
279 281
280 282 Raise KeyError in `BaseFormatter.pop` if passed as the default value to `pop`
281 283 """)
282 284
283 285
284 286 class BaseFormatter(Configurable):
285 287 """A base formatter class that is configurable.
286 288
287 289 This formatter should usually be used as the base class of all formatters.
288 290 It is a traited :class:`Configurable` class and includes an extensible
289 291 API for users to determine how their objects are formatted. The following
290 292 logic is used to find a function to format an given object.
291 293
292 294 1. The object is introspected to see if it has a method with the name
293 295 :attr:`print_method`. If is does, that object is passed to that method
294 296 for formatting.
295 297 2. If no print method is found, three internal dictionaries are consulted
296 298 to find print method: :attr:`singleton_printers`, :attr:`type_printers`
297 299 and :attr:`deferred_printers`.
298 300
299 301 Users should use these dictionaries to register functions that will be
300 302 used to compute the format data for their objects (if those objects don't
301 303 have the special print methods). The easiest way of using these
302 304 dictionaries is through the :meth:`for_type` and :meth:`for_type_by_name`
303 305 methods.
304 306
305 307 If no function/callable is found to compute the format data, ``None`` is
306 308 returned and this format type is not used.
307 309 """
308 310
309 format_type = Unicode('text/plain')
310 _return_type = str
311 format_type = Unicode("text/plain")
312 _return_type: Any = str
311 313
312 314 enabled = Bool(True).tag(config=True)
313 315
314 316 print_method = ObjectName('__repr__')
315 317
316 318 # The singleton printers.
317 319 # Maps the IDs of the builtin singleton objects to the format functions.
318 320 singleton_printers = Dict().tag(config=True)
319 321
320 322 # The type-specific printers.
321 323 # Map type objects to the format functions.
322 324 type_printers = Dict().tag(config=True)
323 325
324 326 # The deferred-import type-specific printers.
325 327 # Map (modulename, classname) pairs to the format functions.
326 328 deferred_printers = Dict().tag(config=True)
327 329
328 330 @catch_format_error
329 331 def __call__(self, obj):
330 332 """Compute the format for an object."""
331 333 if self.enabled:
332 334 # lookup registered printer
333 335 try:
334 336 printer = self.lookup(obj)
335 337 except KeyError:
336 338 pass
337 339 else:
338 340 return printer(obj)
339 341 # Finally look for special method names
340 342 method = get_real_method(obj, self.print_method)
341 343 if method is not None:
342 344 return method()
343 345 return None
344 346 else:
345 347 return None
346 348
347 349 def __contains__(self, typ):
348 350 """map in to lookup_by_type"""
349 351 try:
350 352 self.lookup_by_type(typ)
351 353 except KeyError:
352 354 return False
353 355 else:
354 356 return True
355 357
356 358 def _check_return(self, r, obj):
357 359 """Check that a return value is appropriate
358 360
359 361 Return the value if so, None otherwise, warning if invalid.
360 362 """
361 363 if r is None or isinstance(r, self._return_type) or \
362 364 (isinstance(r, tuple) and r and isinstance(r[0], self._return_type)):
363 365 return r
364 366 else:
365 367 warnings.warn(
366 368 "%s formatter returned invalid type %s (expected %s) for object: %s" % \
367 369 (self.format_type, type(r), self._return_type, _safe_repr(obj)),
368 370 FormatterWarning
369 371 )
370 372
371 373 def lookup(self, obj):
372 374 """Look up the formatter for a given instance.
373 375
374 376 Parameters
375 377 ----------
376 378 obj : object instance
377 379
378 380 Returns
379 381 -------
380 382 f : callable
381 383 The registered formatting callable for the type.
382 384
383 385 Raises
384 386 ------
385 387 KeyError if the type has not been registered.
386 388 """
387 389 # look for singleton first
388 390 obj_id = id(obj)
389 391 if obj_id in self.singleton_printers:
390 392 return self.singleton_printers[obj_id]
391 393 # then lookup by type
392 394 return self.lookup_by_type(_get_type(obj))
393 395
394 396 def lookup_by_type(self, typ):
395 397 """Look up the registered formatter for a type.
396 398
397 399 Parameters
398 400 ----------
399 401 typ : type or '__module__.__name__' string for a type
400 402
401 403 Returns
402 404 -------
403 405 f : callable
404 406 The registered formatting callable for the type.
405 407
406 408 Raises
407 409 ------
408 410 KeyError if the type has not been registered.
409 411 """
410 412 if isinstance(typ, str):
411 413 typ_key = tuple(typ.rsplit('.',1))
412 414 if typ_key not in self.deferred_printers:
413 415 # We may have it cached in the type map. We will have to
414 416 # iterate over all of the types to check.
415 417 for cls in self.type_printers:
416 418 if _mod_name_key(cls) == typ_key:
417 419 return self.type_printers[cls]
418 420 else:
419 421 return self.deferred_printers[typ_key]
420 422 else:
421 423 for cls in pretty._get_mro(typ):
422 424 if cls in self.type_printers or self._in_deferred_types(cls):
423 425 return self.type_printers[cls]
424 426
425 427 # If we have reached here, the lookup failed.
426 428 raise KeyError("No registered printer for {0!r}".format(typ))
427 429
428 430 def for_type(self, typ, func=None):
429 431 """Add a format function for a given type.
430 432
431 433 Parameters
432 434 ----------
433 435 typ : type or '__module__.__name__' string for a type
434 436 The class of the object that will be formatted using `func`.
435 437
436 438 func : callable
437 439 A callable for computing the format data.
438 440 `func` will be called with the object to be formatted,
439 441 and will return the raw data in this formatter's format.
440 442 Subclasses may use a different call signature for the
441 443 `func` argument.
442 444
443 445 If `func` is None or not specified, there will be no change,
444 446 only returning the current value.
445 447
446 448 Returns
447 449 -------
448 450 oldfunc : callable
449 451 The currently registered callable.
450 452 If you are registering a new formatter,
451 453 this will be the previous value (to enable restoring later).
452 454 """
453 455 # if string given, interpret as 'pkg.module.class_name'
454 456 if isinstance(typ, str):
455 457 type_module, type_name = typ.rsplit('.', 1)
456 458 return self.for_type_by_name(type_module, type_name, func)
457 459
458 460 try:
459 461 oldfunc = self.lookup_by_type(typ)
460 462 except KeyError:
461 463 oldfunc = None
462 464
463 465 if func is not None:
464 466 self.type_printers[typ] = func
465 467
466 468 return oldfunc
467 469
468 470 def for_type_by_name(self, type_module, type_name, func=None):
469 471 """Add a format function for a type specified by the full dotted
470 472 module and name of the type, rather than the type of the object.
471 473
472 474 Parameters
473 475 ----------
474 476 type_module : str
475 477 The full dotted name of the module the type is defined in, like
476 478 ``numpy``.
477 479
478 480 type_name : str
479 481 The name of the type (the class name), like ``dtype``
480 482
481 483 func : callable
482 484 A callable for computing the format data.
483 485 `func` will be called with the object to be formatted,
484 486 and will return the raw data in this formatter's format.
485 487 Subclasses may use a different call signature for the
486 488 `func` argument.
487 489
488 490 If `func` is None or unspecified, there will be no change,
489 491 only returning the current value.
490 492
491 493 Returns
492 494 -------
493 495 oldfunc : callable
494 496 The currently registered callable.
495 497 If you are registering a new formatter,
496 498 this will be the previous value (to enable restoring later).
497 499 """
498 500 key = (type_module, type_name)
499 501
500 502 try:
501 503 oldfunc = self.lookup_by_type("%s.%s" % key)
502 504 except KeyError:
503 505 oldfunc = None
504 506
505 507 if func is not None:
506 508 self.deferred_printers[key] = func
507 509 return oldfunc
508 510
509 511 def pop(self, typ, default=_raise_key_error):
510 512 """Pop a formatter for the given type.
511 513
512 514 Parameters
513 515 ----------
514 516 typ : type or '__module__.__name__' string for a type
515 517 default : object
516 518 value to be returned if no formatter is registered for typ.
517 519
518 520 Returns
519 521 -------
520 522 obj : object
521 523 The last registered object for the type.
522 524
523 525 Raises
524 526 ------
525 527 KeyError if the type is not registered and default is not specified.
526 528 """
527 529
528 530 if isinstance(typ, str):
529 531 typ_key = tuple(typ.rsplit('.',1))
530 532 if typ_key not in self.deferred_printers:
531 533 # We may have it cached in the type map. We will have to
532 534 # iterate over all of the types to check.
533 535 for cls in self.type_printers:
534 536 if _mod_name_key(cls) == typ_key:
535 537 old = self.type_printers.pop(cls)
536 538 break
537 539 else:
538 540 old = default
539 541 else:
540 542 old = self.deferred_printers.pop(typ_key)
541 543 else:
542 544 if typ in self.type_printers:
543 545 old = self.type_printers.pop(typ)
544 546 else:
545 547 old = self.deferred_printers.pop(_mod_name_key(typ), default)
546 548 if old is _raise_key_error:
547 549 raise KeyError("No registered value for {0!r}".format(typ))
548 550 return old
549 551
550 552 def _in_deferred_types(self, cls):
551 553 """
552 554 Check if the given class is specified in the deferred type registry.
553 555
554 556 Successful matches will be moved to the regular type registry for future use.
555 557 """
556 558 mod = getattr(cls, '__module__', None)
557 559 name = getattr(cls, '__name__', None)
558 560 key = (mod, name)
559 561 if key in self.deferred_printers:
560 562 # Move the printer over to the regular registry.
561 563 printer = self.deferred_printers.pop(key)
562 564 self.type_printers[cls] = printer
563 565 return True
564 566 return False
565 567
566 568
567 569 class PlainTextFormatter(BaseFormatter):
568 570 """The default pretty-printer.
569 571
570 572 This uses :mod:`IPython.lib.pretty` to compute the format data of
571 573 the object. If the object cannot be pretty printed, :func:`repr` is used.
572 574 See the documentation of :mod:`IPython.lib.pretty` for details on
573 575 how to write pretty printers. Here is a simple example::
574 576
575 577 def dtype_pprinter(obj, p, cycle):
576 578 if cycle:
577 579 return p.text('dtype(...)')
578 580 if hasattr(obj, 'fields'):
579 581 if obj.fields is None:
580 582 p.text(repr(obj))
581 583 else:
582 584 p.begin_group(7, 'dtype([')
583 585 for i, field in enumerate(obj.descr):
584 586 if i > 0:
585 587 p.text(',')
586 588 p.breakable()
587 589 p.pretty(field)
588 590 p.end_group(7, '])')
589 591 """
590 592
591 593 # The format type of data returned.
592 594 format_type = Unicode('text/plain')
593 595
594 596 # This subclass ignores this attribute as it always need to return
595 597 # something.
596 598 enabled = Bool(True).tag(config=False)
597 599
598 600 max_seq_length = Integer(pretty.MAX_SEQ_LENGTH,
599 601 help="""Truncate large collections (lists, dicts, tuples, sets) to this size.
600 602
601 603 Set to 0 to disable truncation.
602 604 """
603 605 ).tag(config=True)
604 606
605 607 # Look for a _repr_pretty_ methods to use for pretty printing.
606 608 print_method = ObjectName('_repr_pretty_')
607 609
608 610 # Whether to pretty-print or not.
609 611 pprint = Bool(True).tag(config=True)
610 612
611 613 # Whether to be verbose or not.
612 614 verbose = Bool(False).tag(config=True)
613 615
614 616 # The maximum width.
615 617 max_width = Integer(79).tag(config=True)
616 618
617 619 # The newline character.
618 620 newline = Unicode('\n').tag(config=True)
619 621
620 622 # format-string for pprinting floats
621 623 float_format = Unicode('%r')
622 624 # setter for float precision, either int or direct format-string
623 625 float_precision = CUnicode('').tag(config=True)
624 626
625 627 @observe('float_precision')
626 628 def _float_precision_changed(self, change):
627 629 """float_precision changed, set float_format accordingly.
628 630
629 631 float_precision can be set by int or str.
630 632 This will set float_format, after interpreting input.
631 633 If numpy has been imported, numpy print precision will also be set.
632 634
633 635 integer `n` sets format to '%.nf', otherwise, format set directly.
634 636
635 637 An empty string returns to defaults (repr for float, 8 for numpy).
636 638
637 639 This parameter can be set via the '%precision' magic.
638 640 """
639 641 new = change['new']
640 642 if '%' in new:
641 643 # got explicit format string
642 644 fmt = new
643 645 try:
644 646 fmt%3.14159
645 647 except Exception as e:
646 648 raise ValueError("Precision must be int or format string, not %r"%new) from e
647 649 elif new:
648 650 # otherwise, should be an int
649 651 try:
650 652 i = int(new)
651 653 assert i >= 0
652 654 except ValueError as e:
653 655 raise ValueError("Precision must be int or format string, not %r"%new) from e
654 656 except AssertionError as e:
655 657 raise ValueError("int precision must be non-negative, not %r"%i) from e
656 658
657 659 fmt = '%%.%if'%i
658 660 if 'numpy' in sys.modules:
659 661 # set numpy precision if it has been imported
660 662 import numpy
661 663 numpy.set_printoptions(precision=i)
662 664 else:
663 665 # default back to repr
664 666 fmt = '%r'
665 667 if 'numpy' in sys.modules:
666 668 import numpy
667 669 # numpy default is 8
668 670 numpy.set_printoptions(precision=8)
669 671 self.float_format = fmt
670 672
671 673 # Use the default pretty printers from IPython.lib.pretty.
672 674 @default('singleton_printers')
673 675 def _singleton_printers_default(self):
674 676 return pretty._singleton_pprinters.copy()
675 677
676 678 @default('type_printers')
677 679 def _type_printers_default(self):
678 680 d = pretty._type_pprinters.copy()
679 681 d[float] = lambda obj,p,cycle: p.text(self.float_format%obj)
680 682 # if NumPy is used, set precision for its float64 type
681 683 if "numpy" in sys.modules:
682 684 import numpy
683 685
684 686 d[numpy.float64] = lambda obj, p, cycle: p.text(self.float_format % obj)
685 687 return d
686 688
687 689 @default('deferred_printers')
688 690 def _deferred_printers_default(self):
689 691 return pretty._deferred_type_pprinters.copy()
690 692
691 693 #### FormatterABC interface ####
692 694
693 695 @catch_format_error
694 696 def __call__(self, obj):
695 697 """Compute the pretty representation of the object."""
696 698 if not self.pprint:
697 699 return repr(obj)
698 700 else:
699 701 stream = StringIO()
700 702 printer = pretty.RepresentationPrinter(stream, self.verbose,
701 703 self.max_width, self.newline,
702 704 max_seq_length=self.max_seq_length,
703 705 singleton_pprinters=self.singleton_printers,
704 706 type_pprinters=self.type_printers,
705 707 deferred_pprinters=self.deferred_printers)
706 708 printer.pretty(obj)
707 709 printer.flush()
708 710 return stream.getvalue()
709 711
710 712
711 713 class HTMLFormatter(BaseFormatter):
712 714 """An HTML formatter.
713 715
714 716 To define the callables that compute the HTML representation of your
715 717 objects, define a :meth:`_repr_html_` method or use the :meth:`for_type`
716 718 or :meth:`for_type_by_name` methods to register functions that handle
717 719 this.
718 720
719 721 The return value of this formatter should be a valid HTML snippet that
720 722 could be injected into an existing DOM. It should *not* include the
721 723 ```<html>`` or ```<body>`` tags.
722 724 """
723 725 format_type = Unicode('text/html')
724 726
725 727 print_method = ObjectName('_repr_html_')
726 728
727 729
728 730 class MarkdownFormatter(BaseFormatter):
729 731 """A Markdown formatter.
730 732
731 733 To define the callables that compute the Markdown representation of your
732 734 objects, define a :meth:`_repr_markdown_` method or use the :meth:`for_type`
733 735 or :meth:`for_type_by_name` methods to register functions that handle
734 736 this.
735 737
736 738 The return value of this formatter should be a valid Markdown.
737 739 """
738 740 format_type = Unicode('text/markdown')
739 741
740 742 print_method = ObjectName('_repr_markdown_')
741 743
742 744 class SVGFormatter(BaseFormatter):
743 745 """An SVG formatter.
744 746
745 747 To define the callables that compute the SVG representation of your
746 748 objects, define a :meth:`_repr_svg_` method or use the :meth:`for_type`
747 749 or :meth:`for_type_by_name` methods to register functions that handle
748 750 this.
749 751
750 752 The return value of this formatter should be valid SVG enclosed in
751 753 ```<svg>``` tags, that could be injected into an existing DOM. It should
752 754 *not* include the ```<html>`` or ```<body>`` tags.
753 755 """
754 756 format_type = Unicode('image/svg+xml')
755 757
756 758 print_method = ObjectName('_repr_svg_')
757 759
758 760
759 761 class PNGFormatter(BaseFormatter):
760 762 """A PNG formatter.
761 763
762 764 To define the callables that compute the PNG representation of your
763 765 objects, define a :meth:`_repr_png_` method or use the :meth:`for_type`
764 766 or :meth:`for_type_by_name` methods to register functions that handle
765 767 this.
766 768
767 769 The return value of this formatter should be raw PNG data, *not*
768 770 base64 encoded.
769 771 """
770 772 format_type = Unicode('image/png')
771 773
772 774 print_method = ObjectName('_repr_png_')
773 775
774 776 _return_type = (bytes, str)
775 777
776 778
777 779 class JPEGFormatter(BaseFormatter):
778 780 """A JPEG formatter.
779 781
780 782 To define the callables that compute the JPEG representation of your
781 783 objects, define a :meth:`_repr_jpeg_` method or use the :meth:`for_type`
782 784 or :meth:`for_type_by_name` methods to register functions that handle
783 785 this.
784 786
785 787 The return value of this formatter should be raw JPEG data, *not*
786 788 base64 encoded.
787 789 """
788 790 format_type = Unicode('image/jpeg')
789 791
790 792 print_method = ObjectName('_repr_jpeg_')
791 793
792 794 _return_type = (bytes, str)
793 795
794 796
795 797 class LatexFormatter(BaseFormatter):
796 798 """A LaTeX formatter.
797 799
798 800 To define the callables that compute the LaTeX representation of your
799 801 objects, define a :meth:`_repr_latex_` method or use the :meth:`for_type`
800 802 or :meth:`for_type_by_name` methods to register functions that handle
801 803 this.
802 804
803 805 The return value of this formatter should be a valid LaTeX equation,
804 806 enclosed in either ```$```, ```$$``` or another LaTeX equation
805 807 environment.
806 808 """
807 809 format_type = Unicode('text/latex')
808 810
809 811 print_method = ObjectName('_repr_latex_')
810 812
811 813
812 814 class JSONFormatter(BaseFormatter):
813 815 """A JSON string formatter.
814 816
815 817 To define the callables that compute the JSONable representation of
816 818 your objects, define a :meth:`_repr_json_` method or use the :meth:`for_type`
817 819 or :meth:`for_type_by_name` methods to register functions that handle
818 820 this.
819 821
820 822 The return value of this formatter should be a JSONable list or dict.
821 823 JSON scalars (None, number, string) are not allowed, only dict or list containers.
822 824 """
823 825 format_type = Unicode('application/json')
824 826 _return_type = (list, dict)
825 827
826 828 print_method = ObjectName('_repr_json_')
827 829
828 830 def _check_return(self, r, obj):
829 831 """Check that a return value is appropriate
830 832
831 833 Return the value if so, None otherwise, warning if invalid.
832 834 """
833 835 if r is None:
834 836 return
835 837 md = None
836 838 if isinstance(r, tuple):
837 839 # unpack data, metadata tuple for type checking on first element
838 840 r, md = r
839 841
840 842 assert not isinstance(
841 843 r, str
842 844 ), "JSON-as-string has been deprecated since IPython < 3"
843 845
844 846 if md is not None:
845 847 # put the tuple back together
846 848 r = (r, md)
847 849 return super(JSONFormatter, self)._check_return(r, obj)
848 850
849 851
850 852 class JavascriptFormatter(BaseFormatter):
851 853 """A Javascript formatter.
852 854
853 855 To define the callables that compute the Javascript representation of
854 856 your objects, define a :meth:`_repr_javascript_` method or use the
855 857 :meth:`for_type` or :meth:`for_type_by_name` methods to register functions
856 858 that handle this.
857 859
858 860 The return value of this formatter should be valid Javascript code and
859 861 should *not* be enclosed in ```<script>``` tags.
860 862 """
861 863 format_type = Unicode('application/javascript')
862 864
863 865 print_method = ObjectName('_repr_javascript_')
864 866
865 867
866 868 class PDFFormatter(BaseFormatter):
867 869 """A PDF formatter.
868 870
869 871 To define the callables that compute the PDF representation of your
870 872 objects, define a :meth:`_repr_pdf_` method or use the :meth:`for_type`
871 873 or :meth:`for_type_by_name` methods to register functions that handle
872 874 this.
873 875
874 876 The return value of this formatter should be raw PDF data, *not*
875 877 base64 encoded.
876 878 """
877 879 format_type = Unicode('application/pdf')
878 880
879 881 print_method = ObjectName('_repr_pdf_')
880 882
881 883 _return_type = (bytes, str)
882 884
883 885 class IPythonDisplayFormatter(BaseFormatter):
884 886 """An escape-hatch Formatter for objects that know how to display themselves.
885 887
886 888 To define the callables that compute the representation of your
887 889 objects, define a :meth:`_ipython_display_` method or use the :meth:`for_type`
888 890 or :meth:`for_type_by_name` methods to register functions that handle
889 891 this. Unlike mime-type displays, this method should not return anything,
890 892 instead calling any appropriate display methods itself.
891 893
892 894 This display formatter has highest priority.
893 895 If it fires, no other display formatter will be called.
894 896
895 897 Prior to IPython 6.1, `_ipython_display_` was the only way to display custom mime-types
896 898 without registering a new Formatter.
897 899
898 900 IPython 6.1 introduces `_repr_mimebundle_` for displaying custom mime-types,
899 901 so `_ipython_display_` should only be used for objects that require unusual
900 902 display patterns, such as multiple display calls.
901 903 """
902 904 print_method = ObjectName('_ipython_display_')
903 905 _return_type = (type(None), bool)
904 906
905 907 @catch_format_error
906 908 def __call__(self, obj):
907 909 """Compute the format for an object."""
908 910 if self.enabled:
909 911 # lookup registered printer
910 912 try:
911 913 printer = self.lookup(obj)
912 914 except KeyError:
913 915 pass
914 916 else:
915 917 printer(obj)
916 918 return True
917 919 # Finally look for special method names
918 920 method = get_real_method(obj, self.print_method)
919 921 if method is not None:
920 922 method()
921 923 return True
922 924
923 925
924 926 class MimeBundleFormatter(BaseFormatter):
925 927 """A Formatter for arbitrary mime-types.
926 928
927 929 Unlike other `_repr_<mimetype>_` methods,
928 930 `_repr_mimebundle_` should return mime-bundle data,
929 931 either the mime-keyed `data` dictionary or the tuple `(data, metadata)`.
930 932 Any mime-type is valid.
931 933
932 934 To define the callables that compute the mime-bundle representation of your
933 935 objects, define a :meth:`_repr_mimebundle_` method or use the :meth:`for_type`
934 936 or :meth:`for_type_by_name` methods to register functions that handle
935 937 this.
936 938
937 939 .. versionadded:: 6.1
938 940 """
939 941 print_method = ObjectName('_repr_mimebundle_')
940 942 _return_type = dict
941 943
942 944 def _check_return(self, r, obj):
943 945 r = super(MimeBundleFormatter, self)._check_return(r, obj)
944 946 # always return (data, metadata):
945 947 if r is None:
946 948 return {}, {}
947 949 if not isinstance(r, tuple):
948 950 return r, {}
949 951 return r
950 952
951 953 @catch_format_error
952 954 def __call__(self, obj, include=None, exclude=None):
953 955 """Compute the format for an object.
954 956
955 957 Identical to parent's method but we pass extra parameters to the method.
956 958
957 959 Unlike other _repr_*_ `_repr_mimebundle_` should allow extra kwargs, in
958 960 particular `include` and `exclude`.
959 961 """
960 962 if self.enabled:
961 963 # lookup registered printer
962 964 try:
963 965 printer = self.lookup(obj)
964 966 except KeyError:
965 967 pass
966 968 else:
967 969 return printer(obj)
968 970 # Finally look for special method names
969 971 method = get_real_method(obj, self.print_method)
970 972
971 973 if method is not None:
972 974 return method(include=include, exclude=exclude)
973 975 return None
974 976 else:
975 977 return None
976 978
977 979
978 980 FormatterABC.register(BaseFormatter)
979 981 FormatterABC.register(PlainTextFormatter)
980 982 FormatterABC.register(HTMLFormatter)
981 983 FormatterABC.register(MarkdownFormatter)
982 984 FormatterABC.register(SVGFormatter)
983 985 FormatterABC.register(PNGFormatter)
984 986 FormatterABC.register(PDFFormatter)
985 987 FormatterABC.register(JPEGFormatter)
986 988 FormatterABC.register(LatexFormatter)
987 989 FormatterABC.register(JSONFormatter)
988 990 FormatterABC.register(JavascriptFormatter)
989 991 FormatterABC.register(IPythonDisplayFormatter)
990 992 FormatterABC.register(MimeBundleFormatter)
991 993
992 994
993 995 def format_display_data(obj, include=None, exclude=None):
994 996 """Return a format data dict for an object.
995 997
996 998 By default all format types will be computed.
997 999
998 1000 Parameters
999 1001 ----------
1000 1002 obj : object
1001 1003 The Python object whose format data will be computed.
1002 1004
1003 1005 Returns
1004 1006 -------
1005 1007 format_dict : dict
1006 1008 A dictionary of key/value pairs, one or each format that was
1007 1009 generated for the object. The keys are the format types, which
1008 1010 will usually be MIME type strings and the values and JSON'able
1009 1011 data structure containing the raw data for the representation in
1010 1012 that format.
1011 1013 include : list or tuple, optional
1012 1014 A list of format type strings (MIME types) to include in the
1013 1015 format data dict. If this is set *only* the format types included
1014 1016 in this list will be computed.
1015 1017 exclude : list or tuple, optional
1016 1018 A list of format type string (MIME types) to exclude in the format
1017 1019 data dict. If this is set all format types will be computed,
1018 1020 except for those included in this argument.
1019 1021 """
1020 1022 from .interactiveshell import InteractiveShell
1021 1023
1022 1024 return InteractiveShell.instance().display_formatter.format(
1023 1025 obj,
1024 1026 include,
1025 1027 exclude
1026 1028 )
@@ -1,772 +1,773 b''
1 1 """DEPRECATED: Input handling and transformation machinery.
2 2
3 3 This module was deprecated in IPython 7.0, in favour of inputtransformer2.
4 4
5 5 The first class in this module, :class:`InputSplitter`, is designed to tell when
6 6 input from a line-oriented frontend is complete and should be executed, and when
7 7 the user should be prompted for another line of code instead. The name 'input
8 8 splitter' is largely for historical reasons.
9 9
10 10 A companion, :class:`IPythonInputSplitter`, provides the same functionality but
11 11 with full support for the extended IPython syntax (magics, system calls, etc).
12 12 The code to actually do these transformations is in :mod:`IPython.core.inputtransformer`.
13 13 :class:`IPythonInputSplitter` feeds the raw code to the transformers in order
14 14 and stores the results.
15 15
16 16 For more details, see the class docstrings below.
17 17 """
18 18
19 19 from warnings import warn
20 20
21 21 warn('IPython.core.inputsplitter is deprecated since IPython 7 in favor of `IPython.core.inputtransformer2`',
22 22 DeprecationWarning)
23 23
24 24 # Copyright (c) IPython Development Team.
25 25 # Distributed under the terms of the Modified BSD License.
26 26 import ast
27 27 import codeop
28 28 import io
29 29 import re
30 30 import sys
31 31 import tokenize
32 32 import warnings
33 33
34 from typing import List
35
34 36 from IPython.core.inputtransformer import (leading_indent,
35 37 classic_prompt,
36 38 ipy_prompt,
37 39 cellmagic,
38 40 assemble_logical_lines,
39 41 help_end,
40 42 escaped_commands,
41 43 assign_from_magic,
42 44 assign_from_system,
43 45 assemble_python_lines,
44 46 )
45 47
46 48 # These are available in this module for backwards compatibility.
47 49 from IPython.core.inputtransformer import (ESC_SHELL, ESC_SH_CAP, ESC_HELP,
48 50 ESC_HELP2, ESC_MAGIC, ESC_MAGIC2,
49 51 ESC_QUOTE, ESC_QUOTE2, ESC_PAREN, ESC_SEQUENCES)
50 52
51 53 #-----------------------------------------------------------------------------
52 54 # Utilities
53 55 #-----------------------------------------------------------------------------
54 56
55 57 # FIXME: These are general-purpose utilities that later can be moved to the
56 58 # general ward. Kept here for now because we're being very strict about test
57 59 # coverage with this code, and this lets us ensure that we keep 100% coverage
58 60 # while developing.
59 61
60 62 # compiled regexps for autoindent management
61 63 dedent_re = re.compile('|'.join([
62 64 r'^\s+raise(\s.*)?$', # raise statement (+ space + other stuff, maybe)
63 65 r'^\s+raise\([^\)]*\).*$', # wacky raise with immediate open paren
64 66 r'^\s+return(\s.*)?$', # normal return (+ space + other stuff, maybe)
65 67 r'^\s+return\([^\)]*\).*$', # wacky return with immediate open paren
66 68 r'^\s+pass\s*$', # pass (optionally followed by trailing spaces)
67 69 r'^\s+break\s*$', # break (optionally followed by trailing spaces)
68 70 r'^\s+continue\s*$', # continue (optionally followed by trailing spaces)
69 71 ]))
70 72 ini_spaces_re = re.compile(r'^([ \t\r\f\v]+)')
71 73
72 74 # regexp to match pure comment lines so we don't accidentally insert 'if 1:'
73 75 # before pure comments
74 76 comment_line_re = re.compile(r'^\s*\#')
75 77
76 78
77 79 def num_ini_spaces(s):
78 80 """Return the number of initial spaces in a string.
79 81
80 82 Note that tabs are counted as a single space. For now, we do *not* support
81 83 mixing of tabs and spaces in the user's input.
82 84
83 85 Parameters
84 86 ----------
85 87 s : string
86 88
87 89 Returns
88 90 -------
89 91 n : int
90 92 """
91 93
92 94 ini_spaces = ini_spaces_re.match(s)
93 95 if ini_spaces:
94 96 return ini_spaces.end()
95 97 else:
96 98 return 0
97 99
98 100 # Fake token types for partial_tokenize:
99 101 INCOMPLETE_STRING = tokenize.N_TOKENS
100 102 IN_MULTILINE_STATEMENT = tokenize.N_TOKENS + 1
101 103
102 104 # The 2 classes below have the same API as TokenInfo, but don't try to look up
103 105 # a token type name that they won't find.
104 106 class IncompleteString:
105 107 type = exact_type = INCOMPLETE_STRING
106 108 def __init__(self, s, start, end, line):
107 109 self.s = s
108 110 self.start = start
109 111 self.end = end
110 112 self.line = line
111 113
112 114 class InMultilineStatement:
113 115 type = exact_type = IN_MULTILINE_STATEMENT
114 116 def __init__(self, pos, line):
115 117 self.s = ''
116 118 self.start = self.end = pos
117 119 self.line = line
118 120
119 121 def partial_tokens(s):
120 122 """Iterate over tokens from a possibly-incomplete string of code.
121 123
122 124 This adds two special token types: INCOMPLETE_STRING and
123 125 IN_MULTILINE_STATEMENT. These can only occur as the last token yielded, and
124 126 represent the two main ways for code to be incomplete.
125 127 """
126 128 readline = io.StringIO(s).readline
127 129 token = tokenize.TokenInfo(tokenize.NEWLINE, '', (1, 0), (1, 0), '')
128 130 try:
129 131 for token in tokenize.generate_tokens(readline):
130 132 yield token
131 133 except tokenize.TokenError as e:
132 134 # catch EOF error
133 135 lines = s.splitlines(keepends=True)
134 136 end = len(lines), len(lines[-1])
135 137 if 'multi-line string' in e.args[0]:
136 138 l, c = start = token.end
137 139 s = lines[l-1][c:] + ''.join(lines[l:])
138 140 yield IncompleteString(s, start, end, lines[-1])
139 141 elif 'multi-line statement' in e.args[0]:
140 142 yield InMultilineStatement(end, lines[-1])
141 143 else:
142 144 raise
143 145
144 146 def find_next_indent(code):
145 147 """Find the number of spaces for the next line of indentation"""
146 148 tokens = list(partial_tokens(code))
147 149 if tokens[-1].type == tokenize.ENDMARKER:
148 150 tokens.pop()
149 151 if not tokens:
150 152 return 0
151 153 while (tokens[-1].type in {tokenize.DEDENT, tokenize.NEWLINE, tokenize.COMMENT}):
152 154 tokens.pop()
153 155
154 156 if tokens[-1].type == INCOMPLETE_STRING:
155 157 # Inside a multiline string
156 158 return 0
157 159
158 160 # Find the indents used before
159 161 prev_indents = [0]
160 162 def _add_indent(n):
161 163 if n != prev_indents[-1]:
162 164 prev_indents.append(n)
163 165
164 166 tokiter = iter(tokens)
165 167 for tok in tokiter:
166 168 if tok.type in {tokenize.INDENT, tokenize.DEDENT}:
167 169 _add_indent(tok.end[1])
168 170 elif (tok.type == tokenize.NL):
169 171 try:
170 172 _add_indent(next(tokiter).start[1])
171 173 except StopIteration:
172 174 break
173 175
174 176 last_indent = prev_indents.pop()
175 177
176 178 # If we've just opened a multiline statement (e.g. 'a = ['), indent more
177 179 if tokens[-1].type == IN_MULTILINE_STATEMENT:
178 180 if tokens[-2].exact_type in {tokenize.LPAR, tokenize.LSQB, tokenize.LBRACE}:
179 181 return last_indent + 4
180 182 return last_indent
181 183
182 184 if tokens[-1].exact_type == tokenize.COLON:
183 185 # Line ends with colon - indent
184 186 return last_indent + 4
185 187
186 188 if last_indent:
187 189 # Examine the last line for dedent cues - statements like return or
188 190 # raise which normally end a block of code.
189 191 last_line_starts = 0
190 192 for i, tok in enumerate(tokens):
191 193 if tok.type == tokenize.NEWLINE:
192 194 last_line_starts = i + 1
193 195
194 196 last_line_tokens = tokens[last_line_starts:]
195 197 names = [t.string for t in last_line_tokens if t.type == tokenize.NAME]
196 198 if names and names[0] in {'raise', 'return', 'pass', 'break', 'continue'}:
197 199 # Find the most recent indentation less than the current level
198 200 for indent in reversed(prev_indents):
199 201 if indent < last_indent:
200 202 return indent
201 203
202 204 return last_indent
203 205
204 206
205 207 def last_blank(src):
206 208 """Determine if the input source ends in a blank.
207 209
208 210 A blank is either a newline or a line consisting of whitespace.
209 211
210 212 Parameters
211 213 ----------
212 214 src : string
213 215 A single or multiline string.
214 216 """
215 217 if not src: return False
216 218 ll = src.splitlines()[-1]
217 219 return (ll == '') or ll.isspace()
218 220
219 221
220 222 last_two_blanks_re = re.compile(r'\n\s*\n\s*$', re.MULTILINE)
221 223 last_two_blanks_re2 = re.compile(r'.+\n\s*\n\s+$', re.MULTILINE)
222 224
223 225 def last_two_blanks(src):
224 226 """Determine if the input source ends in two blanks.
225 227
226 228 A blank is either a newline or a line consisting of whitespace.
227 229
228 230 Parameters
229 231 ----------
230 232 src : string
231 233 A single or multiline string.
232 234 """
233 235 if not src: return False
234 236 # The logic here is tricky: I couldn't get a regexp to work and pass all
235 237 # the tests, so I took a different approach: split the source by lines,
236 238 # grab the last two and prepend '###\n' as a stand-in for whatever was in
237 239 # the body before the last two lines. Then, with that structure, it's
238 240 # possible to analyze with two regexps. Not the most elegant solution, but
239 241 # it works. If anyone tries to change this logic, make sure to validate
240 242 # the whole test suite first!
241 243 new_src = '\n'.join(['###\n'] + src.splitlines()[-2:])
242 244 return (bool(last_two_blanks_re.match(new_src)) or
243 245 bool(last_two_blanks_re2.match(new_src)) )
244 246
245 247
246 248 def remove_comments(src):
247 249 """Remove all comments from input source.
248 250
249 251 Note: comments are NOT recognized inside of strings!
250 252
251 253 Parameters
252 254 ----------
253 255 src : string
254 256 A single or multiline input string.
255 257
256 258 Returns
257 259 -------
258 260 String with all Python comments removed.
259 261 """
260 262
261 263 return re.sub('#.*', '', src)
262 264
263 265
264 266 def get_input_encoding():
265 267 """Return the default standard input encoding.
266 268
267 269 If sys.stdin has no encoding, 'ascii' is returned."""
268 270 # There are strange environments for which sys.stdin.encoding is None. We
269 271 # ensure that a valid encoding is returned.
270 272 encoding = getattr(sys.stdin, 'encoding', None)
271 273 if encoding is None:
272 274 encoding = 'ascii'
273 275 return encoding
274 276
275 277 #-----------------------------------------------------------------------------
276 278 # Classes and functions for normal Python syntax handling
277 279 #-----------------------------------------------------------------------------
278 280
279 281 class InputSplitter(object):
280 282 r"""An object that can accumulate lines of Python source before execution.
281 283
282 284 This object is designed to be fed python source line-by-line, using
283 285 :meth:`push`. It will return on each push whether the currently pushed
284 286 code could be executed already. In addition, it provides a method called
285 287 :meth:`push_accepts_more` that can be used to query whether more input
286 288 can be pushed into a single interactive block.
287 289
288 290 This is a simple example of how an interactive terminal-based client can use
289 291 this tool::
290 292
291 293 isp = InputSplitter()
292 294 while isp.push_accepts_more():
293 295 indent = ' '*isp.indent_spaces
294 296 prompt = '>>> ' + indent
295 297 line = indent + raw_input(prompt)
296 298 isp.push(line)
297 299 print 'Input source was:\n', isp.source_reset(),
298 300 """
299 301 # A cache for storing the current indentation
300 302 # The first value stores the most recently processed source input
301 303 # The second value is the number of spaces for the current indentation
302 304 # If self.source matches the first value, the second value is a valid
303 305 # current indentation. Otherwise, the cache is invalid and the indentation
304 306 # must be recalculated.
305 307 _indent_spaces_cache = None, None
306 308 # String, indicating the default input encoding. It is computed by default
307 309 # at initialization time via get_input_encoding(), but it can be reset by a
308 310 # client with specific knowledge of the encoding.
309 311 encoding = ''
310 312 # String where the current full source input is stored, properly encoded.
311 313 # Reading this attribute is the normal way of querying the currently pushed
312 314 # source code, that has been properly encoded.
313 315 source = ''
314 316 # Code object corresponding to the current source. It is automatically
315 317 # synced to the source, so it can be queried at any time to obtain the code
316 318 # object; it will be None if the source doesn't compile to valid Python.
317 319 code = None
318 320
319 321 # Private attributes
320 322
321 323 # List with lines of input accumulated so far
322 _buffer = None
324 _buffer: List[str]
323 325 # Command compiler
324 _compile = None
326 _compile: codeop.CommandCompiler
325 327 # Boolean indicating whether the current block is complete
326 328 _is_complete = None
327 329 # Boolean indicating whether the current block has an unrecoverable syntax error
328 330 _is_invalid = False
329 331
330 def __init__(self):
331 """Create a new InputSplitter instance.
332 """
332 def __init__(self) -> None:
333 """Create a new InputSplitter instance."""
333 334 self._buffer = []
334 335 self._compile = codeop.CommandCompiler()
335 336 self.encoding = get_input_encoding()
336 337
337 338 def reset(self):
338 339 """Reset the input buffer and associated state."""
339 340 self._buffer[:] = []
340 341 self.source = ''
341 342 self.code = None
342 343 self._is_complete = False
343 344 self._is_invalid = False
344 345
345 346 def source_reset(self):
346 347 """Return the input source and perform a full reset.
347 348 """
348 349 out = self.source
349 350 self.reset()
350 351 return out
351 352
352 353 def check_complete(self, source):
353 354 """Return whether a block of code is ready to execute, or should be continued
354 355
355 356 This is a non-stateful API, and will reset the state of this InputSplitter.
356 357
357 358 Parameters
358 359 ----------
359 360 source : string
360 361 Python input code, which can be multiline.
361 362
362 363 Returns
363 364 -------
364 365 status : str
365 366 One of 'complete', 'incomplete', or 'invalid' if source is not a
366 367 prefix of valid code.
367 368 indent_spaces : int or None
368 369 The number of spaces by which to indent the next line of code. If
369 370 status is not 'incomplete', this is None.
370 371 """
371 372 self.reset()
372 373 try:
373 374 self.push(source)
374 375 except SyntaxError:
375 376 # Transformers in IPythonInputSplitter can raise SyntaxError,
376 377 # which push() will not catch.
377 378 return 'invalid', None
378 379 else:
379 380 if self._is_invalid:
380 381 return 'invalid', None
381 382 elif self.push_accepts_more():
382 383 return 'incomplete', self.get_indent_spaces()
383 384 else:
384 385 return 'complete', None
385 386 finally:
386 387 self.reset()
387 388
388 389 def push(self, lines:str) -> bool:
389 390 """Push one or more lines of input.
390 391
391 392 This stores the given lines and returns a status code indicating
392 393 whether the code forms a complete Python block or not.
393 394
394 395 Any exceptions generated in compilation are swallowed, but if an
395 396 exception was produced, the method returns True.
396 397
397 398 Parameters
398 399 ----------
399 400 lines : string
400 401 One or more lines of Python input.
401 402
402 403 Returns
403 404 -------
404 405 is_complete : boolean
405 406 True if the current input source (the result of the current input
406 407 plus prior inputs) forms a complete Python execution block. Note that
407 408 this value is also stored as a private attribute (``_is_complete``), so it
408 409 can be queried at any time.
409 410 """
410 411 assert isinstance(lines, str)
411 412 self._store(lines)
412 413 source = self.source
413 414
414 415 # Before calling _compile(), reset the code object to None so that if an
415 416 # exception is raised in compilation, we don't mislead by having
416 417 # inconsistent code/source attributes.
417 418 self.code, self._is_complete = None, None
418 419 self._is_invalid = False
419 420
420 421 # Honor termination lines properly
421 422 if source.endswith('\\\n'):
422 423 return False
423 424
424 425 try:
425 426 with warnings.catch_warnings():
426 427 warnings.simplefilter('error', SyntaxWarning)
427 428 self.code = self._compile(source, symbol="exec")
428 429 # Invalid syntax can produce any of a number of different errors from
429 430 # inside the compiler, so we have to catch them all. Syntax errors
430 431 # immediately produce a 'ready' block, so the invalid Python can be
431 432 # sent to the kernel for evaluation with possible ipython
432 433 # special-syntax conversion.
433 434 except (SyntaxError, OverflowError, ValueError, TypeError,
434 435 MemoryError, SyntaxWarning):
435 436 self._is_complete = True
436 437 self._is_invalid = True
437 438 else:
438 439 # Compilation didn't produce any exceptions (though it may not have
439 440 # given a complete code object)
440 441 self._is_complete = self.code is not None
441 442
442 443 return self._is_complete
443 444
444 445 def push_accepts_more(self):
445 446 """Return whether a block of interactive input can accept more input.
446 447
447 448 This method is meant to be used by line-oriented frontends, who need to
448 449 guess whether a block is complete or not based solely on prior and
449 450 current input lines. The InputSplitter considers it has a complete
450 451 interactive block and will not accept more input when either:
451 452
452 453 * A SyntaxError is raised
453 454
454 455 * The code is complete and consists of a single line or a single
455 456 non-compound statement
456 457
457 458 * The code is complete and has a blank line at the end
458 459
459 460 If the current input produces a syntax error, this method immediately
460 461 returns False but does *not* raise the syntax error exception, as
461 462 typically clients will want to send invalid syntax to an execution
462 463 backend which might convert the invalid syntax into valid Python via
463 464 one of the dynamic IPython mechanisms.
464 465 """
465 466
466 467 # With incomplete input, unconditionally accept more
467 468 # A syntax error also sets _is_complete to True - see push()
468 469 if not self._is_complete:
469 470 #print("Not complete") # debug
470 471 return True
471 472
472 473 # The user can make any (complete) input execute by leaving a blank line
473 474 last_line = self.source.splitlines()[-1]
474 475 if (not last_line) or last_line.isspace():
475 476 #print("Blank line") # debug
476 477 return False
477 478
478 479 # If there's just a single line or AST node, and we're flush left, as is
479 480 # the case after a simple statement such as 'a=1', we want to execute it
480 481 # straight away.
481 482 if self.get_indent_spaces() == 0:
482 483 if len(self.source.splitlines()) <= 1:
483 484 return False
484 485
485 486 try:
486 code_ast = ast.parse(u''.join(self._buffer))
487 code_ast = ast.parse("".join(self._buffer))
487 488 except Exception:
488 489 #print("Can't parse AST") # debug
489 490 return False
490 491 else:
491 492 if len(code_ast.body) == 1 and \
492 493 not hasattr(code_ast.body[0], 'body'):
493 494 #print("Simple statement") # debug
494 495 return False
495 496
496 497 # General fallback - accept more code
497 498 return True
498 499
499 500 def get_indent_spaces(self):
500 501 sourcefor, n = self._indent_spaces_cache
501 502 if sourcefor == self.source:
502 503 return n
503 504
504 505 # self.source always has a trailing newline
505 506 n = find_next_indent(self.source[:-1])
506 507 self._indent_spaces_cache = (self.source, n)
507 508 return n
508 509
509 510 # Backwards compatibility. I think all code that used .indent_spaces was
510 511 # inside IPython, but we can leave this here until IPython 7 in case any
511 512 # other modules are using it. -TK, November 2017
512 513 indent_spaces = property(get_indent_spaces)
513 514
514 515 def _store(self, lines, buffer=None, store='source'):
515 516 """Store one or more lines of input.
516 517
517 518 If input lines are not newline-terminated, a newline is automatically
518 519 appended."""
519 520
520 521 if buffer is None:
521 522 buffer = self._buffer
522 523
523 524 if lines.endswith('\n'):
524 525 buffer.append(lines)
525 526 else:
526 527 buffer.append(lines+'\n')
527 528 setattr(self, store, self._set_source(buffer))
528 529
529 530 def _set_source(self, buffer):
530 531 return u''.join(buffer)
531 532
532 533
533 534 class IPythonInputSplitter(InputSplitter):
534 535 """An input splitter that recognizes all of IPython's special syntax."""
535 536
536 537 # String with raw, untransformed input.
537 538 source_raw = ''
538 539
539 540 # Flag to track when a transformer has stored input that it hasn't given
540 541 # back yet.
541 542 transformer_accumulating = False
542 543
543 544 # Flag to track when assemble_python_lines has stored input that it hasn't
544 545 # given back yet.
545 546 within_python_line = False
546 547
547 548 # Private attributes
548 549
549 550 # List with lines of raw input accumulated so far.
550 551 _buffer_raw = None
551 552
552 553 def __init__(self, line_input_checker=True, physical_line_transforms=None,
553 554 logical_line_transforms=None, python_line_transforms=None):
554 555 super(IPythonInputSplitter, self).__init__()
555 556 self._buffer_raw = []
556 557 self._validate = True
557 558
558 559 if physical_line_transforms is not None:
559 560 self.physical_line_transforms = physical_line_transforms
560 561 else:
561 562 self.physical_line_transforms = [
562 563 leading_indent(),
563 564 classic_prompt(),
564 565 ipy_prompt(),
565 566 cellmagic(end_on_blank_line=line_input_checker),
566 567 ]
567 568
568 569 self.assemble_logical_lines = assemble_logical_lines()
569 570 if logical_line_transforms is not None:
570 571 self.logical_line_transforms = logical_line_transforms
571 572 else:
572 573 self.logical_line_transforms = [
573 574 help_end(),
574 575 escaped_commands(),
575 576 assign_from_magic(),
576 577 assign_from_system(),
577 578 ]
578 579
579 580 self.assemble_python_lines = assemble_python_lines()
580 581 if python_line_transforms is not None:
581 582 self.python_line_transforms = python_line_transforms
582 583 else:
583 584 # We don't use any of these at present
584 585 self.python_line_transforms = []
585 586
586 587 @property
587 588 def transforms(self):
588 589 "Quick access to all transformers."
589 590 return self.physical_line_transforms + \
590 591 [self.assemble_logical_lines] + self.logical_line_transforms + \
591 592 [self.assemble_python_lines] + self.python_line_transforms
592 593
593 594 @property
594 595 def transforms_in_use(self):
595 596 """Transformers, excluding logical line transformers if we're in a
596 597 Python line."""
597 598 t = self.physical_line_transforms[:]
598 599 if not self.within_python_line:
599 600 t += [self.assemble_logical_lines] + self.logical_line_transforms
600 601 return t + [self.assemble_python_lines] + self.python_line_transforms
601 602
602 603 def reset(self):
603 604 """Reset the input buffer and associated state."""
604 605 super(IPythonInputSplitter, self).reset()
605 606 self._buffer_raw[:] = []
606 607 self.source_raw = ''
607 608 self.transformer_accumulating = False
608 609 self.within_python_line = False
609 610
610 611 for t in self.transforms:
611 612 try:
612 613 t.reset()
613 614 except SyntaxError:
614 615 # Nothing that calls reset() expects to handle transformer
615 616 # errors
616 617 pass
617 618
618 619 def flush_transformers(self):
619 620 def _flush(transform, outs):
620 621 """yield transformed lines
621 622
622 623 always strings, never None
623 624
624 625 transform: the current transform
625 626 outs: an iterable of previously transformed inputs.
626 627 Each may be multiline, which will be passed
627 628 one line at a time to transform.
628 629 """
629 630 for out in outs:
630 631 for line in out.splitlines():
631 632 # push one line at a time
632 633 tmp = transform.push(line)
633 634 if tmp is not None:
634 635 yield tmp
635 636
636 637 # reset the transform
637 638 tmp = transform.reset()
638 639 if tmp is not None:
639 640 yield tmp
640 641
641 642 out = []
642 643 for t in self.transforms_in_use:
643 644 out = _flush(t, out)
644 645
645 646 out = list(out)
646 647 if out:
647 648 self._store('\n'.join(out))
648 649
649 650 def raw_reset(self):
650 651 """Return raw input only and perform a full reset.
651 652 """
652 653 out = self.source_raw
653 654 self.reset()
654 655 return out
655 656
656 657 def source_reset(self):
657 658 try:
658 659 self.flush_transformers()
659 660 return self.source
660 661 finally:
661 662 self.reset()
662 663
663 664 def push_accepts_more(self):
664 665 if self.transformer_accumulating:
665 666 return True
666 667 else:
667 668 return super(IPythonInputSplitter, self).push_accepts_more()
668 669
669 670 def transform_cell(self, cell):
670 671 """Process and translate a cell of input.
671 672 """
672 673 self.reset()
673 674 try:
674 675 self.push(cell)
675 676 self.flush_transformers()
676 677 return self.source
677 678 finally:
678 679 self.reset()
679 680
680 681 def push(self, lines:str) -> bool:
681 682 """Push one or more lines of IPython input.
682 683
683 684 This stores the given lines and returns a status code indicating
684 685 whether the code forms a complete Python block or not, after processing
685 686 all input lines for special IPython syntax.
686 687
687 688 Any exceptions generated in compilation are swallowed, but if an
688 689 exception was produced, the method returns True.
689 690
690 691 Parameters
691 692 ----------
692 693 lines : string
693 694 One or more lines of Python input.
694 695
695 696 Returns
696 697 -------
697 698 is_complete : boolean
698 699 True if the current input source (the result of the current input
699 700 plus prior inputs) forms a complete Python execution block. Note that
700 701 this value is also stored as a private attribute (_is_complete), so it
701 702 can be queried at any time.
702 703 """
703 704 assert isinstance(lines, str)
704 705 # We must ensure all input is pure unicode
705 706 # ''.splitlines() --> [], but we need to push the empty line to transformers
706 707 lines_list = lines.splitlines()
707 708 if not lines_list:
708 709 lines_list = ['']
709 710
710 711 # Store raw source before applying any transformations to it. Note
711 712 # that this must be done *after* the reset() call that would otherwise
712 713 # flush the buffer.
713 714 self._store(lines, self._buffer_raw, 'source_raw')
714 715
715 716 transformed_lines_list = []
716 717 for line in lines_list:
717 718 transformed = self._transform_line(line)
718 719 if transformed is not None:
719 720 transformed_lines_list.append(transformed)
720 721
721 722 if transformed_lines_list:
722 723 transformed_lines = '\n'.join(transformed_lines_list)
723 724 return super(IPythonInputSplitter, self).push(transformed_lines)
724 725 else:
725 726 # Got nothing back from transformers - they must be waiting for
726 727 # more input.
727 728 return False
728 729
729 730 def _transform_line(self, line):
730 731 """Push a line of input code through the various transformers.
731 732
732 733 Returns any output from the transformers, or None if a transformer
733 734 is accumulating lines.
734 735
735 736 Sets self.transformer_accumulating as a side effect.
736 737 """
737 738 def _accumulating(dbg):
738 739 #print(dbg)
739 740 self.transformer_accumulating = True
740 741 return None
741 742
742 743 for transformer in self.physical_line_transforms:
743 744 line = transformer.push(line)
744 745 if line is None:
745 746 return _accumulating(transformer)
746 747
747 748 if not self.within_python_line:
748 749 line = self.assemble_logical_lines.push(line)
749 750 if line is None:
750 751 return _accumulating('acc logical line')
751 752
752 753 for transformer in self.logical_line_transforms:
753 754 line = transformer.push(line)
754 755 if line is None:
755 756 return _accumulating(transformer)
756 757
757 758 line = self.assemble_python_lines.push(line)
758 759 if line is None:
759 760 self.within_python_line = True
760 761 return _accumulating('acc python line')
761 762 else:
762 763 self.within_python_line = False
763 764
764 765 for transformer in self.python_line_transforms:
765 766 line = transformer.push(line)
766 767 if line is None:
767 768 return _accumulating(transformer)
768 769
769 770 #print("transformers clear") #debug
770 771 self.transformer_accumulating = False
771 772 return line
772 773
@@ -1,3898 +1,3898 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Main IPython class."""
3 3
4 4 #-----------------------------------------------------------------------------
5 5 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de>
6 6 # Copyright (C) 2001-2007 Fernando Perez. <fperez@colorado.edu>
7 7 # Copyright (C) 2008-2011 The IPython Development Team
8 8 #
9 9 # Distributed under the terms of the BSD License. The full license is in
10 10 # the file COPYING, distributed as part of this software.
11 11 #-----------------------------------------------------------------------------
12 12
13 13
14 14 import abc
15 15 import ast
16 16 import atexit
17 17 import bdb
18 18 import builtins as builtin_mod
19 19 import functools
20 20 import inspect
21 21 import os
22 22 import re
23 23 import runpy
24 24 import subprocess
25 25 import sys
26 26 import tempfile
27 27 import traceback
28 28 import types
29 29 import warnings
30 30 from ast import stmt
31 31 from io import open as io_open
32 32 from logging import error
33 33 from pathlib import Path
34 34 from typing import Callable
35 35 from typing import List as ListType, Dict as DictType, Any as AnyType
36 from typing import Optional, Tuple
36 from typing import Optional, Sequence, Tuple
37 37 from warnings import warn
38 38
39 39 from pickleshare import PickleShareDB
40 40 from tempfile import TemporaryDirectory
41 41 from traitlets import (
42 42 Any,
43 43 Bool,
44 44 CaselessStrEnum,
45 45 Dict,
46 46 Enum,
47 47 Instance,
48 48 Integer,
49 49 List,
50 50 Type,
51 51 Unicode,
52 52 default,
53 53 observe,
54 54 validate,
55 55 )
56 56 from traitlets.config.configurable import SingletonConfigurable
57 57 from traitlets.utils.importstring import import_item
58 58
59 59 import IPython.core.hooks
60 60 from IPython.core import magic, oinspect, page, prefilter, ultratb
61 61 from IPython.core.alias import Alias, AliasManager
62 62 from IPython.core.autocall import ExitAutocall
63 63 from IPython.core.builtin_trap import BuiltinTrap
64 64 from IPython.core.compilerop import CachingCompiler
65 65 from IPython.core.debugger import InterruptiblePdb
66 66 from IPython.core.display_trap import DisplayTrap
67 67 from IPython.core.displayhook import DisplayHook
68 68 from IPython.core.displaypub import DisplayPublisher
69 69 from IPython.core.error import InputRejected, UsageError
70 70 from IPython.core.events import EventManager, available_events
71 71 from IPython.core.extensions import ExtensionManager
72 72 from IPython.core.formatters import DisplayFormatter
73 73 from IPython.core.history import HistoryManager
74 74 from IPython.core.inputtransformer2 import ESC_MAGIC, ESC_MAGIC2
75 75 from IPython.core.logger import Logger
76 76 from IPython.core.macro import Macro
77 77 from IPython.core.payload import PayloadManager
78 78 from IPython.core.prefilter import PrefilterManager
79 79 from IPython.core.profiledir import ProfileDir
80 80 from IPython.core.usage import default_banner
81 81 from IPython.display import display
82 82 from IPython.paths import get_ipython_dir
83 83 from IPython.testing.skipdoctest import skip_doctest
84 84 from IPython.utils import PyColorize, io, openpy, py3compat
85 85 from IPython.utils.decorators import undoc
86 86 from IPython.utils.io import ask_yes_no
87 87 from IPython.utils.ipstruct import Struct
88 88 from IPython.utils.path import ensure_dir_exists, get_home_dir, get_py_filename
89 89 from IPython.utils.process import getoutput, system
90 90 from IPython.utils.strdispatch import StrDispatch
91 91 from IPython.utils.syspathcontext import prepended_to_syspath
92 92 from IPython.utils.text import DollarFormatter, LSString, SList, format_screen
93 93 from IPython.core.oinspect import OInfo
94 94
95 95
96 96 sphinxify: Optional[Callable]
97 97
98 98 try:
99 99 import docrepr.sphinxify as sphx
100 100
101 101 def sphinxify(oinfo):
102 102 wrapped_docstring = sphx.wrap_main_docstring(oinfo)
103 103
104 104 def sphinxify_docstring(docstring):
105 105 with TemporaryDirectory() as dirname:
106 106 return {
107 107 "text/html": sphx.sphinxify(wrapped_docstring, dirname),
108 108 "text/plain": docstring,
109 109 }
110 110
111 111 return sphinxify_docstring
112 112 except ImportError:
113 113 sphinxify = None
114 114
115 115
116 116 class ProvisionalWarning(DeprecationWarning):
117 117 """
118 118 Warning class for unstable features
119 119 """
120 120 pass
121 121
122 122 from ast import Module
123 123
124 124 _assign_nodes = (ast.AugAssign, ast.AnnAssign, ast.Assign)
125 125 _single_targets_nodes = (ast.AugAssign, ast.AnnAssign)
126 126
127 127 #-----------------------------------------------------------------------------
128 128 # Await Helpers
129 129 #-----------------------------------------------------------------------------
130 130
131 131 # we still need to run things using the asyncio eventloop, but there is no
132 132 # async integration
133 133 from .async_helpers import (
134 134 _asyncio_runner,
135 135 _curio_runner,
136 136 _pseudo_sync_runner,
137 137 _should_be_async,
138 138 _trio_runner,
139 139 )
140 140
141 141 #-----------------------------------------------------------------------------
142 142 # Globals
143 143 #-----------------------------------------------------------------------------
144 144
145 145 # compiled regexps for autoindent management
146 146 dedent_re = re.compile(r'^\s+raise|^\s+return|^\s+pass')
147 147
148 148 #-----------------------------------------------------------------------------
149 149 # Utilities
150 150 #-----------------------------------------------------------------------------
151 151
152 152
153 153 def is_integer_string(s: str):
154 154 """
155 155 Variant of "str.isnumeric()" that allow negative values and other ints.
156 156 """
157 157 try:
158 158 int(s)
159 159 return True
160 160 except ValueError:
161 161 return False
162 162 raise ValueError("Unexpected error")
163 163
164 164
165 165 @undoc
166 166 def softspace(file, newvalue):
167 167 """Copied from code.py, to remove the dependency"""
168 168
169 169 oldvalue = 0
170 170 try:
171 171 oldvalue = file.softspace
172 172 except AttributeError:
173 173 pass
174 174 try:
175 175 file.softspace = newvalue
176 176 except (AttributeError, TypeError):
177 177 # "attribute-less object" or "read-only attributes"
178 178 pass
179 179 return oldvalue
180 180
181 181 @undoc
182 182 def no_op(*a, **kw):
183 183 pass
184 184
185 185
186 186 class SpaceInInput(Exception): pass
187 187
188 188
189 189 class SeparateUnicode(Unicode):
190 190 r"""A Unicode subclass to validate separate_in, separate_out, etc.
191 191
192 192 This is a Unicode based trait that converts '0'->'' and ``'\\n'->'\n'``.
193 193 """
194 194
195 195 def validate(self, obj, value):
196 196 if value == '0': value = ''
197 197 value = value.replace('\\n','\n')
198 198 return super(SeparateUnicode, self).validate(obj, value)
199 199
200 200
201 201 @undoc
202 202 class DummyMod(object):
203 203 """A dummy module used for IPython's interactive module when
204 204 a namespace must be assigned to the module's __dict__."""
205 205 __spec__ = None
206 206
207 207
208 208 class ExecutionInfo(object):
209 209 """The arguments used for a call to :meth:`InteractiveShell.run_cell`
210 210
211 211 Stores information about what is going to happen.
212 212 """
213 213 raw_cell = None
214 214 store_history = False
215 215 silent = False
216 216 shell_futures = True
217 217 cell_id = None
218 218
219 219 def __init__(self, raw_cell, store_history, silent, shell_futures, cell_id):
220 220 self.raw_cell = raw_cell
221 221 self.store_history = store_history
222 222 self.silent = silent
223 223 self.shell_futures = shell_futures
224 224 self.cell_id = cell_id
225 225
226 226 def __repr__(self):
227 227 name = self.__class__.__qualname__
228 228 raw_cell = (
229 229 (self.raw_cell[:50] + "..") if len(self.raw_cell) > 50 else self.raw_cell
230 230 )
231 231 return (
232 232 '<%s object at %x, raw_cell="%s" store_history=%s silent=%s shell_futures=%s cell_id=%s>'
233 233 % (
234 234 name,
235 235 id(self),
236 236 raw_cell,
237 237 self.store_history,
238 238 self.silent,
239 239 self.shell_futures,
240 240 self.cell_id,
241 241 )
242 242 )
243 243
244 244
245 245 class ExecutionResult(object):
246 246 """The result of a call to :meth:`InteractiveShell.run_cell`
247 247
248 248 Stores information about what took place.
249 249 """
250 250 execution_count = None
251 251 error_before_exec = None
252 252 error_in_exec: Optional[BaseException] = None
253 253 info = None
254 254 result = None
255 255
256 256 def __init__(self, info):
257 257 self.info = info
258 258
259 259 @property
260 260 def success(self):
261 261 return (self.error_before_exec is None) and (self.error_in_exec is None)
262 262
263 263 def raise_error(self):
264 264 """Reraises error if `success` is `False`, otherwise does nothing"""
265 265 if self.error_before_exec is not None:
266 266 raise self.error_before_exec
267 267 if self.error_in_exec is not None:
268 268 raise self.error_in_exec
269 269
270 270 def __repr__(self):
271 271 name = self.__class__.__qualname__
272 272 return '<%s object at %x, execution_count=%s error_before_exec=%s error_in_exec=%s info=%s result=%s>' %\
273 273 (name, id(self), self.execution_count, self.error_before_exec, self.error_in_exec, repr(self.info), repr(self.result))
274 274
275 275 @functools.wraps(io_open)
276 276 def _modified_open(file, *args, **kwargs):
277 277 if file in {0, 1, 2}:
278 278 raise ValueError(
279 279 f"IPython won't let you open fd={file} by default "
280 280 "as it is likely to crash IPython. If you know what you are doing, "
281 281 "you can use builtins' open."
282 282 )
283 283
284 284 return io_open(file, *args, **kwargs)
285 285
286 286 class InteractiveShell(SingletonConfigurable):
287 287 """An enhanced, interactive shell for Python."""
288 288
289 289 _instance = None
290 290
291 291 ast_transformers = List([], help=
292 292 """
293 293 A list of ast.NodeTransformer subclass instances, which will be applied
294 294 to user input before code is run.
295 295 """
296 296 ).tag(config=True)
297 297
298 298 autocall = Enum((0,1,2), default_value=0, help=
299 299 """
300 300 Make IPython automatically call any callable object even if you didn't
301 301 type explicit parentheses. For example, 'str 43' becomes 'str(43)'
302 302 automatically. The value can be '0' to disable the feature, '1' for
303 303 'smart' autocall, where it is not applied if there are no more
304 304 arguments on the line, and '2' for 'full' autocall, where all callable
305 305 objects are automatically called (even if no arguments are present).
306 306 """
307 307 ).tag(config=True)
308 308
309 309 autoindent = Bool(True, help=
310 310 """
311 311 Autoindent IPython code entered interactively.
312 312 """
313 313 ).tag(config=True)
314 314
315 315 autoawait = Bool(True, help=
316 316 """
317 317 Automatically run await statement in the top level repl.
318 318 """
319 319 ).tag(config=True)
320 320
321 321 loop_runner_map ={
322 322 'asyncio':(_asyncio_runner, True),
323 323 'curio':(_curio_runner, True),
324 324 'trio':(_trio_runner, True),
325 325 'sync': (_pseudo_sync_runner, False)
326 326 }
327 327
328 328 loop_runner = Any(default_value="IPython.core.interactiveshell._asyncio_runner",
329 329 allow_none=True,
330 330 help="""Select the loop runner that will be used to execute top-level asynchronous code"""
331 331 ).tag(config=True)
332 332
333 333 @default('loop_runner')
334 334 def _default_loop_runner(self):
335 335 return import_item("IPython.core.interactiveshell._asyncio_runner")
336 336
337 337 @validate('loop_runner')
338 338 def _import_runner(self, proposal):
339 339 if isinstance(proposal.value, str):
340 340 if proposal.value in self.loop_runner_map:
341 341 runner, autoawait = self.loop_runner_map[proposal.value]
342 342 self.autoawait = autoawait
343 343 return runner
344 344 runner = import_item(proposal.value)
345 345 if not callable(runner):
346 346 raise ValueError('loop_runner must be callable')
347 347 return runner
348 348 if not callable(proposal.value):
349 349 raise ValueError('loop_runner must be callable')
350 350 return proposal.value
351 351
352 352 automagic = Bool(True, help=
353 353 """
354 354 Enable magic commands to be called without the leading %.
355 355 """
356 356 ).tag(config=True)
357 357
358 358 banner1 = Unicode(default_banner,
359 359 help="""The part of the banner to be printed before the profile"""
360 360 ).tag(config=True)
361 361 banner2 = Unicode('',
362 362 help="""The part of the banner to be printed after the profile"""
363 363 ).tag(config=True)
364 364
365 365 cache_size = Integer(1000, help=
366 366 """
367 367 Set the size of the output cache. The default is 1000, you can
368 368 change it permanently in your config file. Setting it to 0 completely
369 369 disables the caching system, and the minimum value accepted is 3 (if
370 370 you provide a value less than 3, it is reset to 0 and a warning is
371 371 issued). This limit is defined because otherwise you'll spend more
372 372 time re-flushing a too small cache than working
373 373 """
374 374 ).tag(config=True)
375 375 color_info = Bool(True, help=
376 376 """
377 377 Use colors for displaying information about objects. Because this
378 378 information is passed through a pager (like 'less'), and some pagers
379 379 get confused with color codes, this capability can be turned off.
380 380 """
381 381 ).tag(config=True)
382 382 colors = CaselessStrEnum(('Neutral', 'NoColor','LightBG','Linux'),
383 383 default_value='Neutral',
384 384 help="Set the color scheme (NoColor, Neutral, Linux, or LightBG)."
385 385 ).tag(config=True)
386 386 debug = Bool(False).tag(config=True)
387 387 disable_failing_post_execute = Bool(False,
388 388 help="Don't call post-execute functions that have failed in the past."
389 389 ).tag(config=True)
390 390 display_formatter = Instance(DisplayFormatter, allow_none=True)
391 391 displayhook_class = Type(DisplayHook)
392 392 display_pub_class = Type(DisplayPublisher)
393 393 compiler_class = Type(CachingCompiler)
394 394 inspector_class = Type(
395 395 oinspect.Inspector, help="Class to use to instantiate the shell inspector"
396 396 ).tag(config=True)
397 397
398 398 sphinxify_docstring = Bool(False, help=
399 399 """
400 400 Enables rich html representation of docstrings. (This requires the
401 401 docrepr module).
402 402 """).tag(config=True)
403 403
404 404 @observe("sphinxify_docstring")
405 405 def _sphinxify_docstring_changed(self, change):
406 406 if change['new']:
407 407 warn("`sphinxify_docstring` is provisional since IPython 5.0 and might change in future versions." , ProvisionalWarning)
408 408
409 409 enable_html_pager = Bool(False, help=
410 410 """
411 411 (Provisional API) enables html representation in mime bundles sent
412 412 to pagers.
413 413 """).tag(config=True)
414 414
415 415 @observe("enable_html_pager")
416 416 def _enable_html_pager_changed(self, change):
417 417 if change['new']:
418 418 warn("`enable_html_pager` is provisional since IPython 5.0 and might change in future versions.", ProvisionalWarning)
419 419
420 420 data_pub_class = None
421 421
422 422 exit_now = Bool(False)
423 423 exiter = Instance(ExitAutocall)
424 424 @default('exiter')
425 425 def _exiter_default(self):
426 426 return ExitAutocall(self)
427 427 # Monotonically increasing execution counter
428 428 execution_count = Integer(1)
429 429 filename = Unicode("<ipython console>")
430 430 ipython_dir= Unicode('').tag(config=True) # Set to get_ipython_dir() in __init__
431 431
432 432 # Used to transform cells before running them, and check whether code is complete
433 433 input_transformer_manager = Instance('IPython.core.inputtransformer2.TransformerManager',
434 434 ())
435 435
436 436 @property
437 437 def input_transformers_cleanup(self):
438 438 return self.input_transformer_manager.cleanup_transforms
439 439
440 440 input_transformers_post = List([],
441 441 help="A list of string input transformers, to be applied after IPython's "
442 442 "own input transformations."
443 443 )
444 444
445 445 @property
446 446 def input_splitter(self):
447 447 """Make this available for backward compatibility (pre-7.0 release) with existing code.
448 448
449 449 For example, ipykernel ipykernel currently uses
450 450 `shell.input_splitter.check_complete`
451 451 """
452 452 from warnings import warn
453 453 warn("`input_splitter` is deprecated since IPython 7.0, prefer `input_transformer_manager`.",
454 454 DeprecationWarning, stacklevel=2
455 455 )
456 456 return self.input_transformer_manager
457 457
458 458 logstart = Bool(False, help=
459 459 """
460 460 Start logging to the default log file in overwrite mode.
461 461 Use `logappend` to specify a log file to **append** logs to.
462 462 """
463 463 ).tag(config=True)
464 464 logfile = Unicode('', help=
465 465 """
466 466 The name of the logfile to use.
467 467 """
468 468 ).tag(config=True)
469 469 logappend = Unicode('', help=
470 470 """
471 471 Start logging to the given file in append mode.
472 472 Use `logfile` to specify a log file to **overwrite** logs to.
473 473 """
474 474 ).tag(config=True)
475 475 object_info_string_level = Enum((0,1,2), default_value=0,
476 476 ).tag(config=True)
477 477 pdb = Bool(False, help=
478 478 """
479 479 Automatically call the pdb debugger after every exception.
480 480 """
481 481 ).tag(config=True)
482 482 display_page = Bool(False,
483 483 help="""If True, anything that would be passed to the pager
484 484 will be displayed as regular output instead."""
485 485 ).tag(config=True)
486 486
487 487
488 488 show_rewritten_input = Bool(True,
489 489 help="Show rewritten input, e.g. for autocall."
490 490 ).tag(config=True)
491 491
492 492 quiet = Bool(False).tag(config=True)
493 493
494 494 history_length = Integer(10000,
495 495 help='Total length of command history'
496 496 ).tag(config=True)
497 497
498 498 history_load_length = Integer(1000, help=
499 499 """
500 500 The number of saved history entries to be loaded
501 501 into the history buffer at startup.
502 502 """
503 503 ).tag(config=True)
504 504
505 505 ast_node_interactivity = Enum(['all', 'last', 'last_expr', 'none', 'last_expr_or_assign'],
506 506 default_value='last_expr',
507 507 help="""
508 508 'all', 'last', 'last_expr' or 'none', 'last_expr_or_assign' specifying
509 509 which nodes should be run interactively (displaying output from expressions).
510 510 """
511 511 ).tag(config=True)
512 512
513 513 warn_venv = Bool(
514 514 True,
515 515 help="Warn if running in a virtual environment with no IPython installed (so IPython from the global environment is used).",
516 516 ).tag(config=True)
517 517
518 518 # TODO: this part of prompt management should be moved to the frontends.
519 519 # Use custom TraitTypes that convert '0'->'' and '\\n'->'\n'
520 520 separate_in = SeparateUnicode('\n').tag(config=True)
521 521 separate_out = SeparateUnicode('').tag(config=True)
522 522 separate_out2 = SeparateUnicode('').tag(config=True)
523 523 wildcards_case_sensitive = Bool(True).tag(config=True)
524 524 xmode = CaselessStrEnum(('Context', 'Plain', 'Verbose', 'Minimal'),
525 525 default_value='Context',
526 526 help="Switch modes for the IPython exception handlers."
527 527 ).tag(config=True)
528 528
529 529 # Subcomponents of InteractiveShell
530 530 alias_manager = Instance('IPython.core.alias.AliasManager', allow_none=True)
531 531 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager', allow_none=True)
532 532 builtin_trap = Instance('IPython.core.builtin_trap.BuiltinTrap', allow_none=True)
533 533 display_trap = Instance('IPython.core.display_trap.DisplayTrap', allow_none=True)
534 534 extension_manager = Instance('IPython.core.extensions.ExtensionManager', allow_none=True)
535 535 payload_manager = Instance('IPython.core.payload.PayloadManager', allow_none=True)
536 536 history_manager = Instance('IPython.core.history.HistoryAccessorBase', allow_none=True)
537 537 magics_manager = Instance('IPython.core.magic.MagicsManager', allow_none=True)
538 538
539 539 profile_dir = Instance('IPython.core.application.ProfileDir', allow_none=True)
540 540 @property
541 541 def profile(self):
542 542 if self.profile_dir is not None:
543 543 name = os.path.basename(self.profile_dir.location)
544 544 return name.replace('profile_','')
545 545
546 546
547 547 # Private interface
548 548 _post_execute = Dict()
549 549
550 550 # Tracks any GUI loop loaded for pylab
551 551 pylab_gui_select = None
552 552
553 553 last_execution_succeeded = Bool(True, help='Did last executed command succeeded')
554 554
555 555 last_execution_result = Instance('IPython.core.interactiveshell.ExecutionResult', help='Result of executing the last command', allow_none=True)
556 556
557 557 def __init__(self, ipython_dir=None, profile_dir=None,
558 558 user_module=None, user_ns=None,
559 559 custom_exceptions=((), None), **kwargs):
560 560 # This is where traits with a config_key argument are updated
561 561 # from the values on config.
562 562 super(InteractiveShell, self).__init__(**kwargs)
563 563 if 'PromptManager' in self.config:
564 564 warn('As of IPython 5.0 `PromptManager` config will have no effect'
565 565 ' and has been replaced by TerminalInteractiveShell.prompts_class')
566 566 self.configurables = [self]
567 567
568 568 # These are relatively independent and stateless
569 569 self.init_ipython_dir(ipython_dir)
570 570 self.init_profile_dir(profile_dir)
571 571 self.init_instance_attrs()
572 572 self.init_environment()
573 573
574 574 # Check if we're in a virtualenv, and set up sys.path.
575 575 self.init_virtualenv()
576 576
577 577 # Create namespaces (user_ns, user_global_ns, etc.)
578 578 self.init_create_namespaces(user_module, user_ns)
579 579 # This has to be done after init_create_namespaces because it uses
580 580 # something in self.user_ns, but before init_sys_modules, which
581 581 # is the first thing to modify sys.
582 582 # TODO: When we override sys.stdout and sys.stderr before this class
583 583 # is created, we are saving the overridden ones here. Not sure if this
584 584 # is what we want to do.
585 585 self.save_sys_module_state()
586 586 self.init_sys_modules()
587 587
588 588 # While we're trying to have each part of the code directly access what
589 589 # it needs without keeping redundant references to objects, we have too
590 590 # much legacy code that expects ip.db to exist.
591 591 self.db = PickleShareDB(os.path.join(self.profile_dir.location, 'db'))
592 592
593 593 self.init_history()
594 594 self.init_encoding()
595 595 self.init_prefilter()
596 596
597 597 self.init_syntax_highlighting()
598 598 self.init_hooks()
599 599 self.init_events()
600 600 self.init_pushd_popd_magic()
601 601 self.init_user_ns()
602 602 self.init_logger()
603 603 self.init_builtins()
604 604
605 605 # The following was in post_config_initialization
606 606 self.init_inspector()
607 607 self.raw_input_original = input
608 608 self.init_completer()
609 609 # TODO: init_io() needs to happen before init_traceback handlers
610 610 # because the traceback handlers hardcode the stdout/stderr streams.
611 611 # This logic in in debugger.Pdb and should eventually be changed.
612 612 self.init_io()
613 613 self.init_traceback_handlers(custom_exceptions)
614 614 self.init_prompts()
615 615 self.init_display_formatter()
616 616 self.init_display_pub()
617 617 self.init_data_pub()
618 618 self.init_displayhook()
619 619 self.init_magics()
620 620 self.init_alias()
621 621 self.init_logstart()
622 622 self.init_pdb()
623 623 self.init_extension_manager()
624 624 self.init_payload()
625 625 self.events.trigger('shell_initialized', self)
626 626 atexit.register(self.atexit_operations)
627 627
628 628 # The trio runner is used for running Trio in the foreground thread. It
629 629 # is different from `_trio_runner(async_fn)` in `async_helpers.py`
630 630 # which calls `trio.run()` for every cell. This runner runs all cells
631 631 # inside a single Trio event loop. If used, it is set from
632 632 # `ipykernel.kernelapp`.
633 633 self.trio_runner = None
634 634
635 635 def get_ipython(self):
636 636 """Return the currently running IPython instance."""
637 637 return self
638 638
639 639 #-------------------------------------------------------------------------
640 640 # Trait changed handlers
641 641 #-------------------------------------------------------------------------
642 642 @observe('ipython_dir')
643 643 def _ipython_dir_changed(self, change):
644 644 ensure_dir_exists(change['new'])
645 645
646 646 def set_autoindent(self,value=None):
647 647 """Set the autoindent flag.
648 648
649 649 If called with no arguments, it acts as a toggle."""
650 650 if value is None:
651 651 self.autoindent = not self.autoindent
652 652 else:
653 653 self.autoindent = value
654 654
655 655 def set_trio_runner(self, tr):
656 656 self.trio_runner = tr
657 657
658 658 #-------------------------------------------------------------------------
659 659 # init_* methods called by __init__
660 660 #-------------------------------------------------------------------------
661 661
662 662 def init_ipython_dir(self, ipython_dir):
663 663 if ipython_dir is not None:
664 664 self.ipython_dir = ipython_dir
665 665 return
666 666
667 667 self.ipython_dir = get_ipython_dir()
668 668
669 669 def init_profile_dir(self, profile_dir):
670 670 if profile_dir is not None:
671 671 self.profile_dir = profile_dir
672 672 return
673 673 self.profile_dir = ProfileDir.create_profile_dir_by_name(
674 674 self.ipython_dir, "default"
675 675 )
676 676
677 677 def init_instance_attrs(self):
678 678 self.more = False
679 679
680 680 # command compiler
681 681 self.compile = self.compiler_class()
682 682
683 683 # Make an empty namespace, which extension writers can rely on both
684 684 # existing and NEVER being used by ipython itself. This gives them a
685 685 # convenient location for storing additional information and state
686 686 # their extensions may require, without fear of collisions with other
687 687 # ipython names that may develop later.
688 688 self.meta = Struct()
689 689
690 690 # Temporary files used for various purposes. Deleted at exit.
691 691 # The files here are stored with Path from Pathlib
692 692 self.tempfiles = []
693 693 self.tempdirs = []
694 694
695 695 # keep track of where we started running (mainly for crash post-mortem)
696 696 # This is not being used anywhere currently.
697 697 self.starting_dir = os.getcwd()
698 698
699 699 # Indentation management
700 700 self.indent_current_nsp = 0
701 701
702 702 # Dict to track post-execution functions that have been registered
703 703 self._post_execute = {}
704 704
705 705 def init_environment(self):
706 706 """Any changes we need to make to the user's environment."""
707 707 pass
708 708
709 709 def init_encoding(self):
710 710 # Get system encoding at startup time. Certain terminals (like Emacs
711 711 # under Win32 have it set to None, and we need to have a known valid
712 712 # encoding to use in the raw_input() method
713 713 try:
714 714 self.stdin_encoding = sys.stdin.encoding or 'ascii'
715 715 except AttributeError:
716 716 self.stdin_encoding = 'ascii'
717 717
718 718
719 719 @observe('colors')
720 720 def init_syntax_highlighting(self, changes=None):
721 721 # Python source parser/formatter for syntax highlighting
722 722 pyformat = PyColorize.Parser(style=self.colors, parent=self).format
723 723 self.pycolorize = lambda src: pyformat(src,'str')
724 724
725 725 def refresh_style(self):
726 726 # No-op here, used in subclass
727 727 pass
728 728
729 729 def init_pushd_popd_magic(self):
730 730 # for pushd/popd management
731 731 self.home_dir = get_home_dir()
732 732
733 733 self.dir_stack = []
734 734
735 735 def init_logger(self):
736 736 self.logger = Logger(self.home_dir, logfname='ipython_log.py',
737 737 logmode='rotate')
738 738
739 739 def init_logstart(self):
740 740 """Initialize logging in case it was requested at the command line.
741 741 """
742 742 if self.logappend:
743 743 self.magic('logstart %s append' % self.logappend)
744 744 elif self.logfile:
745 745 self.magic('logstart %s' % self.logfile)
746 746 elif self.logstart:
747 747 self.magic('logstart')
748 748
749 749
750 750 def init_builtins(self):
751 751 # A single, static flag that we set to True. Its presence indicates
752 752 # that an IPython shell has been created, and we make no attempts at
753 753 # removing on exit or representing the existence of more than one
754 754 # IPython at a time.
755 755 builtin_mod.__dict__['__IPYTHON__'] = True
756 756 builtin_mod.__dict__['display'] = display
757 757
758 758 self.builtin_trap = BuiltinTrap(shell=self)
759 759
760 760 @observe('colors')
761 761 def init_inspector(self, changes=None):
762 762 # Object inspector
763 763 self.inspector = self.inspector_class(
764 764 oinspect.InspectColors,
765 765 PyColorize.ANSICodeColors,
766 766 self.colors,
767 767 self.object_info_string_level,
768 768 )
769 769
770 770 def init_io(self):
771 771 # implemented in subclasses, TerminalInteractiveShell does call
772 772 # colorama.init().
773 773 pass
774 774
775 775 def init_prompts(self):
776 776 # Set system prompts, so that scripts can decide if they are running
777 777 # interactively.
778 778 sys.ps1 = 'In : '
779 779 sys.ps2 = '...: '
780 780 sys.ps3 = 'Out: '
781 781
782 782 def init_display_formatter(self):
783 783 self.display_formatter = DisplayFormatter(parent=self)
784 784 self.configurables.append(self.display_formatter)
785 785
786 786 def init_display_pub(self):
787 787 self.display_pub = self.display_pub_class(parent=self, shell=self)
788 788 self.configurables.append(self.display_pub)
789 789
790 790 def init_data_pub(self):
791 791 if not self.data_pub_class:
792 792 self.data_pub = None
793 793 return
794 794 self.data_pub = self.data_pub_class(parent=self)
795 795 self.configurables.append(self.data_pub)
796 796
797 797 def init_displayhook(self):
798 798 # Initialize displayhook, set in/out prompts and printing system
799 799 self.displayhook = self.displayhook_class(
800 800 parent=self,
801 801 shell=self,
802 802 cache_size=self.cache_size,
803 803 )
804 804 self.configurables.append(self.displayhook)
805 805 # This is a context manager that installs/revmoes the displayhook at
806 806 # the appropriate time.
807 807 self.display_trap = DisplayTrap(hook=self.displayhook)
808 808
809 809 @staticmethod
810 810 def get_path_links(p: Path):
811 811 """Gets path links including all symlinks
812 812
813 813 Examples
814 814 --------
815 815 In [1]: from IPython.core.interactiveshell import InteractiveShell
816 816
817 817 In [2]: import sys, pathlib
818 818
819 819 In [3]: paths = InteractiveShell.get_path_links(pathlib.Path(sys.executable))
820 820
821 821 In [4]: len(paths) == len(set(paths))
822 822 Out[4]: True
823 823
824 824 In [5]: bool(paths)
825 825 Out[5]: True
826 826 """
827 827 paths = [p]
828 828 while p.is_symlink():
829 829 new_path = Path(os.readlink(p))
830 830 if not new_path.is_absolute():
831 831 new_path = p.parent / new_path
832 832 p = new_path
833 833 paths.append(p)
834 834 return paths
835 835
836 836 def init_virtualenv(self):
837 837 """Add the current virtualenv to sys.path so the user can import modules from it.
838 838 This isn't perfect: it doesn't use the Python interpreter with which the
839 839 virtualenv was built, and it ignores the --no-site-packages option. A
840 840 warning will appear suggesting the user installs IPython in the
841 841 virtualenv, but for many cases, it probably works well enough.
842 842
843 843 Adapted from code snippets online.
844 844
845 845 http://blog.ufsoft.org/2009/1/29/ipython-and-virtualenv
846 846 """
847 847 if 'VIRTUAL_ENV' not in os.environ:
848 848 # Not in a virtualenv
849 849 return
850 850 elif os.environ["VIRTUAL_ENV"] == "":
851 851 warn("Virtual env path set to '', please check if this is intended.")
852 852 return
853 853
854 854 p = Path(sys.executable)
855 855 p_venv = Path(os.environ["VIRTUAL_ENV"])
856 856
857 857 # fallback venv detection:
858 858 # stdlib venv may symlink sys.executable, so we can't use realpath.
859 859 # but others can symlink *to* the venv Python, so we can't just use sys.executable.
860 860 # So we just check every item in the symlink tree (generally <= 3)
861 861 paths = self.get_path_links(p)
862 862
863 863 # In Cygwin paths like "c:\..." and '\cygdrive\c\...' are possible
864 864 if p_venv.parts[1] == "cygdrive":
865 865 drive_name = p_venv.parts[2]
866 866 p_venv = (drive_name + ":/") / Path(*p_venv.parts[3:])
867 867
868 868 if any(p_venv == p.parents[1] for p in paths):
869 869 # Our exe is inside or has access to the virtualenv, don't need to do anything.
870 870 return
871 871
872 872 if sys.platform == "win32":
873 873 virtual_env = str(Path(os.environ["VIRTUAL_ENV"], "Lib", "site-packages"))
874 874 else:
875 875 virtual_env_path = Path(
876 876 os.environ["VIRTUAL_ENV"], "lib", "python{}.{}", "site-packages"
877 877 )
878 878 p_ver = sys.version_info[:2]
879 879
880 880 # Predict version from py[thon]-x.x in the $VIRTUAL_ENV
881 881 re_m = re.search(r"\bpy(?:thon)?([23])\.(\d+)\b", os.environ["VIRTUAL_ENV"])
882 882 if re_m:
883 883 predicted_path = Path(str(virtual_env_path).format(*re_m.groups()))
884 884 if predicted_path.exists():
885 885 p_ver = re_m.groups()
886 886
887 887 virtual_env = str(virtual_env_path).format(*p_ver)
888 888 if self.warn_venv:
889 889 warn(
890 890 "Attempting to work in a virtualenv. If you encounter problems, "
891 891 "please install IPython inside the virtualenv."
892 892 )
893 893 import site
894 894 sys.path.insert(0, virtual_env)
895 895 site.addsitedir(virtual_env)
896 896
897 897 #-------------------------------------------------------------------------
898 898 # Things related to injections into the sys module
899 899 #-------------------------------------------------------------------------
900 900
901 901 def save_sys_module_state(self):
902 902 """Save the state of hooks in the sys module.
903 903
904 904 This has to be called after self.user_module is created.
905 905 """
906 906 self._orig_sys_module_state = {'stdin': sys.stdin,
907 907 'stdout': sys.stdout,
908 908 'stderr': sys.stderr,
909 909 'excepthook': sys.excepthook}
910 910 self._orig_sys_modules_main_name = self.user_module.__name__
911 911 self._orig_sys_modules_main_mod = sys.modules.get(self.user_module.__name__)
912 912
913 913 def restore_sys_module_state(self):
914 914 """Restore the state of the sys module."""
915 915 try:
916 916 for k, v in self._orig_sys_module_state.items():
917 917 setattr(sys, k, v)
918 918 except AttributeError:
919 919 pass
920 920 # Reset what what done in self.init_sys_modules
921 921 if self._orig_sys_modules_main_mod is not None:
922 922 sys.modules[self._orig_sys_modules_main_name] = self._orig_sys_modules_main_mod
923 923
924 924 #-------------------------------------------------------------------------
925 925 # Things related to the banner
926 926 #-------------------------------------------------------------------------
927 927
928 928 @property
929 929 def banner(self):
930 930 banner = self.banner1
931 931 if self.profile and self.profile != 'default':
932 932 banner += '\nIPython profile: %s\n' % self.profile
933 933 if self.banner2:
934 934 banner += '\n' + self.banner2
935 935 return banner
936 936
937 937 def show_banner(self, banner=None):
938 938 if banner is None:
939 939 banner = self.banner
940 940 sys.stdout.write(banner)
941 941
942 942 #-------------------------------------------------------------------------
943 943 # Things related to hooks
944 944 #-------------------------------------------------------------------------
945 945
946 946 def init_hooks(self):
947 947 # hooks holds pointers used for user-side customizations
948 948 self.hooks = Struct()
949 949
950 950 self.strdispatchers = {}
951 951
952 952 # Set all default hooks, defined in the IPython.hooks module.
953 953 hooks = IPython.core.hooks
954 954 for hook_name in hooks.__all__:
955 955 # default hooks have priority 100, i.e. low; user hooks should have
956 956 # 0-100 priority
957 957 self.set_hook(hook_name, getattr(hooks, hook_name), 100)
958 958
959 959 if self.display_page:
960 960 self.set_hook('show_in_pager', page.as_hook(page.display_page), 90)
961 961
962 962 def set_hook(self, name, hook, priority=50, str_key=None, re_key=None):
963 963 """set_hook(name,hook) -> sets an internal IPython hook.
964 964
965 965 IPython exposes some of its internal API as user-modifiable hooks. By
966 966 adding your function to one of these hooks, you can modify IPython's
967 967 behavior to call at runtime your own routines."""
968 968
969 969 # At some point in the future, this should validate the hook before it
970 970 # accepts it. Probably at least check that the hook takes the number
971 971 # of args it's supposed to.
972 972
973 973 f = types.MethodType(hook,self)
974 974
975 975 # check if the hook is for strdispatcher first
976 976 if str_key is not None:
977 977 sdp = self.strdispatchers.get(name, StrDispatch())
978 978 sdp.add_s(str_key, f, priority )
979 979 self.strdispatchers[name] = sdp
980 980 return
981 981 if re_key is not None:
982 982 sdp = self.strdispatchers.get(name, StrDispatch())
983 983 sdp.add_re(re.compile(re_key), f, priority )
984 984 self.strdispatchers[name] = sdp
985 985 return
986 986
987 987 dp = getattr(self.hooks, name, None)
988 988 if name not in IPython.core.hooks.__all__:
989 989 print("Warning! Hook '%s' is not one of %s" % \
990 990 (name, IPython.core.hooks.__all__ ))
991 991
992 992 if name in IPython.core.hooks.deprecated:
993 993 alternative = IPython.core.hooks.deprecated[name]
994 994 raise ValueError(
995 995 "Hook {} has been deprecated since IPython 5.0. Use {} instead.".format(
996 996 name, alternative
997 997 )
998 998 )
999 999
1000 1000 if not dp:
1001 1001 dp = IPython.core.hooks.CommandChainDispatcher()
1002 1002
1003 1003 try:
1004 1004 dp.add(f,priority)
1005 1005 except AttributeError:
1006 1006 # it was not commandchain, plain old func - replace
1007 1007 dp = f
1008 1008
1009 1009 setattr(self.hooks,name, dp)
1010 1010
1011 1011 #-------------------------------------------------------------------------
1012 1012 # Things related to events
1013 1013 #-------------------------------------------------------------------------
1014 1014
1015 1015 def init_events(self):
1016 1016 self.events = EventManager(self, available_events)
1017 1017
1018 1018 self.events.register("pre_execute", self._clear_warning_registry)
1019 1019
1020 1020 def register_post_execute(self, func):
1021 1021 """DEPRECATED: Use ip.events.register('post_run_cell', func)
1022 1022
1023 1023 Register a function for calling after code execution.
1024 1024 """
1025 1025 raise ValueError(
1026 1026 "ip.register_post_execute is deprecated since IPython 1.0, use "
1027 1027 "ip.events.register('post_run_cell', func) instead."
1028 1028 )
1029 1029
1030 1030 def _clear_warning_registry(self):
1031 1031 # clear the warning registry, so that different code blocks with
1032 1032 # overlapping line number ranges don't cause spurious suppression of
1033 1033 # warnings (see gh-6611 for details)
1034 1034 if "__warningregistry__" in self.user_global_ns:
1035 1035 del self.user_global_ns["__warningregistry__"]
1036 1036
1037 1037 #-------------------------------------------------------------------------
1038 1038 # Things related to the "main" module
1039 1039 #-------------------------------------------------------------------------
1040 1040
1041 1041 def new_main_mod(self, filename, modname):
1042 1042 """Return a new 'main' module object for user code execution.
1043 1043
1044 1044 ``filename`` should be the path of the script which will be run in the
1045 1045 module. Requests with the same filename will get the same module, with
1046 1046 its namespace cleared.
1047 1047
1048 1048 ``modname`` should be the module name - normally either '__main__' or
1049 1049 the basename of the file without the extension.
1050 1050
1051 1051 When scripts are executed via %run, we must keep a reference to their
1052 1052 __main__ module around so that Python doesn't
1053 1053 clear it, rendering references to module globals useless.
1054 1054
1055 1055 This method keeps said reference in a private dict, keyed by the
1056 1056 absolute path of the script. This way, for multiple executions of the
1057 1057 same script we only keep one copy of the namespace (the last one),
1058 1058 thus preventing memory leaks from old references while allowing the
1059 1059 objects from the last execution to be accessible.
1060 1060 """
1061 1061 filename = os.path.abspath(filename)
1062 1062 try:
1063 1063 main_mod = self._main_mod_cache[filename]
1064 1064 except KeyError:
1065 1065 main_mod = self._main_mod_cache[filename] = types.ModuleType(
1066 1066 modname,
1067 1067 doc="Module created for script run in IPython")
1068 1068 else:
1069 1069 main_mod.__dict__.clear()
1070 1070 main_mod.__name__ = modname
1071 1071
1072 1072 main_mod.__file__ = filename
1073 1073 # It seems pydoc (and perhaps others) needs any module instance to
1074 1074 # implement a __nonzero__ method
1075 1075 main_mod.__nonzero__ = lambda : True
1076 1076
1077 1077 return main_mod
1078 1078
1079 1079 def clear_main_mod_cache(self):
1080 1080 """Clear the cache of main modules.
1081 1081
1082 1082 Mainly for use by utilities like %reset.
1083 1083
1084 1084 Examples
1085 1085 --------
1086 1086 In [15]: import IPython
1087 1087
1088 1088 In [16]: m = _ip.new_main_mod(IPython.__file__, 'IPython')
1089 1089
1090 1090 In [17]: len(_ip._main_mod_cache) > 0
1091 1091 Out[17]: True
1092 1092
1093 1093 In [18]: _ip.clear_main_mod_cache()
1094 1094
1095 1095 In [19]: len(_ip._main_mod_cache) == 0
1096 1096 Out[19]: True
1097 1097 """
1098 1098 self._main_mod_cache.clear()
1099 1099
1100 1100 #-------------------------------------------------------------------------
1101 1101 # Things related to debugging
1102 1102 #-------------------------------------------------------------------------
1103 1103
1104 1104 def init_pdb(self):
1105 1105 # Set calling of pdb on exceptions
1106 1106 # self.call_pdb is a property
1107 1107 self.call_pdb = self.pdb
1108 1108
1109 1109 def _get_call_pdb(self):
1110 1110 return self._call_pdb
1111 1111
1112 1112 def _set_call_pdb(self,val):
1113 1113
1114 1114 if val not in (0,1,False,True):
1115 1115 raise ValueError('new call_pdb value must be boolean')
1116 1116
1117 1117 # store value in instance
1118 1118 self._call_pdb = val
1119 1119
1120 1120 # notify the actual exception handlers
1121 1121 self.InteractiveTB.call_pdb = val
1122 1122
1123 1123 call_pdb = property(_get_call_pdb,_set_call_pdb,None,
1124 1124 'Control auto-activation of pdb at exceptions')
1125 1125
1126 1126 def debugger(self,force=False):
1127 1127 """Call the pdb debugger.
1128 1128
1129 1129 Keywords:
1130 1130
1131 1131 - force(False): by default, this routine checks the instance call_pdb
1132 1132 flag and does not actually invoke the debugger if the flag is false.
1133 1133 The 'force' option forces the debugger to activate even if the flag
1134 1134 is false.
1135 1135 """
1136 1136
1137 1137 if not (force or self.call_pdb):
1138 1138 return
1139 1139
1140 1140 if not hasattr(sys,'last_traceback'):
1141 1141 error('No traceback has been produced, nothing to debug.')
1142 1142 return
1143 1143
1144 1144 self.InteractiveTB.debugger(force=True)
1145 1145
1146 1146 #-------------------------------------------------------------------------
1147 1147 # Things related to IPython's various namespaces
1148 1148 #-------------------------------------------------------------------------
1149 1149 default_user_namespaces = True
1150 1150
1151 1151 def init_create_namespaces(self, user_module=None, user_ns=None):
1152 1152 # Create the namespace where the user will operate. user_ns is
1153 1153 # normally the only one used, and it is passed to the exec calls as
1154 1154 # the locals argument. But we do carry a user_global_ns namespace
1155 1155 # given as the exec 'globals' argument, This is useful in embedding
1156 1156 # situations where the ipython shell opens in a context where the
1157 1157 # distinction between locals and globals is meaningful. For
1158 1158 # non-embedded contexts, it is just the same object as the user_ns dict.
1159 1159
1160 1160 # FIXME. For some strange reason, __builtins__ is showing up at user
1161 1161 # level as a dict instead of a module. This is a manual fix, but I
1162 1162 # should really track down where the problem is coming from. Alex
1163 1163 # Schmolck reported this problem first.
1164 1164
1165 1165 # A useful post by Alex Martelli on this topic:
1166 1166 # Re: inconsistent value from __builtins__
1167 1167 # Von: Alex Martelli <aleaxit@yahoo.com>
1168 1168 # Datum: Freitag 01 Oktober 2004 04:45:34 nachmittags/abends
1169 1169 # Gruppen: comp.lang.python
1170 1170
1171 1171 # Michael Hohn <hohn@hooknose.lbl.gov> wrote:
1172 1172 # > >>> print type(builtin_check.get_global_binding('__builtins__'))
1173 1173 # > <type 'dict'>
1174 1174 # > >>> print type(__builtins__)
1175 1175 # > <type 'module'>
1176 1176 # > Is this difference in return value intentional?
1177 1177
1178 1178 # Well, it's documented that '__builtins__' can be either a dictionary
1179 1179 # or a module, and it's been that way for a long time. Whether it's
1180 1180 # intentional (or sensible), I don't know. In any case, the idea is
1181 1181 # that if you need to access the built-in namespace directly, you
1182 1182 # should start with "import __builtin__" (note, no 's') which will
1183 1183 # definitely give you a module. Yeah, it's somewhat confusing:-(.
1184 1184
1185 1185 # These routines return a properly built module and dict as needed by
1186 1186 # the rest of the code, and can also be used by extension writers to
1187 1187 # generate properly initialized namespaces.
1188 1188 if (user_ns is not None) or (user_module is not None):
1189 1189 self.default_user_namespaces = False
1190 1190 self.user_module, self.user_ns = self.prepare_user_module(user_module, user_ns)
1191 1191
1192 1192 # A record of hidden variables we have added to the user namespace, so
1193 1193 # we can list later only variables defined in actual interactive use.
1194 1194 self.user_ns_hidden = {}
1195 1195
1196 1196 # Now that FakeModule produces a real module, we've run into a nasty
1197 1197 # problem: after script execution (via %run), the module where the user
1198 1198 # code ran is deleted. Now that this object is a true module (needed
1199 1199 # so doctest and other tools work correctly), the Python module
1200 1200 # teardown mechanism runs over it, and sets to None every variable
1201 1201 # present in that module. Top-level references to objects from the
1202 1202 # script survive, because the user_ns is updated with them. However,
1203 1203 # calling functions defined in the script that use other things from
1204 1204 # the script will fail, because the function's closure had references
1205 1205 # to the original objects, which are now all None. So we must protect
1206 1206 # these modules from deletion by keeping a cache.
1207 1207 #
1208 1208 # To avoid keeping stale modules around (we only need the one from the
1209 1209 # last run), we use a dict keyed with the full path to the script, so
1210 1210 # only the last version of the module is held in the cache. Note,
1211 1211 # however, that we must cache the module *namespace contents* (their
1212 1212 # __dict__). Because if we try to cache the actual modules, old ones
1213 1213 # (uncached) could be destroyed while still holding references (such as
1214 1214 # those held by GUI objects that tend to be long-lived)>
1215 1215 #
1216 1216 # The %reset command will flush this cache. See the cache_main_mod()
1217 1217 # and clear_main_mod_cache() methods for details on use.
1218 1218
1219 1219 # This is the cache used for 'main' namespaces
1220 1220 self._main_mod_cache = {}
1221 1221
1222 1222 # A table holding all the namespaces IPython deals with, so that
1223 1223 # introspection facilities can search easily.
1224 1224 self.ns_table = {'user_global':self.user_module.__dict__,
1225 1225 'user_local':self.user_ns,
1226 1226 'builtin':builtin_mod.__dict__
1227 1227 }
1228 1228
1229 1229 @property
1230 1230 def user_global_ns(self):
1231 1231 return self.user_module.__dict__
1232 1232
1233 1233 def prepare_user_module(self, user_module=None, user_ns=None):
1234 1234 """Prepare the module and namespace in which user code will be run.
1235 1235
1236 1236 When IPython is started normally, both parameters are None: a new module
1237 1237 is created automatically, and its __dict__ used as the namespace.
1238 1238
1239 1239 If only user_module is provided, its __dict__ is used as the namespace.
1240 1240 If only user_ns is provided, a dummy module is created, and user_ns
1241 1241 becomes the global namespace. If both are provided (as they may be
1242 1242 when embedding), user_ns is the local namespace, and user_module
1243 1243 provides the global namespace.
1244 1244
1245 1245 Parameters
1246 1246 ----------
1247 1247 user_module : module, optional
1248 1248 The current user module in which IPython is being run. If None,
1249 1249 a clean module will be created.
1250 1250 user_ns : dict, optional
1251 1251 A namespace in which to run interactive commands.
1252 1252
1253 1253 Returns
1254 1254 -------
1255 1255 A tuple of user_module and user_ns, each properly initialised.
1256 1256 """
1257 1257 if user_module is None and user_ns is not None:
1258 1258 user_ns.setdefault("__name__", "__main__")
1259 1259 user_module = DummyMod()
1260 1260 user_module.__dict__ = user_ns
1261 1261
1262 1262 if user_module is None:
1263 1263 user_module = types.ModuleType("__main__",
1264 1264 doc="Automatically created module for IPython interactive environment")
1265 1265
1266 1266 # We must ensure that __builtin__ (without the final 's') is always
1267 1267 # available and pointing to the __builtin__ *module*. For more details:
1268 1268 # http://mail.python.org/pipermail/python-dev/2001-April/014068.html
1269 1269 user_module.__dict__.setdefault('__builtin__', builtin_mod)
1270 1270 user_module.__dict__.setdefault('__builtins__', builtin_mod)
1271 1271
1272 1272 if user_ns is None:
1273 1273 user_ns = user_module.__dict__
1274 1274
1275 1275 return user_module, user_ns
1276 1276
1277 1277 def init_sys_modules(self):
1278 1278 # We need to insert into sys.modules something that looks like a
1279 1279 # module but which accesses the IPython namespace, for shelve and
1280 1280 # pickle to work interactively. Normally they rely on getting
1281 1281 # everything out of __main__, but for embedding purposes each IPython
1282 1282 # instance has its own private namespace, so we can't go shoving
1283 1283 # everything into __main__.
1284 1284
1285 1285 # note, however, that we should only do this for non-embedded
1286 1286 # ipythons, which really mimic the __main__.__dict__ with their own
1287 1287 # namespace. Embedded instances, on the other hand, should not do
1288 1288 # this because they need to manage the user local/global namespaces
1289 1289 # only, but they live within a 'normal' __main__ (meaning, they
1290 1290 # shouldn't overtake the execution environment of the script they're
1291 1291 # embedded in).
1292 1292
1293 1293 # This is overridden in the InteractiveShellEmbed subclass to a no-op.
1294 1294 main_name = self.user_module.__name__
1295 1295 sys.modules[main_name] = self.user_module
1296 1296
1297 1297 def init_user_ns(self):
1298 1298 """Initialize all user-visible namespaces to their minimum defaults.
1299 1299
1300 1300 Certain history lists are also initialized here, as they effectively
1301 1301 act as user namespaces.
1302 1302
1303 1303 Notes
1304 1304 -----
1305 1305 All data structures here are only filled in, they are NOT reset by this
1306 1306 method. If they were not empty before, data will simply be added to
1307 1307 them.
1308 1308 """
1309 1309 # This function works in two parts: first we put a few things in
1310 1310 # user_ns, and we sync that contents into user_ns_hidden so that these
1311 1311 # initial variables aren't shown by %who. After the sync, we add the
1312 1312 # rest of what we *do* want the user to see with %who even on a new
1313 1313 # session (probably nothing, so they really only see their own stuff)
1314 1314
1315 1315 # The user dict must *always* have a __builtin__ reference to the
1316 1316 # Python standard __builtin__ namespace, which must be imported.
1317 1317 # This is so that certain operations in prompt evaluation can be
1318 1318 # reliably executed with builtins. Note that we can NOT use
1319 1319 # __builtins__ (note the 's'), because that can either be a dict or a
1320 1320 # module, and can even mutate at runtime, depending on the context
1321 1321 # (Python makes no guarantees on it). In contrast, __builtin__ is
1322 1322 # always a module object, though it must be explicitly imported.
1323 1323
1324 1324 # For more details:
1325 1325 # http://mail.python.org/pipermail/python-dev/2001-April/014068.html
1326 1326 ns = {}
1327 1327
1328 1328 # make global variables for user access to the histories
1329 1329 ns['_ih'] = self.history_manager.input_hist_parsed
1330 1330 ns['_oh'] = self.history_manager.output_hist
1331 1331 ns['_dh'] = self.history_manager.dir_hist
1332 1332
1333 1333 # user aliases to input and output histories. These shouldn't show up
1334 1334 # in %who, as they can have very large reprs.
1335 1335 ns['In'] = self.history_manager.input_hist_parsed
1336 1336 ns['Out'] = self.history_manager.output_hist
1337 1337
1338 1338 # Store myself as the public api!!!
1339 1339 ns['get_ipython'] = self.get_ipython
1340 1340
1341 1341 ns['exit'] = self.exiter
1342 1342 ns['quit'] = self.exiter
1343 1343 ns["open"] = _modified_open
1344 1344
1345 1345 # Sync what we've added so far to user_ns_hidden so these aren't seen
1346 1346 # by %who
1347 1347 self.user_ns_hidden.update(ns)
1348 1348
1349 1349 # Anything put into ns now would show up in %who. Think twice before
1350 1350 # putting anything here, as we really want %who to show the user their
1351 1351 # stuff, not our variables.
1352 1352
1353 1353 # Finally, update the real user's namespace
1354 1354 self.user_ns.update(ns)
1355 1355
1356 1356 @property
1357 1357 def all_ns_refs(self):
1358 1358 """Get a list of references to all the namespace dictionaries in which
1359 1359 IPython might store a user-created object.
1360 1360
1361 1361 Note that this does not include the displayhook, which also caches
1362 1362 objects from the output."""
1363 1363 return [self.user_ns, self.user_global_ns, self.user_ns_hidden] + \
1364 1364 [m.__dict__ for m in self._main_mod_cache.values()]
1365 1365
1366 1366 def reset(self, new_session=True, aggressive=False):
1367 1367 """Clear all internal namespaces, and attempt to release references to
1368 1368 user objects.
1369 1369
1370 1370 If new_session is True, a new history session will be opened.
1371 1371 """
1372 1372 # Clear histories
1373 1373 self.history_manager.reset(new_session)
1374 1374 # Reset counter used to index all histories
1375 1375 if new_session:
1376 1376 self.execution_count = 1
1377 1377
1378 1378 # Reset last execution result
1379 1379 self.last_execution_succeeded = True
1380 1380 self.last_execution_result = None
1381 1381
1382 1382 # Flush cached output items
1383 1383 if self.displayhook.do_full_cache:
1384 1384 self.displayhook.flush()
1385 1385
1386 1386 # The main execution namespaces must be cleared very carefully,
1387 1387 # skipping the deletion of the builtin-related keys, because doing so
1388 1388 # would cause errors in many object's __del__ methods.
1389 1389 if self.user_ns is not self.user_global_ns:
1390 1390 self.user_ns.clear()
1391 1391 ns = self.user_global_ns
1392 1392 drop_keys = set(ns.keys())
1393 1393 drop_keys.discard('__builtin__')
1394 1394 drop_keys.discard('__builtins__')
1395 1395 drop_keys.discard('__name__')
1396 1396 for k in drop_keys:
1397 1397 del ns[k]
1398 1398
1399 1399 self.user_ns_hidden.clear()
1400 1400
1401 1401 # Restore the user namespaces to minimal usability
1402 1402 self.init_user_ns()
1403 1403 if aggressive and not hasattr(self, "_sys_modules_keys"):
1404 1404 print("Cannot restore sys.module, no snapshot")
1405 1405 elif aggressive:
1406 1406 print("culling sys module...")
1407 1407 current_keys = set(sys.modules.keys())
1408 1408 for k in current_keys - self._sys_modules_keys:
1409 1409 if k.startswith("multiprocessing"):
1410 1410 continue
1411 1411 del sys.modules[k]
1412 1412
1413 1413 # Restore the default and user aliases
1414 1414 self.alias_manager.clear_aliases()
1415 1415 self.alias_manager.init_aliases()
1416 1416
1417 1417 # Now define aliases that only make sense on the terminal, because they
1418 1418 # need direct access to the console in a way that we can't emulate in
1419 1419 # GUI or web frontend
1420 1420 if os.name == 'posix':
1421 1421 for cmd in ('clear', 'more', 'less', 'man'):
1422 1422 if cmd not in self.magics_manager.magics['line']:
1423 1423 self.alias_manager.soft_define_alias(cmd, cmd)
1424 1424
1425 1425 # Flush the private list of module references kept for script
1426 1426 # execution protection
1427 1427 self.clear_main_mod_cache()
1428 1428
1429 1429 def del_var(self, varname, by_name=False):
1430 1430 """Delete a variable from the various namespaces, so that, as
1431 1431 far as possible, we're not keeping any hidden references to it.
1432 1432
1433 1433 Parameters
1434 1434 ----------
1435 1435 varname : str
1436 1436 The name of the variable to delete.
1437 1437 by_name : bool
1438 1438 If True, delete variables with the given name in each
1439 1439 namespace. If False (default), find the variable in the user
1440 1440 namespace, and delete references to it.
1441 1441 """
1442 1442 if varname in ('__builtin__', '__builtins__'):
1443 1443 raise ValueError("Refusing to delete %s" % varname)
1444 1444
1445 1445 ns_refs = self.all_ns_refs
1446 1446
1447 1447 if by_name: # Delete by name
1448 1448 for ns in ns_refs:
1449 1449 try:
1450 1450 del ns[varname]
1451 1451 except KeyError:
1452 1452 pass
1453 1453 else: # Delete by object
1454 1454 try:
1455 1455 obj = self.user_ns[varname]
1456 1456 except KeyError as e:
1457 1457 raise NameError("name '%s' is not defined" % varname) from e
1458 1458 # Also check in output history
1459 1459 ns_refs.append(self.history_manager.output_hist)
1460 1460 for ns in ns_refs:
1461 1461 to_delete = [n for n, o in ns.items() if o is obj]
1462 1462 for name in to_delete:
1463 1463 del ns[name]
1464 1464
1465 1465 # Ensure it is removed from the last execution result
1466 1466 if self.last_execution_result.result is obj:
1467 1467 self.last_execution_result = None
1468 1468
1469 1469 # displayhook keeps extra references, but not in a dictionary
1470 1470 for name in ('_', '__', '___'):
1471 1471 if getattr(self.displayhook, name) is obj:
1472 1472 setattr(self.displayhook, name, None)
1473 1473
1474 1474 def reset_selective(self, regex=None):
1475 1475 """Clear selective variables from internal namespaces based on a
1476 1476 specified regular expression.
1477 1477
1478 1478 Parameters
1479 1479 ----------
1480 1480 regex : string or compiled pattern, optional
1481 1481 A regular expression pattern that will be used in searching
1482 1482 variable names in the users namespaces.
1483 1483 """
1484 1484 if regex is not None:
1485 1485 try:
1486 1486 m = re.compile(regex)
1487 1487 except TypeError as e:
1488 1488 raise TypeError('regex must be a string or compiled pattern') from e
1489 1489 # Search for keys in each namespace that match the given regex
1490 1490 # If a match is found, delete the key/value pair.
1491 1491 for ns in self.all_ns_refs:
1492 1492 for var in ns:
1493 1493 if m.search(var):
1494 1494 del ns[var]
1495 1495
1496 1496 def push(self, variables, interactive=True):
1497 1497 """Inject a group of variables into the IPython user namespace.
1498 1498
1499 1499 Parameters
1500 1500 ----------
1501 1501 variables : dict, str or list/tuple of str
1502 1502 The variables to inject into the user's namespace. If a dict, a
1503 1503 simple update is done. If a str, the string is assumed to have
1504 1504 variable names separated by spaces. A list/tuple of str can also
1505 1505 be used to give the variable names. If just the variable names are
1506 1506 give (list/tuple/str) then the variable values looked up in the
1507 1507 callers frame.
1508 1508 interactive : bool
1509 1509 If True (default), the variables will be listed with the ``who``
1510 1510 magic.
1511 1511 """
1512 1512 vdict = None
1513 1513
1514 1514 # We need a dict of name/value pairs to do namespace updates.
1515 1515 if isinstance(variables, dict):
1516 1516 vdict = variables
1517 1517 elif isinstance(variables, (str, list, tuple)):
1518 1518 if isinstance(variables, str):
1519 1519 vlist = variables.split()
1520 1520 else:
1521 1521 vlist = variables
1522 1522 vdict = {}
1523 1523 cf = sys._getframe(1)
1524 1524 for name in vlist:
1525 1525 try:
1526 1526 vdict[name] = eval(name, cf.f_globals, cf.f_locals)
1527 1527 except:
1528 1528 print('Could not get variable %s from %s' %
1529 1529 (name,cf.f_code.co_name))
1530 1530 else:
1531 1531 raise ValueError('variables must be a dict/str/list/tuple')
1532 1532
1533 1533 # Propagate variables to user namespace
1534 1534 self.user_ns.update(vdict)
1535 1535
1536 1536 # And configure interactive visibility
1537 1537 user_ns_hidden = self.user_ns_hidden
1538 1538 if interactive:
1539 1539 for name in vdict:
1540 1540 user_ns_hidden.pop(name, None)
1541 1541 else:
1542 1542 user_ns_hidden.update(vdict)
1543 1543
1544 1544 def drop_by_id(self, variables):
1545 1545 """Remove a dict of variables from the user namespace, if they are the
1546 1546 same as the values in the dictionary.
1547 1547
1548 1548 This is intended for use by extensions: variables that they've added can
1549 1549 be taken back out if they are unloaded, without removing any that the
1550 1550 user has overwritten.
1551 1551
1552 1552 Parameters
1553 1553 ----------
1554 1554 variables : dict
1555 1555 A dictionary mapping object names (as strings) to the objects.
1556 1556 """
1557 1557 for name, obj in variables.items():
1558 1558 if name in self.user_ns and self.user_ns[name] is obj:
1559 1559 del self.user_ns[name]
1560 1560 self.user_ns_hidden.pop(name, None)
1561 1561
1562 1562 #-------------------------------------------------------------------------
1563 1563 # Things related to object introspection
1564 1564 #-------------------------------------------------------------------------
1565 1565 @staticmethod
1566 def _find_parts(oname: str) -> ListType[str]:
1566 def _find_parts(oname: str) -> Tuple[bool, ListType[str]]:
1567 1567 """
1568 1568 Given an object name, return a list of parts of this object name.
1569 1569
1570 1570 Basically split on docs when using attribute access,
1571 1571 and extract the value when using square bracket.
1572 1572
1573 1573
1574 1574 For example foo.bar[3].baz[x] -> foo, bar, 3, baz, x
1575 1575
1576 1576
1577 1577 Returns
1578 1578 -------
1579 1579 parts_ok: bool
1580 1580 wether we were properly able to parse parts.
1581 1581 parts: list of str
1582 1582 extracted parts
1583 1583
1584 1584
1585 1585
1586 1586 """
1587 1587 raw_parts = oname.split(".")
1588 1588 parts = []
1589 1589 parts_ok = True
1590 1590 for p in raw_parts:
1591 1591 if p.endswith("]"):
1592 1592 var, *indices = p.split("[")
1593 1593 if not var.isidentifier():
1594 1594 parts_ok = False
1595 1595 break
1596 1596 parts.append(var)
1597 1597 for ind in indices:
1598 1598 if ind[-1] != "]" and not is_integer_string(ind[:-1]):
1599 1599 parts_ok = False
1600 1600 break
1601 1601 parts.append(ind[:-1])
1602 1602 continue
1603 1603
1604 1604 if not p.isidentifier():
1605 1605 parts_ok = False
1606 1606 parts.append(p)
1607 1607
1608 1608 return parts_ok, parts
1609 1609
1610 def _ofind(self, oname: str, namespaces: DictType[str, AnyType] = None):
1610 def _ofind(
1611 self, oname: str, namespaces: Optional[Sequence[Tuple[str, AnyType]]] = None
1612 ):
1611 1613 """Find an object in the available namespaces.
1612 1614
1613 1615 self._ofind(oname) -> dict with keys: found,obj,ospace,ismagic
1614 1616
1615 1617 Has special code to detect magic functions.
1616 1618 """
1617 1619 oname = oname.strip()
1618 1620 parts_ok, parts = self._find_parts(oname)
1619 1621
1620 1622 if (
1621 1623 not oname.startswith(ESC_MAGIC)
1622 1624 and not oname.startswith(ESC_MAGIC2)
1623 1625 and not parts_ok
1624 1626 ):
1625 1627 return OInfo(
1626 1628 ismagic=False,
1627 1629 isalias=False,
1628 1630 found=False,
1629 1631 obj=None,
1630 namespace="",
1632 namespace=None,
1631 1633 parent=None,
1632 1634 )
1633 1635
1634 1636 if namespaces is None:
1635 1637 # Namespaces to search in:
1636 1638 # Put them in a list. The order is important so that we
1637 1639 # find things in the same order that Python finds them.
1638 1640 namespaces = [ ('Interactive', self.user_ns),
1639 1641 ('Interactive (global)', self.user_global_ns),
1640 1642 ('Python builtin', builtin_mod.__dict__),
1641 1643 ]
1642 1644
1643 1645 ismagic = False
1644 1646 isalias = False
1645 1647 found = False
1646 1648 ospace = None
1647 1649 parent = None
1648 1650 obj = None
1649 1651
1650 1652
1651 1653 # Look for the given name by splitting it in parts. If the head is
1652 1654 # found, then we look for all the remaining parts as members, and only
1653 1655 # declare success if we can find them all.
1654 1656 oname_parts = parts
1655 1657 oname_head, oname_rest = oname_parts[0],oname_parts[1:]
1656 1658 for nsname,ns in namespaces:
1657 1659 try:
1658 1660 obj = ns[oname_head]
1659 1661 except KeyError:
1660 1662 continue
1661 1663 else:
1662 1664 for idx, part in enumerate(oname_rest):
1663 1665 try:
1664 1666 parent = obj
1665 1667 # The last part is looked up in a special way to avoid
1666 1668 # descriptor invocation as it may raise or have side
1667 1669 # effects.
1668 1670 if idx == len(oname_rest) - 1:
1669 1671 obj = self._getattr_property(obj, part)
1670 1672 else:
1671 1673 if is_integer_string(part):
1672 1674 obj = obj[int(part)]
1673 1675 else:
1674 1676 obj = getattr(obj, part)
1675 1677 except:
1676 1678 # Blanket except b/c some badly implemented objects
1677 1679 # allow __getattr__ to raise exceptions other than
1678 1680 # AttributeError, which then crashes IPython.
1679 1681 break
1680 1682 else:
1681 1683 # If we finish the for loop (no break), we got all members
1682 1684 found = True
1683 1685 ospace = nsname
1684 1686 break # namespace loop
1685 1687
1686 1688 # Try to see if it's magic
1687 1689 if not found:
1688 1690 obj = None
1689 1691 if oname.startswith(ESC_MAGIC2):
1690 1692 oname = oname.lstrip(ESC_MAGIC2)
1691 1693 obj = self.find_cell_magic(oname)
1692 1694 elif oname.startswith(ESC_MAGIC):
1693 1695 oname = oname.lstrip(ESC_MAGIC)
1694 1696 obj = self.find_line_magic(oname)
1695 1697 else:
1696 1698 # search without prefix, so run? will find %run?
1697 1699 obj = self.find_line_magic(oname)
1698 1700 if obj is None:
1699 1701 obj = self.find_cell_magic(oname)
1700 1702 if obj is not None:
1701 1703 found = True
1702 1704 ospace = 'IPython internal'
1703 1705 ismagic = True
1704 1706 isalias = isinstance(obj, Alias)
1705 1707
1706 1708 # Last try: special-case some literals like '', [], {}, etc:
1707 1709 if not found and oname_head in ["''",'""','[]','{}','()']:
1708 1710 obj = eval(oname_head)
1709 1711 found = True
1710 1712 ospace = 'Interactive'
1711 1713
1712 1714 return OInfo(
1713 **{
1714 "obj": obj,
1715 "found": found,
1716 "parent": parent,
1717 "ismagic": ismagic,
1718 "isalias": isalias,
1719 "namespace": ospace,
1720 }
1715 obj=obj,
1716 found=found,
1717 parent=parent,
1718 ismagic=ismagic,
1719 isalias=isalias,
1720 namespace=ospace,
1721 1721 )
1722 1722
1723 1723 @staticmethod
1724 1724 def _getattr_property(obj, attrname):
1725 1725 """Property-aware getattr to use in object finding.
1726 1726
1727 1727 If attrname represents a property, return it unevaluated (in case it has
1728 1728 side effects or raises an error.
1729 1729
1730 1730 """
1731 1731 if not isinstance(obj, type):
1732 1732 try:
1733 1733 # `getattr(type(obj), attrname)` is not guaranteed to return
1734 1734 # `obj`, but does so for property:
1735 1735 #
1736 1736 # property.__get__(self, None, cls) -> self
1737 1737 #
1738 1738 # The universal alternative is to traverse the mro manually
1739 1739 # searching for attrname in class dicts.
1740 1740 if is_integer_string(attrname):
1741 1741 return obj[int(attrname)]
1742 1742 else:
1743 1743 attr = getattr(type(obj), attrname)
1744 1744 except AttributeError:
1745 1745 pass
1746 1746 else:
1747 1747 # This relies on the fact that data descriptors (with both
1748 1748 # __get__ & __set__ magic methods) take precedence over
1749 1749 # instance-level attributes:
1750 1750 #
1751 1751 # class A(object):
1752 1752 # @property
1753 1753 # def foobar(self): return 123
1754 1754 # a = A()
1755 1755 # a.__dict__['foobar'] = 345
1756 1756 # a.foobar # == 123
1757 1757 #
1758 1758 # So, a property may be returned right away.
1759 1759 if isinstance(attr, property):
1760 1760 return attr
1761 1761
1762 1762 # Nothing helped, fall back.
1763 1763 return getattr(obj, attrname)
1764 1764
1765 1765 def _object_find(self, oname, namespaces=None) -> OInfo:
1766 1766 """Find an object and return a struct with info about it."""
1767 1767 return self._ofind(oname, namespaces)
1768 1768
1769 1769 def _inspect(self, meth, oname, namespaces=None, **kw):
1770 1770 """Generic interface to the inspector system.
1771 1771
1772 1772 This function is meant to be called by pdef, pdoc & friends.
1773 1773 """
1774 1774 info = self._object_find(oname, namespaces)
1775 1775 docformat = (
1776 1776 sphinxify(self.object_inspect(oname)) if self.sphinxify_docstring else None
1777 1777 )
1778 1778 if info.found:
1779 1779 pmethod = getattr(self.inspector, meth)
1780 1780 # TODO: only apply format_screen to the plain/text repr of the mime
1781 1781 # bundle.
1782 1782 formatter = format_screen if info.ismagic else docformat
1783 1783 if meth == 'pdoc':
1784 1784 pmethod(info.obj, oname, formatter)
1785 1785 elif meth == 'pinfo':
1786 1786 pmethod(
1787 1787 info.obj,
1788 1788 oname,
1789 1789 formatter,
1790 1790 info,
1791 1791 enable_html_pager=self.enable_html_pager,
1792 1792 **kw,
1793 1793 )
1794 1794 else:
1795 1795 pmethod(info.obj, oname)
1796 1796 else:
1797 1797 print('Object `%s` not found.' % oname)
1798 1798 return 'not found' # so callers can take other action
1799 1799
1800 1800 def object_inspect(self, oname, detail_level=0):
1801 1801 """Get object info about oname"""
1802 1802 with self.builtin_trap:
1803 1803 info = self._object_find(oname)
1804 1804 if info.found:
1805 1805 return self.inspector.info(info.obj, oname, info=info,
1806 1806 detail_level=detail_level
1807 1807 )
1808 1808 else:
1809 1809 return oinspect.object_info(name=oname, found=False)
1810 1810
1811 1811 def object_inspect_text(self, oname, detail_level=0):
1812 1812 """Get object info as formatted text"""
1813 1813 return self.object_inspect_mime(oname, detail_level)['text/plain']
1814 1814
1815 1815 def object_inspect_mime(self, oname, detail_level=0, omit_sections=()):
1816 1816 """Get object info as a mimebundle of formatted representations.
1817 1817
1818 1818 A mimebundle is a dictionary, keyed by mime-type.
1819 1819 It must always have the key `'text/plain'`.
1820 1820 """
1821 1821 with self.builtin_trap:
1822 1822 info = self._object_find(oname)
1823 1823 if info.found:
1824 1824 docformat = (
1825 1825 sphinxify(self.object_inspect(oname))
1826 1826 if self.sphinxify_docstring
1827 1827 else None
1828 1828 )
1829 1829 return self.inspector._get_info(
1830 1830 info.obj,
1831 1831 oname,
1832 1832 info=info,
1833 1833 detail_level=detail_level,
1834 1834 formatter=docformat,
1835 1835 omit_sections=omit_sections,
1836 1836 )
1837 1837 else:
1838 1838 raise KeyError(oname)
1839 1839
1840 1840 #-------------------------------------------------------------------------
1841 1841 # Things related to history management
1842 1842 #-------------------------------------------------------------------------
1843 1843
1844 1844 def init_history(self):
1845 1845 """Sets up the command history, and starts regular autosaves."""
1846 1846 self.history_manager = HistoryManager(shell=self, parent=self)
1847 1847 self.configurables.append(self.history_manager)
1848 1848
1849 1849 #-------------------------------------------------------------------------
1850 1850 # Things related to exception handling and tracebacks (not debugging)
1851 1851 #-------------------------------------------------------------------------
1852 1852
1853 1853 debugger_cls = InterruptiblePdb
1854 1854
1855 1855 def init_traceback_handlers(self, custom_exceptions):
1856 1856 # Syntax error handler.
1857 1857 self.SyntaxTB = ultratb.SyntaxTB(color_scheme='NoColor', parent=self)
1858 1858
1859 1859 # The interactive one is initialized with an offset, meaning we always
1860 1860 # want to remove the topmost item in the traceback, which is our own
1861 1861 # internal code. Valid modes: ['Plain','Context','Verbose','Minimal']
1862 1862 self.InteractiveTB = ultratb.AutoFormattedTB(mode = 'Plain',
1863 1863 color_scheme='NoColor',
1864 1864 tb_offset = 1,
1865 1865 debugger_cls=self.debugger_cls, parent=self)
1866 1866
1867 1867 # The instance will store a pointer to the system-wide exception hook,
1868 1868 # so that runtime code (such as magics) can access it. This is because
1869 1869 # during the read-eval loop, it may get temporarily overwritten.
1870 1870 self.sys_excepthook = sys.excepthook
1871 1871
1872 1872 # and add any custom exception handlers the user may have specified
1873 1873 self.set_custom_exc(*custom_exceptions)
1874 1874
1875 1875 # Set the exception mode
1876 1876 self.InteractiveTB.set_mode(mode=self.xmode)
1877 1877
1878 1878 def set_custom_exc(self, exc_tuple, handler):
1879 1879 """set_custom_exc(exc_tuple, handler)
1880 1880
1881 1881 Set a custom exception handler, which will be called if any of the
1882 1882 exceptions in exc_tuple occur in the mainloop (specifically, in the
1883 1883 run_code() method).
1884 1884
1885 1885 Parameters
1886 1886 ----------
1887 1887 exc_tuple : tuple of exception classes
1888 1888 A *tuple* of exception classes, for which to call the defined
1889 1889 handler. It is very important that you use a tuple, and NOT A
1890 1890 LIST here, because of the way Python's except statement works. If
1891 1891 you only want to trap a single exception, use a singleton tuple::
1892 1892
1893 1893 exc_tuple == (MyCustomException,)
1894 1894
1895 1895 handler : callable
1896 1896 handler must have the following signature::
1897 1897
1898 1898 def my_handler(self, etype, value, tb, tb_offset=None):
1899 1899 ...
1900 1900 return structured_traceback
1901 1901
1902 1902 Your handler must return a structured traceback (a list of strings),
1903 1903 or None.
1904 1904
1905 1905 This will be made into an instance method (via types.MethodType)
1906 1906 of IPython itself, and it will be called if any of the exceptions
1907 1907 listed in the exc_tuple are caught. If the handler is None, an
1908 1908 internal basic one is used, which just prints basic info.
1909 1909
1910 1910 To protect IPython from crashes, if your handler ever raises an
1911 1911 exception or returns an invalid result, it will be immediately
1912 1912 disabled.
1913 1913
1914 1914 Notes
1915 1915 -----
1916 1916 WARNING: by putting in your own exception handler into IPython's main
1917 1917 execution loop, you run a very good chance of nasty crashes. This
1918 1918 facility should only be used if you really know what you are doing.
1919 1919 """
1920 1920
1921 1921 if not isinstance(exc_tuple, tuple):
1922 1922 raise TypeError("The custom exceptions must be given as a tuple.")
1923 1923
1924 1924 def dummy_handler(self, etype, value, tb, tb_offset=None):
1925 1925 print('*** Simple custom exception handler ***')
1926 1926 print('Exception type :', etype)
1927 1927 print('Exception value:', value)
1928 1928 print('Traceback :', tb)
1929 1929
1930 1930 def validate_stb(stb):
1931 1931 """validate structured traceback return type
1932 1932
1933 1933 return type of CustomTB *should* be a list of strings, but allow
1934 1934 single strings or None, which are harmless.
1935 1935
1936 1936 This function will *always* return a list of strings,
1937 1937 and will raise a TypeError if stb is inappropriate.
1938 1938 """
1939 1939 msg = "CustomTB must return list of strings, not %r" % stb
1940 1940 if stb is None:
1941 1941 return []
1942 1942 elif isinstance(stb, str):
1943 1943 return [stb]
1944 1944 elif not isinstance(stb, list):
1945 1945 raise TypeError(msg)
1946 1946 # it's a list
1947 1947 for line in stb:
1948 1948 # check every element
1949 1949 if not isinstance(line, str):
1950 1950 raise TypeError(msg)
1951 1951 return stb
1952 1952
1953 1953 if handler is None:
1954 1954 wrapped = dummy_handler
1955 1955 else:
1956 1956 def wrapped(self,etype,value,tb,tb_offset=None):
1957 1957 """wrap CustomTB handler, to protect IPython from user code
1958 1958
1959 1959 This makes it harder (but not impossible) for custom exception
1960 1960 handlers to crash IPython.
1961 1961 """
1962 1962 try:
1963 1963 stb = handler(self,etype,value,tb,tb_offset=tb_offset)
1964 1964 return validate_stb(stb)
1965 1965 except:
1966 1966 # clear custom handler immediately
1967 1967 self.set_custom_exc((), None)
1968 1968 print("Custom TB Handler failed, unregistering", file=sys.stderr)
1969 1969 # show the exception in handler first
1970 1970 stb = self.InteractiveTB.structured_traceback(*sys.exc_info())
1971 1971 print(self.InteractiveTB.stb2text(stb))
1972 1972 print("The original exception:")
1973 1973 stb = self.InteractiveTB.structured_traceback(
1974 1974 (etype,value,tb), tb_offset=tb_offset
1975 1975 )
1976 1976 return stb
1977 1977
1978 1978 self.CustomTB = types.MethodType(wrapped,self)
1979 1979 self.custom_exceptions = exc_tuple
1980 1980
1981 1981 def excepthook(self, etype, value, tb):
1982 1982 """One more defense for GUI apps that call sys.excepthook.
1983 1983
1984 1984 GUI frameworks like wxPython trap exceptions and call
1985 1985 sys.excepthook themselves. I guess this is a feature that
1986 1986 enables them to keep running after exceptions that would
1987 1987 otherwise kill their mainloop. This is a bother for IPython
1988 1988 which expects to catch all of the program exceptions with a try:
1989 1989 except: statement.
1990 1990
1991 1991 Normally, IPython sets sys.excepthook to a CrashHandler instance, so if
1992 1992 any app directly invokes sys.excepthook, it will look to the user like
1993 1993 IPython crashed. In order to work around this, we can disable the
1994 1994 CrashHandler and replace it with this excepthook instead, which prints a
1995 1995 regular traceback using our InteractiveTB. In this fashion, apps which
1996 1996 call sys.excepthook will generate a regular-looking exception from
1997 1997 IPython, and the CrashHandler will only be triggered by real IPython
1998 1998 crashes.
1999 1999
2000 2000 This hook should be used sparingly, only in places which are not likely
2001 2001 to be true IPython errors.
2002 2002 """
2003 2003 self.showtraceback((etype, value, tb), tb_offset=0)
2004 2004
2005 2005 def _get_exc_info(self, exc_tuple=None):
2006 2006 """get exc_info from a given tuple, sys.exc_info() or sys.last_type etc.
2007 2007
2008 2008 Ensures sys.last_type,value,traceback hold the exc_info we found,
2009 2009 from whichever source.
2010 2010
2011 2011 raises ValueError if none of these contain any information
2012 2012 """
2013 2013 if exc_tuple is None:
2014 2014 etype, value, tb = sys.exc_info()
2015 2015 else:
2016 2016 etype, value, tb = exc_tuple
2017 2017
2018 2018 if etype is None:
2019 2019 if hasattr(sys, 'last_type'):
2020 2020 etype, value, tb = sys.last_type, sys.last_value, \
2021 2021 sys.last_traceback
2022 2022
2023 2023 if etype is None:
2024 2024 raise ValueError("No exception to find")
2025 2025
2026 2026 # Now store the exception info in sys.last_type etc.
2027 2027 # WARNING: these variables are somewhat deprecated and not
2028 2028 # necessarily safe to use in a threaded environment, but tools
2029 2029 # like pdb depend on their existence, so let's set them. If we
2030 2030 # find problems in the field, we'll need to revisit their use.
2031 2031 sys.last_type = etype
2032 2032 sys.last_value = value
2033 2033 sys.last_traceback = tb
2034 2034
2035 2035 return etype, value, tb
2036 2036
2037 2037 def show_usage_error(self, exc):
2038 2038 """Show a short message for UsageErrors
2039 2039
2040 2040 These are special exceptions that shouldn't show a traceback.
2041 2041 """
2042 2042 print("UsageError: %s" % exc, file=sys.stderr)
2043 2043
2044 2044 def get_exception_only(self, exc_tuple=None):
2045 2045 """
2046 2046 Return as a string (ending with a newline) the exception that
2047 2047 just occurred, without any traceback.
2048 2048 """
2049 2049 etype, value, tb = self._get_exc_info(exc_tuple)
2050 2050 msg = traceback.format_exception_only(etype, value)
2051 2051 return ''.join(msg)
2052 2052
2053 2053 def showtraceback(self, exc_tuple=None, filename=None, tb_offset=None,
2054 2054 exception_only=False, running_compiled_code=False):
2055 2055 """Display the exception that just occurred.
2056 2056
2057 2057 If nothing is known about the exception, this is the method which
2058 2058 should be used throughout the code for presenting user tracebacks,
2059 2059 rather than directly invoking the InteractiveTB object.
2060 2060
2061 2061 A specific showsyntaxerror() also exists, but this method can take
2062 2062 care of calling it if needed, so unless you are explicitly catching a
2063 2063 SyntaxError exception, don't try to analyze the stack manually and
2064 2064 simply call this method."""
2065 2065
2066 2066 try:
2067 2067 try:
2068 2068 etype, value, tb = self._get_exc_info(exc_tuple)
2069 2069 except ValueError:
2070 2070 print('No traceback available to show.', file=sys.stderr)
2071 2071 return
2072 2072
2073 2073 if issubclass(etype, SyntaxError):
2074 2074 # Though this won't be called by syntax errors in the input
2075 2075 # line, there may be SyntaxError cases with imported code.
2076 2076 self.showsyntaxerror(filename, running_compiled_code)
2077 2077 elif etype is UsageError:
2078 2078 self.show_usage_error(value)
2079 2079 else:
2080 2080 if exception_only:
2081 2081 stb = ['An exception has occurred, use %tb to see '
2082 2082 'the full traceback.\n']
2083 2083 stb.extend(self.InteractiveTB.get_exception_only(etype,
2084 2084 value))
2085 2085 else:
2086 2086 try:
2087 2087 # Exception classes can customise their traceback - we
2088 2088 # use this in IPython.parallel for exceptions occurring
2089 2089 # in the engines. This should return a list of strings.
2090 2090 if hasattr(value, "_render_traceback_"):
2091 2091 stb = value._render_traceback_()
2092 2092 else:
2093 2093 stb = self.InteractiveTB.structured_traceback(
2094 2094 etype, value, tb, tb_offset=tb_offset
2095 2095 )
2096 2096
2097 2097 except Exception:
2098 2098 print(
2099 2099 "Unexpected exception formatting exception. Falling back to standard exception"
2100 2100 )
2101 2101 traceback.print_exc()
2102 2102 return None
2103 2103
2104 2104 self._showtraceback(etype, value, stb)
2105 2105 if self.call_pdb:
2106 2106 # drop into debugger
2107 2107 self.debugger(force=True)
2108 2108 return
2109 2109
2110 2110 # Actually show the traceback
2111 2111 self._showtraceback(etype, value, stb)
2112 2112
2113 2113 except KeyboardInterrupt:
2114 2114 print('\n' + self.get_exception_only(), file=sys.stderr)
2115 2115
2116 2116 def _showtraceback(self, etype, evalue, stb: str):
2117 2117 """Actually show a traceback.
2118 2118
2119 2119 Subclasses may override this method to put the traceback on a different
2120 2120 place, like a side channel.
2121 2121 """
2122 2122 val = self.InteractiveTB.stb2text(stb)
2123 2123 try:
2124 2124 print(val)
2125 2125 except UnicodeEncodeError:
2126 2126 print(val.encode("utf-8", "backslashreplace").decode())
2127 2127
2128 2128 def showsyntaxerror(self, filename=None, running_compiled_code=False):
2129 2129 """Display the syntax error that just occurred.
2130 2130
2131 2131 This doesn't display a stack trace because there isn't one.
2132 2132
2133 2133 If a filename is given, it is stuffed in the exception instead
2134 2134 of what was there before (because Python's parser always uses
2135 2135 "<string>" when reading from a string).
2136 2136
2137 2137 If the syntax error occurred when running a compiled code (i.e. running_compile_code=True),
2138 2138 longer stack trace will be displayed.
2139 2139 """
2140 2140 etype, value, last_traceback = self._get_exc_info()
2141 2141
2142 2142 if filename and issubclass(etype, SyntaxError):
2143 2143 try:
2144 2144 value.filename = filename
2145 2145 except:
2146 2146 # Not the format we expect; leave it alone
2147 2147 pass
2148 2148
2149 2149 # If the error occurred when executing compiled code, we should provide full stacktrace.
2150 2150 elist = traceback.extract_tb(last_traceback) if running_compiled_code else []
2151 2151 stb = self.SyntaxTB.structured_traceback(etype, value, elist)
2152 2152 self._showtraceback(etype, value, stb)
2153 2153
2154 2154 # This is overridden in TerminalInteractiveShell to show a message about
2155 2155 # the %paste magic.
2156 2156 def showindentationerror(self):
2157 2157 """Called by _run_cell when there's an IndentationError in code entered
2158 2158 at the prompt.
2159 2159
2160 2160 This is overridden in TerminalInteractiveShell to show a message about
2161 2161 the %paste magic."""
2162 2162 self.showsyntaxerror()
2163 2163
2164 2164 @skip_doctest
2165 2165 def set_next_input(self, s, replace=False):
2166 2166 """ Sets the 'default' input string for the next command line.
2167 2167
2168 2168 Example::
2169 2169
2170 2170 In [1]: _ip.set_next_input("Hello Word")
2171 2171 In [2]: Hello Word_ # cursor is here
2172 2172 """
2173 2173 self.rl_next_input = s
2174 2174
2175 2175 def _indent_current_str(self):
2176 2176 """return the current level of indentation as a string"""
2177 2177 return self.input_splitter.get_indent_spaces() * ' '
2178 2178
2179 2179 #-------------------------------------------------------------------------
2180 2180 # Things related to text completion
2181 2181 #-------------------------------------------------------------------------
2182 2182
2183 2183 def init_completer(self):
2184 2184 """Initialize the completion machinery.
2185 2185
2186 2186 This creates completion machinery that can be used by client code,
2187 2187 either interactively in-process (typically triggered by the readline
2188 2188 library), programmatically (such as in test suites) or out-of-process
2189 2189 (typically over the network by remote frontends).
2190 2190 """
2191 2191 from IPython.core.completer import IPCompleter
2192 2192 from IPython.core.completerlib import (
2193 2193 cd_completer,
2194 2194 magic_run_completer,
2195 2195 module_completer,
2196 2196 reset_completer,
2197 2197 )
2198 2198
2199 2199 self.Completer = IPCompleter(shell=self,
2200 2200 namespace=self.user_ns,
2201 2201 global_namespace=self.user_global_ns,
2202 2202 parent=self,
2203 2203 )
2204 2204 self.configurables.append(self.Completer)
2205 2205
2206 2206 # Add custom completers to the basic ones built into IPCompleter
2207 2207 sdisp = self.strdispatchers.get('complete_command', StrDispatch())
2208 2208 self.strdispatchers['complete_command'] = sdisp
2209 2209 self.Completer.custom_completers = sdisp
2210 2210
2211 2211 self.set_hook('complete_command', module_completer, str_key = 'import')
2212 2212 self.set_hook('complete_command', module_completer, str_key = 'from')
2213 2213 self.set_hook('complete_command', module_completer, str_key = '%aimport')
2214 2214 self.set_hook('complete_command', magic_run_completer, str_key = '%run')
2215 2215 self.set_hook('complete_command', cd_completer, str_key = '%cd')
2216 2216 self.set_hook('complete_command', reset_completer, str_key = '%reset')
2217 2217
2218 2218 @skip_doctest
2219 2219 def complete(self, text, line=None, cursor_pos=None):
2220 2220 """Return the completed text and a list of completions.
2221 2221
2222 2222 Parameters
2223 2223 ----------
2224 2224 text : string
2225 2225 A string of text to be completed on. It can be given as empty and
2226 2226 instead a line/position pair are given. In this case, the
2227 2227 completer itself will split the line like readline does.
2228 2228 line : string, optional
2229 2229 The complete line that text is part of.
2230 2230 cursor_pos : int, optional
2231 2231 The position of the cursor on the input line.
2232 2232
2233 2233 Returns
2234 2234 -------
2235 2235 text : string
2236 2236 The actual text that was completed.
2237 2237 matches : list
2238 2238 A sorted list with all possible completions.
2239 2239
2240 2240 Notes
2241 2241 -----
2242 2242 The optional arguments allow the completion to take more context into
2243 2243 account, and are part of the low-level completion API.
2244 2244
2245 2245 This is a wrapper around the completion mechanism, similar to what
2246 2246 readline does at the command line when the TAB key is hit. By
2247 2247 exposing it as a method, it can be used by other non-readline
2248 2248 environments (such as GUIs) for text completion.
2249 2249
2250 2250 Examples
2251 2251 --------
2252 2252 In [1]: x = 'hello'
2253 2253
2254 2254 In [2]: _ip.complete('x.l')
2255 2255 Out[2]: ('x.l', ['x.ljust', 'x.lower', 'x.lstrip'])
2256 2256 """
2257 2257
2258 2258 # Inject names into __builtin__ so we can complete on the added names.
2259 2259 with self.builtin_trap:
2260 2260 return self.Completer.complete(text, line, cursor_pos)
2261 2261
2262 2262 def set_custom_completer(self, completer, pos=0) -> None:
2263 2263 """Adds a new custom completer function.
2264 2264
2265 2265 The position argument (defaults to 0) is the index in the completers
2266 2266 list where you want the completer to be inserted.
2267 2267
2268 2268 `completer` should have the following signature::
2269 2269
2270 2270 def completion(self: Completer, text: string) -> List[str]:
2271 2271 raise NotImplementedError
2272 2272
2273 2273 It will be bound to the current Completer instance and pass some text
2274 2274 and return a list with current completions to suggest to the user.
2275 2275 """
2276 2276
2277 2277 newcomp = types.MethodType(completer, self.Completer)
2278 2278 self.Completer.custom_matchers.insert(pos,newcomp)
2279 2279
2280 2280 def set_completer_frame(self, frame=None):
2281 2281 """Set the frame of the completer."""
2282 2282 if frame:
2283 2283 self.Completer.namespace = frame.f_locals
2284 2284 self.Completer.global_namespace = frame.f_globals
2285 2285 else:
2286 2286 self.Completer.namespace = self.user_ns
2287 2287 self.Completer.global_namespace = self.user_global_ns
2288 2288
2289 2289 #-------------------------------------------------------------------------
2290 2290 # Things related to magics
2291 2291 #-------------------------------------------------------------------------
2292 2292
2293 2293 def init_magics(self):
2294 2294 from IPython.core import magics as m
2295 2295 self.magics_manager = magic.MagicsManager(shell=self,
2296 2296 parent=self,
2297 2297 user_magics=m.UserMagics(self))
2298 2298 self.configurables.append(self.magics_manager)
2299 2299
2300 2300 # Expose as public API from the magics manager
2301 2301 self.register_magics = self.magics_manager.register
2302 2302
2303 2303 self.register_magics(m.AutoMagics, m.BasicMagics, m.CodeMagics,
2304 2304 m.ConfigMagics, m.DisplayMagics, m.ExecutionMagics,
2305 2305 m.ExtensionMagics, m.HistoryMagics, m.LoggingMagics,
2306 2306 m.NamespaceMagics, m.OSMagics, m.PackagingMagics,
2307 2307 m.PylabMagics, m.ScriptMagics,
2308 2308 )
2309 2309 self.register_magics(m.AsyncMagics)
2310 2310
2311 2311 # Register Magic Aliases
2312 2312 mman = self.magics_manager
2313 2313 # FIXME: magic aliases should be defined by the Magics classes
2314 2314 # or in MagicsManager, not here
2315 2315 mman.register_alias('ed', 'edit')
2316 2316 mman.register_alias('hist', 'history')
2317 2317 mman.register_alias('rep', 'recall')
2318 2318 mman.register_alias('SVG', 'svg', 'cell')
2319 2319 mman.register_alias('HTML', 'html', 'cell')
2320 2320 mman.register_alias('file', 'writefile', 'cell')
2321 2321
2322 2322 # FIXME: Move the color initialization to the DisplayHook, which
2323 2323 # should be split into a prompt manager and displayhook. We probably
2324 2324 # even need a centralize colors management object.
2325 2325 self.run_line_magic('colors', self.colors)
2326 2326
2327 2327 # Defined here so that it's included in the documentation
2328 2328 @functools.wraps(magic.MagicsManager.register_function)
2329 2329 def register_magic_function(self, func, magic_kind='line', magic_name=None):
2330 2330 self.magics_manager.register_function(
2331 2331 func, magic_kind=magic_kind, magic_name=magic_name
2332 2332 )
2333 2333
2334 2334 def _find_with_lazy_load(self, /, type_, magic_name: str):
2335 2335 """
2336 2336 Try to find a magic potentially lazy-loading it.
2337 2337
2338 2338 Parameters
2339 2339 ----------
2340 2340
2341 2341 type_: "line"|"cell"
2342 2342 the type of magics we are trying to find/lazy load.
2343 2343 magic_name: str
2344 2344 The name of the magic we are trying to find/lazy load
2345 2345
2346 2346
2347 2347 Note that this may have any side effects
2348 2348 """
2349 2349 finder = {"line": self.find_line_magic, "cell": self.find_cell_magic}[type_]
2350 2350 fn = finder(magic_name)
2351 2351 if fn is not None:
2352 2352 return fn
2353 2353 lazy = self.magics_manager.lazy_magics.get(magic_name)
2354 2354 if lazy is None:
2355 2355 return None
2356 2356
2357 2357 self.run_line_magic("load_ext", lazy)
2358 2358 res = finder(magic_name)
2359 2359 return res
2360 2360
2361 2361 def run_line_magic(self, magic_name: str, line, _stack_depth=1):
2362 2362 """Execute the given line magic.
2363 2363
2364 2364 Parameters
2365 2365 ----------
2366 2366 magic_name : str
2367 2367 Name of the desired magic function, without '%' prefix.
2368 2368 line : str
2369 2369 The rest of the input line as a single string.
2370 2370 _stack_depth : int
2371 2371 If run_line_magic() is called from magic() then _stack_depth=2.
2372 2372 This is added to ensure backward compatibility for use of 'get_ipython().magic()'
2373 2373 """
2374 2374 fn = self._find_with_lazy_load("line", magic_name)
2375 2375 if fn is None:
2376 2376 lazy = self.magics_manager.lazy_magics.get(magic_name)
2377 2377 if lazy:
2378 2378 self.run_line_magic("load_ext", lazy)
2379 2379 fn = self.find_line_magic(magic_name)
2380 2380 if fn is None:
2381 2381 cm = self.find_cell_magic(magic_name)
2382 2382 etpl = "Line magic function `%%%s` not found%s."
2383 2383 extra = '' if cm is None else (' (But cell magic `%%%%%s` exists, '
2384 2384 'did you mean that instead?)' % magic_name )
2385 2385 raise UsageError(etpl % (magic_name, extra))
2386 2386 else:
2387 2387 # Note: this is the distance in the stack to the user's frame.
2388 2388 # This will need to be updated if the internal calling logic gets
2389 2389 # refactored, or else we'll be expanding the wrong variables.
2390 2390
2391 2391 # Determine stack_depth depending on where run_line_magic() has been called
2392 2392 stack_depth = _stack_depth
2393 2393 if getattr(fn, magic.MAGIC_NO_VAR_EXPAND_ATTR, False):
2394 2394 # magic has opted out of var_expand
2395 2395 magic_arg_s = line
2396 2396 else:
2397 2397 magic_arg_s = self.var_expand(line, stack_depth)
2398 2398 # Put magic args in a list so we can call with f(*a) syntax
2399 2399 args = [magic_arg_s]
2400 2400 kwargs = {}
2401 2401 # Grab local namespace if we need it:
2402 2402 if getattr(fn, "needs_local_scope", False):
2403 2403 kwargs['local_ns'] = self.get_local_scope(stack_depth)
2404 2404 with self.builtin_trap:
2405 2405 result = fn(*args, **kwargs)
2406 2406
2407 2407 # The code below prevents the output from being displayed
2408 2408 # when using magics with decodator @output_can_be_silenced
2409 2409 # when the last Python token in the expression is a ';'.
2410 2410 if getattr(fn, magic.MAGIC_OUTPUT_CAN_BE_SILENCED, False):
2411 2411 if DisplayHook.semicolon_at_end_of_expression(magic_arg_s):
2412 2412 return None
2413 2413
2414 2414 return result
2415 2415
2416 2416 def get_local_scope(self, stack_depth):
2417 2417 """Get local scope at given stack depth.
2418 2418
2419 2419 Parameters
2420 2420 ----------
2421 2421 stack_depth : int
2422 2422 Depth relative to calling frame
2423 2423 """
2424 2424 return sys._getframe(stack_depth + 1).f_locals
2425 2425
2426 2426 def run_cell_magic(self, magic_name, line, cell):
2427 2427 """Execute the given cell magic.
2428 2428
2429 2429 Parameters
2430 2430 ----------
2431 2431 magic_name : str
2432 2432 Name of the desired magic function, without '%' prefix.
2433 2433 line : str
2434 2434 The rest of the first input line as a single string.
2435 2435 cell : str
2436 2436 The body of the cell as a (possibly multiline) string.
2437 2437 """
2438 2438 fn = self._find_with_lazy_load("cell", magic_name)
2439 2439 if fn is None:
2440 2440 lm = self.find_line_magic(magic_name)
2441 2441 etpl = "Cell magic `%%{0}` not found{1}."
2442 2442 extra = '' if lm is None else (' (But line magic `%{0}` exists, '
2443 2443 'did you mean that instead?)'.format(magic_name))
2444 2444 raise UsageError(etpl.format(magic_name, extra))
2445 2445 elif cell == '':
2446 2446 message = '%%{0} is a cell magic, but the cell body is empty.'.format(magic_name)
2447 2447 if self.find_line_magic(magic_name) is not None:
2448 2448 message += ' Did you mean the line magic %{0} (single %)?'.format(magic_name)
2449 2449 raise UsageError(message)
2450 2450 else:
2451 2451 # Note: this is the distance in the stack to the user's frame.
2452 2452 # This will need to be updated if the internal calling logic gets
2453 2453 # refactored, or else we'll be expanding the wrong variables.
2454 2454 stack_depth = 2
2455 2455 if getattr(fn, magic.MAGIC_NO_VAR_EXPAND_ATTR, False):
2456 2456 # magic has opted out of var_expand
2457 2457 magic_arg_s = line
2458 2458 else:
2459 2459 magic_arg_s = self.var_expand(line, stack_depth)
2460 2460 kwargs = {}
2461 2461 if getattr(fn, "needs_local_scope", False):
2462 2462 kwargs['local_ns'] = self.user_ns
2463 2463
2464 2464 with self.builtin_trap:
2465 2465 args = (magic_arg_s, cell)
2466 2466 result = fn(*args, **kwargs)
2467 2467
2468 2468 # The code below prevents the output from being displayed
2469 2469 # when using magics with decodator @output_can_be_silenced
2470 2470 # when the last Python token in the expression is a ';'.
2471 2471 if getattr(fn, magic.MAGIC_OUTPUT_CAN_BE_SILENCED, False):
2472 2472 if DisplayHook.semicolon_at_end_of_expression(cell):
2473 2473 return None
2474 2474
2475 2475 return result
2476 2476
2477 2477 def find_line_magic(self, magic_name):
2478 2478 """Find and return a line magic by name.
2479 2479
2480 2480 Returns None if the magic isn't found."""
2481 2481 return self.magics_manager.magics['line'].get(magic_name)
2482 2482
2483 2483 def find_cell_magic(self, magic_name):
2484 2484 """Find and return a cell magic by name.
2485 2485
2486 2486 Returns None if the magic isn't found."""
2487 2487 return self.magics_manager.magics['cell'].get(magic_name)
2488 2488
2489 2489 def find_magic(self, magic_name, magic_kind='line'):
2490 2490 """Find and return a magic of the given type by name.
2491 2491
2492 2492 Returns None if the magic isn't found."""
2493 2493 return self.magics_manager.magics[magic_kind].get(magic_name)
2494 2494
2495 2495 def magic(self, arg_s):
2496 2496 """
2497 2497 DEPRECATED
2498 2498
2499 2499 Deprecated since IPython 0.13 (warning added in
2500 2500 8.1), use run_line_magic(magic_name, parameter_s).
2501 2501
2502 2502 Call a magic function by name.
2503 2503
2504 2504 Input: a string containing the name of the magic function to call and
2505 2505 any additional arguments to be passed to the magic.
2506 2506
2507 2507 magic('name -opt foo bar') is equivalent to typing at the ipython
2508 2508 prompt:
2509 2509
2510 2510 In[1]: %name -opt foo bar
2511 2511
2512 2512 To call a magic without arguments, simply use magic('name').
2513 2513
2514 2514 This provides a proper Python function to call IPython's magics in any
2515 2515 valid Python code you can type at the interpreter, including loops and
2516 2516 compound statements.
2517 2517 """
2518 2518 warnings.warn(
2519 2519 "`magic(...)` is deprecated since IPython 0.13 (warning added in "
2520 2520 "8.1), use run_line_magic(magic_name, parameter_s).",
2521 2521 DeprecationWarning,
2522 2522 stacklevel=2,
2523 2523 )
2524 2524 # TODO: should we issue a loud deprecation warning here?
2525 2525 magic_name, _, magic_arg_s = arg_s.partition(' ')
2526 2526 magic_name = magic_name.lstrip(prefilter.ESC_MAGIC)
2527 2527 return self.run_line_magic(magic_name, magic_arg_s, _stack_depth=2)
2528 2528
2529 2529 #-------------------------------------------------------------------------
2530 2530 # Things related to macros
2531 2531 #-------------------------------------------------------------------------
2532 2532
2533 2533 def define_macro(self, name, themacro):
2534 2534 """Define a new macro
2535 2535
2536 2536 Parameters
2537 2537 ----------
2538 2538 name : str
2539 2539 The name of the macro.
2540 2540 themacro : str or Macro
2541 2541 The action to do upon invoking the macro. If a string, a new
2542 2542 Macro object is created by passing the string to it.
2543 2543 """
2544 2544
2545 2545 from IPython.core import macro
2546 2546
2547 2547 if isinstance(themacro, str):
2548 2548 themacro = macro.Macro(themacro)
2549 2549 if not isinstance(themacro, macro.Macro):
2550 2550 raise ValueError('A macro must be a string or a Macro instance.')
2551 2551 self.user_ns[name] = themacro
2552 2552
2553 2553 #-------------------------------------------------------------------------
2554 2554 # Things related to the running of system commands
2555 2555 #-------------------------------------------------------------------------
2556 2556
2557 2557 def system_piped(self, cmd):
2558 2558 """Call the given cmd in a subprocess, piping stdout/err
2559 2559
2560 2560 Parameters
2561 2561 ----------
2562 2562 cmd : str
2563 2563 Command to execute (can not end in '&', as background processes are
2564 2564 not supported. Should not be a command that expects input
2565 2565 other than simple text.
2566 2566 """
2567 2567 if cmd.rstrip().endswith('&'):
2568 2568 # this is *far* from a rigorous test
2569 2569 # We do not support backgrounding processes because we either use
2570 2570 # pexpect or pipes to read from. Users can always just call
2571 2571 # os.system() or use ip.system=ip.system_raw
2572 2572 # if they really want a background process.
2573 2573 raise OSError("Background processes not supported.")
2574 2574
2575 2575 # we explicitly do NOT return the subprocess status code, because
2576 2576 # a non-None value would trigger :func:`sys.displayhook` calls.
2577 2577 # Instead, we store the exit_code in user_ns.
2578 2578 self.user_ns['_exit_code'] = system(self.var_expand(cmd, depth=1))
2579 2579
2580 2580 def system_raw(self, cmd):
2581 2581 """Call the given cmd in a subprocess using os.system on Windows or
2582 2582 subprocess.call using the system shell on other platforms.
2583 2583
2584 2584 Parameters
2585 2585 ----------
2586 2586 cmd : str
2587 2587 Command to execute.
2588 2588 """
2589 2589 cmd = self.var_expand(cmd, depth=1)
2590 2590 # warn if there is an IPython magic alternative.
2591 2591 main_cmd = cmd.split()[0]
2592 2592 has_magic_alternatives = ("pip", "conda", "cd")
2593 2593
2594 2594 if main_cmd in has_magic_alternatives:
2595 2595 warnings.warn(
2596 2596 (
2597 2597 "You executed the system command !{0} which may not work "
2598 2598 "as expected. Try the IPython magic %{0} instead."
2599 2599 ).format(main_cmd)
2600 2600 )
2601 2601
2602 2602 # protect os.system from UNC paths on Windows, which it can't handle:
2603 2603 if sys.platform == 'win32':
2604 2604 from IPython.utils._process_win32 import AvoidUNCPath
2605 2605 with AvoidUNCPath() as path:
2606 2606 if path is not None:
2607 2607 cmd = '"pushd %s &&"%s' % (path, cmd)
2608 2608 try:
2609 2609 ec = os.system(cmd)
2610 2610 except KeyboardInterrupt:
2611 2611 print('\n' + self.get_exception_only(), file=sys.stderr)
2612 2612 ec = -2
2613 2613 else:
2614 2614 # For posix the result of the subprocess.call() below is an exit
2615 2615 # code, which by convention is zero for success, positive for
2616 2616 # program failure. Exit codes above 128 are reserved for signals,
2617 2617 # and the formula for converting a signal to an exit code is usually
2618 2618 # signal_number+128. To more easily differentiate between exit
2619 2619 # codes and signals, ipython uses negative numbers. For instance
2620 2620 # since control-c is signal 2 but exit code 130, ipython's
2621 2621 # _exit_code variable will read -2. Note that some shells like
2622 2622 # csh and fish don't follow sh/bash conventions for exit codes.
2623 2623 executable = os.environ.get('SHELL', None)
2624 2624 try:
2625 2625 # Use env shell instead of default /bin/sh
2626 2626 ec = subprocess.call(cmd, shell=True, executable=executable)
2627 2627 except KeyboardInterrupt:
2628 2628 # intercept control-C; a long traceback is not useful here
2629 2629 print('\n' + self.get_exception_only(), file=sys.stderr)
2630 2630 ec = 130
2631 2631 if ec > 128:
2632 2632 ec = -(ec - 128)
2633 2633
2634 2634 # We explicitly do NOT return the subprocess status code, because
2635 2635 # a non-None value would trigger :func:`sys.displayhook` calls.
2636 2636 # Instead, we store the exit_code in user_ns. Note the semantics
2637 2637 # of _exit_code: for control-c, _exit_code == -signal.SIGNIT,
2638 2638 # but raising SystemExit(_exit_code) will give status 254!
2639 2639 self.user_ns['_exit_code'] = ec
2640 2640
2641 2641 # use piped system by default, because it is better behaved
2642 2642 system = system_piped
2643 2643
2644 2644 def getoutput(self, cmd, split=True, depth=0):
2645 2645 """Get output (possibly including stderr) from a subprocess.
2646 2646
2647 2647 Parameters
2648 2648 ----------
2649 2649 cmd : str
2650 2650 Command to execute (can not end in '&', as background processes are
2651 2651 not supported.
2652 2652 split : bool, optional
2653 2653 If True, split the output into an IPython SList. Otherwise, an
2654 2654 IPython LSString is returned. These are objects similar to normal
2655 2655 lists and strings, with a few convenience attributes for easier
2656 2656 manipulation of line-based output. You can use '?' on them for
2657 2657 details.
2658 2658 depth : int, optional
2659 2659 How many frames above the caller are the local variables which should
2660 2660 be expanded in the command string? The default (0) assumes that the
2661 2661 expansion variables are in the stack frame calling this function.
2662 2662 """
2663 2663 if cmd.rstrip().endswith('&'):
2664 2664 # this is *far* from a rigorous test
2665 2665 raise OSError("Background processes not supported.")
2666 2666 out = getoutput(self.var_expand(cmd, depth=depth+1))
2667 2667 if split:
2668 2668 out = SList(out.splitlines())
2669 2669 else:
2670 2670 out = LSString(out)
2671 2671 return out
2672 2672
2673 2673 #-------------------------------------------------------------------------
2674 2674 # Things related to aliases
2675 2675 #-------------------------------------------------------------------------
2676 2676
2677 2677 def init_alias(self):
2678 2678 self.alias_manager = AliasManager(shell=self, parent=self)
2679 2679 self.configurables.append(self.alias_manager)
2680 2680
2681 2681 #-------------------------------------------------------------------------
2682 2682 # Things related to extensions
2683 2683 #-------------------------------------------------------------------------
2684 2684
2685 2685 def init_extension_manager(self):
2686 2686 self.extension_manager = ExtensionManager(shell=self, parent=self)
2687 2687 self.configurables.append(self.extension_manager)
2688 2688
2689 2689 #-------------------------------------------------------------------------
2690 2690 # Things related to payloads
2691 2691 #-------------------------------------------------------------------------
2692 2692
2693 2693 def init_payload(self):
2694 2694 self.payload_manager = PayloadManager(parent=self)
2695 2695 self.configurables.append(self.payload_manager)
2696 2696
2697 2697 #-------------------------------------------------------------------------
2698 2698 # Things related to the prefilter
2699 2699 #-------------------------------------------------------------------------
2700 2700
2701 2701 def init_prefilter(self):
2702 2702 self.prefilter_manager = PrefilterManager(shell=self, parent=self)
2703 2703 self.configurables.append(self.prefilter_manager)
2704 2704 # Ultimately this will be refactored in the new interpreter code, but
2705 2705 # for now, we should expose the main prefilter method (there's legacy
2706 2706 # code out there that may rely on this).
2707 2707 self.prefilter = self.prefilter_manager.prefilter_lines
2708 2708
2709 2709 def auto_rewrite_input(self, cmd):
2710 2710 """Print to the screen the rewritten form of the user's command.
2711 2711
2712 2712 This shows visual feedback by rewriting input lines that cause
2713 2713 automatic calling to kick in, like::
2714 2714
2715 2715 /f x
2716 2716
2717 2717 into::
2718 2718
2719 2719 ------> f(x)
2720 2720
2721 2721 after the user's input prompt. This helps the user understand that the
2722 2722 input line was transformed automatically by IPython.
2723 2723 """
2724 2724 if not self.show_rewritten_input:
2725 2725 return
2726 2726
2727 2727 # This is overridden in TerminalInteractiveShell to use fancy prompts
2728 2728 print("------> " + cmd)
2729 2729
2730 2730 #-------------------------------------------------------------------------
2731 2731 # Things related to extracting values/expressions from kernel and user_ns
2732 2732 #-------------------------------------------------------------------------
2733 2733
2734 2734 def _user_obj_error(self):
2735 2735 """return simple exception dict
2736 2736
2737 2737 for use in user_expressions
2738 2738 """
2739 2739
2740 2740 etype, evalue, tb = self._get_exc_info()
2741 2741 stb = self.InteractiveTB.get_exception_only(etype, evalue)
2742 2742
2743 2743 exc_info = {
2744 2744 "status": "error",
2745 2745 "traceback": stb,
2746 2746 "ename": etype.__name__,
2747 2747 "evalue": py3compat.safe_unicode(evalue),
2748 2748 }
2749 2749
2750 2750 return exc_info
2751 2751
2752 2752 def _format_user_obj(self, obj):
2753 2753 """format a user object to display dict
2754 2754
2755 2755 for use in user_expressions
2756 2756 """
2757 2757
2758 2758 data, md = self.display_formatter.format(obj)
2759 2759 value = {
2760 2760 'status' : 'ok',
2761 2761 'data' : data,
2762 2762 'metadata' : md,
2763 2763 }
2764 2764 return value
2765 2765
2766 2766 def user_expressions(self, expressions):
2767 2767 """Evaluate a dict of expressions in the user's namespace.
2768 2768
2769 2769 Parameters
2770 2770 ----------
2771 2771 expressions : dict
2772 2772 A dict with string keys and string values. The expression values
2773 2773 should be valid Python expressions, each of which will be evaluated
2774 2774 in the user namespace.
2775 2775
2776 2776 Returns
2777 2777 -------
2778 2778 A dict, keyed like the input expressions dict, with the rich mime-typed
2779 2779 display_data of each value.
2780 2780 """
2781 2781 out = {}
2782 2782 user_ns = self.user_ns
2783 2783 global_ns = self.user_global_ns
2784 2784
2785 2785 for key, expr in expressions.items():
2786 2786 try:
2787 2787 value = self._format_user_obj(eval(expr, global_ns, user_ns))
2788 2788 except:
2789 2789 value = self._user_obj_error()
2790 2790 out[key] = value
2791 2791 return out
2792 2792
2793 2793 #-------------------------------------------------------------------------
2794 2794 # Things related to the running of code
2795 2795 #-------------------------------------------------------------------------
2796 2796
2797 2797 def ex(self, cmd):
2798 2798 """Execute a normal python statement in user namespace."""
2799 2799 with self.builtin_trap:
2800 2800 exec(cmd, self.user_global_ns, self.user_ns)
2801 2801
2802 2802 def ev(self, expr):
2803 2803 """Evaluate python expression expr in user namespace.
2804 2804
2805 2805 Returns the result of evaluation
2806 2806 """
2807 2807 with self.builtin_trap:
2808 2808 return eval(expr, self.user_global_ns, self.user_ns)
2809 2809
2810 2810 def safe_execfile(self, fname, *where, exit_ignore=False, raise_exceptions=False, shell_futures=False):
2811 2811 """A safe version of the builtin execfile().
2812 2812
2813 2813 This version will never throw an exception, but instead print
2814 2814 helpful error messages to the screen. This only works on pure
2815 2815 Python files with the .py extension.
2816 2816
2817 2817 Parameters
2818 2818 ----------
2819 2819 fname : string
2820 2820 The name of the file to be executed.
2821 2821 *where : tuple
2822 2822 One or two namespaces, passed to execfile() as (globals,locals).
2823 2823 If only one is given, it is passed as both.
2824 2824 exit_ignore : bool (False)
2825 2825 If True, then silence SystemExit for non-zero status (it is always
2826 2826 silenced for zero status, as it is so common).
2827 2827 raise_exceptions : bool (False)
2828 2828 If True raise exceptions everywhere. Meant for testing.
2829 2829 shell_futures : bool (False)
2830 2830 If True, the code will share future statements with the interactive
2831 2831 shell. It will both be affected by previous __future__ imports, and
2832 2832 any __future__ imports in the code will affect the shell. If False,
2833 2833 __future__ imports are not shared in either direction.
2834 2834
2835 2835 """
2836 2836 fname = Path(fname).expanduser().resolve()
2837 2837
2838 2838 # Make sure we can open the file
2839 2839 try:
2840 2840 with fname.open("rb"):
2841 2841 pass
2842 2842 except:
2843 2843 warn('Could not open file <%s> for safe execution.' % fname)
2844 2844 return
2845 2845
2846 2846 # Find things also in current directory. This is needed to mimic the
2847 2847 # behavior of running a script from the system command line, where
2848 2848 # Python inserts the script's directory into sys.path
2849 2849 dname = str(fname.parent)
2850 2850
2851 2851 with prepended_to_syspath(dname), self.builtin_trap:
2852 2852 try:
2853 2853 glob, loc = (where + (None, ))[:2]
2854 2854 py3compat.execfile(
2855 2855 fname, glob, loc,
2856 2856 self.compile if shell_futures else None)
2857 2857 except SystemExit as status:
2858 2858 # If the call was made with 0 or None exit status (sys.exit(0)
2859 2859 # or sys.exit() ), don't bother showing a traceback, as both of
2860 2860 # these are considered normal by the OS:
2861 2861 # > python -c'import sys;sys.exit(0)'; echo $?
2862 2862 # 0
2863 2863 # > python -c'import sys;sys.exit()'; echo $?
2864 2864 # 0
2865 2865 # For other exit status, we show the exception unless
2866 2866 # explicitly silenced, but only in short form.
2867 2867 if status.code:
2868 2868 if raise_exceptions:
2869 2869 raise
2870 2870 if not exit_ignore:
2871 2871 self.showtraceback(exception_only=True)
2872 2872 except:
2873 2873 if raise_exceptions:
2874 2874 raise
2875 2875 # tb offset is 2 because we wrap execfile
2876 2876 self.showtraceback(tb_offset=2)
2877 2877
2878 2878 def safe_execfile_ipy(self, fname, shell_futures=False, raise_exceptions=False):
2879 2879 """Like safe_execfile, but for .ipy or .ipynb files with IPython syntax.
2880 2880
2881 2881 Parameters
2882 2882 ----------
2883 2883 fname : str
2884 2884 The name of the file to execute. The filename must have a
2885 2885 .ipy or .ipynb extension.
2886 2886 shell_futures : bool (False)
2887 2887 If True, the code will share future statements with the interactive
2888 2888 shell. It will both be affected by previous __future__ imports, and
2889 2889 any __future__ imports in the code will affect the shell. If False,
2890 2890 __future__ imports are not shared in either direction.
2891 2891 raise_exceptions : bool (False)
2892 2892 If True raise exceptions everywhere. Meant for testing.
2893 2893 """
2894 2894 fname = Path(fname).expanduser().resolve()
2895 2895
2896 2896 # Make sure we can open the file
2897 2897 try:
2898 2898 with fname.open("rb"):
2899 2899 pass
2900 2900 except:
2901 2901 warn('Could not open file <%s> for safe execution.' % fname)
2902 2902 return
2903 2903
2904 2904 # Find things also in current directory. This is needed to mimic the
2905 2905 # behavior of running a script from the system command line, where
2906 2906 # Python inserts the script's directory into sys.path
2907 2907 dname = str(fname.parent)
2908 2908
2909 2909 def get_cells():
2910 2910 """generator for sequence of code blocks to run"""
2911 2911 if fname.suffix == ".ipynb":
2912 2912 from nbformat import read
2913 2913 nb = read(fname, as_version=4)
2914 2914 if not nb.cells:
2915 2915 return
2916 2916 for cell in nb.cells:
2917 2917 if cell.cell_type == 'code':
2918 2918 yield cell.source
2919 2919 else:
2920 2920 yield fname.read_text(encoding="utf-8")
2921 2921
2922 2922 with prepended_to_syspath(dname):
2923 2923 try:
2924 2924 for cell in get_cells():
2925 2925 result = self.run_cell(cell, silent=True, shell_futures=shell_futures)
2926 2926 if raise_exceptions:
2927 2927 result.raise_error()
2928 2928 elif not result.success:
2929 2929 break
2930 2930 except:
2931 2931 if raise_exceptions:
2932 2932 raise
2933 2933 self.showtraceback()
2934 2934 warn('Unknown failure executing file: <%s>' % fname)
2935 2935
2936 2936 def safe_run_module(self, mod_name, where):
2937 2937 """A safe version of runpy.run_module().
2938 2938
2939 2939 This version will never throw an exception, but instead print
2940 2940 helpful error messages to the screen.
2941 2941
2942 2942 `SystemExit` exceptions with status code 0 or None are ignored.
2943 2943
2944 2944 Parameters
2945 2945 ----------
2946 2946 mod_name : string
2947 2947 The name of the module to be executed.
2948 2948 where : dict
2949 2949 The globals namespace.
2950 2950 """
2951 2951 try:
2952 2952 try:
2953 2953 where.update(
2954 2954 runpy.run_module(str(mod_name), run_name="__main__",
2955 2955 alter_sys=True)
2956 2956 )
2957 2957 except SystemExit as status:
2958 2958 if status.code:
2959 2959 raise
2960 2960 except:
2961 2961 self.showtraceback()
2962 2962 warn('Unknown failure executing module: <%s>' % mod_name)
2963 2963
2964 2964 def run_cell(
2965 2965 self,
2966 2966 raw_cell,
2967 2967 store_history=False,
2968 2968 silent=False,
2969 2969 shell_futures=True,
2970 2970 cell_id=None,
2971 2971 ):
2972 2972 """Run a complete IPython cell.
2973 2973
2974 2974 Parameters
2975 2975 ----------
2976 2976 raw_cell : str
2977 2977 The code (including IPython code such as %magic functions) to run.
2978 2978 store_history : bool
2979 2979 If True, the raw and translated cell will be stored in IPython's
2980 2980 history. For user code calling back into IPython's machinery, this
2981 2981 should be set to False.
2982 2982 silent : bool
2983 2983 If True, avoid side-effects, such as implicit displayhooks and
2984 2984 and logging. silent=True forces store_history=False.
2985 2985 shell_futures : bool
2986 2986 If True, the code will share future statements with the interactive
2987 2987 shell. It will both be affected by previous __future__ imports, and
2988 2988 any __future__ imports in the code will affect the shell. If False,
2989 2989 __future__ imports are not shared in either direction.
2990 2990
2991 2991 Returns
2992 2992 -------
2993 2993 result : :class:`ExecutionResult`
2994 2994 """
2995 2995 result = None
2996 2996 try:
2997 2997 result = self._run_cell(
2998 2998 raw_cell, store_history, silent, shell_futures, cell_id
2999 2999 )
3000 3000 finally:
3001 3001 self.events.trigger('post_execute')
3002 3002 if not silent:
3003 3003 self.events.trigger('post_run_cell', result)
3004 3004 return result
3005 3005
3006 3006 def _run_cell(
3007 3007 self,
3008 3008 raw_cell: str,
3009 3009 store_history: bool,
3010 3010 silent: bool,
3011 3011 shell_futures: bool,
3012 3012 cell_id: str,
3013 3013 ) -> ExecutionResult:
3014 3014 """Internal method to run a complete IPython cell."""
3015 3015
3016 3016 # we need to avoid calling self.transform_cell multiple time on the same thing
3017 3017 # so we need to store some results:
3018 3018 preprocessing_exc_tuple = None
3019 3019 try:
3020 3020 transformed_cell = self.transform_cell(raw_cell)
3021 3021 except Exception:
3022 3022 transformed_cell = raw_cell
3023 3023 preprocessing_exc_tuple = sys.exc_info()
3024 3024
3025 3025 assert transformed_cell is not None
3026 3026 coro = self.run_cell_async(
3027 3027 raw_cell,
3028 3028 store_history=store_history,
3029 3029 silent=silent,
3030 3030 shell_futures=shell_futures,
3031 3031 transformed_cell=transformed_cell,
3032 3032 preprocessing_exc_tuple=preprocessing_exc_tuple,
3033 3033 cell_id=cell_id,
3034 3034 )
3035 3035
3036 3036 # run_cell_async is async, but may not actually need an eventloop.
3037 3037 # when this is the case, we want to run it using the pseudo_sync_runner
3038 3038 # so that code can invoke eventloops (for example via the %run , and
3039 3039 # `%paste` magic.
3040 3040 if self.trio_runner:
3041 3041 runner = self.trio_runner
3042 3042 elif self.should_run_async(
3043 3043 raw_cell,
3044 3044 transformed_cell=transformed_cell,
3045 3045 preprocessing_exc_tuple=preprocessing_exc_tuple,
3046 3046 ):
3047 3047 runner = self.loop_runner
3048 3048 else:
3049 3049 runner = _pseudo_sync_runner
3050 3050
3051 3051 try:
3052 3052 result = runner(coro)
3053 3053 except BaseException as e:
3054 3054 info = ExecutionInfo(
3055 3055 raw_cell, store_history, silent, shell_futures, cell_id
3056 3056 )
3057 3057 result = ExecutionResult(info)
3058 3058 result.error_in_exec = e
3059 3059 self.showtraceback(running_compiled_code=True)
3060 3060 finally:
3061 3061 return result
3062 3062
3063 3063 def should_run_async(
3064 3064 self, raw_cell: str, *, transformed_cell=None, preprocessing_exc_tuple=None
3065 3065 ) -> bool:
3066 3066 """Return whether a cell should be run asynchronously via a coroutine runner
3067 3067
3068 3068 Parameters
3069 3069 ----------
3070 3070 raw_cell : str
3071 3071 The code to be executed
3072 3072
3073 3073 Returns
3074 3074 -------
3075 3075 result: bool
3076 3076 Whether the code needs to be run with a coroutine runner or not
3077 3077 .. versionadded:: 7.0
3078 3078 """
3079 3079 if not self.autoawait:
3080 3080 return False
3081 3081 if preprocessing_exc_tuple is not None:
3082 3082 return False
3083 3083 assert preprocessing_exc_tuple is None
3084 3084 if transformed_cell is None:
3085 3085 warnings.warn(
3086 3086 "`should_run_async` will not call `transform_cell`"
3087 3087 " automatically in the future. Please pass the result to"
3088 3088 " `transformed_cell` argument and any exception that happen"
3089 3089 " during the"
3090 3090 "transform in `preprocessing_exc_tuple` in"
3091 3091 " IPython 7.17 and above.",
3092 3092 DeprecationWarning,
3093 3093 stacklevel=2,
3094 3094 )
3095 3095 try:
3096 3096 cell = self.transform_cell(raw_cell)
3097 3097 except Exception:
3098 3098 # any exception during transform will be raised
3099 3099 # prior to execution
3100 3100 return False
3101 3101 else:
3102 3102 cell = transformed_cell
3103 3103 return _should_be_async(cell)
3104 3104
3105 3105 async def run_cell_async(
3106 3106 self,
3107 3107 raw_cell: str,
3108 3108 store_history=False,
3109 3109 silent=False,
3110 3110 shell_futures=True,
3111 3111 *,
3112 3112 transformed_cell: Optional[str] = None,
3113 preprocessing_exc_tuple: Optional[Any] = None,
3113 preprocessing_exc_tuple: Optional[AnyType] = None,
3114 3114 cell_id=None,
3115 3115 ) -> ExecutionResult:
3116 3116 """Run a complete IPython cell asynchronously.
3117 3117
3118 3118 Parameters
3119 3119 ----------
3120 3120 raw_cell : str
3121 3121 The code (including IPython code such as %magic functions) to run.
3122 3122 store_history : bool
3123 3123 If True, the raw and translated cell will be stored in IPython's
3124 3124 history. For user code calling back into IPython's machinery, this
3125 3125 should be set to False.
3126 3126 silent : bool
3127 3127 If True, avoid side-effects, such as implicit displayhooks and
3128 3128 and logging. silent=True forces store_history=False.
3129 3129 shell_futures : bool
3130 3130 If True, the code will share future statements with the interactive
3131 3131 shell. It will both be affected by previous __future__ imports, and
3132 3132 any __future__ imports in the code will affect the shell. If False,
3133 3133 __future__ imports are not shared in either direction.
3134 3134 transformed_cell: str
3135 3135 cell that was passed through transformers
3136 3136 preprocessing_exc_tuple:
3137 3137 trace if the transformation failed.
3138 3138
3139 3139 Returns
3140 3140 -------
3141 3141 result : :class:`ExecutionResult`
3142 3142
3143 3143 .. versionadded:: 7.0
3144 3144 """
3145 3145 info = ExecutionInfo(raw_cell, store_history, silent, shell_futures, cell_id)
3146 3146 result = ExecutionResult(info)
3147 3147
3148 3148 if (not raw_cell) or raw_cell.isspace():
3149 3149 self.last_execution_succeeded = True
3150 3150 self.last_execution_result = result
3151 3151 return result
3152 3152
3153 3153 if silent:
3154 3154 store_history = False
3155 3155
3156 3156 if store_history:
3157 3157 result.execution_count = self.execution_count
3158 3158
3159 3159 def error_before_exec(value):
3160 3160 if store_history:
3161 3161 self.execution_count += 1
3162 3162 result.error_before_exec = value
3163 3163 self.last_execution_succeeded = False
3164 3164 self.last_execution_result = result
3165 3165 return result
3166 3166
3167 3167 self.events.trigger('pre_execute')
3168 3168 if not silent:
3169 3169 self.events.trigger('pre_run_cell', info)
3170 3170
3171 3171 if transformed_cell is None:
3172 3172 warnings.warn(
3173 3173 "`run_cell_async` will not call `transform_cell`"
3174 3174 " automatically in the future. Please pass the result to"
3175 3175 " `transformed_cell` argument and any exception that happen"
3176 3176 " during the"
3177 3177 "transform in `preprocessing_exc_tuple` in"
3178 3178 " IPython 7.17 and above.",
3179 3179 DeprecationWarning,
3180 3180 stacklevel=2,
3181 3181 )
3182 3182 # If any of our input transformation (input_transformer_manager or
3183 3183 # prefilter_manager) raises an exception, we store it in this variable
3184 3184 # so that we can display the error after logging the input and storing
3185 3185 # it in the history.
3186 3186 try:
3187 3187 cell = self.transform_cell(raw_cell)
3188 3188 except Exception:
3189 3189 preprocessing_exc_tuple = sys.exc_info()
3190 3190 cell = raw_cell # cell has to exist so it can be stored/logged
3191 3191 else:
3192 3192 preprocessing_exc_tuple = None
3193 3193 else:
3194 3194 if preprocessing_exc_tuple is None:
3195 3195 cell = transformed_cell
3196 3196 else:
3197 3197 cell = raw_cell
3198 3198
3199 3199 # Do NOT store paste/cpaste magic history
3200 3200 if "get_ipython().run_line_magic(" in cell and "paste" in cell:
3201 3201 store_history = False
3202 3202
3203 3203 # Store raw and processed history
3204 3204 if store_history:
3205 3205 self.history_manager.store_inputs(self.execution_count, cell, raw_cell)
3206 3206 if not silent:
3207 3207 self.logger.log(cell, raw_cell)
3208 3208
3209 3209 # Display the exception if input processing failed.
3210 3210 if preprocessing_exc_tuple is not None:
3211 3211 self.showtraceback(preprocessing_exc_tuple)
3212 3212 if store_history:
3213 3213 self.execution_count += 1
3214 3214 return error_before_exec(preprocessing_exc_tuple[1])
3215 3215
3216 3216 # Our own compiler remembers the __future__ environment. If we want to
3217 3217 # run code with a separate __future__ environment, use the default
3218 3218 # compiler
3219 3219 compiler = self.compile if shell_futures else self.compiler_class()
3220 3220
3221 3221 _run_async = False
3222 3222
3223 3223 with self.builtin_trap:
3224 3224 cell_name = compiler.cache(cell, self.execution_count, raw_code=raw_cell)
3225 3225
3226 3226 with self.display_trap:
3227 3227 # Compile to bytecode
3228 3228 try:
3229 3229 code_ast = compiler.ast_parse(cell, filename=cell_name)
3230 3230 except self.custom_exceptions as e:
3231 3231 etype, value, tb = sys.exc_info()
3232 3232 self.CustomTB(etype, value, tb)
3233 3233 return error_before_exec(e)
3234 3234 except IndentationError as e:
3235 3235 self.showindentationerror()
3236 3236 return error_before_exec(e)
3237 3237 except (OverflowError, SyntaxError, ValueError, TypeError,
3238 3238 MemoryError) as e:
3239 3239 self.showsyntaxerror()
3240 3240 return error_before_exec(e)
3241 3241
3242 3242 # Apply AST transformations
3243 3243 try:
3244 3244 code_ast = self.transform_ast(code_ast)
3245 3245 except InputRejected as e:
3246 3246 self.showtraceback()
3247 3247 return error_before_exec(e)
3248 3248
3249 3249 # Give the displayhook a reference to our ExecutionResult so it
3250 3250 # can fill in the output value.
3251 3251 self.displayhook.exec_result = result
3252 3252
3253 3253 # Execute the user code
3254 3254 interactivity = "none" if silent else self.ast_node_interactivity
3255 3255
3256 3256
3257 3257 has_raised = await self.run_ast_nodes(code_ast.body, cell_name,
3258 3258 interactivity=interactivity, compiler=compiler, result=result)
3259 3259
3260 3260 self.last_execution_succeeded = not has_raised
3261 3261 self.last_execution_result = result
3262 3262
3263 3263 # Reset this so later displayed values do not modify the
3264 3264 # ExecutionResult
3265 3265 self.displayhook.exec_result = None
3266 3266
3267 3267 if store_history:
3268 3268 # Write output to the database. Does nothing unless
3269 3269 # history output logging is enabled.
3270 3270 self.history_manager.store_output(self.execution_count)
3271 3271 # Each cell is a *single* input, regardless of how many lines it has
3272 3272 self.execution_count += 1
3273 3273
3274 3274 return result
3275 3275
3276 3276 def transform_cell(self, raw_cell):
3277 3277 """Transform an input cell before parsing it.
3278 3278
3279 3279 Static transformations, implemented in IPython.core.inputtransformer2,
3280 3280 deal with things like ``%magic`` and ``!system`` commands.
3281 3281 These run on all input.
3282 3282 Dynamic transformations, for things like unescaped magics and the exit
3283 3283 autocall, depend on the state of the interpreter.
3284 3284 These only apply to single line inputs.
3285 3285
3286 3286 These string-based transformations are followed by AST transformations;
3287 3287 see :meth:`transform_ast`.
3288 3288 """
3289 3289 # Static input transformations
3290 3290 cell = self.input_transformer_manager.transform_cell(raw_cell)
3291 3291
3292 3292 if len(cell.splitlines()) == 1:
3293 3293 # Dynamic transformations - only applied for single line commands
3294 3294 with self.builtin_trap:
3295 3295 # use prefilter_lines to handle trailing newlines
3296 3296 # restore trailing newline for ast.parse
3297 3297 cell = self.prefilter_manager.prefilter_lines(cell) + '\n'
3298 3298
3299 3299 lines = cell.splitlines(keepends=True)
3300 3300 for transform in self.input_transformers_post:
3301 3301 lines = transform(lines)
3302 3302 cell = ''.join(lines)
3303 3303
3304 3304 return cell
3305 3305
3306 3306 def transform_ast(self, node):
3307 3307 """Apply the AST transformations from self.ast_transformers
3308 3308
3309 3309 Parameters
3310 3310 ----------
3311 3311 node : ast.Node
3312 3312 The root node to be transformed. Typically called with the ast.Module
3313 3313 produced by parsing user input.
3314 3314
3315 3315 Returns
3316 3316 -------
3317 3317 An ast.Node corresponding to the node it was called with. Note that it
3318 3318 may also modify the passed object, so don't rely on references to the
3319 3319 original AST.
3320 3320 """
3321 3321 for transformer in self.ast_transformers:
3322 3322 try:
3323 3323 node = transformer.visit(node)
3324 3324 except InputRejected:
3325 3325 # User-supplied AST transformers can reject an input by raising
3326 3326 # an InputRejected. Short-circuit in this case so that we
3327 3327 # don't unregister the transform.
3328 3328 raise
3329 3329 except Exception:
3330 3330 warn("AST transformer %r threw an error. It will be unregistered." % transformer)
3331 3331 self.ast_transformers.remove(transformer)
3332 3332
3333 3333 if self.ast_transformers:
3334 3334 ast.fix_missing_locations(node)
3335 3335 return node
3336 3336
3337 3337 async def run_ast_nodes(
3338 3338 self,
3339 3339 nodelist: ListType[stmt],
3340 3340 cell_name: str,
3341 3341 interactivity="last_expr",
3342 3342 compiler=compile,
3343 3343 result=None,
3344 3344 ):
3345 3345 """Run a sequence of AST nodes. The execution mode depends on the
3346 3346 interactivity parameter.
3347 3347
3348 3348 Parameters
3349 3349 ----------
3350 3350 nodelist : list
3351 3351 A sequence of AST nodes to run.
3352 3352 cell_name : str
3353 3353 Will be passed to the compiler as the filename of the cell. Typically
3354 3354 the value returned by ip.compile.cache(cell).
3355 3355 interactivity : str
3356 3356 'all', 'last', 'last_expr' , 'last_expr_or_assign' or 'none',
3357 3357 specifying which nodes should be run interactively (displaying output
3358 3358 from expressions). 'last_expr' will run the last node interactively
3359 3359 only if it is an expression (i.e. expressions in loops or other blocks
3360 3360 are not displayed) 'last_expr_or_assign' will run the last expression
3361 3361 or the last assignment. Other values for this parameter will raise a
3362 3362 ValueError.
3363 3363
3364 3364 compiler : callable
3365 3365 A function with the same interface as the built-in compile(), to turn
3366 3366 the AST nodes into code objects. Default is the built-in compile().
3367 3367 result : ExecutionResult, optional
3368 3368 An object to store exceptions that occur during execution.
3369 3369
3370 3370 Returns
3371 3371 -------
3372 3372 True if an exception occurred while running code, False if it finished
3373 3373 running.
3374 3374 """
3375 3375 if not nodelist:
3376 3376 return
3377 3377
3378 3378
3379 3379 if interactivity == 'last_expr_or_assign':
3380 3380 if isinstance(nodelist[-1], _assign_nodes):
3381 3381 asg = nodelist[-1]
3382 3382 if isinstance(asg, ast.Assign) and len(asg.targets) == 1:
3383 3383 target = asg.targets[0]
3384 3384 elif isinstance(asg, _single_targets_nodes):
3385 3385 target = asg.target
3386 3386 else:
3387 3387 target = None
3388 3388 if isinstance(target, ast.Name):
3389 3389 nnode = ast.Expr(ast.Name(target.id, ast.Load()))
3390 3390 ast.fix_missing_locations(nnode)
3391 3391 nodelist.append(nnode)
3392 3392 interactivity = 'last_expr'
3393 3393
3394 3394 _async = False
3395 3395 if interactivity == 'last_expr':
3396 3396 if isinstance(nodelist[-1], ast.Expr):
3397 3397 interactivity = "last"
3398 3398 else:
3399 3399 interactivity = "none"
3400 3400
3401 3401 if interactivity == 'none':
3402 3402 to_run_exec, to_run_interactive = nodelist, []
3403 3403 elif interactivity == 'last':
3404 3404 to_run_exec, to_run_interactive = nodelist[:-1], nodelist[-1:]
3405 3405 elif interactivity == 'all':
3406 3406 to_run_exec, to_run_interactive = [], nodelist
3407 3407 else:
3408 3408 raise ValueError("Interactivity was %r" % interactivity)
3409 3409
3410 3410 try:
3411 3411
3412 3412 def compare(code):
3413 3413 is_async = inspect.CO_COROUTINE & code.co_flags == inspect.CO_COROUTINE
3414 3414 return is_async
3415 3415
3416 3416 # refactor that to just change the mod constructor.
3417 3417 to_run = []
3418 3418 for node in to_run_exec:
3419 3419 to_run.append((node, "exec"))
3420 3420
3421 3421 for node in to_run_interactive:
3422 3422 to_run.append((node, "single"))
3423 3423
3424 3424 for node, mode in to_run:
3425 3425 if mode == "exec":
3426 3426 mod = Module([node], [])
3427 3427 elif mode == "single":
3428 mod = ast.Interactive([node])
3428 mod = ast.Interactive([node]) # type: ignore
3429 3429 with compiler.extra_flags(
3430 3430 getattr(ast, "PyCF_ALLOW_TOP_LEVEL_AWAIT", 0x0)
3431 3431 if self.autoawait
3432 3432 else 0x0
3433 3433 ):
3434 3434 code = compiler(mod, cell_name, mode)
3435 3435 asy = compare(code)
3436 3436 if await self.run_code(code, result, async_=asy):
3437 3437 return True
3438 3438
3439 3439 # Flush softspace
3440 3440 if softspace(sys.stdout, 0):
3441 3441 print()
3442 3442
3443 3443 except:
3444 3444 # It's possible to have exceptions raised here, typically by
3445 3445 # compilation of odd code (such as a naked 'return' outside a
3446 3446 # function) that did parse but isn't valid. Typically the exception
3447 3447 # is a SyntaxError, but it's safest just to catch anything and show
3448 3448 # the user a traceback.
3449 3449
3450 3450 # We do only one try/except outside the loop to minimize the impact
3451 3451 # on runtime, and also because if any node in the node list is
3452 3452 # broken, we should stop execution completely.
3453 3453 if result:
3454 3454 result.error_before_exec = sys.exc_info()[1]
3455 3455 self.showtraceback()
3456 3456 return True
3457 3457
3458 3458 return False
3459 3459
3460 3460 async def run_code(self, code_obj, result=None, *, async_=False):
3461 3461 """Execute a code object.
3462 3462
3463 3463 When an exception occurs, self.showtraceback() is called to display a
3464 3464 traceback.
3465 3465
3466 3466 Parameters
3467 3467 ----------
3468 3468 code_obj : code object
3469 3469 A compiled code object, to be executed
3470 3470 result : ExecutionResult, optional
3471 3471 An object to store exceptions that occur during execution.
3472 3472 async_ : Bool (Experimental)
3473 3473 Attempt to run top-level asynchronous code in a default loop.
3474 3474
3475 3475 Returns
3476 3476 -------
3477 3477 False : successful execution.
3478 3478 True : an error occurred.
3479 3479 """
3480 3480 # special value to say that anything above is IPython and should be
3481 3481 # hidden.
3482 3482 __tracebackhide__ = "__ipython_bottom__"
3483 3483 # Set our own excepthook in case the user code tries to call it
3484 3484 # directly, so that the IPython crash handler doesn't get triggered
3485 3485 old_excepthook, sys.excepthook = sys.excepthook, self.excepthook
3486 3486
3487 3487 # we save the original sys.excepthook in the instance, in case config
3488 3488 # code (such as magics) needs access to it.
3489 3489 self.sys_excepthook = old_excepthook
3490 3490 outflag = True # happens in more places, so it's easier as default
3491 3491 try:
3492 3492 try:
3493 3493 if async_:
3494 3494 await eval(code_obj, self.user_global_ns, self.user_ns)
3495 3495 else:
3496 3496 exec(code_obj, self.user_global_ns, self.user_ns)
3497 3497 finally:
3498 3498 # Reset our crash handler in place
3499 3499 sys.excepthook = old_excepthook
3500 3500 except SystemExit as e:
3501 3501 if result is not None:
3502 3502 result.error_in_exec = e
3503 3503 self.showtraceback(exception_only=True)
3504 3504 warn("To exit: use 'exit', 'quit', or Ctrl-D.", stacklevel=1)
3505 3505 except bdb.BdbQuit:
3506 3506 etype, value, tb = sys.exc_info()
3507 3507 if result is not None:
3508 3508 result.error_in_exec = value
3509 3509 # the BdbQuit stops here
3510 3510 except self.custom_exceptions:
3511 3511 etype, value, tb = sys.exc_info()
3512 3512 if result is not None:
3513 3513 result.error_in_exec = value
3514 3514 self.CustomTB(etype, value, tb)
3515 3515 except:
3516 3516 if result is not None:
3517 3517 result.error_in_exec = sys.exc_info()[1]
3518 3518 self.showtraceback(running_compiled_code=True)
3519 3519 else:
3520 3520 outflag = False
3521 3521 return outflag
3522 3522
3523 3523 # For backwards compatibility
3524 3524 runcode = run_code
3525 3525
3526 3526 def check_complete(self, code: str) -> Tuple[str, str]:
3527 3527 """Return whether a block of code is ready to execute, or should be continued
3528 3528
3529 3529 Parameters
3530 3530 ----------
3531 3531 code : string
3532 3532 Python input code, which can be multiline.
3533 3533
3534 3534 Returns
3535 3535 -------
3536 3536 status : str
3537 3537 One of 'complete', 'incomplete', or 'invalid' if source is not a
3538 3538 prefix of valid code.
3539 3539 indent : str
3540 3540 When status is 'incomplete', this is some whitespace to insert on
3541 3541 the next line of the prompt.
3542 3542 """
3543 3543 status, nspaces = self.input_transformer_manager.check_complete(code)
3544 3544 return status, ' ' * (nspaces or 0)
3545 3545
3546 3546 #-------------------------------------------------------------------------
3547 3547 # Things related to GUI support and pylab
3548 3548 #-------------------------------------------------------------------------
3549 3549
3550 3550 active_eventloop = None
3551 3551
3552 3552 def enable_gui(self, gui=None):
3553 3553 raise NotImplementedError('Implement enable_gui in a subclass')
3554 3554
3555 3555 def enable_matplotlib(self, gui=None):
3556 3556 """Enable interactive matplotlib and inline figure support.
3557 3557
3558 3558 This takes the following steps:
3559 3559
3560 3560 1. select the appropriate eventloop and matplotlib backend
3561 3561 2. set up matplotlib for interactive use with that backend
3562 3562 3. configure formatters for inline figure display
3563 3563 4. enable the selected gui eventloop
3564 3564
3565 3565 Parameters
3566 3566 ----------
3567 3567 gui : optional, string
3568 3568 If given, dictates the choice of matplotlib GUI backend to use
3569 3569 (should be one of IPython's supported backends, 'qt', 'osx', 'tk',
3570 3570 'gtk', 'wx' or 'inline'), otherwise we use the default chosen by
3571 3571 matplotlib (as dictated by the matplotlib build-time options plus the
3572 3572 user's matplotlibrc configuration file). Note that not all backends
3573 3573 make sense in all contexts, for example a terminal ipython can't
3574 3574 display figures inline.
3575 3575 """
3576 3576 from matplotlib_inline.backend_inline import configure_inline_support
3577 3577
3578 3578 from IPython.core import pylabtools as pt
3579 3579 gui, backend = pt.find_gui_and_backend(gui, self.pylab_gui_select)
3580 3580
3581 3581 if gui != 'inline':
3582 3582 # If we have our first gui selection, store it
3583 3583 if self.pylab_gui_select is None:
3584 3584 self.pylab_gui_select = gui
3585 3585 # Otherwise if they are different
3586 3586 elif gui != self.pylab_gui_select:
3587 3587 print('Warning: Cannot change to a different GUI toolkit: %s.'
3588 3588 ' Using %s instead.' % (gui, self.pylab_gui_select))
3589 3589 gui, backend = pt.find_gui_and_backend(self.pylab_gui_select)
3590 3590
3591 3591 pt.activate_matplotlib(backend)
3592 3592 configure_inline_support(self, backend)
3593 3593
3594 3594 # Now we must activate the gui pylab wants to use, and fix %run to take
3595 3595 # plot updates into account
3596 3596 self.enable_gui(gui)
3597 3597 self.magics_manager.registry['ExecutionMagics'].default_runner = \
3598 3598 pt.mpl_runner(self.safe_execfile)
3599 3599
3600 3600 return gui, backend
3601 3601
3602 3602 def enable_pylab(self, gui=None, import_all=True, welcome_message=False):
3603 3603 """Activate pylab support at runtime.
3604 3604
3605 3605 This turns on support for matplotlib, preloads into the interactive
3606 3606 namespace all of numpy and pylab, and configures IPython to correctly
3607 3607 interact with the GUI event loop. The GUI backend to be used can be
3608 3608 optionally selected with the optional ``gui`` argument.
3609 3609
3610 3610 This method only adds preloading the namespace to InteractiveShell.enable_matplotlib.
3611 3611
3612 3612 Parameters
3613 3613 ----------
3614 3614 gui : optional, string
3615 3615 If given, dictates the choice of matplotlib GUI backend to use
3616 3616 (should be one of IPython's supported backends, 'qt', 'osx', 'tk',
3617 3617 'gtk', 'wx' or 'inline'), otherwise we use the default chosen by
3618 3618 matplotlib (as dictated by the matplotlib build-time options plus the
3619 3619 user's matplotlibrc configuration file). Note that not all backends
3620 3620 make sense in all contexts, for example a terminal ipython can't
3621 3621 display figures inline.
3622 3622 import_all : optional, bool, default: True
3623 3623 Whether to do `from numpy import *` and `from pylab import *`
3624 3624 in addition to module imports.
3625 3625 welcome_message : deprecated
3626 3626 This argument is ignored, no welcome message will be displayed.
3627 3627 """
3628 3628 from IPython.core.pylabtools import import_pylab
3629 3629
3630 3630 gui, backend = self.enable_matplotlib(gui)
3631 3631
3632 3632 # We want to prevent the loading of pylab to pollute the user's
3633 3633 # namespace as shown by the %who* magics, so we execute the activation
3634 3634 # code in an empty namespace, and we update *both* user_ns and
3635 3635 # user_ns_hidden with this information.
3636 3636 ns = {}
3637 3637 import_pylab(ns, import_all)
3638 3638 # warn about clobbered names
3639 3639 ignored = {"__builtins__"}
3640 3640 both = set(ns).intersection(self.user_ns).difference(ignored)
3641 3641 clobbered = [ name for name in both if self.user_ns[name] is not ns[name] ]
3642 3642 self.user_ns.update(ns)
3643 3643 self.user_ns_hidden.update(ns)
3644 3644 return gui, backend, clobbered
3645 3645
3646 3646 #-------------------------------------------------------------------------
3647 3647 # Utilities
3648 3648 #-------------------------------------------------------------------------
3649 3649
3650 3650 def var_expand(self, cmd, depth=0, formatter=DollarFormatter()):
3651 3651 """Expand python variables in a string.
3652 3652
3653 3653 The depth argument indicates how many frames above the caller should
3654 3654 be walked to look for the local namespace where to expand variables.
3655 3655
3656 3656 The global namespace for expansion is always the user's interactive
3657 3657 namespace.
3658 3658 """
3659 3659 ns = self.user_ns.copy()
3660 3660 try:
3661 3661 frame = sys._getframe(depth+1)
3662 3662 except ValueError:
3663 3663 # This is thrown if there aren't that many frames on the stack,
3664 3664 # e.g. if a script called run_line_magic() directly.
3665 3665 pass
3666 3666 else:
3667 3667 ns.update(frame.f_locals)
3668 3668
3669 3669 try:
3670 3670 # We have to use .vformat() here, because 'self' is a valid and common
3671 3671 # name, and expanding **ns for .format() would make it collide with
3672 3672 # the 'self' argument of the method.
3673 3673 cmd = formatter.vformat(cmd, args=[], kwargs=ns)
3674 3674 except Exception:
3675 3675 # if formatter couldn't format, just let it go untransformed
3676 3676 pass
3677 3677 return cmd
3678 3678
3679 3679 def mktempfile(self, data=None, prefix='ipython_edit_'):
3680 3680 """Make a new tempfile and return its filename.
3681 3681
3682 3682 This makes a call to tempfile.mkstemp (created in a tempfile.mkdtemp),
3683 3683 but it registers the created filename internally so ipython cleans it up
3684 3684 at exit time.
3685 3685
3686 3686 Optional inputs:
3687 3687
3688 3688 - data(None): if data is given, it gets written out to the temp file
3689 3689 immediately, and the file is closed again."""
3690 3690
3691 3691 dir_path = Path(tempfile.mkdtemp(prefix=prefix))
3692 3692 self.tempdirs.append(dir_path)
3693 3693
3694 3694 handle, filename = tempfile.mkstemp(".py", prefix, dir=str(dir_path))
3695 3695 os.close(handle) # On Windows, there can only be one open handle on a file
3696 3696
3697 3697 file_path = Path(filename)
3698 3698 self.tempfiles.append(file_path)
3699 3699
3700 3700 if data:
3701 3701 file_path.write_text(data, encoding="utf-8")
3702 3702 return filename
3703 3703
3704 3704 def ask_yes_no(self, prompt, default=None, interrupt=None):
3705 3705 if self.quiet:
3706 3706 return True
3707 3707 return ask_yes_no(prompt,default,interrupt)
3708 3708
3709 3709 def show_usage(self):
3710 3710 """Show a usage message"""
3711 3711 page.page(IPython.core.usage.interactive_usage)
3712 3712
3713 3713 def extract_input_lines(self, range_str, raw=False):
3714 3714 """Return as a string a set of input history slices.
3715 3715
3716 3716 Parameters
3717 3717 ----------
3718 3718 range_str : str
3719 3719 The set of slices is given as a string, like "~5/6-~4/2 4:8 9",
3720 3720 since this function is for use by magic functions which get their
3721 3721 arguments as strings. The number before the / is the session
3722 3722 number: ~n goes n back from the current session.
3723 3723
3724 3724 If empty string is given, returns history of current session
3725 3725 without the last input.
3726 3726
3727 3727 raw : bool, optional
3728 3728 By default, the processed input is used. If this is true, the raw
3729 3729 input history is used instead.
3730 3730
3731 3731 Notes
3732 3732 -----
3733 3733 Slices can be described with two notations:
3734 3734
3735 3735 * ``N:M`` -> standard python form, means including items N...(M-1).
3736 3736 * ``N-M`` -> include items N..M (closed endpoint).
3737 3737 """
3738 3738 lines = self.history_manager.get_range_by_str(range_str, raw=raw)
3739 3739 text = "\n".join(x for _, _, x in lines)
3740 3740
3741 3741 # Skip the last line, as it's probably the magic that called this
3742 3742 if not range_str:
3743 3743 if "\n" not in text:
3744 3744 text = ""
3745 3745 else:
3746 3746 text = text[: text.rfind("\n")]
3747 3747
3748 3748 return text
3749 3749
3750 3750 def find_user_code(self, target, raw=True, py_only=False, skip_encoding_cookie=True, search_ns=False):
3751 3751 """Get a code string from history, file, url, or a string or macro.
3752 3752
3753 3753 This is mainly used by magic functions.
3754 3754
3755 3755 Parameters
3756 3756 ----------
3757 3757 target : str
3758 3758 A string specifying code to retrieve. This will be tried respectively
3759 3759 as: ranges of input history (see %history for syntax), url,
3760 3760 corresponding .py file, filename, or an expression evaluating to a
3761 3761 string or Macro in the user namespace.
3762 3762
3763 3763 If empty string is given, returns complete history of current
3764 3764 session, without the last line.
3765 3765
3766 3766 raw : bool
3767 3767 If true (default), retrieve raw history. Has no effect on the other
3768 3768 retrieval mechanisms.
3769 3769
3770 3770 py_only : bool (default False)
3771 3771 Only try to fetch python code, do not try alternative methods to decode file
3772 3772 if unicode fails.
3773 3773
3774 3774 Returns
3775 3775 -------
3776 3776 A string of code.
3777 3777 ValueError is raised if nothing is found, and TypeError if it evaluates
3778 3778 to an object of another type. In each case, .args[0] is a printable
3779 3779 message.
3780 3780 """
3781 3781 code = self.extract_input_lines(target, raw=raw) # Grab history
3782 3782 if code:
3783 3783 return code
3784 3784 try:
3785 3785 if target.startswith(('http://', 'https://')):
3786 3786 return openpy.read_py_url(target, skip_encoding_cookie=skip_encoding_cookie)
3787 3787 except UnicodeDecodeError as e:
3788 3788 if not py_only :
3789 3789 # Deferred import
3790 3790 from urllib.request import urlopen
3791 3791 response = urlopen(target)
3792 3792 return response.read().decode('latin1')
3793 3793 raise ValueError(("'%s' seem to be unreadable.") % target) from e
3794 3794
3795 3795 potential_target = [target]
3796 3796 try :
3797 3797 potential_target.insert(0,get_py_filename(target))
3798 3798 except IOError:
3799 3799 pass
3800 3800
3801 3801 for tgt in potential_target :
3802 3802 if os.path.isfile(tgt): # Read file
3803 3803 try :
3804 3804 return openpy.read_py_file(tgt, skip_encoding_cookie=skip_encoding_cookie)
3805 3805 except UnicodeDecodeError as e:
3806 3806 if not py_only :
3807 3807 with io_open(tgt,'r', encoding='latin1') as f :
3808 3808 return f.read()
3809 3809 raise ValueError(("'%s' seem to be unreadable.") % target) from e
3810 3810 elif os.path.isdir(os.path.expanduser(tgt)):
3811 3811 raise ValueError("'%s' is a directory, not a regular file." % target)
3812 3812
3813 3813 if search_ns:
3814 3814 # Inspect namespace to load object source
3815 3815 object_info = self.object_inspect(target, detail_level=1)
3816 3816 if object_info['found'] and object_info['source']:
3817 3817 return object_info['source']
3818 3818
3819 3819 try: # User namespace
3820 3820 codeobj = eval(target, self.user_ns)
3821 3821 except Exception as e:
3822 3822 raise ValueError(("'%s' was not found in history, as a file, url, "
3823 3823 "nor in the user namespace.") % target) from e
3824 3824
3825 3825 if isinstance(codeobj, str):
3826 3826 return codeobj
3827 3827 elif isinstance(codeobj, Macro):
3828 3828 return codeobj.value
3829 3829
3830 3830 raise TypeError("%s is neither a string nor a macro." % target,
3831 3831 codeobj)
3832 3832
3833 3833 def _atexit_once(self):
3834 3834 """
3835 3835 At exist operation that need to be called at most once.
3836 3836 Second call to this function per instance will do nothing.
3837 3837 """
3838 3838
3839 3839 if not getattr(self, "_atexit_once_called", False):
3840 3840 self._atexit_once_called = True
3841 3841 # Clear all user namespaces to release all references cleanly.
3842 3842 self.reset(new_session=False)
3843 3843 # Close the history session (this stores the end time and line count)
3844 3844 # this must be *before* the tempfile cleanup, in case of temporary
3845 3845 # history db
3846 3846 self.history_manager.end_session()
3847 3847 self.history_manager = None
3848 3848
3849 3849 #-------------------------------------------------------------------------
3850 3850 # Things related to IPython exiting
3851 3851 #-------------------------------------------------------------------------
3852 3852 def atexit_operations(self):
3853 3853 """This will be executed at the time of exit.
3854 3854
3855 3855 Cleanup operations and saving of persistent data that is done
3856 3856 unconditionally by IPython should be performed here.
3857 3857
3858 3858 For things that may depend on startup flags or platform specifics (such
3859 3859 as having readline or not), register a separate atexit function in the
3860 3860 code that has the appropriate information, rather than trying to
3861 3861 clutter
3862 3862 """
3863 3863 self._atexit_once()
3864 3864
3865 3865 # Cleanup all tempfiles and folders left around
3866 3866 for tfile in self.tempfiles:
3867 3867 try:
3868 3868 tfile.unlink()
3869 3869 self.tempfiles.remove(tfile)
3870 3870 except FileNotFoundError:
3871 3871 pass
3872 3872 del self.tempfiles
3873 3873 for tdir in self.tempdirs:
3874 3874 try:
3875 3875 tdir.rmdir()
3876 3876 self.tempdirs.remove(tdir)
3877 3877 except FileNotFoundError:
3878 3878 pass
3879 3879 del self.tempdirs
3880 3880
3881 3881 # Restore user's cursor
3882 3882 if hasattr(self, "editing_mode") and self.editing_mode == "vi":
3883 3883 sys.stdout.write("\x1b[0 q")
3884 3884 sys.stdout.flush()
3885 3885
3886 3886 def cleanup(self):
3887 3887 self.restore_sys_module_state()
3888 3888
3889 3889
3890 3890 # Overridden in terminal subclass to change prompts
3891 3891 def switch_doctest_mode(self, mode):
3892 3892 pass
3893 3893
3894 3894
3895 3895 class InteractiveShellABC(metaclass=abc.ABCMeta):
3896 3896 """An abstract base class for InteractiveShell."""
3897 3897
3898 3898 InteractiveShellABC.register(InteractiveShell)
@@ -1,310 +1,310 b''
1 1 ''' A decorator-based method of constructing IPython magics with `argparse`
2 2 option handling.
3 3
4 4 New magic functions can be defined like so::
5 5
6 6 from IPython.core.magic_arguments import (argument, magic_arguments,
7 7 parse_argstring)
8 8
9 9 @magic_arguments()
10 10 @argument('-o', '--option', help='An optional argument.')
11 11 @argument('arg', type=int, help='An integer positional argument.')
12 12 def magic_cool(self, arg):
13 13 """ A really cool magic command.
14 14
15 15 """
16 16 args = parse_argstring(magic_cool, arg)
17 17 ...
18 18
19 19 The `@magic_arguments` decorator marks the function as having argparse arguments.
20 20 The `@argument` decorator adds an argument using the same syntax as argparse's
21 21 `add_argument()` method. More sophisticated uses may also require the
22 22 `@argument_group` or `@kwds` decorator to customize the formatting and the
23 23 parsing.
24 24
25 25 Help text for the magic is automatically generated from the docstring and the
26 26 arguments::
27 27
28 28 In[1]: %cool?
29 29 %cool [-o OPTION] arg
30 30
31 31 A really cool magic command.
32 32
33 33 positional arguments:
34 34 arg An integer positional argument.
35 35
36 36 optional arguments:
37 37 -o OPTION, --option OPTION
38 38 An optional argument.
39 39
40 40 Here is an elaborated example that uses default parameters in `argument` and calls the `args` in the cell magic::
41 41
42 42 from IPython.core.magic import register_cell_magic
43 43 from IPython.core.magic_arguments import (argument, magic_arguments,
44 44 parse_argstring)
45 45
46 46
47 47 @magic_arguments()
48 48 @argument(
49 49 "--option",
50 50 "-o",
51 51 help=("Add an option here"),
52 52 )
53 53 @argument(
54 54 "--style",
55 55 "-s",
56 56 default="foo",
57 57 help=("Add some style arguments"),
58 58 )
59 59 @register_cell_magic
60 60 def my_cell_magic(line, cell):
61 61 args = parse_argstring(my_cell_magic, line)
62 62 print(f"{args.option=}")
63 63 print(f"{args.style=}")
64 64 print(f"{cell=}")
65 65
66 66 In a jupyter notebook, this cell magic can be executed like this::
67 67
68 68 %%my_cell_magic -o Hello
69 69 print("bar")
70 70 i = 42
71 71
72 72 Inheritance diagram:
73 73
74 74 .. inheritance-diagram:: IPython.core.magic_arguments
75 75 :parts: 3
76 76
77 77 '''
78 78 #-----------------------------------------------------------------------------
79 79 # Copyright (C) 2010-2011, IPython Development Team.
80 80 #
81 81 # Distributed under the terms of the Modified BSD License.
82 82 #
83 83 # The full license is in the file COPYING.txt, distributed with this software.
84 84 #-----------------------------------------------------------------------------
85 85 import argparse
86 86 import re
87 87
88 88 # Our own imports
89 89 from IPython.core.error import UsageError
90 90 from IPython.utils.decorators import undoc
91 91 from IPython.utils.process import arg_split
92 92 from IPython.utils.text import dedent
93 93
94 94 NAME_RE = re.compile(r"[a-zA-Z][a-zA-Z0-9_-]*$")
95 95
96 96 @undoc
97 97 class MagicHelpFormatter(argparse.RawDescriptionHelpFormatter):
98 98 """A HelpFormatter with a couple of changes to meet our needs.
99 99 """
100 100 # Modified to dedent text.
101 101 def _fill_text(self, text, width, indent):
102 102 return argparse.RawDescriptionHelpFormatter._fill_text(self, dedent(text), width, indent)
103 103
104 104 # Modified to wrap argument placeholders in <> where necessary.
105 105 def _format_action_invocation(self, action):
106 106 if not action.option_strings:
107 107 metavar, = self._metavar_formatter(action, action.dest)(1)
108 108 return metavar
109 109
110 110 else:
111 111 parts = []
112 112
113 113 # if the Optional doesn't take a value, format is:
114 114 # -s, --long
115 115 if action.nargs == 0:
116 116 parts.extend(action.option_strings)
117 117
118 118 # if the Optional takes a value, format is:
119 119 # -s ARGS, --long ARGS
120 120 else:
121 121 default = action.dest.upper()
122 122 args_string = self._format_args(action, default)
123 123 # IPYTHON MODIFICATION: If args_string is not a plain name, wrap
124 124 # it in <> so it's valid RST.
125 125 if not NAME_RE.match(args_string):
126 126 args_string = "<%s>" % args_string
127 127 for option_string in action.option_strings:
128 128 parts.append('%s %s' % (option_string, args_string))
129 129
130 130 return ', '.join(parts)
131 131
132 132 # Override the default prefix ('usage') to our % magic escape,
133 133 # in a code block.
134 134 def add_usage(self, usage, actions, groups, prefix="::\n\n %"):
135 135 super(MagicHelpFormatter, self).add_usage(usage, actions, groups, prefix)
136 136
137 137 class MagicArgumentParser(argparse.ArgumentParser):
138 138 """ An ArgumentParser tweaked for use by IPython magics.
139 139 """
140 140 def __init__(self,
141 141 prog=None,
142 142 usage=None,
143 143 description=None,
144 144 epilog=None,
145 145 parents=None,
146 146 formatter_class=MagicHelpFormatter,
147 147 prefix_chars='-',
148 148 argument_default=None,
149 149 conflict_handler='error',
150 150 add_help=False):
151 151 if parents is None:
152 152 parents = []
153 153 super(MagicArgumentParser, self).__init__(prog=prog, usage=usage,
154 154 description=description, epilog=epilog,
155 155 parents=parents, formatter_class=formatter_class,
156 156 prefix_chars=prefix_chars, argument_default=argument_default,
157 157 conflict_handler=conflict_handler, add_help=add_help)
158 158
159 159 def error(self, message):
160 160 """ Raise a catchable error instead of exiting.
161 161 """
162 162 raise UsageError(message)
163 163
164 164 def parse_argstring(self, argstring):
165 165 """ Split a string into an argument list and parse that argument list.
166 166 """
167 167 argv = arg_split(argstring)
168 168 return self.parse_args(argv)
169 169
170 170
171 171 def construct_parser(magic_func):
172 172 """ Construct an argument parser using the function decorations.
173 173 """
174 174 kwds = getattr(magic_func, 'argcmd_kwds', {})
175 175 if 'description' not in kwds:
176 176 kwds['description'] = getattr(magic_func, '__doc__', None)
177 177 arg_name = real_name(magic_func)
178 178 parser = MagicArgumentParser(arg_name, **kwds)
179 179 # Reverse the list of decorators in order to apply them in the
180 180 # order in which they appear in the source.
181 181 group = None
182 182 for deco in magic_func.decorators[::-1]:
183 183 result = deco.add_to_parser(parser, group)
184 184 if result is not None:
185 185 group = result
186 186
187 187 # Replace the magic function's docstring with the full help text.
188 188 magic_func.__doc__ = parser.format_help()
189 189
190 190 return parser
191 191
192 192
193 193 def parse_argstring(magic_func, argstring):
194 194 """ Parse the string of arguments for the given magic function.
195 195 """
196 196 return magic_func.parser.parse_argstring(argstring)
197 197
198 198
199 199 def real_name(magic_func):
200 200 """ Find the real name of the magic.
201 201 """
202 202 magic_name = magic_func.__name__
203 203 if magic_name.startswith('magic_'):
204 204 magic_name = magic_name[len('magic_'):]
205 205 return getattr(magic_func, 'argcmd_name', magic_name)
206 206
207 207
208 208 class ArgDecorator(object):
209 209 """ Base class for decorators to add ArgumentParser information to a method.
210 210 """
211 211
212 212 def __call__(self, func):
213 213 if not getattr(func, 'has_arguments', False):
214 214 func.has_arguments = True
215 215 func.decorators = []
216 216 func.decorators.append(self)
217 217 return func
218 218
219 219 def add_to_parser(self, parser, group):
220 220 """ Add this object's information to the parser, if necessary.
221 221 """
222 222 pass
223 223
224 224
225 225 class magic_arguments(ArgDecorator):
226 226 """ Mark the magic as having argparse arguments and possibly adjust the
227 227 name.
228 228 """
229 229
230 230 def __init__(self, name=None):
231 231 self.name = name
232 232
233 233 def __call__(self, func):
234 234 if not getattr(func, 'has_arguments', False):
235 235 func.has_arguments = True
236 236 func.decorators = []
237 237 if self.name is not None:
238 238 func.argcmd_name = self.name
239 239 # This should be the first decorator in the list of decorators, thus the
240 240 # last to execute. Build the parser.
241 241 func.parser = construct_parser(func)
242 242 return func
243 243
244 244
245 245 class ArgMethodWrapper(ArgDecorator):
246 246
247 247 """
248 248 Base class to define a wrapper for ArgumentParser method.
249 249
250 250 Child class must define either `_method_name` or `add_to_parser`.
251 251
252 252 """
253 253
254 _method_name = None
254 _method_name: str
255 255
256 256 def __init__(self, *args, **kwds):
257 257 self.args = args
258 258 self.kwds = kwds
259 259
260 260 def add_to_parser(self, parser, group):
261 261 """ Add this object's information to the parser.
262 262 """
263 263 if group is not None:
264 264 parser = group
265 265 getattr(parser, self._method_name)(*self.args, **self.kwds)
266 266 return None
267 267
268 268
269 269 class argument(ArgMethodWrapper):
270 270 """ Store arguments and keywords to pass to add_argument().
271 271
272 272 Instances also serve to decorate command methods.
273 273 """
274 274 _method_name = 'add_argument'
275 275
276 276
277 277 class defaults(ArgMethodWrapper):
278 278 """ Store arguments and keywords to pass to set_defaults().
279 279
280 280 Instances also serve to decorate command methods.
281 281 """
282 282 _method_name = 'set_defaults'
283 283
284 284
285 285 class argument_group(ArgMethodWrapper):
286 286 """ Store arguments and keywords to pass to add_argument_group().
287 287
288 288 Instances also serve to decorate command methods.
289 289 """
290 290
291 291 def add_to_parser(self, parser, group):
292 292 """ Add this object's information to the parser.
293 293 """
294 294 return parser.add_argument_group(*self.args, **self.kwds)
295 295
296 296
297 297 class kwds(ArgDecorator):
298 298 """ Provide other keywords to the sub-parser constructor.
299 299 """
300 300 def __init__(self, **kwds):
301 301 self.kwds = kwds
302 302
303 303 def __call__(self, func):
304 304 func = super(kwds, self).__call__(func)
305 305 func.argcmd_kwds = self.kwds
306 306 return func
307 307
308 308
309 309 __all__ = ['magic_arguments', 'argument', 'argument_group', 'kwds',
310 310 'parse_argstring']
@@ -1,1093 +1,1098 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Tools for inspecting Python objects.
3 3
4 4 Uses syntax highlighting for presenting the various information elements.
5 5
6 6 Similar in spirit to the inspect module, but all calls take a name argument to
7 7 reference the name under which an object is being read.
8 8 """
9 9
10 10 # Copyright (c) IPython Development Team.
11 11 # Distributed under the terms of the Modified BSD License.
12 12
13 13 __all__ = ['Inspector','InspectColors']
14 14
15 15 # stdlib modules
16 16 import ast
17 17 import inspect
18 18 from inspect import signature
19 19 import html
20 20 import linecache
21 21 import warnings
22 22 import os
23 23 from textwrap import dedent
24 24 import types
25 25 import io as stdlib_io
26 26
27 27 from typing import Union
28 28
29 29 # IPython's own
30 30 from IPython.core import page
31 31 from IPython.lib.pretty import pretty
32 32 from IPython.testing.skipdoctest import skip_doctest
33 33 from IPython.utils import PyColorize
34 34 from IPython.utils import openpy
35 35 from IPython.utils.dir2 import safe_hasattr
36 36 from IPython.utils.path import compress_user
37 37 from IPython.utils.text import indent
38 38 from IPython.utils.wildcard import list_namespace
39 39 from IPython.utils.wildcard import typestr2type
40 40 from IPython.utils.coloransi import TermColors, ColorScheme, ColorSchemeTable
41 41 from IPython.utils.py3compat import cast_unicode
42 42 from IPython.utils.colorable import Colorable
43 43 from IPython.utils.decorators import undoc
44 44
45 45 from pygments import highlight
46 46 from pygments.lexers import PythonLexer
47 47 from pygments.formatters import HtmlFormatter
48 48
49 from typing import Any
49 from typing import Any, Optional
50 50 from dataclasses import dataclass
51 51
52 52
53 53 @dataclass
54 54 class OInfo:
55 55 ismagic: bool
56 56 isalias: bool
57 57 found: bool
58 namespace: str
58 namespace: Optional[str]
59 59 parent: Any
60 60 obj: Any
61 61
62 62 def pylight(code):
63 63 return highlight(code, PythonLexer(), HtmlFormatter(noclasses=True))
64 64
65 65 # builtin docstrings to ignore
66 66 _func_call_docstring = types.FunctionType.__call__.__doc__
67 67 _object_init_docstring = object.__init__.__doc__
68 68 _builtin_type_docstrings = {
69 69 inspect.getdoc(t) for t in (types.ModuleType, types.MethodType,
70 70 types.FunctionType, property)
71 71 }
72 72
73 73 _builtin_func_type = type(all)
74 74 _builtin_meth_type = type(str.upper) # Bound methods have the same type as builtin functions
75 75 #****************************************************************************
76 76 # Builtin color schemes
77 77
78 78 Colors = TermColors # just a shorthand
79 79
80 80 InspectColors = PyColorize.ANSICodeColors
81 81
82 82 #****************************************************************************
83 83 # Auxiliary functions and objects
84 84
85 85 # See the messaging spec for the definition of all these fields. This list
86 86 # effectively defines the order of display
87 87 info_fields = ['type_name', 'base_class', 'string_form', 'namespace',
88 88 'length', 'file', 'definition', 'docstring', 'source',
89 89 'init_definition', 'class_docstring', 'init_docstring',
90 90 'call_def', 'call_docstring',
91 91 # These won't be printed but will be used to determine how to
92 92 # format the object
93 93 'ismagic', 'isalias', 'isclass', 'found', 'name'
94 94 ]
95 95
96 96
97 97 def object_info(**kw):
98 98 """Make an object info dict with all fields present."""
99 99 infodict = {k:None for k in info_fields}
100 100 infodict.update(kw)
101 101 return infodict
102 102
103 103
104 104 def get_encoding(obj):
105 105 """Get encoding for python source file defining obj
106 106
107 107 Returns None if obj is not defined in a sourcefile.
108 108 """
109 109 ofile = find_file(obj)
110 110 # run contents of file through pager starting at line where the object
111 111 # is defined, as long as the file isn't binary and is actually on the
112 112 # filesystem.
113 113 if ofile is None:
114 114 return None
115 115 elif ofile.endswith(('.so', '.dll', '.pyd')):
116 116 return None
117 117 elif not os.path.isfile(ofile):
118 118 return None
119 119 else:
120 120 # Print only text files, not extension binaries. Note that
121 121 # getsourcelines returns lineno with 1-offset and page() uses
122 122 # 0-offset, so we must adjust.
123 123 with stdlib_io.open(ofile, 'rb') as buffer: # Tweaked to use io.open for Python 2
124 124 encoding, lines = openpy.detect_encoding(buffer.readline)
125 125 return encoding
126 126
127 127 def getdoc(obj) -> Union[str,None]:
128 128 """Stable wrapper around inspect.getdoc.
129 129
130 130 This can't crash because of attribute problems.
131 131
132 132 It also attempts to call a getdoc() method on the given object. This
133 133 allows objects which provide their docstrings via non-standard mechanisms
134 134 (like Pyro proxies) to still be inspected by ipython's ? system.
135 135 """
136 136 # Allow objects to offer customized documentation via a getdoc method:
137 137 try:
138 138 ds = obj.getdoc()
139 139 except Exception:
140 140 pass
141 141 else:
142 142 if isinstance(ds, str):
143 143 return inspect.cleandoc(ds)
144 144 docstr = inspect.getdoc(obj)
145 145 return docstr
146 146
147 147
148 148 def getsource(obj, oname='') -> Union[str,None]:
149 149 """Wrapper around inspect.getsource.
150 150
151 151 This can be modified by other projects to provide customized source
152 152 extraction.
153 153
154 154 Parameters
155 155 ----------
156 156 obj : object
157 157 an object whose source code we will attempt to extract
158 158 oname : str
159 159 (optional) a name under which the object is known
160 160
161 161 Returns
162 162 -------
163 163 src : unicode or None
164 164
165 165 """
166 166
167 167 if isinstance(obj, property):
168 168 sources = []
169 169 for attrname in ['fget', 'fset', 'fdel']:
170 170 fn = getattr(obj, attrname)
171 171 if fn is not None:
172 172 encoding = get_encoding(fn)
173 173 oname_prefix = ('%s.' % oname) if oname else ''
174 174 sources.append(''.join(('# ', oname_prefix, attrname)))
175 175 if inspect.isfunction(fn):
176 sources.append(dedent(getsource(fn)))
176 _src = getsource(fn)
177 if _src:
178 # assert _src is not None, "please mypy"
179 sources.append(dedent(_src))
177 180 else:
178 181 # Default str/repr only prints function name,
179 182 # pretty.pretty prints module name too.
180 183 sources.append(
181 184 '%s%s = %s\n' % (oname_prefix, attrname, pretty(fn))
182 185 )
183 186 if sources:
184 187 return '\n'.join(sources)
185 188 else:
186 189 return None
187 190
188 191 else:
189 192 # Get source for non-property objects.
190 193
191 194 obj = _get_wrapped(obj)
192 195
193 196 try:
194 197 src = inspect.getsource(obj)
195 198 except TypeError:
196 199 # The object itself provided no meaningful source, try looking for
197 200 # its class definition instead.
198 201 try:
199 202 src = inspect.getsource(obj.__class__)
200 203 except (OSError, TypeError):
201 204 return None
202 205 except OSError:
203 206 return None
204 207
205 208 return src
206 209
207 210
208 211 def is_simple_callable(obj):
209 212 """True if obj is a function ()"""
210 213 return (inspect.isfunction(obj) or inspect.ismethod(obj) or \
211 214 isinstance(obj, _builtin_func_type) or isinstance(obj, _builtin_meth_type))
212 215
213 216 @undoc
214 217 def getargspec(obj):
215 218 """Wrapper around :func:`inspect.getfullargspec`
216 219
217 220 In addition to functions and methods, this can also handle objects with a
218 221 ``__call__`` attribute.
219 222
220 223 DEPRECATED: Deprecated since 7.10. Do not use, will be removed.
221 224 """
222 225
223 226 warnings.warn('`getargspec` function is deprecated as of IPython 7.10'
224 227 'and will be removed in future versions.', DeprecationWarning, stacklevel=2)
225 228
226 229 if safe_hasattr(obj, '__call__') and not is_simple_callable(obj):
227 230 obj = obj.__call__
228 231
229 232 return inspect.getfullargspec(obj)
230 233
231 234 @undoc
232 235 def format_argspec(argspec):
233 236 """Format argspect, convenience wrapper around inspect's.
234 237
235 238 This takes a dict instead of ordered arguments and calls
236 239 inspect.format_argspec with the arguments in the necessary order.
237 240
238 241 DEPRECATED (since 7.10): Do not use; will be removed in future versions.
239 242 """
240 243
241 244 warnings.warn('`format_argspec` function is deprecated as of IPython 7.10'
242 245 'and will be removed in future versions.', DeprecationWarning, stacklevel=2)
243 246
244 247
245 248 return inspect.formatargspec(argspec['args'], argspec['varargs'],
246 249 argspec['varkw'], argspec['defaults'])
247 250
248 251 @undoc
249 252 def call_tip(oinfo, format_call=True):
250 253 """DEPRECATED since 6.0. Extract call tip data from an oinfo dict."""
251 254 warnings.warn(
252 255 "`call_tip` function is deprecated as of IPython 6.0"
253 256 "and will be removed in future versions.",
254 257 DeprecationWarning,
255 258 stacklevel=2,
256 259 )
257 260 # Get call definition
258 261 argspec = oinfo.get('argspec')
259 262 if argspec is None:
260 263 call_line = None
261 264 else:
262 265 # Callable objects will have 'self' as their first argument, prune
263 266 # it out if it's there for clarity (since users do *not* pass an
264 267 # extra first argument explicitly).
265 268 try:
266 269 has_self = argspec['args'][0] == 'self'
267 270 except (KeyError, IndexError):
268 271 pass
269 272 else:
270 273 if has_self:
271 274 argspec['args'] = argspec['args'][1:]
272 275
273 276 call_line = oinfo['name']+format_argspec(argspec)
274 277
275 278 # Now get docstring.
276 279 # The priority is: call docstring, constructor docstring, main one.
277 280 doc = oinfo.get('call_docstring')
278 281 if doc is None:
279 282 doc = oinfo.get('init_docstring')
280 283 if doc is None:
281 284 doc = oinfo.get('docstring','')
282 285
283 286 return call_line, doc
284 287
285 288
286 289 def _get_wrapped(obj):
287 290 """Get the original object if wrapped in one or more @decorators
288 291
289 292 Some objects automatically construct similar objects on any unrecognised
290 293 attribute access (e.g. unittest.mock.call). To protect against infinite loops,
291 294 this will arbitrarily cut off after 100 levels of obj.__wrapped__
292 295 attribute access. --TK, Jan 2016
293 296 """
294 297 orig_obj = obj
295 298 i = 0
296 299 while safe_hasattr(obj, '__wrapped__'):
297 300 obj = obj.__wrapped__
298 301 i += 1
299 302 if i > 100:
300 303 # __wrapped__ is probably a lie, so return the thing we started with
301 304 return orig_obj
302 305 return obj
303 306
304 307 def find_file(obj) -> str:
305 308 """Find the absolute path to the file where an object was defined.
306 309
307 310 This is essentially a robust wrapper around `inspect.getabsfile`.
308 311
309 312 Returns None if no file can be found.
310 313
311 314 Parameters
312 315 ----------
313 316 obj : any Python object
314 317
315 318 Returns
316 319 -------
317 320 fname : str
318 321 The absolute path to the file where the object was defined.
319 322 """
320 323 obj = _get_wrapped(obj)
321 324
322 325 fname = None
323 326 try:
324 327 fname = inspect.getabsfile(obj)
325 328 except TypeError:
326 329 # For an instance, the file that matters is where its class was
327 330 # declared.
328 331 try:
329 332 fname = inspect.getabsfile(obj.__class__)
330 333 except (OSError, TypeError):
331 334 # Can happen for builtins
332 335 pass
333 336 except OSError:
334 337 pass
335 338
336 339 return cast_unicode(fname)
337 340
338 341
339 342 def find_source_lines(obj):
340 343 """Find the line number in a file where an object was defined.
341 344
342 345 This is essentially a robust wrapper around `inspect.getsourcelines`.
343 346
344 347 Returns None if no file can be found.
345 348
346 349 Parameters
347 350 ----------
348 351 obj : any Python object
349 352
350 353 Returns
351 354 -------
352 355 lineno : int
353 356 The line number where the object definition starts.
354 357 """
355 358 obj = _get_wrapped(obj)
356 359
357 360 try:
358 361 lineno = inspect.getsourcelines(obj)[1]
359 362 except TypeError:
360 363 # For instances, try the class object like getsource() does
361 364 try:
362 365 lineno = inspect.getsourcelines(obj.__class__)[1]
363 366 except (OSError, TypeError):
364 367 return None
365 368 except OSError:
366 369 return None
367 370
368 371 return lineno
369 372
370 373 class Inspector(Colorable):
371 374
372 375 def __init__(self, color_table=InspectColors,
373 376 code_color_table=PyColorize.ANSICodeColors,
374 377 scheme=None,
375 378 str_detail_level=0,
376 379 parent=None, config=None):
377 380 super(Inspector, self).__init__(parent=parent, config=config)
378 381 self.color_table = color_table
379 382 self.parser = PyColorize.Parser(out='str', parent=self, style=scheme)
380 383 self.format = self.parser.format
381 384 self.str_detail_level = str_detail_level
382 385 self.set_active_scheme(scheme)
383 386
384 387 def _getdef(self,obj,oname='') -> Union[str,None]:
385 388 """Return the call signature for any callable object.
386 389
387 390 If any exception is generated, None is returned instead and the
388 391 exception is suppressed."""
389 392 try:
390 393 return _render_signature(signature(obj), oname)
391 394 except:
392 395 return None
393 396
394 397 def __head(self,h) -> str:
395 398 """Return a header string with proper colors."""
396 399 return '%s%s%s' % (self.color_table.active_colors.header,h,
397 400 self.color_table.active_colors.normal)
398 401
399 402 def set_active_scheme(self, scheme):
400 403 if scheme is not None:
401 404 self.color_table.set_active_scheme(scheme)
402 405 self.parser.color_table.set_active_scheme(scheme)
403 406
404 407 def noinfo(self, msg, oname):
405 408 """Generic message when no information is found."""
406 409 print('No %s found' % msg, end=' ')
407 410 if oname:
408 411 print('for %s' % oname)
409 412 else:
410 413 print()
411 414
412 415 def pdef(self, obj, oname=''):
413 416 """Print the call signature for any callable object.
414 417
415 418 If the object is a class, print the constructor information."""
416 419
417 420 if not callable(obj):
418 421 print('Object is not callable.')
419 422 return
420 423
421 424 header = ''
422 425
423 426 if inspect.isclass(obj):
424 427 header = self.__head('Class constructor information:\n')
425 428
426 429
427 430 output = self._getdef(obj,oname)
428 431 if output is None:
429 432 self.noinfo('definition header',oname)
430 433 else:
431 434 print(header,self.format(output), end=' ')
432 435
433 436 # In Python 3, all classes are new-style, so they all have __init__.
434 437 @skip_doctest
435 438 def pdoc(self, obj, oname='', formatter=None):
436 439 """Print the docstring for any object.
437 440
438 441 Optional:
439 442 -formatter: a function to run the docstring through for specially
440 443 formatted docstrings.
441 444
442 445 Examples
443 446 --------
444 447 In [1]: class NoInit:
445 448 ...: pass
446 449
447 450 In [2]: class NoDoc:
448 451 ...: def __init__(self):
449 452 ...: pass
450 453
451 454 In [3]: %pdoc NoDoc
452 455 No documentation found for NoDoc
453 456
454 457 In [4]: %pdoc NoInit
455 458 No documentation found for NoInit
456 459
457 460 In [5]: obj = NoInit()
458 461
459 462 In [6]: %pdoc obj
460 463 No documentation found for obj
461 464
462 465 In [5]: obj2 = NoDoc()
463 466
464 467 In [6]: %pdoc obj2
465 468 No documentation found for obj2
466 469 """
467 470
468 471 head = self.__head # For convenience
469 472 lines = []
470 473 ds = getdoc(obj)
471 474 if formatter:
472 475 ds = formatter(ds).get('plain/text', ds)
473 476 if ds:
474 477 lines.append(head("Class docstring:"))
475 478 lines.append(indent(ds))
476 479 if inspect.isclass(obj) and hasattr(obj, '__init__'):
477 480 init_ds = getdoc(obj.__init__)
478 481 if init_ds is not None:
479 482 lines.append(head("Init docstring:"))
480 483 lines.append(indent(init_ds))
481 484 elif hasattr(obj,'__call__'):
482 485 call_ds = getdoc(obj.__call__)
483 486 if call_ds:
484 487 lines.append(head("Call docstring:"))
485 488 lines.append(indent(call_ds))
486 489
487 490 if not lines:
488 491 self.noinfo('documentation',oname)
489 492 else:
490 493 page.page('\n'.join(lines))
491 494
492 495 def psource(self, obj, oname=''):
493 496 """Print the source code for an object."""
494 497
495 498 # Flush the source cache because inspect can return out-of-date source
496 499 linecache.checkcache()
497 500 try:
498 501 src = getsource(obj, oname=oname)
499 502 except Exception:
500 503 src = None
501 504
502 505 if src is None:
503 506 self.noinfo('source', oname)
504 507 else:
505 508 page.page(self.format(src))
506 509
507 510 def pfile(self, obj, oname=''):
508 511 """Show the whole file where an object was defined."""
509 512
510 513 lineno = find_source_lines(obj)
511 514 if lineno is None:
512 515 self.noinfo('file', oname)
513 516 return
514 517
515 518 ofile = find_file(obj)
516 519 # run contents of file through pager starting at line where the object
517 520 # is defined, as long as the file isn't binary and is actually on the
518 521 # filesystem.
519 522 if ofile.endswith(('.so', '.dll', '.pyd')):
520 523 print('File %r is binary, not printing.' % ofile)
521 524 elif not os.path.isfile(ofile):
522 525 print('File %r does not exist, not printing.' % ofile)
523 526 else:
524 527 # Print only text files, not extension binaries. Note that
525 528 # getsourcelines returns lineno with 1-offset and page() uses
526 529 # 0-offset, so we must adjust.
527 530 page.page(self.format(openpy.read_py_file(ofile, skip_encoding_cookie=False)), lineno - 1)
528 531
529 532
530 533 def _mime_format(self, text:str, formatter=None) -> dict:
531 534 """Return a mime bundle representation of the input text.
532 535
533 536 - if `formatter` is None, the returned mime bundle has
534 537 a ``text/plain`` field, with the input text.
535 538 a ``text/html`` field with a ``<pre>`` tag containing the input text.
536 539
537 540 - if ``formatter`` is not None, it must be a callable transforming the
538 541 input text into a mime bundle. Default values for ``text/plain`` and
539 542 ``text/html`` representations are the ones described above.
540 543
541 544 Note:
542 545
543 546 Formatters returning strings are supported but this behavior is deprecated.
544 547
545 548 """
546 549 defaults = {
547 550 "text/plain": text,
548 551 "text/html": f"<pre>{html.escape(text)}</pre>",
549 552 }
550 553
551 554 if formatter is None:
552 555 return defaults
553 556 else:
554 557 formatted = formatter(text)
555 558
556 559 if not isinstance(formatted, dict):
557 560 # Handle the deprecated behavior of a formatter returning
558 561 # a string instead of a mime bundle.
559 562 return {"text/plain": formatted, "text/html": f"<pre>{formatted}</pre>"}
560 563
561 564 else:
562 565 return dict(defaults, **formatted)
563 566
564 567
565 568 def format_mime(self, bundle):
566 569 """Format a mimebundle being created by _make_info_unformatted into a real mimebundle"""
567 570 # Format text/plain mimetype
568 571 if isinstance(bundle["text/plain"], (list, tuple)):
569 572 # bundle['text/plain'] is a list of (head, formatted body) pairs
570 573 lines = []
571 574 _len = max(len(h) for h, _ in bundle["text/plain"])
572 575
573 576 for head, body in bundle["text/plain"]:
574 577 body = body.strip("\n")
575 578 delim = "\n" if "\n" in body else " "
576 579 lines.append(
577 580 f"{self.__head(head+':')}{(_len - len(head))*' '}{delim}{body}"
578 581 )
579 582
580 583 bundle["text/plain"] = "\n".join(lines)
581 584
582 585 # Format the text/html mimetype
583 586 if isinstance(bundle["text/html"], (list, tuple)):
584 587 # bundle['text/html'] is a list of (head, formatted body) pairs
585 588 bundle["text/html"] = "\n".join(
586 589 (f"<h1>{head}</h1>\n{body}" for (head, body) in bundle["text/html"])
587 590 )
588 591 return bundle
589 592
590 593 def _append_info_field(
591 594 self, bundle, title: str, key: str, info, omit_sections, formatter
592 595 ):
593 596 """Append an info value to the unformatted mimebundle being constructed by _make_info_unformatted"""
594 597 if title in omit_sections or key in omit_sections:
595 598 return
596 599 field = info[key]
597 600 if field is not None:
598 601 formatted_field = self._mime_format(field, formatter)
599 602 bundle["text/plain"].append((title, formatted_field["text/plain"]))
600 603 bundle["text/html"].append((title, formatted_field["text/html"]))
601 604
602 605 def _make_info_unformatted(self, obj, info, formatter, detail_level, omit_sections):
603 606 """Assemble the mimebundle as unformatted lists of information"""
604 607 bundle = {
605 608 "text/plain": [],
606 609 "text/html": [],
607 610 }
608 611
609 612 # A convenience function to simplify calls below
610 613 def append_field(bundle, title: str, key: str, formatter=None):
611 614 self._append_info_field(
612 615 bundle,
613 616 title=title,
614 617 key=key,
615 618 info=info,
616 619 omit_sections=omit_sections,
617 620 formatter=formatter,
618 621 )
619 622
620 623 def code_formatter(text):
621 624 return {
622 625 'text/plain': self.format(text),
623 626 'text/html': pylight(text)
624 627 }
625 628
626 629 if info["isalias"]:
627 630 append_field(bundle, "Repr", "string_form")
628 631
629 632 elif info['ismagic']:
630 633 if detail_level > 0:
631 634 append_field(bundle, "Source", "source", code_formatter)
632 635 else:
633 636 append_field(bundle, "Docstring", "docstring", formatter)
634 637 append_field(bundle, "File", "file")
635 638
636 639 elif info['isclass'] or is_simple_callable(obj):
637 640 # Functions, methods, classes
638 641 append_field(bundle, "Signature", "definition", code_formatter)
639 642 append_field(bundle, "Init signature", "init_definition", code_formatter)
640 643 append_field(bundle, "Docstring", "docstring", formatter)
641 644 if detail_level > 0 and info["source"]:
642 645 append_field(bundle, "Source", "source", code_formatter)
643 646 else:
644 647 append_field(bundle, "Init docstring", "init_docstring", formatter)
645 648
646 649 append_field(bundle, "File", "file")
647 650 append_field(bundle, "Type", "type_name")
648 651 append_field(bundle, "Subclasses", "subclasses")
649 652
650 653 else:
651 654 # General Python objects
652 655 append_field(bundle, "Signature", "definition", code_formatter)
653 656 append_field(bundle, "Call signature", "call_def", code_formatter)
654 657 append_field(bundle, "Type", "type_name")
655 658 append_field(bundle, "String form", "string_form")
656 659
657 660 # Namespace
658 661 if info["namespace"] != "Interactive":
659 662 append_field(bundle, "Namespace", "namespace")
660 663
661 664 append_field(bundle, "Length", "length")
662 665 append_field(bundle, "File", "file")
663 666
664 667 # Source or docstring, depending on detail level and whether
665 668 # source found.
666 669 if detail_level > 0 and info["source"]:
667 670 append_field(bundle, "Source", "source", code_formatter)
668 671 else:
669 672 append_field(bundle, "Docstring", "docstring", formatter)
670 673
671 674 append_field(bundle, "Class docstring", "class_docstring", formatter)
672 675 append_field(bundle, "Init docstring", "init_docstring", formatter)
673 676 append_field(bundle, "Call docstring", "call_docstring", formatter)
674 677 return bundle
675 678
676 679
677 680 def _get_info(
678 681 self, obj, oname="", formatter=None, info=None, detail_level=0, omit_sections=()
679 682 ):
680 683 """Retrieve an info dict and format it.
681 684
682 685 Parameters
683 686 ----------
684 687 obj : any
685 688 Object to inspect and return info from
686 689 oname : str (default: ''):
687 690 Name of the variable pointing to `obj`.
688 691 formatter : callable
689 692 info
690 693 already computed information
691 694 detail_level : integer
692 695 Granularity of detail level, if set to 1, give more information.
693 696 omit_sections : container[str]
694 697 Titles or keys to omit from output (can be set, tuple, etc., anything supporting `in`)
695 698 """
696 699
697 700 info = self.info(obj, oname=oname, info=info, detail_level=detail_level)
698 701 bundle = self._make_info_unformatted(
699 702 obj, info, formatter, detail_level=detail_level, omit_sections=omit_sections
700 703 )
701 704 return self.format_mime(bundle)
702 705
703 706 def pinfo(
704 707 self,
705 708 obj,
706 709 oname="",
707 710 formatter=None,
708 711 info=None,
709 712 detail_level=0,
710 713 enable_html_pager=True,
711 714 omit_sections=(),
712 715 ):
713 716 """Show detailed information about an object.
714 717
715 718 Optional arguments:
716 719
717 720 - oname: name of the variable pointing to the object.
718 721
719 722 - formatter: callable (optional)
720 723 A special formatter for docstrings.
721 724
722 725 The formatter is a callable that takes a string as an input
723 726 and returns either a formatted string or a mime type bundle
724 727 in the form of a dictionary.
725 728
726 729 Although the support of custom formatter returning a string
727 730 instead of a mime type bundle is deprecated.
728 731
729 732 - info: a structure with some information fields which may have been
730 733 precomputed already.
731 734
732 735 - detail_level: if set to 1, more information is given.
733 736
734 737 - omit_sections: set of section keys and titles to omit
735 738 """
736 739 info = self._get_info(
737 740 obj, oname, formatter, info, detail_level, omit_sections=omit_sections
738 741 )
739 742 if not enable_html_pager:
740 743 del info['text/html']
741 744 page.page(info)
742 745
743 746 def _info(self, obj, oname="", info=None, detail_level=0):
744 747 """
745 748 Inspector.info() was likely improperly marked as deprecated
746 749 while only a parameter was deprecated. We "un-deprecate" it.
747 750 """
748 751
749 752 warnings.warn(
750 753 "The `Inspector.info()` method has been un-deprecated as of 8.0 "
751 754 "and the `formatter=` keyword removed. `Inspector._info` is now "
752 755 "an alias, and you can just call `.info()` directly.",
753 756 DeprecationWarning,
754 757 stacklevel=2,
755 758 )
756 759 return self.info(obj, oname=oname, info=info, detail_level=detail_level)
757 760
758 761 def info(self, obj, oname="", info=None, detail_level=0) -> dict:
759 762 """Compute a dict with detailed information about an object.
760 763
761 764 Parameters
762 765 ----------
763 766 obj : any
764 767 An object to find information about
765 768 oname : str (default: '')
766 769 Name of the variable pointing to `obj`.
767 770 info : (default: None)
768 771 A struct (dict like with attr access) with some information fields
769 772 which may have been precomputed already.
770 773 detail_level : int (default:0)
771 774 If set to 1, more information is given.
772 775
773 776 Returns
774 777 -------
775 778 An object info dict with known fields from `info_fields`. Keys are
776 779 strings, values are string or None.
777 780 """
778 781
779 782 if info is None:
780 783 ismagic = False
781 784 isalias = False
782 785 ospace = ''
783 786 else:
784 787 ismagic = info.ismagic
785 788 isalias = info.isalias
786 789 ospace = info.namespace
787 790
788 791 # Get docstring, special-casing aliases:
789 792 if isalias:
790 793 if not callable(obj):
791 794 try:
792 795 ds = "Alias to the system command:\n %s" % obj[1]
793 796 except:
794 797 ds = "Alias: " + str(obj)
795 798 else:
796 799 ds = "Alias to " + str(obj)
797 800 if obj.__doc__:
798 801 ds += "\nDocstring:\n" + obj.__doc__
799 802 else:
800 ds = getdoc(obj)
801 if ds is None:
803 ds_or_None = getdoc(obj)
804 if ds_or_None is None:
802 805 ds = '<no docstring>'
806 else:
807 ds = ds_or_None
803 808
804 809 # store output in a dict, we initialize it here and fill it as we go
805 810 out = dict(name=oname, found=True, isalias=isalias, ismagic=ismagic, subclasses=None)
806 811
807 812 string_max = 200 # max size of strings to show (snipped if longer)
808 813 shalf = int((string_max - 5) / 2)
809 814
810 815 if ismagic:
811 816 out['type_name'] = 'Magic function'
812 817 elif isalias:
813 818 out['type_name'] = 'System alias'
814 819 else:
815 820 out['type_name'] = type(obj).__name__
816 821
817 822 try:
818 823 bclass = obj.__class__
819 824 out['base_class'] = str(bclass)
820 825 except:
821 826 pass
822 827
823 828 # String form, but snip if too long in ? form (full in ??)
824 829 if detail_level >= self.str_detail_level:
825 830 try:
826 831 ostr = str(obj)
827 832 str_head = 'string_form'
828 833 if not detail_level and len(ostr)>string_max:
829 834 ostr = ostr[:shalf] + ' <...> ' + ostr[-shalf:]
830 835 ostr = ("\n" + " " * len(str_head.expandtabs())).\
831 836 join(q.strip() for q in ostr.split("\n"))
832 837 out[str_head] = ostr
833 838 except:
834 839 pass
835 840
836 841 if ospace:
837 842 out['namespace'] = ospace
838 843
839 844 # Length (for strings and lists)
840 845 try:
841 846 out['length'] = str(len(obj))
842 847 except Exception:
843 848 pass
844 849
845 850 # Filename where object was defined
846 851 binary_file = False
847 852 fname = find_file(obj)
848 853 if fname is None:
849 854 # if anything goes wrong, we don't want to show source, so it's as
850 855 # if the file was binary
851 856 binary_file = True
852 857 else:
853 858 if fname.endswith(('.so', '.dll', '.pyd')):
854 859 binary_file = True
855 860 elif fname.endswith('<string>'):
856 861 fname = 'Dynamically generated function. No source code available.'
857 862 out['file'] = compress_user(fname)
858 863
859 864 # Original source code for a callable, class or property.
860 865 if detail_level:
861 866 # Flush the source cache because inspect can return out-of-date
862 867 # source
863 868 linecache.checkcache()
864 869 try:
865 870 if isinstance(obj, property) or not binary_file:
866 871 src = getsource(obj, oname)
867 872 if src is not None:
868 873 src = src.rstrip()
869 874 out['source'] = src
870 875
871 876 except Exception:
872 877 pass
873 878
874 879 # Add docstring only if no source is to be shown (avoid repetitions).
875 880 if ds and not self._source_contains_docstring(out.get('source'), ds):
876 881 out['docstring'] = ds
877 882
878 883 # Constructor docstring for classes
879 884 if inspect.isclass(obj):
880 885 out['isclass'] = True
881 886
882 887 # get the init signature:
883 888 try:
884 889 init_def = self._getdef(obj, oname)
885 890 except AttributeError:
886 891 init_def = None
887 892
888 893 # get the __init__ docstring
889 894 try:
890 895 obj_init = obj.__init__
891 896 except AttributeError:
892 897 init_ds = None
893 898 else:
894 899 if init_def is None:
895 900 # Get signature from init if top-level sig failed.
896 901 # Can happen for built-in types (list, etc.).
897 902 try:
898 903 init_def = self._getdef(obj_init, oname)
899 904 except AttributeError:
900 905 pass
901 906 init_ds = getdoc(obj_init)
902 907 # Skip Python's auto-generated docstrings
903 908 if init_ds == _object_init_docstring:
904 909 init_ds = None
905 910
906 911 if init_def:
907 912 out['init_definition'] = init_def
908 913
909 914 if init_ds:
910 915 out['init_docstring'] = init_ds
911 916
912 917 names = [sub.__name__ for sub in type.__subclasses__(obj)]
913 918 if len(names) < 10:
914 919 all_names = ', '.join(names)
915 920 else:
916 921 all_names = ', '.join(names[:10]+['...'])
917 922 out['subclasses'] = all_names
918 923 # and class docstring for instances:
919 924 else:
920 925 # reconstruct the function definition and print it:
921 926 defln = self._getdef(obj, oname)
922 927 if defln:
923 928 out['definition'] = defln
924 929
925 930 # First, check whether the instance docstring is identical to the
926 931 # class one, and print it separately if they don't coincide. In
927 932 # most cases they will, but it's nice to print all the info for
928 933 # objects which use instance-customized docstrings.
929 934 if ds:
930 935 try:
931 936 cls = getattr(obj,'__class__')
932 937 except:
933 938 class_ds = None
934 939 else:
935 940 class_ds = getdoc(cls)
936 941 # Skip Python's auto-generated docstrings
937 942 if class_ds in _builtin_type_docstrings:
938 943 class_ds = None
939 944 if class_ds and ds != class_ds:
940 945 out['class_docstring'] = class_ds
941 946
942 947 # Next, try to show constructor docstrings
943 948 try:
944 949 init_ds = getdoc(obj.__init__)
945 950 # Skip Python's auto-generated docstrings
946 951 if init_ds == _object_init_docstring:
947 952 init_ds = None
948 953 except AttributeError:
949 954 init_ds = None
950 955 if init_ds:
951 956 out['init_docstring'] = init_ds
952 957
953 958 # Call form docstring for callable instances
954 959 if safe_hasattr(obj, '__call__') and not is_simple_callable(obj):
955 960 call_def = self._getdef(obj.__call__, oname)
956 961 if call_def and (call_def != out.get('definition')):
957 962 # it may never be the case that call def and definition differ,
958 963 # but don't include the same signature twice
959 964 out['call_def'] = call_def
960 965 call_ds = getdoc(obj.__call__)
961 966 # Skip Python's auto-generated docstrings
962 967 if call_ds == _func_call_docstring:
963 968 call_ds = None
964 969 if call_ds:
965 970 out['call_docstring'] = call_ds
966 971
967 972 return object_info(**out)
968 973
969 974 @staticmethod
970 975 def _source_contains_docstring(src, doc):
971 976 """
972 977 Check whether the source *src* contains the docstring *doc*.
973 978
974 979 This is is helper function to skip displaying the docstring if the
975 980 source already contains it, avoiding repetition of information.
976 981 """
977 982 try:
978 983 def_node, = ast.parse(dedent(src)).body
979 984 return ast.get_docstring(def_node) == doc
980 985 except Exception:
981 986 # The source can become invalid or even non-existent (because it
982 987 # is re-fetched from the source file) so the above code fail in
983 988 # arbitrary ways.
984 989 return False
985 990
986 991 def psearch(self,pattern,ns_table,ns_search=[],
987 992 ignore_case=False,show_all=False, *, list_types=False):
988 993 """Search namespaces with wildcards for objects.
989 994
990 995 Arguments:
991 996
992 997 - pattern: string containing shell-like wildcards to use in namespace
993 998 searches and optionally a type specification to narrow the search to
994 999 objects of that type.
995 1000
996 1001 - ns_table: dict of name->namespaces for search.
997 1002
998 1003 Optional arguments:
999 1004
1000 1005 - ns_search: list of namespace names to include in search.
1001 1006
1002 1007 - ignore_case(False): make the search case-insensitive.
1003 1008
1004 1009 - show_all(False): show all names, including those starting with
1005 1010 underscores.
1006 1011
1007 1012 - list_types(False): list all available object types for object matching.
1008 1013 """
1009 1014 #print 'ps pattern:<%r>' % pattern # dbg
1010 1015
1011 1016 # defaults
1012 1017 type_pattern = 'all'
1013 1018 filter = ''
1014 1019
1015 1020 # list all object types
1016 1021 if list_types:
1017 1022 page.page('\n'.join(sorted(typestr2type)))
1018 1023 return
1019 1024
1020 1025 cmds = pattern.split()
1021 1026 len_cmds = len(cmds)
1022 1027 if len_cmds == 1:
1023 1028 # Only filter pattern given
1024 1029 filter = cmds[0]
1025 1030 elif len_cmds == 2:
1026 1031 # Both filter and type specified
1027 1032 filter,type_pattern = cmds
1028 1033 else:
1029 1034 raise ValueError('invalid argument string for psearch: <%s>' %
1030 1035 pattern)
1031 1036
1032 1037 # filter search namespaces
1033 1038 for name in ns_search:
1034 1039 if name not in ns_table:
1035 1040 raise ValueError('invalid namespace <%s>. Valid names: %s' %
1036 1041 (name,ns_table.keys()))
1037 1042
1038 1043 #print 'type_pattern:',type_pattern # dbg
1039 1044 search_result, namespaces_seen = set(), set()
1040 1045 for ns_name in ns_search:
1041 1046 ns = ns_table[ns_name]
1042 1047 # Normally, locals and globals are the same, so we just check one.
1043 1048 if id(ns) in namespaces_seen:
1044 1049 continue
1045 1050 namespaces_seen.add(id(ns))
1046 1051 tmp_res = list_namespace(ns, type_pattern, filter,
1047 1052 ignore_case=ignore_case, show_all=show_all)
1048 1053 search_result.update(tmp_res)
1049 1054
1050 1055 page.page('\n'.join(sorted(search_result)))
1051 1056
1052 1057
1053 1058 def _render_signature(obj_signature, obj_name) -> str:
1054 1059 """
1055 1060 This was mostly taken from inspect.Signature.__str__.
1056 1061 Look there for the comments.
1057 1062 The only change is to add linebreaks when this gets too long.
1058 1063 """
1059 1064 result = []
1060 1065 pos_only = False
1061 1066 kw_only = True
1062 1067 for param in obj_signature.parameters.values():
1063 if param.kind == inspect._POSITIONAL_ONLY:
1068 if param.kind == inspect.Parameter.POSITIONAL_ONLY:
1064 1069 pos_only = True
1065 1070 elif pos_only:
1066 1071 result.append('/')
1067 1072 pos_only = False
1068 1073
1069 if param.kind == inspect._VAR_POSITIONAL:
1074 if param.kind == inspect.Parameter.VAR_POSITIONAL:
1070 1075 kw_only = False
1071 elif param.kind == inspect._KEYWORD_ONLY and kw_only:
1076 elif param.kind == inspect.Parameter.KEYWORD_ONLY and kw_only:
1072 1077 result.append('*')
1073 1078 kw_only = False
1074 1079
1075 1080 result.append(str(param))
1076 1081
1077 1082 if pos_only:
1078 1083 result.append('/')
1079 1084
1080 1085 # add up name, parameters, braces (2), and commas
1081 1086 if len(obj_name) + sum(len(r) + 2 for r in result) > 75:
1082 1087 # This doesn’t fit behind “Signature: ” in an inspect window.
1083 1088 rendered = '{}(\n{})'.format(obj_name, ''.join(
1084 1089 ' {},\n'.format(r) for r in result)
1085 1090 )
1086 1091 else:
1087 1092 rendered = '{}({})'.format(obj_name, ', '.join(result))
1088 1093
1089 1094 if obj_signature.return_annotation is not inspect._empty:
1090 1095 anno = inspect.formatannotation(obj_signature.return_annotation)
1091 1096 rendered += ' -> {}'.format(anno)
1092 1097
1093 1098 return rendered
@@ -1,1200 +1,1200 b''
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 import pytest
21 21 from unittest import mock
22 22
23 23 from os.path import join
24 24
25 25 from IPython.core.error import InputRejected
26 26 from IPython.core.inputtransformer import InputTransformer
27 27 from IPython.core import interactiveshell
28 28 from IPython.core.oinspect import OInfo
29 29 from IPython.testing.decorators import (
30 30 skipif, skip_win32, onlyif_unicode_paths, onlyif_cmds_exist,
31 31 )
32 32 from IPython.testing import tools as tt
33 33 from IPython.utils.process import find_cmd
34 34
35 35 #-----------------------------------------------------------------------------
36 36 # Globals
37 37 #-----------------------------------------------------------------------------
38 38 # This is used by every single test, no point repeating it ad nauseam
39 39
40 40 #-----------------------------------------------------------------------------
41 41 # Tests
42 42 #-----------------------------------------------------------------------------
43 43
44 44 class DerivedInterrupt(KeyboardInterrupt):
45 45 pass
46 46
47 47 class InteractiveShellTestCase(unittest.TestCase):
48 48 def test_naked_string_cells(self):
49 49 """Test that cells with only naked strings are fully executed"""
50 50 # First, single-line inputs
51 51 ip.run_cell('"a"\n')
52 52 self.assertEqual(ip.user_ns['_'], 'a')
53 53 # And also multi-line cells
54 54 ip.run_cell('"""a\nb"""\n')
55 55 self.assertEqual(ip.user_ns['_'], 'a\nb')
56 56
57 57 def test_run_empty_cell(self):
58 58 """Just make sure we don't get a horrible error with a blank
59 59 cell of input. Yes, I did overlook that."""
60 60 old_xc = ip.execution_count
61 61 res = ip.run_cell('')
62 62 self.assertEqual(ip.execution_count, old_xc)
63 63 self.assertEqual(res.execution_count, None)
64 64
65 65 def test_run_cell_multiline(self):
66 66 """Multi-block, multi-line cells must execute correctly.
67 67 """
68 68 src = '\n'.join(["x=1",
69 69 "y=2",
70 70 "if 1:",
71 71 " x += 1",
72 72 " y += 1",])
73 73 res = ip.run_cell(src)
74 74 self.assertEqual(ip.user_ns['x'], 2)
75 75 self.assertEqual(ip.user_ns['y'], 3)
76 76 self.assertEqual(res.success, True)
77 77 self.assertEqual(res.result, None)
78 78
79 79 def test_multiline_string_cells(self):
80 80 "Code sprinkled with multiline strings should execute (GH-306)"
81 81 ip.run_cell('tmp=0')
82 82 self.assertEqual(ip.user_ns['tmp'], 0)
83 83 res = ip.run_cell('tmp=1;"""a\nb"""\n')
84 84 self.assertEqual(ip.user_ns['tmp'], 1)
85 85 self.assertEqual(res.success, True)
86 86 self.assertEqual(res.result, "a\nb")
87 87
88 88 def test_dont_cache_with_semicolon(self):
89 89 "Ending a line with semicolon should not cache the returned object (GH-307)"
90 90 oldlen = len(ip.user_ns['Out'])
91 91 for cell in ['1;', '1;1;']:
92 92 res = ip.run_cell(cell, store_history=True)
93 93 newlen = len(ip.user_ns['Out'])
94 94 self.assertEqual(oldlen, newlen)
95 95 self.assertIsNone(res.result)
96 96 i = 0
97 97 #also test the default caching behavior
98 98 for cell in ['1', '1;1']:
99 99 ip.run_cell(cell, store_history=True)
100 100 newlen = len(ip.user_ns['Out'])
101 101 i += 1
102 102 self.assertEqual(oldlen+i, newlen)
103 103
104 104 def test_syntax_error(self):
105 105 res = ip.run_cell("raise = 3")
106 106 self.assertIsInstance(res.error_before_exec, SyntaxError)
107 107
108 108 def test_open_standard_input_stream(self):
109 109 res = ip.run_cell("open(0)")
110 110 self.assertIsInstance(res.error_in_exec, ValueError)
111 111
112 112 def test_open_standard_output_stream(self):
113 113 res = ip.run_cell("open(1)")
114 114 self.assertIsInstance(res.error_in_exec, ValueError)
115 115
116 116 def test_open_standard_error_stream(self):
117 117 res = ip.run_cell("open(2)")
118 118 self.assertIsInstance(res.error_in_exec, ValueError)
119 119
120 120 def test_In_variable(self):
121 121 "Verify that In variable grows with user input (GH-284)"
122 122 oldlen = len(ip.user_ns['In'])
123 123 ip.run_cell('1;', store_history=True)
124 124 newlen = len(ip.user_ns['In'])
125 125 self.assertEqual(oldlen+1, newlen)
126 126 self.assertEqual(ip.user_ns['In'][-1],'1;')
127 127
128 128 def test_magic_names_in_string(self):
129 129 ip.run_cell('a = """\n%exit\n"""')
130 130 self.assertEqual(ip.user_ns['a'], '\n%exit\n')
131 131
132 132 def test_trailing_newline(self):
133 133 """test that running !(command) does not raise a SyntaxError"""
134 134 ip.run_cell('!(true)\n', False)
135 135 ip.run_cell('!(true)\n\n\n', False)
136 136
137 137 def test_gh_597(self):
138 138 """Pretty-printing lists of objects with non-ascii reprs may cause
139 139 problems."""
140 140 class Spam(object):
141 141 def __repr__(self):
142 142 return "\xe9"*50
143 143 import IPython.core.formatters
144 144 f = IPython.core.formatters.PlainTextFormatter()
145 145 f([Spam(),Spam()])
146 146
147 147
148 148 def test_future_flags(self):
149 149 """Check that future flags are used for parsing code (gh-777)"""
150 150 ip.run_cell('from __future__ import barry_as_FLUFL')
151 151 try:
152 152 ip.run_cell('prfunc_return_val = 1 <> 2')
153 153 assert 'prfunc_return_val' in ip.user_ns
154 154 finally:
155 155 # Reset compiler flags so we don't mess up other tests.
156 156 ip.compile.reset_compiler_flags()
157 157
158 158 def test_can_pickle(self):
159 159 "Can we pickle objects defined interactively (GH-29)"
160 160 ip = get_ipython()
161 161 ip.reset()
162 162 ip.run_cell(("class Mylist(list):\n"
163 163 " def __init__(self,x=[]):\n"
164 164 " list.__init__(self,x)"))
165 165 ip.run_cell("w=Mylist([1,2,3])")
166 166
167 167 from pickle import dumps
168 168
169 169 # We need to swap in our main module - this is only necessary
170 170 # inside the test framework, because IPython puts the interactive module
171 171 # in place (but the test framework undoes this).
172 172 _main = sys.modules['__main__']
173 173 sys.modules['__main__'] = ip.user_module
174 174 try:
175 175 res = dumps(ip.user_ns["w"])
176 176 finally:
177 177 sys.modules['__main__'] = _main
178 178 self.assertTrue(isinstance(res, bytes))
179 179
180 180 def test_global_ns(self):
181 181 "Code in functions must be able to access variables outside them."
182 182 ip = get_ipython()
183 183 ip.run_cell("a = 10")
184 184 ip.run_cell(("def f(x):\n"
185 185 " return x + a"))
186 186 ip.run_cell("b = f(12)")
187 187 self.assertEqual(ip.user_ns["b"], 22)
188 188
189 189 def test_bad_custom_tb(self):
190 190 """Check that InteractiveShell is protected from bad custom exception handlers"""
191 191 ip.set_custom_exc((IOError,), lambda etype,value,tb: 1/0)
192 192 self.assertEqual(ip.custom_exceptions, (IOError,))
193 193 with tt.AssertPrints("Custom TB Handler failed", channel='stderr'):
194 194 ip.run_cell(u'raise IOError("foo")')
195 195 self.assertEqual(ip.custom_exceptions, ())
196 196
197 197 def test_bad_custom_tb_return(self):
198 198 """Check that InteractiveShell is protected from bad return types in custom exception handlers"""
199 199 ip.set_custom_exc((NameError,),lambda etype,value,tb, tb_offset=None: 1)
200 200 self.assertEqual(ip.custom_exceptions, (NameError,))
201 201 with tt.AssertPrints("Custom TB Handler failed", channel='stderr'):
202 202 ip.run_cell(u'a=abracadabra')
203 203 self.assertEqual(ip.custom_exceptions, ())
204 204
205 205 def test_drop_by_id(self):
206 206 myvars = {"a":object(), "b":object(), "c": object()}
207 207 ip.push(myvars, interactive=False)
208 208 for name in myvars:
209 209 assert name in ip.user_ns, name
210 210 assert name in ip.user_ns_hidden, name
211 211 ip.user_ns['b'] = 12
212 212 ip.drop_by_id(myvars)
213 213 for name in ["a", "c"]:
214 214 assert name not in ip.user_ns, name
215 215 assert name not in ip.user_ns_hidden, name
216 216 assert ip.user_ns['b'] == 12
217 217 ip.reset()
218 218
219 219 def test_var_expand(self):
220 220 ip.user_ns['f'] = u'Ca\xf1o'
221 221 self.assertEqual(ip.var_expand(u'echo $f'), u'echo Ca\xf1o')
222 222 self.assertEqual(ip.var_expand(u'echo {f}'), u'echo Ca\xf1o')
223 223 self.assertEqual(ip.var_expand(u'echo {f[:-1]}'), u'echo Ca\xf1')
224 224 self.assertEqual(ip.var_expand(u'echo {1*2}'), u'echo 2')
225 225
226 226 self.assertEqual(ip.var_expand(u"grep x | awk '{print $1}'"), u"grep x | awk '{print $1}'")
227 227
228 228 ip.user_ns['f'] = b'Ca\xc3\xb1o'
229 229 # This should not raise any exception:
230 230 ip.var_expand(u'echo $f')
231 231
232 232 def test_var_expand_local(self):
233 233 """Test local variable expansion in !system and %magic calls"""
234 234 # !system
235 235 ip.run_cell(
236 236 "def test():\n"
237 237 ' lvar = "ttt"\n'
238 238 " ret = !echo {lvar}\n"
239 239 " return ret[0]\n"
240 240 )
241 241 res = ip.user_ns["test"]()
242 242 self.assertIn("ttt", res)
243 243
244 244 # %magic
245 245 ip.run_cell(
246 246 "def makemacro():\n"
247 247 ' macroname = "macro_var_expand_locals"\n'
248 248 " %macro {macroname} codestr\n"
249 249 )
250 250 ip.user_ns["codestr"] = "str(12)"
251 251 ip.run_cell("makemacro()")
252 252 self.assertIn("macro_var_expand_locals", ip.user_ns)
253 253
254 254 def test_var_expand_self(self):
255 255 """Test variable expansion with the name 'self', which was failing.
256 256
257 257 See https://github.com/ipython/ipython/issues/1878#issuecomment-7698218
258 258 """
259 259 ip.run_cell(
260 260 "class cTest:\n"
261 261 ' classvar="see me"\n'
262 262 " def test(self):\n"
263 263 " res = !echo Variable: {self.classvar}\n"
264 264 " return res[0]\n"
265 265 )
266 266 self.assertIn("see me", ip.user_ns["cTest"]().test())
267 267
268 268 def test_bad_var_expand(self):
269 269 """var_expand on invalid formats shouldn't raise"""
270 270 # SyntaxError
271 271 self.assertEqual(ip.var_expand(u"{'a':5}"), u"{'a':5}")
272 272 # NameError
273 273 self.assertEqual(ip.var_expand(u"{asdf}"), u"{asdf}")
274 274 # ZeroDivisionError
275 275 self.assertEqual(ip.var_expand(u"{1/0}"), u"{1/0}")
276 276
277 277 def test_silent_postexec(self):
278 278 """run_cell(silent=True) doesn't invoke pre/post_run_cell callbacks"""
279 279 pre_explicit = mock.Mock()
280 280 pre_always = mock.Mock()
281 281 post_explicit = mock.Mock()
282 282 post_always = mock.Mock()
283 283 all_mocks = [pre_explicit, pre_always, post_explicit, post_always]
284 284
285 285 ip.events.register('pre_run_cell', pre_explicit)
286 286 ip.events.register('pre_execute', pre_always)
287 287 ip.events.register('post_run_cell', post_explicit)
288 288 ip.events.register('post_execute', post_always)
289 289
290 290 try:
291 291 ip.run_cell("1", silent=True)
292 292 assert pre_always.called
293 293 assert not pre_explicit.called
294 294 assert post_always.called
295 295 assert not post_explicit.called
296 296 # double-check that non-silent exec did what we expected
297 297 # silent to avoid
298 298 ip.run_cell("1")
299 299 assert pre_explicit.called
300 300 assert post_explicit.called
301 301 info, = pre_explicit.call_args[0]
302 302 result, = post_explicit.call_args[0]
303 303 self.assertEqual(info, result.info)
304 304 # check that post hooks are always called
305 305 [m.reset_mock() for m in all_mocks]
306 306 ip.run_cell("syntax error")
307 307 assert pre_always.called
308 308 assert pre_explicit.called
309 309 assert post_always.called
310 310 assert post_explicit.called
311 311 info, = pre_explicit.call_args[0]
312 312 result, = post_explicit.call_args[0]
313 313 self.assertEqual(info, result.info)
314 314 finally:
315 315 # remove post-exec
316 316 ip.events.unregister('pre_run_cell', pre_explicit)
317 317 ip.events.unregister('pre_execute', pre_always)
318 318 ip.events.unregister('post_run_cell', post_explicit)
319 319 ip.events.unregister('post_execute', post_always)
320 320
321 321 def test_silent_noadvance(self):
322 322 """run_cell(silent=True) doesn't advance execution_count"""
323 323 ec = ip.execution_count
324 324 # silent should force store_history=False
325 325 ip.run_cell("1", store_history=True, silent=True)
326 326
327 327 self.assertEqual(ec, ip.execution_count)
328 328 # double-check that non-silent exec did what we expected
329 329 # silent to avoid
330 330 ip.run_cell("1", store_history=True)
331 331 self.assertEqual(ec+1, ip.execution_count)
332 332
333 333 def test_silent_nodisplayhook(self):
334 334 """run_cell(silent=True) doesn't trigger displayhook"""
335 335 d = dict(called=False)
336 336
337 337 trap = ip.display_trap
338 338 save_hook = trap.hook
339 339
340 340 def failing_hook(*args, **kwargs):
341 341 d['called'] = True
342 342
343 343 try:
344 344 trap.hook = failing_hook
345 345 res = ip.run_cell("1", silent=True)
346 346 self.assertFalse(d['called'])
347 347 self.assertIsNone(res.result)
348 348 # double-check that non-silent exec did what we expected
349 349 # silent to avoid
350 350 ip.run_cell("1")
351 351 self.assertTrue(d['called'])
352 352 finally:
353 353 trap.hook = save_hook
354 354
355 355 def test_ofind_line_magic(self):
356 356 from IPython.core.magic import register_line_magic
357 357
358 358 @register_line_magic
359 359 def lmagic(line):
360 360 "A line magic"
361 361
362 362 # Get info on line magic
363 363 lfind = ip._ofind("lmagic")
364 364 info = OInfo(
365 365 found=True,
366 366 isalias=False,
367 367 ismagic=True,
368 368 namespace="IPython internal",
369 369 obj=lmagic,
370 370 parent=None,
371 371 )
372 372 self.assertEqual(lfind, info)
373 373
374 374 def test_ofind_cell_magic(self):
375 375 from IPython.core.magic import register_cell_magic
376 376
377 377 @register_cell_magic
378 378 def cmagic(line, cell):
379 379 "A cell magic"
380 380
381 381 # Get info on cell magic
382 382 find = ip._ofind("cmagic")
383 383 info = OInfo(
384 384 found=True,
385 385 isalias=False,
386 386 ismagic=True,
387 387 namespace="IPython internal",
388 388 obj=cmagic,
389 389 parent=None,
390 390 )
391 391 self.assertEqual(find, info)
392 392
393 393 def test_ofind_property_with_error(self):
394 394 class A(object):
395 395 @property
396 396 def foo(self):
397 397 raise NotImplementedError() # pragma: no cover
398 398
399 399 a = A()
400 400
401 401 found = ip._ofind("a.foo", [("locals", locals())])
402 402 info = OInfo(
403 403 found=True,
404 404 isalias=False,
405 405 ismagic=False,
406 406 namespace="locals",
407 407 obj=A.foo,
408 408 parent=a,
409 409 )
410 410 self.assertEqual(found, info)
411 411
412 412 def test_ofind_multiple_attribute_lookups(self):
413 413 class A(object):
414 414 @property
415 415 def foo(self):
416 416 raise NotImplementedError() # pragma: no cover
417 417
418 418 a = A()
419 419 a.a = A()
420 420 a.a.a = A()
421 421
422 422 found = ip._ofind("a.a.a.foo", [("locals", locals())])
423 423 info = OInfo(
424 424 found=True,
425 425 isalias=False,
426 426 ismagic=False,
427 427 namespace="locals",
428 428 obj=A.foo,
429 429 parent=a.a.a,
430 430 )
431 431 self.assertEqual(found, info)
432 432
433 433 def test_ofind_slotted_attributes(self):
434 434 class A(object):
435 435 __slots__ = ['foo']
436 436 def __init__(self):
437 437 self.foo = 'bar'
438 438
439 439 a = A()
440 440 found = ip._ofind("a.foo", [("locals", locals())])
441 441 info = OInfo(
442 442 found=True,
443 443 isalias=False,
444 444 ismagic=False,
445 445 namespace="locals",
446 446 obj=a.foo,
447 447 parent=a,
448 448 )
449 449 self.assertEqual(found, info)
450 450
451 451 found = ip._ofind("a.bar", [("locals", locals())])
452 info = OInfo(
452 expected = OInfo(
453 453 found=False,
454 454 isalias=False,
455 455 ismagic=False,
456 456 namespace=None,
457 457 obj=None,
458 458 parent=a,
459 459 )
460 self.assertEqual(found, info)
460 assert found == expected
461 461
462 462 def test_ofind_prefers_property_to_instance_level_attribute(self):
463 463 class A(object):
464 464 @property
465 465 def foo(self):
466 466 return 'bar'
467 467 a = A()
468 468 a.__dict__["foo"] = "baz"
469 469 self.assertEqual(a.foo, "bar")
470 470 found = ip._ofind("a.foo", [("locals", locals())])
471 471 self.assertIs(found.obj, A.foo)
472 472
473 473 def test_custom_syntaxerror_exception(self):
474 474 called = []
475 475 def my_handler(shell, etype, value, tb, tb_offset=None):
476 476 called.append(etype)
477 477 shell.showtraceback((etype, value, tb), tb_offset=tb_offset)
478 478
479 479 ip.set_custom_exc((SyntaxError,), my_handler)
480 480 try:
481 481 ip.run_cell("1f")
482 482 # Check that this was called, and only once.
483 483 self.assertEqual(called, [SyntaxError])
484 484 finally:
485 485 # Reset the custom exception hook
486 486 ip.set_custom_exc((), None)
487 487
488 488 def test_custom_exception(self):
489 489 called = []
490 490 def my_handler(shell, etype, value, tb, tb_offset=None):
491 491 called.append(etype)
492 492 shell.showtraceback((etype, value, tb), tb_offset=tb_offset)
493 493
494 494 ip.set_custom_exc((ValueError,), my_handler)
495 495 try:
496 496 res = ip.run_cell("raise ValueError('test')")
497 497 # Check that this was called, and only once.
498 498 self.assertEqual(called, [ValueError])
499 499 # Check that the error is on the result object
500 500 self.assertIsInstance(res.error_in_exec, ValueError)
501 501 finally:
502 502 # Reset the custom exception hook
503 503 ip.set_custom_exc((), None)
504 504
505 505 @mock.patch("builtins.print")
506 506 def test_showtraceback_with_surrogates(self, mocked_print):
507 507 values = []
508 508
509 509 def mock_print_func(value, sep=" ", end="\n", file=sys.stdout, flush=False):
510 510 values.append(value)
511 511 if value == chr(0xD8FF):
512 512 raise UnicodeEncodeError("utf-8", chr(0xD8FF), 0, 1, "")
513 513
514 514 # mock builtins.print
515 515 mocked_print.side_effect = mock_print_func
516 516
517 517 # ip._showtraceback() is replaced in globalipapp.py.
518 518 # Call original method to test.
519 519 interactiveshell.InteractiveShell._showtraceback(ip, None, None, chr(0xD8FF))
520 520
521 521 self.assertEqual(mocked_print.call_count, 2)
522 522 self.assertEqual(values, [chr(0xD8FF), "\\ud8ff"])
523 523
524 524 def test_mktempfile(self):
525 525 filename = ip.mktempfile()
526 526 # Check that we can open the file again on Windows
527 527 with open(filename, "w", encoding="utf-8") as f:
528 528 f.write("abc")
529 529
530 530 filename = ip.mktempfile(data="blah")
531 531 with open(filename, "r", encoding="utf-8") as f:
532 532 self.assertEqual(f.read(), "blah")
533 533
534 534 def test_new_main_mod(self):
535 535 # Smoketest to check that this accepts a unicode module name
536 536 name = u'jiefmw'
537 537 mod = ip.new_main_mod(u'%s.py' % name, name)
538 538 self.assertEqual(mod.__name__, name)
539 539
540 540 def test_get_exception_only(self):
541 541 try:
542 542 raise KeyboardInterrupt
543 543 except KeyboardInterrupt:
544 544 msg = ip.get_exception_only()
545 545 self.assertEqual(msg, 'KeyboardInterrupt\n')
546 546
547 547 try:
548 548 raise DerivedInterrupt("foo")
549 549 except KeyboardInterrupt:
550 550 msg = ip.get_exception_only()
551 551 self.assertEqual(msg, 'IPython.core.tests.test_interactiveshell.DerivedInterrupt: foo\n')
552 552
553 553 def test_inspect_text(self):
554 554 ip.run_cell('a = 5')
555 555 text = ip.object_inspect_text('a')
556 556 self.assertIsInstance(text, str)
557 557
558 558 def test_last_execution_result(self):
559 559 """ Check that last execution result gets set correctly (GH-10702) """
560 560 result = ip.run_cell('a = 5; a')
561 561 self.assertTrue(ip.last_execution_succeeded)
562 562 self.assertEqual(ip.last_execution_result.result, 5)
563 563
564 564 result = ip.run_cell('a = x_invalid_id_x')
565 565 self.assertFalse(ip.last_execution_succeeded)
566 566 self.assertFalse(ip.last_execution_result.success)
567 567 self.assertIsInstance(ip.last_execution_result.error_in_exec, NameError)
568 568
569 569 def test_reset_aliasing(self):
570 570 """ Check that standard posix aliases work after %reset. """
571 571 if os.name != 'posix':
572 572 return
573 573
574 574 ip.reset()
575 575 for cmd in ('clear', 'more', 'less', 'man'):
576 576 res = ip.run_cell('%' + cmd)
577 577 self.assertEqual(res.success, True)
578 578
579 579
580 580 class TestSafeExecfileNonAsciiPath(unittest.TestCase):
581 581
582 582 @onlyif_unicode_paths
583 583 def setUp(self):
584 584 self.BASETESTDIR = tempfile.mkdtemp()
585 585 self.TESTDIR = join(self.BASETESTDIR, u"åäö")
586 586 os.mkdir(self.TESTDIR)
587 587 with open(
588 588 join(self.TESTDIR, "åäötestscript.py"), "w", encoding="utf-8"
589 589 ) as sfile:
590 590 sfile.write("pass\n")
591 591 self.oldpath = os.getcwd()
592 592 os.chdir(self.TESTDIR)
593 593 self.fname = u"åäötestscript.py"
594 594
595 595 def tearDown(self):
596 596 os.chdir(self.oldpath)
597 597 shutil.rmtree(self.BASETESTDIR)
598 598
599 599 @onlyif_unicode_paths
600 600 def test_1(self):
601 601 """Test safe_execfile with non-ascii path
602 602 """
603 603 ip.safe_execfile(self.fname, {}, raise_exceptions=True)
604 604
605 605 class ExitCodeChecks(tt.TempFileMixin):
606 606
607 607 def setUp(self):
608 608 self.system = ip.system_raw
609 609
610 610 def test_exit_code_ok(self):
611 611 self.system('exit 0')
612 612 self.assertEqual(ip.user_ns['_exit_code'], 0)
613 613
614 614 def test_exit_code_error(self):
615 615 self.system('exit 1')
616 616 self.assertEqual(ip.user_ns['_exit_code'], 1)
617 617
618 618 @skipif(not hasattr(signal, 'SIGALRM'))
619 619 def test_exit_code_signal(self):
620 620 self.mktmp("import signal, time\n"
621 621 "signal.setitimer(signal.ITIMER_REAL, 0.1)\n"
622 622 "time.sleep(1)\n")
623 623 self.system("%s %s" % (sys.executable, self.fname))
624 624 self.assertEqual(ip.user_ns['_exit_code'], -signal.SIGALRM)
625 625
626 626 @onlyif_cmds_exist("csh")
627 627 def test_exit_code_signal_csh(self): # pragma: no cover
628 628 SHELL = os.environ.get("SHELL", None)
629 629 os.environ["SHELL"] = find_cmd("csh")
630 630 try:
631 631 self.test_exit_code_signal()
632 632 finally:
633 633 if SHELL is not None:
634 634 os.environ['SHELL'] = SHELL
635 635 else:
636 636 del os.environ['SHELL']
637 637
638 638
639 639 class TestSystemRaw(ExitCodeChecks):
640 640
641 641 def setUp(self):
642 642 super().setUp()
643 643 self.system = ip.system_raw
644 644
645 645 @onlyif_unicode_paths
646 646 def test_1(self):
647 647 """Test system_raw with non-ascii cmd
648 648 """
649 649 cmd = u'''python -c "'åäö'" '''
650 650 ip.system_raw(cmd)
651 651
652 652 @mock.patch('subprocess.call', side_effect=KeyboardInterrupt)
653 653 @mock.patch('os.system', side_effect=KeyboardInterrupt)
654 654 def test_control_c(self, *mocks):
655 655 try:
656 656 self.system("sleep 1 # wont happen")
657 657 except KeyboardInterrupt: # pragma: no cove
658 658 self.fail(
659 659 "system call should intercept "
660 660 "keyboard interrupt from subprocess.call"
661 661 )
662 662 self.assertEqual(ip.user_ns["_exit_code"], -signal.SIGINT)
663 663
664 664
665 665 @pytest.mark.parametrize("magic_cmd", ["pip", "conda", "cd"])
666 666 def test_magic_warnings(magic_cmd):
667 667 if sys.platform == "win32":
668 668 to_mock = "os.system"
669 669 expected_arg, expected_kwargs = magic_cmd, dict()
670 670 else:
671 671 to_mock = "subprocess.call"
672 672 expected_arg, expected_kwargs = magic_cmd, dict(
673 673 shell=True, executable=os.environ.get("SHELL", None)
674 674 )
675 675
676 676 with mock.patch(to_mock, return_value=0) as mock_sub:
677 677 with pytest.warns(Warning, match=r"You executed the system command"):
678 678 ip.system_raw(magic_cmd)
679 679 mock_sub.assert_called_once_with(expected_arg, **expected_kwargs)
680 680
681 681
682 682 # TODO: Exit codes are currently ignored on Windows.
683 683 class TestSystemPipedExitCode(ExitCodeChecks):
684 684
685 685 def setUp(self):
686 686 super().setUp()
687 687 self.system = ip.system_piped
688 688
689 689 @skip_win32
690 690 def test_exit_code_ok(self):
691 691 ExitCodeChecks.test_exit_code_ok(self)
692 692
693 693 @skip_win32
694 694 def test_exit_code_error(self):
695 695 ExitCodeChecks.test_exit_code_error(self)
696 696
697 697 @skip_win32
698 698 def test_exit_code_signal(self):
699 699 ExitCodeChecks.test_exit_code_signal(self)
700 700
701 701 class TestModules(tt.TempFileMixin):
702 702 def test_extraneous_loads(self):
703 703 """Test we're not loading modules on startup that we shouldn't.
704 704 """
705 705 self.mktmp("import sys\n"
706 706 "print('numpy' in sys.modules)\n"
707 707 "print('ipyparallel' in sys.modules)\n"
708 708 "print('ipykernel' in sys.modules)\n"
709 709 )
710 710 out = "False\nFalse\nFalse\n"
711 711 tt.ipexec_validate(self.fname, out)
712 712
713 713 class Negator(ast.NodeTransformer):
714 714 """Negates all number literals in an AST."""
715 715
716 716 # for python 3.7 and earlier
717 717 def visit_Num(self, node):
718 718 node.n = -node.n
719 719 return node
720 720
721 721 # for python 3.8+
722 722 def visit_Constant(self, node):
723 723 if isinstance(node.value, int):
724 724 return self.visit_Num(node)
725 725 return node
726 726
727 727 class TestAstTransform(unittest.TestCase):
728 728 def setUp(self):
729 729 self.negator = Negator()
730 730 ip.ast_transformers.append(self.negator)
731 731
732 732 def tearDown(self):
733 733 ip.ast_transformers.remove(self.negator)
734 734
735 735 def test_non_int_const(self):
736 736 with tt.AssertPrints("hello"):
737 737 ip.run_cell('print("hello")')
738 738
739 739 def test_run_cell(self):
740 740 with tt.AssertPrints("-34"):
741 741 ip.run_cell("print(12 + 22)")
742 742
743 743 # A named reference to a number shouldn't be transformed.
744 744 ip.user_ns["n"] = 55
745 745 with tt.AssertNotPrints("-55"):
746 746 ip.run_cell("print(n)")
747 747
748 748 def test_timeit(self):
749 749 called = set()
750 750 def f(x):
751 751 called.add(x)
752 752 ip.push({'f':f})
753 753
754 754 with tt.AssertPrints("std. dev. of"):
755 755 ip.run_line_magic("timeit", "-n1 f(1)")
756 756 self.assertEqual(called, {-1})
757 757 called.clear()
758 758
759 759 with tt.AssertPrints("std. dev. of"):
760 760 ip.run_cell_magic("timeit", "-n1 f(2)", "f(3)")
761 761 self.assertEqual(called, {-2, -3})
762 762
763 763 def test_time(self):
764 764 called = []
765 765 def f(x):
766 766 called.append(x)
767 767 ip.push({'f':f})
768 768
769 769 # Test with an expression
770 770 with tt.AssertPrints("Wall time: "):
771 771 ip.run_line_magic("time", "f(5+9)")
772 772 self.assertEqual(called, [-14])
773 773 called[:] = []
774 774
775 775 # Test with a statement (different code path)
776 776 with tt.AssertPrints("Wall time: "):
777 777 ip.run_line_magic("time", "a = f(-3 + -2)")
778 778 self.assertEqual(called, [5])
779 779
780 780 def test_macro(self):
781 781 ip.push({'a':10})
782 782 # The AST transformation makes this do a+=-1
783 783 ip.define_macro("amacro", "a+=1\nprint(a)")
784 784
785 785 with tt.AssertPrints("9"):
786 786 ip.run_cell("amacro")
787 787 with tt.AssertPrints("8"):
788 788 ip.run_cell("amacro")
789 789
790 790 class TestMiscTransform(unittest.TestCase):
791 791
792 792
793 793 def test_transform_only_once(self):
794 794 cleanup = 0
795 795 line_t = 0
796 796 def count_cleanup(lines):
797 797 nonlocal cleanup
798 798 cleanup += 1
799 799 return lines
800 800
801 801 def count_line_t(lines):
802 802 nonlocal line_t
803 803 line_t += 1
804 804 return lines
805 805
806 806 ip.input_transformer_manager.cleanup_transforms.append(count_cleanup)
807 807 ip.input_transformer_manager.line_transforms.append(count_line_t)
808 808
809 809 ip.run_cell('1')
810 810
811 811 assert cleanup == 1
812 812 assert line_t == 1
813 813
814 814 class IntegerWrapper(ast.NodeTransformer):
815 815 """Wraps all integers in a call to Integer()"""
816 816
817 817 # for Python 3.7 and earlier
818 818
819 819 # for Python 3.7 and earlier
820 820 def visit_Num(self, node):
821 821 if isinstance(node.n, int):
822 822 return ast.Call(func=ast.Name(id='Integer', ctx=ast.Load()),
823 823 args=[node], keywords=[])
824 824 return node
825 825
826 826 # For Python 3.8+
827 827 def visit_Constant(self, node):
828 828 if isinstance(node.value, int):
829 829 return self.visit_Num(node)
830 830 return node
831 831
832 832
833 833 class TestAstTransform2(unittest.TestCase):
834 834 def setUp(self):
835 835 self.intwrapper = IntegerWrapper()
836 836 ip.ast_transformers.append(self.intwrapper)
837 837
838 838 self.calls = []
839 839 def Integer(*args):
840 840 self.calls.append(args)
841 841 return args
842 842 ip.push({"Integer": Integer})
843 843
844 844 def tearDown(self):
845 845 ip.ast_transformers.remove(self.intwrapper)
846 846 del ip.user_ns['Integer']
847 847
848 848 def test_run_cell(self):
849 849 ip.run_cell("n = 2")
850 850 self.assertEqual(self.calls, [(2,)])
851 851
852 852 # This shouldn't throw an error
853 853 ip.run_cell("o = 2.0")
854 854 self.assertEqual(ip.user_ns['o'], 2.0)
855 855
856 856 def test_run_cell_non_int(self):
857 857 ip.run_cell("n = 'a'")
858 858 assert self.calls == []
859 859
860 860 def test_timeit(self):
861 861 called = set()
862 862 def f(x):
863 863 called.add(x)
864 864 ip.push({'f':f})
865 865
866 866 with tt.AssertPrints("std. dev. of"):
867 867 ip.run_line_magic("timeit", "-n1 f(1)")
868 868 self.assertEqual(called, {(1,)})
869 869 called.clear()
870 870
871 871 with tt.AssertPrints("std. dev. of"):
872 872 ip.run_cell_magic("timeit", "-n1 f(2)", "f(3)")
873 873 self.assertEqual(called, {(2,), (3,)})
874 874
875 875 class ErrorTransformer(ast.NodeTransformer):
876 876 """Throws an error when it sees a number."""
877 877
878 878 def visit_Constant(self, node):
879 879 if isinstance(node.value, int):
880 880 raise ValueError("test")
881 881 return node
882 882
883 883
884 884 class TestAstTransformError(unittest.TestCase):
885 885 def test_unregistering(self):
886 886 err_transformer = ErrorTransformer()
887 887 ip.ast_transformers.append(err_transformer)
888 888
889 889 with self.assertWarnsRegex(UserWarning, "It will be unregistered"):
890 890 ip.run_cell("1 + 2")
891 891
892 892 # This should have been removed.
893 893 self.assertNotIn(err_transformer, ip.ast_transformers)
894 894
895 895
896 896 class StringRejector(ast.NodeTransformer):
897 897 """Throws an InputRejected when it sees a string literal.
898 898
899 899 Used to verify that NodeTransformers can signal that a piece of code should
900 900 not be executed by throwing an InputRejected.
901 901 """
902 902
903 903 # 3.8 only
904 904 def visit_Constant(self, node):
905 905 if isinstance(node.value, str):
906 906 raise InputRejected("test")
907 907 return node
908 908
909 909
910 910 class TestAstTransformInputRejection(unittest.TestCase):
911 911
912 912 def setUp(self):
913 913 self.transformer = StringRejector()
914 914 ip.ast_transformers.append(self.transformer)
915 915
916 916 def tearDown(self):
917 917 ip.ast_transformers.remove(self.transformer)
918 918
919 919 def test_input_rejection(self):
920 920 """Check that NodeTransformers can reject input."""
921 921
922 922 expect_exception_tb = tt.AssertPrints("InputRejected: test")
923 923 expect_no_cell_output = tt.AssertNotPrints("'unsafe'", suppress=False)
924 924
925 925 # Run the same check twice to verify that the transformer is not
926 926 # disabled after raising.
927 927 with expect_exception_tb, expect_no_cell_output:
928 928 ip.run_cell("'unsafe'")
929 929
930 930 with expect_exception_tb, expect_no_cell_output:
931 931 res = ip.run_cell("'unsafe'")
932 932
933 933 self.assertIsInstance(res.error_before_exec, InputRejected)
934 934
935 935 def test__IPYTHON__():
936 936 # This shouldn't raise a NameError, that's all
937 937 __IPYTHON__
938 938
939 939
940 940 class DummyRepr(object):
941 941 def __repr__(self):
942 942 return "DummyRepr"
943 943
944 944 def _repr_html_(self):
945 945 return "<b>dummy</b>"
946 946
947 947 def _repr_javascript_(self):
948 948 return "console.log('hi');", {'key': 'value'}
949 949
950 950
951 951 def test_user_variables():
952 952 # enable all formatters
953 953 ip.display_formatter.active_types = ip.display_formatter.format_types
954 954
955 955 ip.user_ns['dummy'] = d = DummyRepr()
956 956 keys = {'dummy', 'doesnotexist'}
957 957 r = ip.user_expressions({ key:key for key in keys})
958 958
959 959 assert keys == set(r.keys())
960 960 dummy = r["dummy"]
961 961 assert {"status", "data", "metadata"} == set(dummy.keys())
962 962 assert dummy["status"] == "ok"
963 963 data = dummy["data"]
964 964 metadata = dummy["metadata"]
965 965 assert data.get("text/html") == d._repr_html_()
966 966 js, jsmd = d._repr_javascript_()
967 967 assert data.get("application/javascript") == js
968 968 assert metadata.get("application/javascript") == jsmd
969 969
970 970 dne = r["doesnotexist"]
971 971 assert dne["status"] == "error"
972 972 assert dne["ename"] == "NameError"
973 973
974 974 # back to text only
975 975 ip.display_formatter.active_types = ['text/plain']
976 976
977 977 def test_user_expression():
978 978 # enable all formatters
979 979 ip.display_formatter.active_types = ip.display_formatter.format_types
980 980 query = {
981 981 'a' : '1 + 2',
982 982 'b' : '1/0',
983 983 }
984 984 r = ip.user_expressions(query)
985 985 import pprint
986 986 pprint.pprint(r)
987 987 assert set(r.keys()) == set(query.keys())
988 988 a = r["a"]
989 989 assert {"status", "data", "metadata"} == set(a.keys())
990 990 assert a["status"] == "ok"
991 991 data = a["data"]
992 992 metadata = a["metadata"]
993 993 assert data.get("text/plain") == "3"
994 994
995 995 b = r["b"]
996 996 assert b["status"] == "error"
997 997 assert b["ename"] == "ZeroDivisionError"
998 998
999 999 # back to text only
1000 1000 ip.display_formatter.active_types = ['text/plain']
1001 1001
1002 1002
1003 1003 class TestSyntaxErrorTransformer(unittest.TestCase):
1004 1004 """Check that SyntaxError raised by an input transformer is handled by run_cell()"""
1005 1005
1006 1006 @staticmethod
1007 1007 def transformer(lines):
1008 1008 for line in lines:
1009 1009 pos = line.find('syntaxerror')
1010 1010 if pos >= 0:
1011 1011 e = SyntaxError('input contains "syntaxerror"')
1012 1012 e.text = line
1013 1013 e.offset = pos + 1
1014 1014 raise e
1015 1015 return lines
1016 1016
1017 1017 def setUp(self):
1018 1018 ip.input_transformers_post.append(self.transformer)
1019 1019
1020 1020 def tearDown(self):
1021 1021 ip.input_transformers_post.remove(self.transformer)
1022 1022
1023 1023 def test_syntaxerror_input_transformer(self):
1024 1024 with tt.AssertPrints('1234'):
1025 1025 ip.run_cell('1234')
1026 1026 with tt.AssertPrints('SyntaxError: invalid syntax'):
1027 1027 ip.run_cell('1 2 3') # plain python syntax error
1028 1028 with tt.AssertPrints('SyntaxError: input contains "syntaxerror"'):
1029 1029 ip.run_cell('2345 # syntaxerror') # input transformer syntax error
1030 1030 with tt.AssertPrints('3456'):
1031 1031 ip.run_cell('3456')
1032 1032
1033 1033
1034 1034 class TestWarningSuppression(unittest.TestCase):
1035 1035 def test_warning_suppression(self):
1036 1036 ip.run_cell("import warnings")
1037 1037 try:
1038 1038 with self.assertWarnsRegex(UserWarning, "asdf"):
1039 1039 ip.run_cell("warnings.warn('asdf')")
1040 1040 # Here's the real test -- if we run that again, we should get the
1041 1041 # warning again. Traditionally, each warning was only issued once per
1042 1042 # IPython session (approximately), even if the user typed in new and
1043 1043 # different code that should have also triggered the warning, leading
1044 1044 # to much confusion.
1045 1045 with self.assertWarnsRegex(UserWarning, "asdf"):
1046 1046 ip.run_cell("warnings.warn('asdf')")
1047 1047 finally:
1048 1048 ip.run_cell("del warnings")
1049 1049
1050 1050
1051 1051 def test_deprecation_warning(self):
1052 1052 ip.run_cell("""
1053 1053 import warnings
1054 1054 def wrn():
1055 1055 warnings.warn(
1056 1056 "I AM A WARNING",
1057 1057 DeprecationWarning
1058 1058 )
1059 1059 """)
1060 1060 try:
1061 1061 with self.assertWarnsRegex(DeprecationWarning, "I AM A WARNING"):
1062 1062 ip.run_cell("wrn()")
1063 1063 finally:
1064 1064 ip.run_cell("del warnings")
1065 1065 ip.run_cell("del wrn")
1066 1066
1067 1067
1068 1068 class TestImportNoDeprecate(tt.TempFileMixin):
1069 1069
1070 1070 def setUp(self):
1071 1071 """Make a valid python temp file."""
1072 1072 self.mktmp("""
1073 1073 import warnings
1074 1074 def wrn():
1075 1075 warnings.warn(
1076 1076 "I AM A WARNING",
1077 1077 DeprecationWarning
1078 1078 )
1079 1079 """)
1080 1080 super().setUp()
1081 1081
1082 1082 def test_no_dep(self):
1083 1083 """
1084 1084 No deprecation warning should be raised from imported functions
1085 1085 """
1086 1086 ip.run_cell("from {} import wrn".format(self.fname))
1087 1087
1088 1088 with tt.AssertNotPrints("I AM A WARNING"):
1089 1089 ip.run_cell("wrn()")
1090 1090 ip.run_cell("del wrn")
1091 1091
1092 1092
1093 1093 def test_custom_exc_count():
1094 1094 hook = mock.Mock(return_value=None)
1095 1095 ip.set_custom_exc((SyntaxError,), hook)
1096 1096 before = ip.execution_count
1097 1097 ip.run_cell("def foo()", store_history=True)
1098 1098 # restore default excepthook
1099 1099 ip.set_custom_exc((), None)
1100 1100 assert hook.call_count == 1
1101 1101 assert ip.execution_count == before + 1
1102 1102
1103 1103
1104 1104 def test_run_cell_async():
1105 1105 ip.run_cell("import asyncio")
1106 1106 coro = ip.run_cell_async("await asyncio.sleep(0.01)\n5")
1107 1107 assert asyncio.iscoroutine(coro)
1108 1108 loop = asyncio.new_event_loop()
1109 1109 result = loop.run_until_complete(coro)
1110 1110 assert isinstance(result, interactiveshell.ExecutionResult)
1111 1111 assert result.result == 5
1112 1112
1113 1113
1114 1114 def test_run_cell_await():
1115 1115 ip.run_cell("import asyncio")
1116 1116 result = ip.run_cell("await asyncio.sleep(0.01); 10")
1117 1117 assert ip.user_ns["_"] == 10
1118 1118
1119 1119
1120 1120 def test_run_cell_asyncio_run():
1121 1121 ip.run_cell("import asyncio")
1122 1122 result = ip.run_cell("await asyncio.sleep(0.01); 1")
1123 1123 assert ip.user_ns["_"] == 1
1124 1124 result = ip.run_cell("asyncio.run(asyncio.sleep(0.01)); 2")
1125 1125 assert ip.user_ns["_"] == 2
1126 1126 result = ip.run_cell("await asyncio.sleep(0.01); 3")
1127 1127 assert ip.user_ns["_"] == 3
1128 1128
1129 1129
1130 1130 def test_should_run_async():
1131 1131 assert not ip.should_run_async("a = 5", transformed_cell="a = 5")
1132 1132 assert ip.should_run_async("await x", transformed_cell="await x")
1133 1133 assert ip.should_run_async(
1134 1134 "import asyncio; await asyncio.sleep(1)",
1135 1135 transformed_cell="import asyncio; await asyncio.sleep(1)",
1136 1136 )
1137 1137
1138 1138
1139 1139 def test_set_custom_completer():
1140 1140 num_completers = len(ip.Completer.matchers)
1141 1141
1142 1142 def foo(*args, **kwargs):
1143 1143 return "I'm a completer!"
1144 1144
1145 1145 ip.set_custom_completer(foo, 0)
1146 1146
1147 1147 # check that we've really added a new completer
1148 1148 assert len(ip.Completer.matchers) == num_completers + 1
1149 1149
1150 1150 # check that the first completer is the function we defined
1151 1151 assert ip.Completer.matchers[0]() == "I'm a completer!"
1152 1152
1153 1153 # clean up
1154 1154 ip.Completer.custom_matchers.pop()
1155 1155
1156 1156
1157 1157 class TestShowTracebackAttack(unittest.TestCase):
1158 1158 """Test that the interactive shell is resilient against the client attack of
1159 1159 manipulating the showtracebacks method. These attacks shouldn't result in an
1160 1160 unhandled exception in the kernel."""
1161 1161
1162 1162 def setUp(self):
1163 1163 self.orig_showtraceback = interactiveshell.InteractiveShell.showtraceback
1164 1164
1165 1165 def tearDown(self):
1166 1166 interactiveshell.InteractiveShell.showtraceback = self.orig_showtraceback
1167 1167
1168 1168 def test_set_show_tracebacks_none(self):
1169 1169 """Test the case of the client setting showtracebacks to None"""
1170 1170
1171 1171 result = ip.run_cell(
1172 1172 """
1173 1173 import IPython.core.interactiveshell
1174 1174 IPython.core.interactiveshell.InteractiveShell.showtraceback = None
1175 1175
1176 1176 assert False, "This should not raise an exception"
1177 1177 """
1178 1178 )
1179 1179 print(result)
1180 1180
1181 1181 assert result.result is None
1182 1182 assert isinstance(result.error_in_exec, TypeError)
1183 1183 assert str(result.error_in_exec) == "'NoneType' object is not callable"
1184 1184
1185 1185 def test_set_show_tracebacks_noop(self):
1186 1186 """Test the case of the client setting showtracebacks to a no op lambda"""
1187 1187
1188 1188 result = ip.run_cell(
1189 1189 """
1190 1190 import IPython.core.interactiveshell
1191 1191 IPython.core.interactiveshell.InteractiveShell.showtraceback = lambda *args, **kwargs: None
1192 1192
1193 1193 assert False, "This should not raise an exception"
1194 1194 """
1195 1195 )
1196 1196 print(result)
1197 1197
1198 1198 assert result.result is None
1199 1199 assert isinstance(result.error_in_exec, AssertionError)
1200 1200 assert str(result.error_in_exec) == "This should not raise an exception"
@@ -1,1377 +1,1395 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 Verbose and colourful traceback formatting.
4 4
5 5 **ColorTB**
6 6
7 7 I've always found it a bit hard to visually parse tracebacks in Python. The
8 8 ColorTB class is a solution to that problem. It colors the different parts of a
9 9 traceback in a manner similar to what you would expect from a syntax-highlighting
10 10 text editor.
11 11
12 12 Installation instructions for ColorTB::
13 13
14 14 import sys,ultratb
15 15 sys.excepthook = ultratb.ColorTB()
16 16
17 17 **VerboseTB**
18 18
19 19 I've also included a port of Ka-Ping Yee's "cgitb.py" that produces all kinds
20 20 of useful info when a traceback occurs. Ping originally had it spit out HTML
21 21 and intended it for CGI programmers, but why should they have all the fun? I
22 22 altered it to spit out colored text to the terminal. It's a bit overwhelming,
23 23 but kind of neat, and maybe useful for long-running programs that you believe
24 24 are bug-free. If a crash *does* occur in that type of program you want details.
25 25 Give it a shot--you'll love it or you'll hate it.
26 26
27 27 .. note::
28 28
29 29 The Verbose mode prints the variables currently visible where the exception
30 30 happened (shortening their strings if too long). This can potentially be
31 31 very slow, if you happen to have a huge data structure whose string
32 32 representation is complex to compute. Your computer may appear to freeze for
33 33 a while with cpu usage at 100%. If this occurs, you can cancel the traceback
34 34 with Ctrl-C (maybe hitting it more than once).
35 35
36 36 If you encounter this kind of situation often, you may want to use the
37 37 Verbose_novars mode instead of the regular Verbose, which avoids formatting
38 38 variables (but otherwise includes the information and context given by
39 39 Verbose).
40 40
41 41 .. note::
42 42
43 43 The verbose mode print all variables in the stack, which means it can
44 44 potentially leak sensitive information like access keys, or unencrypted
45 45 password.
46 46
47 47 Installation instructions for VerboseTB::
48 48
49 49 import sys,ultratb
50 50 sys.excepthook = ultratb.VerboseTB()
51 51
52 52 Note: Much of the code in this module was lifted verbatim from the standard
53 53 library module 'traceback.py' and Ka-Ping Yee's 'cgitb.py'.
54 54
55 55 Color schemes
56 56 -------------
57 57
58 58 The colors are defined in the class TBTools through the use of the
59 59 ColorSchemeTable class. Currently the following exist:
60 60
61 61 - NoColor: allows all of this module to be used in any terminal (the color
62 62 escapes are just dummy blank strings).
63 63
64 64 - Linux: is meant to look good in a terminal like the Linux console (black
65 65 or very dark background).
66 66
67 67 - LightBG: similar to Linux but swaps dark/light colors to be more readable
68 68 in light background terminals.
69 69
70 70 - Neutral: a neutral color scheme that should be readable on both light and
71 71 dark background
72 72
73 73 You can implement other color schemes easily, the syntax is fairly
74 74 self-explanatory. Please send back new schemes you develop to the author for
75 75 possible inclusion in future releases.
76 76
77 77 Inheritance diagram:
78 78
79 79 .. inheritance-diagram:: IPython.core.ultratb
80 80 :parts: 3
81 81 """
82 82
83 83 #*****************************************************************************
84 84 # Copyright (C) 2001 Nathaniel Gray <n8gray@caltech.edu>
85 85 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
86 86 #
87 87 # Distributed under the terms of the BSD License. The full license is in
88 88 # the file COPYING, distributed as part of this software.
89 89 #*****************************************************************************
90 90
91 91
92 92 import inspect
93 93 import linecache
94 94 import pydoc
95 95 import sys
96 96 import time
97 97 import traceback
98 98 from types import TracebackType
99 99 from typing import Tuple, List, Any, Optional
100 100
101 101 import stack_data
102 102 from stack_data import FrameInfo as SDFrameInfo
103 103 from pygments.formatters.terminal256 import Terminal256Formatter
104 104 from pygments.styles import get_style_by_name
105 105
106 106 # IPython's own modules
107 107 from IPython import get_ipython
108 108 from IPython.core import debugger
109 109 from IPython.core.display_trap import DisplayTrap
110 110 from IPython.core.excolors import exception_colors
111 111 from IPython.utils import PyColorize
112 112 from IPython.utils import path as util_path
113 113 from IPython.utils import py3compat
114 114 from IPython.utils.terminal import get_terminal_size
115 115
116 116 import IPython.utils.colorable as colorable
117 117
118 118 # Globals
119 119 # amount of space to put line numbers before verbose tracebacks
120 120 INDENT_SIZE = 8
121 121
122 122 # Default color scheme. This is used, for example, by the traceback
123 123 # formatter. When running in an actual IPython instance, the user's rc.colors
124 124 # value is used, but having a module global makes this functionality available
125 125 # to users of ultratb who are NOT running inside ipython.
126 126 DEFAULT_SCHEME = 'NoColor'
127 127 FAST_THRESHOLD = 10_000
128 128
129 129 # ---------------------------------------------------------------------------
130 130 # Code begins
131 131
132 132 # Helper function -- largely belongs to VerboseTB, but we need the same
133 133 # functionality to produce a pseudo verbose TB for SyntaxErrors, so that they
134 134 # can be recognized properly by ipython.el's py-traceback-line-re
135 135 # (SyntaxErrors have to be treated specially because they have no traceback)
136 136
137 137
138 138 def _format_traceback_lines(lines, Colors, has_colors: bool, lvals):
139 139 """
140 140 Format tracebacks lines with pointing arrow, leading numbers...
141 141
142 142 Parameters
143 143 ----------
144 144 lines : list[Line]
145 145 Colors
146 146 ColorScheme used.
147 147 lvals : str
148 148 Values of local variables, already colored, to inject just after the error line.
149 149 """
150 150 numbers_width = INDENT_SIZE - 1
151 151 res = []
152 152
153 153 for stack_line in lines:
154 154 if stack_line is stack_data.LINE_GAP:
155 155 res.append('%s (...)%s\n' % (Colors.linenoEm, Colors.Normal))
156 156 continue
157 157
158 158 line = stack_line.render(pygmented=has_colors).rstrip('\n') + '\n'
159 159 lineno = stack_line.lineno
160 160 if stack_line.is_current:
161 161 # This is the line with the error
162 162 pad = numbers_width - len(str(lineno))
163 163 num = '%s%s' % (debugger.make_arrow(pad), str(lineno))
164 164 start_color = Colors.linenoEm
165 165 else:
166 166 num = '%*s' % (numbers_width, lineno)
167 167 start_color = Colors.lineno
168 168
169 169 line = '%s%s%s %s' % (start_color, num, Colors.Normal, line)
170 170
171 171 res.append(line)
172 172 if lvals and stack_line.is_current:
173 173 res.append(lvals + '\n')
174 174 return res
175 175
176 176 def _simple_format_traceback_lines(lnum, index, lines, Colors, lvals, _line_format):
177 177 """
178 178 Format tracebacks lines with pointing arrow, leading numbers...
179 179
180 180 Parameters
181 181 ==========
182 182
183 183 lnum: int
184 184 number of the target line of code.
185 185 index: int
186 186 which line in the list should be highlighted.
187 187 lines: list[string]
188 188 Colors:
189 189 ColorScheme used.
190 190 lvals: bytes
191 191 Values of local variables, already colored, to inject just after the error line.
192 192 _line_format: f (str) -> (str, bool)
193 193 return (colorized version of str, failure to do so)
194 194 """
195 195 numbers_width = INDENT_SIZE - 1
196 196 res = []
197 197
198 198 for i, line in enumerate(lines, lnum - index):
199 199 line = py3compat.cast_unicode(line)
200 200
201 201 new_line, err = _line_format(line, "str")
202 202 if not err:
203 203 line = new_line
204 204
205 205 if i == lnum:
206 206 # This is the line with the error
207 207 pad = numbers_width - len(str(i))
208 208 num = "%s%s" % (debugger.make_arrow(pad), str(lnum))
209 209 line = "%s%s%s %s%s" % (
210 210 Colors.linenoEm,
211 211 num,
212 212 Colors.line,
213 213 line,
214 214 Colors.Normal,
215 215 )
216 216 else:
217 217 num = "%*s" % (numbers_width, i)
218 218 line = "%s%s%s %s" % (Colors.lineno, num, Colors.Normal, line)
219 219
220 220 res.append(line)
221 221 if lvals and i == lnum:
222 222 res.append(lvals + "\n")
223 223 return res
224 224
225 225
226 226 def _format_filename(file, ColorFilename, ColorNormal, *, lineno=None):
227 227 """
228 228 Format filename lines with custom formatting from caching compiler or `File *.py` by default
229 229
230 230 Parameters
231 231 ----------
232 232 file : str
233 233 ColorFilename
234 234 ColorScheme's filename coloring to be used.
235 235 ColorNormal
236 236 ColorScheme's normal coloring to be used.
237 237 """
238 238 ipinst = get_ipython()
239 239 if (
240 240 ipinst is not None
241 241 and (data := ipinst.compile.format_code_name(file)) is not None
242 242 ):
243 243 label, name = data
244 244 if lineno is None:
245 245 tpl_link = f"{{label}} {ColorFilename}{{name}}{ColorNormal}"
246 246 else:
247 247 tpl_link = (
248 248 f"{{label}} {ColorFilename}{{name}}, line {{lineno}}{ColorNormal}"
249 249 )
250 250 else:
251 251 label = "File"
252 252 name = util_path.compress_user(
253 253 py3compat.cast_unicode(file, util_path.fs_encoding)
254 254 )
255 255 if lineno is None:
256 256 tpl_link = f"{{label}} {ColorFilename}{{name}}{ColorNormal}"
257 257 else:
258 258 # can we make this the more friendly ", line {{lineno}}", or do we need to preserve the formatting with the colon?
259 259 tpl_link = f"{{label}} {ColorFilename}{{name}}:{{lineno}}{ColorNormal}"
260 260
261 261 return tpl_link.format(label=label, name=name, lineno=lineno)
262 262
263 263 #---------------------------------------------------------------------------
264 264 # Module classes
265 265 class TBTools(colorable.Colorable):
266 266 """Basic tools used by all traceback printer classes."""
267 267
268 268 # Number of frames to skip when reporting tracebacks
269 269 tb_offset = 0
270 270
271 271 def __init__(
272 272 self,
273 273 color_scheme="NoColor",
274 274 call_pdb=False,
275 275 ostream=None,
276 276 parent=None,
277 277 config=None,
278 278 *,
279 279 debugger_cls=None,
280 280 ):
281 281 # Whether to call the interactive pdb debugger after printing
282 282 # tracebacks or not
283 283 super(TBTools, self).__init__(parent=parent, config=config)
284 284 self.call_pdb = call_pdb
285 285
286 286 # Output stream to write to. Note that we store the original value in
287 287 # a private attribute and then make the public ostream a property, so
288 288 # that we can delay accessing sys.stdout until runtime. The way
289 289 # things are written now, the sys.stdout object is dynamically managed
290 290 # so a reference to it should NEVER be stored statically. This
291 291 # property approach confines this detail to a single location, and all
292 292 # subclasses can simply access self.ostream for writing.
293 293 self._ostream = ostream
294 294
295 295 # Create color table
296 296 self.color_scheme_table = exception_colors()
297 297
298 298 self.set_colors(color_scheme)
299 299 self.old_scheme = color_scheme # save initial value for toggles
300 300 self.debugger_cls = debugger_cls or debugger.Pdb
301 301
302 302 if call_pdb:
303 303 self.pdb = self.debugger_cls()
304 304 else:
305 305 self.pdb = None
306 306
307 307 def _get_ostream(self):
308 308 """Output stream that exceptions are written to.
309 309
310 310 Valid values are:
311 311
312 312 - None: the default, which means that IPython will dynamically resolve
313 313 to sys.stdout. This ensures compatibility with most tools, including
314 314 Windows (where plain stdout doesn't recognize ANSI escapes).
315 315
316 316 - Any object with 'write' and 'flush' attributes.
317 317 """
318 318 return sys.stdout if self._ostream is None else self._ostream
319 319
320 320 def _set_ostream(self, val):
321 321 assert val is None or (hasattr(val, 'write') and hasattr(val, 'flush'))
322 322 self._ostream = val
323 323
324 324 ostream = property(_get_ostream, _set_ostream)
325 325
326 326 @staticmethod
327 327 def _get_chained_exception(exception_value):
328 328 cause = getattr(exception_value, "__cause__", None)
329 329 if cause:
330 330 return cause
331 331 if getattr(exception_value, "__suppress_context__", False):
332 332 return None
333 333 return getattr(exception_value, "__context__", None)
334 334
335 335 def get_parts_of_chained_exception(
336 336 self, evalue
337 337 ) -> Optional[Tuple[type, BaseException, TracebackType]]:
338 338 chained_evalue = self._get_chained_exception(evalue)
339 339
340 340 if chained_evalue:
341 341 return chained_evalue.__class__, chained_evalue, chained_evalue.__traceback__
342 342 return None
343 343
344 344 def prepare_chained_exception_message(self, cause) -> List[Any]:
345 345 direct_cause = "\nThe above exception was the direct cause of the following exception:\n"
346 346 exception_during_handling = "\nDuring handling of the above exception, another exception occurred:\n"
347 347
348 348 if cause:
349 349 message = [[direct_cause]]
350 350 else:
351 351 message = [[exception_during_handling]]
352 352 return message
353 353
354 354 @property
355 355 def has_colors(self) -> bool:
356 356 return self.color_scheme_table.active_scheme_name.lower() != "nocolor"
357 357
358 358 def set_colors(self, *args, **kw):
359 359 """Shorthand access to the color table scheme selector method."""
360 360
361 361 # Set own color table
362 362 self.color_scheme_table.set_active_scheme(*args, **kw)
363 363 # for convenience, set Colors to the active scheme
364 364 self.Colors = self.color_scheme_table.active_colors
365 365 # Also set colors of debugger
366 366 if hasattr(self, 'pdb') and self.pdb is not None:
367 367 self.pdb.set_colors(*args, **kw)
368 368
369 369 def color_toggle(self):
370 370 """Toggle between the currently active color scheme and NoColor."""
371 371
372 372 if self.color_scheme_table.active_scheme_name == 'NoColor':
373 373 self.color_scheme_table.set_active_scheme(self.old_scheme)
374 374 self.Colors = self.color_scheme_table.active_colors
375 375 else:
376 376 self.old_scheme = self.color_scheme_table.active_scheme_name
377 377 self.color_scheme_table.set_active_scheme('NoColor')
378 378 self.Colors = self.color_scheme_table.active_colors
379 379
380 380 def stb2text(self, stb):
381 381 """Convert a structured traceback (a list) to a string."""
382 382 return '\n'.join(stb)
383 383
384 384 def text(self, etype, value, tb, tb_offset: Optional[int] = None, context=5):
385 385 """Return formatted traceback.
386 386
387 387 Subclasses may override this if they add extra arguments.
388 388 """
389 389 tb_list = self.structured_traceback(etype, value, tb,
390 390 tb_offset, context)
391 391 return self.stb2text(tb_list)
392 392
393 393 def structured_traceback(
394 self, etype, evalue, tb, tb_offset: Optional[int] = None, context=5, mode=None
394 self,
395 etype: type,
396 evalue: Optional[BaseException],
397 etb: Optional[TracebackType] = None,
398 tb_offset: Optional[int] = None,
399 context=5,
395 400 ):
396 401 """Return a list of traceback frames.
397 402
398 403 Must be implemented by each class.
399 404 """
400 405 raise NotImplementedError()
401 406
402 407
403 408 #---------------------------------------------------------------------------
404 409 class ListTB(TBTools):
405 410 """Print traceback information from a traceback list, with optional color.
406 411
407 412 Calling requires 3 arguments: (etype, evalue, elist)
408 413 as would be obtained by::
409 414
410 415 etype, evalue, tb = sys.exc_info()
411 416 if tb:
412 417 elist = traceback.extract_tb(tb)
413 418 else:
414 419 elist = None
415 420
416 421 It can thus be used by programs which need to process the traceback before
417 422 printing (such as console replacements based on the code module from the
418 423 standard library).
419 424
420 425 Because they are meant to be called without a full traceback (only a
421 426 list), instances of this class can't call the interactive pdb debugger."""
422 427
423 428
424 429 def __call__(self, etype, value, elist):
425 430 self.ostream.flush()
426 431 self.ostream.write(self.text(etype, value, elist))
427 432 self.ostream.write('\n')
428 433
429 434 def _extract_tb(self, tb):
430 435 if tb:
431 436 return traceback.extract_tb(tb)
432 437 else:
433 438 return None
434 439
435 440 def structured_traceback(
436 441 self,
437 442 etype: type,
438 evalue: BaseException,
443 evalue: Optional[BaseException],
439 444 etb: Optional[TracebackType] = None,
440 445 tb_offset: Optional[int] = None,
441 446 context=5,
442 447 ):
443 448 """Return a color formatted string with the traceback info.
444 449
445 450 Parameters
446 451 ----------
447 452 etype : exception type
448 453 Type of the exception raised.
449 454 evalue : object
450 455 Data stored in the exception
451 456 etb : list | TracebackType | None
452 457 If list: List of frames, see class docstring for details.
453 458 If Traceback: Traceback of the exception.
454 459 tb_offset : int, optional
455 460 Number of frames in the traceback to skip. If not given, the
456 461 instance evalue is used (set in constructor).
457 462 context : int, optional
458 463 Number of lines of context information to print.
459 464
460 465 Returns
461 466 -------
462 467 String with formatted exception.
463 468 """
464 469 # This is a workaround to get chained_exc_ids in recursive calls
465 470 # etb should not be a tuple if structured_traceback is not recursive
466 471 if isinstance(etb, tuple):
467 472 etb, chained_exc_ids = etb
468 473 else:
469 474 chained_exc_ids = set()
470 475
471 476 if isinstance(etb, list):
472 477 elist = etb
473 478 elif etb is not None:
474 479 elist = self._extract_tb(etb)
475 480 else:
476 481 elist = []
477 482 tb_offset = self.tb_offset if tb_offset is None else tb_offset
478 483 assert isinstance(tb_offset, int)
479 484 Colors = self.Colors
480 485 out_list = []
481 486 if elist:
482 487
483 488 if tb_offset and len(elist) > tb_offset:
484 489 elist = elist[tb_offset:]
485 490
486 491 out_list.append('Traceback %s(most recent call last)%s:' %
487 492 (Colors.normalEm, Colors.Normal) + '\n')
488 493 out_list.extend(self._format_list(elist))
489 494 # The exception info should be a single entry in the list.
490 495 lines = ''.join(self._format_exception_only(etype, evalue))
491 496 out_list.append(lines)
492 497
493 498 exception = self.get_parts_of_chained_exception(evalue)
494 499
495 500 if exception and not id(exception[1]) in chained_exc_ids:
496 chained_exception_message = self.prepare_chained_exception_message(
497 evalue.__cause__)[0]
501 chained_exception_message = (
502 self.prepare_chained_exception_message(evalue.__cause__)[0]
503 if evalue is not None
504 else ""
505 )
498 506 etype, evalue, etb = exception
499 507 # Trace exception to avoid infinite 'cause' loop
500 508 chained_exc_ids.add(id(exception[1]))
501 509 chained_exceptions_tb_offset = 0
502 510 out_list = (
503 511 self.structured_traceback(
504 512 etype, evalue, (etb, chained_exc_ids),
505 513 chained_exceptions_tb_offset, context)
506 514 + chained_exception_message
507 515 + out_list)
508 516
509 517 return out_list
510 518
511 519 def _format_list(self, extracted_list):
512 520 """Format a list of traceback entry tuples for printing.
513 521
514 522 Given a list of tuples as returned by extract_tb() or
515 523 extract_stack(), return a list of strings ready for printing.
516 524 Each string in the resulting list corresponds to the item with the
517 525 same index in the argument list. Each string ends in a newline;
518 526 the strings may contain internal newlines as well, for those items
519 527 whose source text line is not None.
520 528
521 529 Lifted almost verbatim from traceback.py
522 530 """
523 531
524 532 Colors = self.Colors
525 533 list = []
526 534 for ind, (filename, lineno, name, line) in enumerate(extracted_list):
527 535 normalCol, nameCol, fileCol, lineCol = (
528 536 # Emphasize the last entry
529 537 (Colors.normalEm, Colors.nameEm, Colors.filenameEm, Colors.line)
530 538 if ind == len(extracted_list) - 1
531 539 else (Colors.Normal, Colors.name, Colors.filename, "")
532 540 )
533 541
534 542 fns = _format_filename(filename, fileCol, normalCol, lineno=lineno)
535 543 item = f"{normalCol} {fns}"
536 544
537 545 if name != "<module>":
538 546 item += f" in {nameCol}{name}{normalCol}\n"
539 547 else:
540 548 item += "\n"
541 549 if line:
542 550 item += f"{lineCol} {line.strip()}{normalCol}\n"
543 551 list.append(item)
544 552
545 553 return list
546 554
547 555 def _format_exception_only(self, etype, value):
548 556 """Format the exception part of a traceback.
549 557
550 558 The arguments are the exception type and value such as given by
551 559 sys.exc_info()[:2]. The return value is a list of strings, each ending
552 560 in a newline. Normally, the list contains a single string; however,
553 561 for SyntaxError exceptions, it contains several lines that (when
554 562 printed) display detailed information about where the syntax error
555 563 occurred. The message indicating which exception occurred is the
556 564 always last string in the list.
557 565
558 566 Also lifted nearly verbatim from traceback.py
559 567 """
560 568 have_filedata = False
561 569 Colors = self.Colors
562 570 list = []
563 571 stype = py3compat.cast_unicode(Colors.excName + etype.__name__ + Colors.Normal)
564 572 if value is None:
565 573 # Not sure if this can still happen in Python 2.6 and above
566 574 list.append(stype + '\n')
567 575 else:
568 576 if issubclass(etype, SyntaxError):
569 577 have_filedata = True
570 578 if not value.filename: value.filename = "<string>"
571 579 if value.lineno:
572 580 lineno = value.lineno
573 581 textline = linecache.getline(value.filename, value.lineno)
574 582 else:
575 583 lineno = "unknown"
576 584 textline = ""
577 585 list.append(
578 586 "%s %s%s\n"
579 587 % (
580 588 Colors.normalEm,
581 589 _format_filename(
582 590 value.filename,
583 591 Colors.filenameEm,
584 592 Colors.normalEm,
585 593 lineno=(None if lineno == "unknown" else lineno),
586 594 ),
587 595 Colors.Normal,
588 596 )
589 597 )
590 598 if textline == "":
591 599 textline = py3compat.cast_unicode(value.text, "utf-8")
592 600
593 601 if textline is not None:
594 602 i = 0
595 603 while i < len(textline) and textline[i].isspace():
596 604 i += 1
597 605 list.append('%s %s%s\n' % (Colors.line,
598 606 textline.strip(),
599 607 Colors.Normal))
600 608 if value.offset is not None:
601 609 s = ' '
602 610 for c in textline[i:value.offset - 1]:
603 611 if c.isspace():
604 612 s += c
605 613 else:
606 614 s += ' '
607 615 list.append('%s%s^%s\n' % (Colors.caret, s,
608 616 Colors.Normal))
609 617
610 618 try:
611 619 s = value.msg
612 620 except Exception:
613 621 s = self._some_str(value)
614 622 if s:
615 623 list.append('%s%s:%s %s\n' % (stype, Colors.excName,
616 624 Colors.Normal, s))
617 625 else:
618 626 list.append('%s\n' % stype)
619 627
620 628 # sync with user hooks
621 629 if have_filedata:
622 630 ipinst = get_ipython()
623 631 if ipinst is not None:
624 632 ipinst.hooks.synchronize_with_editor(value.filename, value.lineno, 0)
625 633
626 634 return list
627 635
628 636 def get_exception_only(self, etype, value):
629 637 """Only print the exception type and message, without a traceback.
630 638
631 639 Parameters
632 640 ----------
633 641 etype : exception type
634 642 value : exception value
635 643 """
636 644 return ListTB.structured_traceback(self, etype, value)
637 645
638 646 def show_exception_only(self, etype, evalue):
639 647 """Only print the exception type and message, without a traceback.
640 648
641 649 Parameters
642 650 ----------
643 651 etype : exception type
644 652 evalue : exception value
645 653 """
646 654 # This method needs to use __call__ from *this* class, not the one from
647 655 # a subclass whose signature or behavior may be different
648 656 ostream = self.ostream
649 657 ostream.flush()
650 658 ostream.write('\n'.join(self.get_exception_only(etype, evalue)))
651 659 ostream.flush()
652 660
653 661 def _some_str(self, value):
654 662 # Lifted from traceback.py
655 663 try:
656 664 return py3compat.cast_unicode(str(value))
657 665 except:
658 666 return u'<unprintable %s object>' % type(value).__name__
659 667
660 668
661 669 class FrameInfo:
662 670 """
663 671 Mirror of stack data's FrameInfo, but so that we can bypass highlighting on
664 672 really long frames.
665 673 """
666 674
667 675 description: Optional[str]
668 676 filename: str
669 677 lineno: int
670 678
671 679 @classmethod
672 680 def _from_stack_data_FrameInfo(cls, frame_info):
673 681 return cls(
674 682 getattr(frame_info, "description", None),
675 683 getattr(frame_info, "filename", None),
676 684 getattr(frame_info, "lineno", None),
677 685 getattr(frame_info, "frame", None),
678 686 getattr(frame_info, "code", None),
679 687 sd=frame_info,
680 688 )
681 689
682 690 def __init__(self, description, filename, lineno, frame, code, sd=None):
683 691 self.description = description
684 692 self.filename = filename
685 693 self.lineno = lineno
686 694 self.frame = frame
687 695 self.code = code
688 696 self._sd = sd
689 697
690 698 # self.lines = []
691 699 if sd is None:
692 700 ix = inspect.getsourcelines(frame)
693 701 self.raw_lines = ix[0]
694 702
695 703 @property
696 704 def variables_in_executing_piece(self):
697 705 if self._sd:
698 706 return self._sd.variables_in_executing_piece
699 707 else:
700 708 return []
701 709
702 710 @property
703 711 def lines(self):
704 712 return self._sd.lines
705 713
706 714 @property
707 715 def executing(self):
708 716 if self._sd:
709 717 return self._sd.executing
710 718 else:
711 719 return None
712 720
713 721
714 722 # ----------------------------------------------------------------------------
715 723 class VerboseTB(TBTools):
716 724 """A port of Ka-Ping Yee's cgitb.py module that outputs color text instead
717 725 of HTML. Requires inspect and pydoc. Crazy, man.
718 726
719 727 Modified version which optionally strips the topmost entries from the
720 728 traceback, to be used with alternate interpreters (because their own code
721 729 would appear in the traceback)."""
722 730
723 731 _tb_highlight = "bg:ansiyellow"
724 732
725 733 def __init__(
726 734 self,
727 735 color_scheme: str = "Linux",
728 736 call_pdb: bool = False,
729 737 ostream=None,
730 738 tb_offset: int = 0,
731 739 long_header: bool = False,
732 740 include_vars: bool = True,
733 741 check_cache=None,
734 742 debugger_cls=None,
735 743 parent=None,
736 744 config=None,
737 745 ):
738 746 """Specify traceback offset, headers and color scheme.
739 747
740 748 Define how many frames to drop from the tracebacks. Calling it with
741 749 tb_offset=1 allows use of this handler in interpreters which will have
742 750 their own code at the top of the traceback (VerboseTB will first
743 751 remove that frame before printing the traceback info)."""
744 752 TBTools.__init__(
745 753 self,
746 754 color_scheme=color_scheme,
747 755 call_pdb=call_pdb,
748 756 ostream=ostream,
749 757 parent=parent,
750 758 config=config,
751 759 debugger_cls=debugger_cls,
752 760 )
753 761 self.tb_offset = tb_offset
754 762 self.long_header = long_header
755 763 self.include_vars = include_vars
756 764 # By default we use linecache.checkcache, but the user can provide a
757 765 # different check_cache implementation. This was formerly used by the
758 766 # IPython kernel for interactive code, but is no longer necessary.
759 767 if check_cache is None:
760 768 check_cache = linecache.checkcache
761 769 self.check_cache = check_cache
762 770
763 771 self.skip_hidden = True
764 772
765 773 def format_record(self, frame_info: FrameInfo):
766 774 """Format a single stack frame"""
767 775 assert isinstance(frame_info, FrameInfo)
768 776 Colors = self.Colors # just a shorthand + quicker name lookup
769 777 ColorsNormal = Colors.Normal # used a lot
770 778
771 779 if isinstance(frame_info._sd, stack_data.RepeatedFrames):
772 780 return ' %s[... skipping similar frames: %s]%s\n' % (
773 781 Colors.excName, frame_info.description, ColorsNormal)
774 782
775 783 indent = " " * INDENT_SIZE
776 784 em_normal = "%s\n%s%s" % (Colors.valEm, indent, ColorsNormal)
777 785 tpl_call = f"in {Colors.vName}{{file}}{Colors.valEm}{{scope}}{ColorsNormal}"
778 786 tpl_call_fail = "in %s%%s%s(***failed resolving arguments***)%s" % (
779 787 Colors.vName,
780 788 Colors.valEm,
781 789 ColorsNormal,
782 790 )
783 791 tpl_name_val = "%%s %s= %%s%s" % (Colors.valEm, ColorsNormal)
784 792
785 793 link = _format_filename(
786 794 frame_info.filename,
787 795 Colors.filenameEm,
788 796 ColorsNormal,
789 797 lineno=frame_info.lineno,
790 798 )
791 799 args, varargs, varkw, locals_ = inspect.getargvalues(frame_info.frame)
792 800 if frame_info.executing is not None:
793 801 func = frame_info.executing.code_qualname()
794 802 else:
795 803 func = "?"
796 804 if func == "<module>":
797 805 call = ""
798 806 else:
799 807 # Decide whether to include variable details or not
800 808 var_repr = eqrepr if self.include_vars else nullrepr
801 809 try:
802 810 scope = inspect.formatargvalues(
803 811 args, varargs, varkw, locals_, formatvalue=var_repr
804 812 )
805 813 call = tpl_call.format(file=func, scope=scope)
806 814 except KeyError:
807 815 # This happens in situations like errors inside generator
808 816 # expressions, where local variables are listed in the
809 817 # line, but can't be extracted from the frame. I'm not
810 818 # 100% sure this isn't actually a bug in inspect itself,
811 819 # but since there's no info for us to compute with, the
812 820 # best we can do is report the failure and move on. Here
813 821 # we must *not* call any traceback construction again,
814 822 # because that would mess up use of %debug later on. So we
815 823 # simply report the failure and move on. The only
816 824 # limitation will be that this frame won't have locals
817 825 # listed in the call signature. Quite subtle problem...
818 826 # I can't think of a good way to validate this in a unit
819 827 # test, but running a script consisting of:
820 828 # dict( (k,v.strip()) for (k,v) in range(10) )
821 829 # will illustrate the error, if this exception catch is
822 830 # disabled.
823 831 call = tpl_call_fail % func
824 832
825 833 lvals = ''
826 834 lvals_list = []
827 835 if self.include_vars:
828 836 try:
829 837 # we likely want to fix stackdata at some point, but
830 838 # still need a workaround.
831 839 fibp = frame_info.variables_in_executing_piece
832 840 for var in fibp:
833 841 lvals_list.append(tpl_name_val % (var.name, repr(var.value)))
834 842 except Exception:
835 843 lvals_list.append(
836 844 "Exception trying to inspect frame. No more locals available."
837 845 )
838 846 if lvals_list:
839 847 lvals = '%s%s' % (indent, em_normal.join(lvals_list))
840 848
841 849 result = f'{link}{", " if call else ""}{call}\n'
842 850 if frame_info._sd is None:
843 851 assert False
844 852 # fast fallback if file is too long
845 853 tpl_link = "%s%%s%s" % (Colors.filenameEm, ColorsNormal)
846 854 link = tpl_link % util_path.compress_user(frame_info.filename)
847 855 level = "%s %s\n" % (link, call)
848 856 _line_format = PyColorize.Parser(
849 857 style=self.color_scheme_table.active_scheme_name, parent=self
850 858 ).format2
851 859 first_line = frame_info.code.co_firstlineno
852 860 current_line = frame_info.lineno[0]
853 861 return "%s%s" % (
854 862 level,
855 863 "".join(
856 864 _simple_format_traceback_lines(
857 865 current_line,
858 866 current_line - first_line,
859 867 frame_info.raw_lines,
860 868 Colors,
861 869 lvals,
862 870 _line_format,
863 871 )
864 872 ),
865 873 )
866 874 # result += "\n".join(frame_info.raw_lines)
867 875 else:
868 876 result += "".join(
869 877 _format_traceback_lines(
870 878 frame_info.lines, Colors, self.has_colors, lvals
871 879 )
872 880 )
873 881 return result
874 882
875 def prepare_header(self, etype, long_version=False):
883 def prepare_header(self, etype: str, long_version: bool = False):
876 884 colors = self.Colors # just a shorthand + quicker name lookup
877 885 colorsnormal = colors.Normal # used a lot
878 886 exc = '%s%s%s' % (colors.excName, etype, colorsnormal)
879 887 width = min(75, get_terminal_size()[0])
880 888 if long_version:
881 889 # Header with the exception type, python version, and date
882 890 pyver = 'Python ' + sys.version.split()[0] + ': ' + sys.executable
883 891 date = time.ctime(time.time())
884 892
885 head = '%s%s%s\n%s%s%s\n%s' % (colors.topline, '-' * width, colorsnormal,
886 exc, ' ' * (width - len(str(etype)) - len(pyver)),
887 pyver, date.rjust(width) )
888 head += "\nA problem occurred executing Python code. Here is the sequence of function" \
889 "\ncalls leading up to the error, with the most recent (innermost) call last."
893 head = "%s%s%s\n%s%s%s\n%s" % (
894 colors.topline,
895 "-" * width,
896 colorsnormal,
897 exc,
898 " " * (width - len(etype) - len(pyver)),
899 pyver,
900 date.rjust(width),
901 )
902 head += (
903 "\nA problem occurred executing Python code. Here is the sequence of function"
904 "\ncalls leading up to the error, with the most recent (innermost) call last."
905 )
890 906 else:
891 907 # Simplified header
892 head = '%s%s' % (exc, 'Traceback (most recent call last)'. \
893 rjust(width - len(str(etype))) )
908 head = "%s%s" % (
909 exc,
910 "Traceback (most recent call last)".rjust(width - len(etype)),
911 )
894 912
895 913 return head
896 914
897 915 def format_exception(self, etype, evalue):
898 916 colors = self.Colors # just a shorthand + quicker name lookup
899 917 colorsnormal = colors.Normal # used a lot
900 918 # Get (safely) a string form of the exception info
901 919 try:
902 920 etype_str, evalue_str = map(str, (etype, evalue))
903 921 except:
904 922 # User exception is improperly defined.
905 923 etype, evalue = str, sys.exc_info()[:2]
906 924 etype_str, evalue_str = map(str, (etype, evalue))
907 925 # ... and format it
908 926 return ['%s%s%s: %s' % (colors.excName, etype_str,
909 927 colorsnormal, py3compat.cast_unicode(evalue_str))]
910 928
911 929 def format_exception_as_a_whole(
912 930 self,
913 931 etype: type,
914 evalue: BaseException,
932 evalue: Optional[BaseException],
915 933 etb: Optional[TracebackType],
916 934 number_of_lines_of_context,
917 935 tb_offset: Optional[int],
918 936 ):
919 937 """Formats the header, traceback and exception message for a single exception.
920 938
921 939 This may be called multiple times by Python 3 exception chaining
922 940 (PEP 3134).
923 941 """
924 942 # some locals
925 943 orig_etype = etype
926 944 try:
927 945 etype = etype.__name__
928 946 except AttributeError:
929 947 pass
930 948
931 949 tb_offset = self.tb_offset if tb_offset is None else tb_offset
932 950 assert isinstance(tb_offset, int)
933 951 head = self.prepare_header(etype, self.long_header)
934 952 records = (
935 953 self.get_records(etb, number_of_lines_of_context, tb_offset) if etb else []
936 954 )
937 955
938 956 frames = []
939 957 skipped = 0
940 958 lastrecord = len(records) - 1
941 959 for i, record in enumerate(records):
942 960 if (
943 961 not isinstance(record._sd, stack_data.RepeatedFrames)
944 962 and self.skip_hidden
945 963 ):
946 964 if (
947 965 record.frame.f_locals.get("__tracebackhide__", 0)
948 966 and i != lastrecord
949 967 ):
950 968 skipped += 1
951 969 continue
952 970 if skipped:
953 971 Colors = self.Colors # just a shorthand + quicker name lookup
954 972 ColorsNormal = Colors.Normal # used a lot
955 973 frames.append(
956 974 " %s[... skipping hidden %s frame]%s\n"
957 975 % (Colors.excName, skipped, ColorsNormal)
958 976 )
959 977 skipped = 0
960 978 frames.append(self.format_record(record))
961 979 if skipped:
962 980 Colors = self.Colors # just a shorthand + quicker name lookup
963 981 ColorsNormal = Colors.Normal # used a lot
964 982 frames.append(
965 983 " %s[... skipping hidden %s frame]%s\n"
966 984 % (Colors.excName, skipped, ColorsNormal)
967 985 )
968 986
969 987 formatted_exception = self.format_exception(etype, evalue)
970 988 if records:
971 989 frame_info = records[-1]
972 990 ipinst = get_ipython()
973 991 if ipinst is not None:
974 992 ipinst.hooks.synchronize_with_editor(frame_info.filename, frame_info.lineno, 0)
975 993
976 994 return [[head] + frames + [''.join(formatted_exception[0])]]
977 995
978 996 def get_records(
979 997 self, etb: TracebackType, number_of_lines_of_context: int, tb_offset: int
980 998 ):
981 999 assert etb is not None
982 1000 context = number_of_lines_of_context - 1
983 1001 after = context // 2
984 1002 before = context - after
985 1003 if self.has_colors:
986 1004 style = get_style_by_name("default")
987 1005 style = stack_data.style_with_executing_node(style, self._tb_highlight)
988 1006 formatter = Terminal256Formatter(style=style)
989 1007 else:
990 1008 formatter = None
991 1009 options = stack_data.Options(
992 1010 before=before,
993 1011 after=after,
994 1012 pygments_formatter=formatter,
995 1013 )
996 1014
997 1015 # Let's estimate the amount of code we will have to parse/highlight.
998 cf = etb
1016 cf: Optional[TracebackType] = etb
999 1017 max_len = 0
1000 1018 tbs = []
1001 1019 while cf is not None:
1002 1020 source_file = inspect.getsourcefile(etb.tb_frame)
1003 1021 lines, first = inspect.getsourcelines(etb.tb_frame)
1004 1022 max_len = max(max_len, first + len(lines))
1005 1023 tbs.append(cf)
1006 1024 cf = cf.tb_next
1007 1025
1008 1026 if max_len > FAST_THRESHOLD:
1009 1027 FIs = []
1010 1028 for tb in tbs:
1011 1029 frame = tb.tb_frame
1012 1030 lineno = (frame.f_lineno,)
1013 1031 code = frame.f_code
1014 1032 filename = code.co_filename
1015 1033 FIs.append(FrameInfo("Raw frame", filename, lineno, frame, code))
1016 1034 return FIs
1017 1035 res = list(stack_data.FrameInfo.stack_data(etb, options=options))[tb_offset:]
1018 1036 res = [FrameInfo._from_stack_data_FrameInfo(r) for r in res]
1019 1037 return res
1020 1038
1021 1039 def structured_traceback(
1022 1040 self,
1023 1041 etype: type,
1024 1042 evalue: Optional[BaseException],
1025 1043 etb: Optional[TracebackType],
1026 1044 tb_offset: Optional[int] = None,
1027 1045 number_of_lines_of_context: int = 5,
1028 1046 ):
1029 1047 """Return a nice text document describing the traceback."""
1030 1048 formatted_exception = self.format_exception_as_a_whole(etype, evalue, etb, number_of_lines_of_context,
1031 1049 tb_offset)
1032 1050
1033 1051 colors = self.Colors # just a shorthand + quicker name lookup
1034 1052 colorsnormal = colors.Normal # used a lot
1035 1053 head = '%s%s%s' % (colors.topline, '-' * min(75, get_terminal_size()[0]), colorsnormal)
1036 1054 structured_traceback_parts = [head]
1037 1055 chained_exceptions_tb_offset = 0
1038 1056 lines_of_context = 3
1039 1057 formatted_exceptions = formatted_exception
1040 1058 exception = self.get_parts_of_chained_exception(evalue)
1041 1059 if exception:
1042 1060 assert evalue is not None
1043 1061 formatted_exceptions += self.prepare_chained_exception_message(evalue.__cause__)
1044 1062 etype, evalue, etb = exception
1045 1063 else:
1046 1064 evalue = None
1047 1065 chained_exc_ids = set()
1048 1066 while evalue:
1049 1067 formatted_exceptions += self.format_exception_as_a_whole(etype, evalue, etb, lines_of_context,
1050 1068 chained_exceptions_tb_offset)
1051 1069 exception = self.get_parts_of_chained_exception(evalue)
1052 1070
1053 1071 if exception and not id(exception[1]) in chained_exc_ids:
1054 1072 chained_exc_ids.add(id(exception[1])) # trace exception to avoid infinite 'cause' loop
1055 1073 formatted_exceptions += self.prepare_chained_exception_message(evalue.__cause__)
1056 1074 etype, evalue, etb = exception
1057 1075 else:
1058 1076 evalue = None
1059 1077
1060 1078 # we want to see exceptions in a reversed order:
1061 1079 # the first exception should be on top
1062 1080 for formatted_exception in reversed(formatted_exceptions):
1063 1081 structured_traceback_parts += formatted_exception
1064 1082
1065 1083 return structured_traceback_parts
1066 1084
1067 1085 def debugger(self, force: bool = False):
1068 1086 """Call up the pdb debugger if desired, always clean up the tb
1069 1087 reference.
1070 1088
1071 1089 Keywords:
1072 1090
1073 1091 - force(False): by default, this routine checks the instance call_pdb
1074 1092 flag and does not actually invoke the debugger if the flag is false.
1075 1093 The 'force' option forces the debugger to activate even if the flag
1076 1094 is false.
1077 1095
1078 1096 If the call_pdb flag is set, the pdb interactive debugger is
1079 1097 invoked. In all cases, the self.tb reference to the current traceback
1080 1098 is deleted to prevent lingering references which hamper memory
1081 1099 management.
1082 1100
1083 1101 Note that each call to pdb() does an 'import readline', so if your app
1084 1102 requires a special setup for the readline completers, you'll have to
1085 1103 fix that by hand after invoking the exception handler."""
1086 1104
1087 1105 if force or self.call_pdb:
1088 1106 if self.pdb is None:
1089 1107 self.pdb = self.debugger_cls()
1090 1108 # the system displayhook may have changed, restore the original
1091 1109 # for pdb
1092 1110 display_trap = DisplayTrap(hook=sys.__displayhook__)
1093 1111 with display_trap:
1094 1112 self.pdb.reset()
1095 1113 # Find the right frame so we don't pop up inside ipython itself
1096 1114 if hasattr(self, 'tb') and self.tb is not None:
1097 1115 etb = self.tb
1098 1116 else:
1099 1117 etb = self.tb = sys.last_traceback
1100 1118 while self.tb is not None and self.tb.tb_next is not None:
1101 1119 assert self.tb.tb_next is not None
1102 1120 self.tb = self.tb.tb_next
1103 1121 if etb and etb.tb_next:
1104 1122 etb = etb.tb_next
1105 1123 self.pdb.botframe = etb.tb_frame
1106 1124 self.pdb.interaction(None, etb)
1107 1125
1108 1126 if hasattr(self, 'tb'):
1109 1127 del self.tb
1110 1128
1111 1129 def handler(self, info=None):
1112 1130 (etype, evalue, etb) = info or sys.exc_info()
1113 1131 self.tb = etb
1114 1132 ostream = self.ostream
1115 1133 ostream.flush()
1116 1134 ostream.write(self.text(etype, evalue, etb))
1117 1135 ostream.write('\n')
1118 1136 ostream.flush()
1119 1137
1120 1138 # Changed so an instance can just be called as VerboseTB_inst() and print
1121 1139 # out the right info on its own.
1122 1140 def __call__(self, etype=None, evalue=None, etb=None):
1123 1141 """This hook can replace sys.excepthook (for Python 2.1 or higher)."""
1124 1142 if etb is None:
1125 1143 self.handler()
1126 1144 else:
1127 1145 self.handler((etype, evalue, etb))
1128 1146 try:
1129 1147 self.debugger()
1130 1148 except KeyboardInterrupt:
1131 1149 print("\nKeyboardInterrupt")
1132 1150
1133 1151
1134 1152 #----------------------------------------------------------------------------
1135 1153 class FormattedTB(VerboseTB, ListTB):
1136 1154 """Subclass ListTB but allow calling with a traceback.
1137 1155
1138 1156 It can thus be used as a sys.excepthook for Python > 2.1.
1139 1157
1140 1158 Also adds 'Context' and 'Verbose' modes, not available in ListTB.
1141 1159
1142 1160 Allows a tb_offset to be specified. This is useful for situations where
1143 1161 one needs to remove a number of topmost frames from the traceback (such as
1144 1162 occurs with python programs that themselves execute other python code,
1145 1163 like Python shells). """
1146 1164
1147 1165 mode: str
1148 1166
1149 1167 def __init__(self, mode='Plain', color_scheme='Linux', call_pdb=False,
1150 1168 ostream=None,
1151 1169 tb_offset=0, long_header=False, include_vars=False,
1152 1170 check_cache=None, debugger_cls=None,
1153 1171 parent=None, config=None):
1154 1172
1155 1173 # NEVER change the order of this list. Put new modes at the end:
1156 1174 self.valid_modes = ['Plain', 'Context', 'Verbose', 'Minimal']
1157 1175 self.verbose_modes = self.valid_modes[1:3]
1158 1176
1159 1177 VerboseTB.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
1160 1178 ostream=ostream, tb_offset=tb_offset,
1161 1179 long_header=long_header, include_vars=include_vars,
1162 1180 check_cache=check_cache, debugger_cls=debugger_cls,
1163 1181 parent=parent, config=config)
1164 1182
1165 1183 # Different types of tracebacks are joined with different separators to
1166 1184 # form a single string. They are taken from this dict
1167 1185 self._join_chars = dict(Plain='', Context='\n', Verbose='\n',
1168 1186 Minimal='')
1169 1187 # set_mode also sets the tb_join_char attribute
1170 1188 self.set_mode(mode)
1171 1189
1172 1190 def structured_traceback(self, etype, value, tb, tb_offset=None, number_of_lines_of_context=5):
1173 1191 tb_offset = self.tb_offset if tb_offset is None else tb_offset
1174 1192 mode = self.mode
1175 1193 if mode in self.verbose_modes:
1176 1194 # Verbose modes need a full traceback
1177 1195 return VerboseTB.structured_traceback(
1178 1196 self, etype, value, tb, tb_offset, number_of_lines_of_context
1179 1197 )
1180 1198 elif mode == 'Minimal':
1181 1199 return ListTB.get_exception_only(self, etype, value)
1182 1200 else:
1183 1201 # We must check the source cache because otherwise we can print
1184 1202 # out-of-date source code.
1185 1203 self.check_cache()
1186 1204 # Now we can extract and format the exception
1187 1205 return ListTB.structured_traceback(
1188 1206 self, etype, value, tb, tb_offset, number_of_lines_of_context
1189 1207 )
1190 1208
1191 1209 def stb2text(self, stb):
1192 1210 """Convert a structured traceback (a list) to a string."""
1193 1211 return self.tb_join_char.join(stb)
1194 1212
1195 1213 def set_mode(self, mode: Optional[str] = None):
1196 1214 """Switch to the desired mode.
1197 1215
1198 1216 If mode is not specified, cycles through the available modes."""
1199 1217
1200 1218 if not mode:
1201 1219 new_idx = (self.valid_modes.index(self.mode) + 1 ) % \
1202 1220 len(self.valid_modes)
1203 1221 self.mode = self.valid_modes[new_idx]
1204 1222 elif mode not in self.valid_modes:
1205 1223 raise ValueError(
1206 1224 "Unrecognized mode in FormattedTB: <" + mode + ">\n"
1207 1225 "Valid modes: " + str(self.valid_modes)
1208 1226 )
1209 1227 else:
1210 1228 assert isinstance(mode, str)
1211 1229 self.mode = mode
1212 1230 # include variable details only in 'Verbose' mode
1213 1231 self.include_vars = (self.mode == self.valid_modes[2])
1214 1232 # Set the join character for generating text tracebacks
1215 1233 self.tb_join_char = self._join_chars[self.mode]
1216 1234
1217 1235 # some convenient shortcuts
1218 1236 def plain(self):
1219 1237 self.set_mode(self.valid_modes[0])
1220 1238
1221 1239 def context(self):
1222 1240 self.set_mode(self.valid_modes[1])
1223 1241
1224 1242 def verbose(self):
1225 1243 self.set_mode(self.valid_modes[2])
1226 1244
1227 1245 def minimal(self):
1228 1246 self.set_mode(self.valid_modes[3])
1229 1247
1230 1248
1231 1249 #----------------------------------------------------------------------------
1232 1250 class AutoFormattedTB(FormattedTB):
1233 1251 """A traceback printer which can be called on the fly.
1234 1252
1235 1253 It will find out about exceptions by itself.
1236 1254
1237 1255 A brief example::
1238 1256
1239 1257 AutoTB = AutoFormattedTB(mode = 'Verbose',color_scheme='Linux')
1240 1258 try:
1241 1259 ...
1242 1260 except:
1243 1261 AutoTB() # or AutoTB(out=logfile) where logfile is an open file object
1244 1262 """
1245 1263
1246 1264 def __call__(self, etype=None, evalue=None, etb=None,
1247 1265 out=None, tb_offset=None):
1248 1266 """Print out a formatted exception traceback.
1249 1267
1250 1268 Optional arguments:
1251 1269 - out: an open file-like object to direct output to.
1252 1270
1253 1271 - tb_offset: the number of frames to skip over in the stack, on a
1254 1272 per-call basis (this overrides temporarily the instance's tb_offset
1255 1273 given at initialization time."""
1256 1274
1257 1275 if out is None:
1258 1276 out = self.ostream
1259 1277 out.flush()
1260 1278 out.write(self.text(etype, evalue, etb, tb_offset))
1261 1279 out.write('\n')
1262 1280 out.flush()
1263 1281 # FIXME: we should remove the auto pdb behavior from here and leave
1264 1282 # that to the clients.
1265 1283 try:
1266 1284 self.debugger()
1267 1285 except KeyboardInterrupt:
1268 1286 print("\nKeyboardInterrupt")
1269 1287
1270 1288 def structured_traceback(
1271 1289 self,
1272 1290 etype=None,
1273 1291 value=None,
1274 1292 tb=None,
1275 1293 tb_offset=None,
1276 1294 number_of_lines_of_context=5,
1277 1295 ):
1278 1296 etype: type
1279 1297 value: BaseException
1280 1298 # tb: TracebackType or tupleof tb types ?
1281 1299 if etype is None:
1282 1300 etype, value, tb = sys.exc_info()
1283 1301 if isinstance(tb, tuple):
1284 1302 # tb is a tuple if this is a chained exception.
1285 1303 self.tb = tb[0]
1286 1304 else:
1287 1305 self.tb = tb
1288 1306 return FormattedTB.structured_traceback(
1289 1307 self, etype, value, tb, tb_offset, number_of_lines_of_context)
1290 1308
1291 1309
1292 1310 #---------------------------------------------------------------------------
1293 1311
1294 1312 # A simple class to preserve Nathan's original functionality.
1295 1313 class ColorTB(FormattedTB):
1296 1314 """Shorthand to initialize a FormattedTB in Linux colors mode."""
1297 1315
1298 1316 def __init__(self, color_scheme='Linux', call_pdb=0, **kwargs):
1299 1317 FormattedTB.__init__(self, color_scheme=color_scheme,
1300 1318 call_pdb=call_pdb, **kwargs)
1301 1319
1302 1320
1303 1321 class SyntaxTB(ListTB):
1304 1322 """Extension which holds some state: the last exception value"""
1305 1323
1306 1324 def __init__(self, color_scheme='NoColor', parent=None, config=None):
1307 1325 ListTB.__init__(self, color_scheme, parent=parent, config=config)
1308 1326 self.last_syntax_error = None
1309 1327
1310 1328 def __call__(self, etype, value, elist):
1311 1329 self.last_syntax_error = value
1312 1330
1313 1331 ListTB.__call__(self, etype, value, elist)
1314 1332
1315 1333 def structured_traceback(self, etype, value, elist, tb_offset=None,
1316 1334 context=5):
1317 1335 # If the source file has been edited, the line in the syntax error can
1318 1336 # be wrong (retrieved from an outdated cache). This replaces it with
1319 1337 # the current value.
1320 1338 if isinstance(value, SyntaxError) \
1321 1339 and isinstance(value.filename, str) \
1322 1340 and isinstance(value.lineno, int):
1323 1341 linecache.checkcache(value.filename)
1324 1342 newtext = linecache.getline(value.filename, value.lineno)
1325 1343 if newtext:
1326 1344 value.text = newtext
1327 1345 self.last_syntax_error = value
1328 1346 return super(SyntaxTB, self).structured_traceback(etype, value, elist,
1329 1347 tb_offset=tb_offset, context=context)
1330 1348
1331 1349 def clear_err_state(self):
1332 1350 """Return the current error state and clear it"""
1333 1351 e = self.last_syntax_error
1334 1352 self.last_syntax_error = None
1335 1353 return e
1336 1354
1337 1355 def stb2text(self, stb):
1338 1356 """Convert a structured traceback (a list) to a string."""
1339 1357 return ''.join(stb)
1340 1358
1341 1359
1342 1360 # some internal-use functions
1343 1361 def text_repr(value):
1344 1362 """Hopefully pretty robust repr equivalent."""
1345 1363 # this is pretty horrible but should always return *something*
1346 1364 try:
1347 1365 return pydoc.text.repr(value)
1348 1366 except KeyboardInterrupt:
1349 1367 raise
1350 1368 except:
1351 1369 try:
1352 1370 return repr(value)
1353 1371 except KeyboardInterrupt:
1354 1372 raise
1355 1373 except:
1356 1374 try:
1357 1375 # all still in an except block so we catch
1358 1376 # getattr raising
1359 1377 name = getattr(value, '__name__', None)
1360 1378 if name:
1361 1379 # ick, recursion
1362 1380 return text_repr(name)
1363 1381 klass = getattr(value, '__class__', None)
1364 1382 if klass:
1365 1383 return '%s instance' % text_repr(klass)
1366 1384 except KeyboardInterrupt:
1367 1385 raise
1368 1386 except:
1369 1387 return 'UNRECOVERABLE REPR FAILURE'
1370 1388
1371 1389
1372 1390 def eqrepr(value, repr=text_repr):
1373 1391 return '=%s' % repr(value)
1374 1392
1375 1393
1376 1394 def nullrepr(value, repr=text_repr):
1377 1395 return ''
@@ -1,675 +1,677 b''
1 1 """Various display related classes.
2 2
3 3 Authors : MinRK, gregcaporaso, dannystaple
4 4 """
5 5 from html import escape as html_escape
6 6 from os.path import exists, isfile, splitext, abspath, join, isdir
7 7 from os import walk, sep, fsdecode
8 8
9 9 from IPython.core.display import DisplayObject, TextDisplayObject
10 10
11 from typing import Tuple, Iterable
11 from typing import Tuple, Iterable, Optional
12 12
13 13 __all__ = ['Audio', 'IFrame', 'YouTubeVideo', 'VimeoVideo', 'ScribdDocument',
14 14 'FileLink', 'FileLinks', 'Code']
15 15
16 16
17 17 class Audio(DisplayObject):
18 18 """Create an audio object.
19 19
20 20 When this object is returned by an input cell or passed to the
21 21 display function, it will result in Audio controls being displayed
22 22 in the frontend (only works in the notebook).
23 23
24 24 Parameters
25 25 ----------
26 26 data : numpy array, list, unicode, str or bytes
27 27 Can be one of
28 28
29 29 * Numpy 1d array containing the desired waveform (mono)
30 30 * Numpy 2d array containing waveforms for each channel.
31 31 Shape=(NCHAN, NSAMPLES). For the standard channel order, see
32 32 http://msdn.microsoft.com/en-us/library/windows/hardware/dn653308(v=vs.85).aspx
33 33 * List of float or integer representing the waveform (mono)
34 34 * String containing the filename
35 35 * Bytestring containing raw PCM data or
36 36 * URL pointing to a file on the web.
37 37
38 38 If the array option is used, the waveform will be normalized.
39 39
40 40 If a filename or url is used, the format support will be browser
41 41 dependent.
42 42 url : unicode
43 43 A URL to download the data from.
44 44 filename : unicode
45 45 Path to a local file to load the data from.
46 46 embed : boolean
47 47 Should the audio data be embedded using a data URI (True) or should
48 48 the original source be referenced. Set this to True if you want the
49 49 audio to playable later with no internet connection in the notebook.
50 50
51 51 Default is `True`, unless the keyword argument `url` is set, then
52 52 default value is `False`.
53 53 rate : integer
54 54 The sampling rate of the raw data.
55 55 Only required when data parameter is being used as an array
56 56 autoplay : bool
57 57 Set to True if the audio should immediately start playing.
58 58 Default is `False`.
59 59 normalize : bool
60 60 Whether audio should be normalized (rescaled) to the maximum possible
61 61 range. Default is `True`. When set to `False`, `data` must be between
62 62 -1 and 1 (inclusive), otherwise an error is raised.
63 63 Applies only when `data` is a list or array of samples; other types of
64 64 audio are never normalized.
65 65
66 66 Examples
67 67 --------
68 68
69 69 >>> import pytest
70 70 >>> np = pytest.importorskip("numpy")
71 71
72 72 Generate a sound
73 73
74 74 >>> import numpy as np
75 75 >>> framerate = 44100
76 76 >>> t = np.linspace(0,5,framerate*5)
77 77 >>> data = np.sin(2*np.pi*220*t) + np.sin(2*np.pi*224*t)
78 78 >>> Audio(data, rate=framerate)
79 79 <IPython.lib.display.Audio object>
80 80
81 81 Can also do stereo or more channels
82 82
83 83 >>> dataleft = np.sin(2*np.pi*220*t)
84 84 >>> dataright = np.sin(2*np.pi*224*t)
85 85 >>> Audio([dataleft, dataright], rate=framerate)
86 86 <IPython.lib.display.Audio object>
87 87
88 88 From URL:
89 89
90 90 >>> Audio("http://www.nch.com.au/acm/8k16bitpcm.wav") # doctest: +SKIP
91 91 >>> Audio(url="http://www.w3schools.com/html/horse.ogg") # doctest: +SKIP
92 92
93 93 From a File:
94 94
95 95 >>> Audio('IPython/lib/tests/test.wav') # doctest: +SKIP
96 96 >>> Audio(filename='IPython/lib/tests/test.wav') # doctest: +SKIP
97 97
98 98 From Bytes:
99 99
100 100 >>> Audio(b'RAW_WAV_DATA..') # doctest: +SKIP
101 101 >>> Audio(data=b'RAW_WAV_DATA..') # doctest: +SKIP
102 102
103 103 See Also
104 104 --------
105 105 ipywidgets.Audio
106 106
107 107 Audio widget with more more flexibility and options.
108 108
109 109 """
110 110 _read_flags = 'rb'
111 111
112 112 def __init__(self, data=None, filename=None, url=None, embed=None, rate=None, autoplay=False, normalize=True, *,
113 113 element_id=None):
114 114 if filename is None and url is None and data is None:
115 115 raise ValueError("No audio data found. Expecting filename, url, or data.")
116 116 if embed is False and url is None:
117 117 raise ValueError("No url found. Expecting url when embed=False")
118 118
119 119 if url is not None and embed is not True:
120 120 self.embed = False
121 121 else:
122 122 self.embed = True
123 123 self.autoplay = autoplay
124 124 self.element_id = element_id
125 125 super(Audio, self).__init__(data=data, url=url, filename=filename)
126 126
127 127 if self.data is not None and not isinstance(self.data, bytes):
128 128 if rate is None:
129 129 raise ValueError("rate must be specified when data is a numpy array or list of audio samples.")
130 130 self.data = Audio._make_wav(data, rate, normalize)
131 131
132 132 def reload(self):
133 133 """Reload the raw data from file or URL."""
134 134 import mimetypes
135 135 if self.embed:
136 136 super(Audio, self).reload()
137 137
138 138 if self.filename is not None:
139 139 self.mimetype = mimetypes.guess_type(self.filename)[0]
140 140 elif self.url is not None:
141 141 self.mimetype = mimetypes.guess_type(self.url)[0]
142 142 else:
143 143 self.mimetype = "audio/wav"
144 144
145 145 @staticmethod
146 146 def _make_wav(data, rate, normalize):
147 147 """ Transform a numpy array to a PCM bytestring """
148 148 from io import BytesIO
149 149 import wave
150 150
151 151 try:
152 152 scaled, nchan = Audio._validate_and_normalize_with_numpy(data, normalize)
153 153 except ImportError:
154 154 scaled, nchan = Audio._validate_and_normalize_without_numpy(data, normalize)
155 155
156 156 fp = BytesIO()
157 157 waveobj = wave.open(fp,mode='wb')
158 158 waveobj.setnchannels(nchan)
159 159 waveobj.setframerate(rate)
160 160 waveobj.setsampwidth(2)
161 161 waveobj.setcomptype('NONE','NONE')
162 162 waveobj.writeframes(scaled)
163 163 val = fp.getvalue()
164 164 waveobj.close()
165 165
166 166 return val
167 167
168 168 @staticmethod
169 169 def _validate_and_normalize_with_numpy(data, normalize) -> Tuple[bytes, int]:
170 170 import numpy as np
171 171
172 172 data = np.array(data, dtype=float)
173 173 if len(data.shape) == 1:
174 174 nchan = 1
175 175 elif len(data.shape) == 2:
176 176 # In wave files,channels are interleaved. E.g.,
177 177 # "L1R1L2R2..." for stereo. See
178 178 # http://msdn.microsoft.com/en-us/library/windows/hardware/dn653308(v=vs.85).aspx
179 179 # for channel ordering
180 180 nchan = data.shape[0]
181 181 data = data.T.ravel()
182 182 else:
183 183 raise ValueError('Array audio input must be a 1D or 2D array')
184 184
185 185 max_abs_value = np.max(np.abs(data))
186 186 normalization_factor = Audio._get_normalization_factor(max_abs_value, normalize)
187 187 scaled = data / normalization_factor * 32767
188 188 return scaled.astype("<h").tobytes(), nchan
189 189
190 190 @staticmethod
191 191 def _validate_and_normalize_without_numpy(data, normalize):
192 192 import array
193 193 import sys
194 194
195 195 data = array.array('f', data)
196 196
197 197 try:
198 198 max_abs_value = float(max([abs(x) for x in data]))
199 199 except TypeError as e:
200 200 raise TypeError('Only lists of mono audio are '
201 201 'supported if numpy is not installed') from e
202 202
203 203 normalization_factor = Audio._get_normalization_factor(max_abs_value, normalize)
204 204 scaled = array.array('h', [int(x / normalization_factor * 32767) for x in data])
205 205 if sys.byteorder == 'big':
206 206 scaled.byteswap()
207 207 nchan = 1
208 208 return scaled.tobytes(), nchan
209 209
210 210 @staticmethod
211 211 def _get_normalization_factor(max_abs_value, normalize):
212 212 if not normalize and max_abs_value > 1:
213 213 raise ValueError('Audio data must be between -1 and 1 when normalize=False.')
214 214 return max_abs_value if normalize else 1
215 215
216 216 def _data_and_metadata(self):
217 217 """shortcut for returning metadata with url information, if defined"""
218 218 md = {}
219 219 if self.url:
220 220 md['url'] = self.url
221 221 if md:
222 222 return self.data, md
223 223 else:
224 224 return self.data
225 225
226 226 def _repr_html_(self):
227 227 src = """
228 228 <audio {element_id} controls="controls" {autoplay}>
229 229 <source src="{src}" type="{type}" />
230 230 Your browser does not support the audio element.
231 231 </audio>
232 232 """
233 233 return src.format(src=self.src_attr(), type=self.mimetype, autoplay=self.autoplay_attr(),
234 234 element_id=self.element_id_attr())
235 235
236 236 def src_attr(self):
237 237 import base64
238 238 if self.embed and (self.data is not None):
239 239 data = base64=base64.b64encode(self.data).decode('ascii')
240 240 return """data:{type};base64,{base64}""".format(type=self.mimetype,
241 241 base64=data)
242 242 elif self.url is not None:
243 243 return self.url
244 244 else:
245 245 return ""
246 246
247 247 def autoplay_attr(self):
248 248 if(self.autoplay):
249 249 return 'autoplay="autoplay"'
250 250 else:
251 251 return ''
252 252
253 253 def element_id_attr(self):
254 254 if (self.element_id):
255 255 return 'id="{element_id}"'.format(element_id=self.element_id)
256 256 else:
257 257 return ''
258 258
259 259 class IFrame(object):
260 260 """
261 261 Generic class to embed an iframe in an IPython notebook
262 262 """
263 263
264 264 iframe = """
265 265 <iframe
266 266 width="{width}"
267 267 height="{height}"
268 268 src="{src}{params}"
269 269 frameborder="0"
270 270 allowfullscreen
271 271 {extras}
272 272 ></iframe>
273 273 """
274 274
275 def __init__(self, src, width, height, extras: Iterable[str] = None, **kwargs):
275 def __init__(
276 self, src, width, height, extras: Optional[Iterable[str]] = None, **kwargs
277 ):
276 278 if extras is None:
277 279 extras = []
278 280
279 281 self.src = src
280 282 self.width = width
281 283 self.height = height
282 284 self.extras = extras
283 285 self.params = kwargs
284 286
285 287 def _repr_html_(self):
286 288 """return the embed iframe"""
287 289 if self.params:
288 290 from urllib.parse import urlencode
289 291 params = "?" + urlencode(self.params)
290 292 else:
291 293 params = ""
292 294 return self.iframe.format(
293 295 src=self.src,
294 296 width=self.width,
295 297 height=self.height,
296 298 params=params,
297 299 extras=" ".join(self.extras),
298 300 )
299 301
300 302
301 303 class YouTubeVideo(IFrame):
302 304 """Class for embedding a YouTube Video in an IPython session, based on its video id.
303 305
304 306 e.g. to embed the video from https://www.youtube.com/watch?v=foo , you would
305 307 do::
306 308
307 309 vid = YouTubeVideo("foo")
308 310 display(vid)
309 311
310 312 To start from 30 seconds::
311 313
312 314 vid = YouTubeVideo("abc", start=30)
313 315 display(vid)
314 316
315 317 To calculate seconds from time as hours, minutes, seconds use
316 318 :class:`datetime.timedelta`::
317 319
318 320 start=int(timedelta(hours=1, minutes=46, seconds=40).total_seconds())
319 321
320 322 Other parameters can be provided as documented at
321 323 https://developers.google.com/youtube/player_parameters#Parameters
322 324
323 325 When converting the notebook using nbconvert, a jpeg representation of the video
324 326 will be inserted in the document.
325 327 """
326 328
327 329 def __init__(self, id, width=400, height=300, allow_autoplay=False, **kwargs):
328 330 self.id=id
329 331 src = "https://www.youtube.com/embed/{0}".format(id)
330 332 if allow_autoplay:
331 333 extras = list(kwargs.get("extras", [])) + ['allow="autoplay"']
332 334 kwargs.update(autoplay=1, extras=extras)
333 335 super(YouTubeVideo, self).__init__(src, width, height, **kwargs)
334 336
335 337 def _repr_jpeg_(self):
336 338 # Deferred import
337 339 from urllib.request import urlopen
338 340
339 341 try:
340 342 return urlopen("https://img.youtube.com/vi/{id}/hqdefault.jpg".format(id=self.id)).read()
341 343 except IOError:
342 344 return None
343 345
344 346 class VimeoVideo(IFrame):
345 347 """
346 348 Class for embedding a Vimeo video in an IPython session, based on its video id.
347 349 """
348 350
349 351 def __init__(self, id, width=400, height=300, **kwargs):
350 352 src="https://player.vimeo.com/video/{0}".format(id)
351 353 super(VimeoVideo, self).__init__(src, width, height, **kwargs)
352 354
353 355 class ScribdDocument(IFrame):
354 356 """
355 357 Class for embedding a Scribd document in an IPython session
356 358
357 359 Use the start_page params to specify a starting point in the document
358 360 Use the view_mode params to specify display type one off scroll | slideshow | book
359 361
360 362 e.g to Display Wes' foundational paper about PANDAS in book mode from page 3
361 363
362 364 ScribdDocument(71048089, width=800, height=400, start_page=3, view_mode="book")
363 365 """
364 366
365 367 def __init__(self, id, width=400, height=300, **kwargs):
366 368 src="https://www.scribd.com/embeds/{0}/content".format(id)
367 369 super(ScribdDocument, self).__init__(src, width, height, **kwargs)
368 370
369 371 class FileLink(object):
370 372 """Class for embedding a local file link in an IPython session, based on path
371 373
372 374 e.g. to embed a link that was generated in the IPython notebook as my/data.txt
373 375
374 376 you would do::
375 377
376 378 local_file = FileLink("my/data.txt")
377 379 display(local_file)
378 380
379 381 or in the HTML notebook, just::
380 382
381 383 FileLink("my/data.txt")
382 384 """
383 385
384 386 html_link_str = "<a href='%s' target='_blank'>%s</a>"
385 387
386 388 def __init__(self,
387 389 path,
388 390 url_prefix='',
389 391 result_html_prefix='',
390 392 result_html_suffix='<br>'):
391 393 """
392 394 Parameters
393 395 ----------
394 396 path : str
395 397 path to the file or directory that should be formatted
396 398 url_prefix : str
397 399 prefix to be prepended to all files to form a working link [default:
398 400 '']
399 401 result_html_prefix : str
400 402 text to append to beginning to link [default: '']
401 403 result_html_suffix : str
402 404 text to append at the end of link [default: '<br>']
403 405 """
404 406 if isdir(path):
405 407 raise ValueError("Cannot display a directory using FileLink. "
406 408 "Use FileLinks to display '%s'." % path)
407 409 self.path = fsdecode(path)
408 410 self.url_prefix = url_prefix
409 411 self.result_html_prefix = result_html_prefix
410 412 self.result_html_suffix = result_html_suffix
411 413
412 414 def _format_path(self):
413 415 fp = ''.join([self.url_prefix, html_escape(self.path)])
414 416 return ''.join([self.result_html_prefix,
415 417 self.html_link_str % \
416 418 (fp, html_escape(self.path, quote=False)),
417 419 self.result_html_suffix])
418 420
419 421 def _repr_html_(self):
420 422 """return html link to file
421 423 """
422 424 if not exists(self.path):
423 425 return ("Path (<tt>%s</tt>) doesn't exist. "
424 426 "It may still be in the process of "
425 427 "being generated, or you may have the "
426 428 "incorrect path." % self.path)
427 429
428 430 return self._format_path()
429 431
430 432 def __repr__(self):
431 433 """return absolute path to file
432 434 """
433 435 return abspath(self.path)
434 436
435 437 class FileLinks(FileLink):
436 438 """Class for embedding local file links in an IPython session, based on path
437 439
438 440 e.g. to embed links to files that were generated in the IPython notebook
439 441 under ``my/data``, you would do::
440 442
441 443 local_files = FileLinks("my/data")
442 444 display(local_files)
443 445
444 446 or in the HTML notebook, just::
445 447
446 448 FileLinks("my/data")
447 449 """
448 450 def __init__(self,
449 451 path,
450 452 url_prefix='',
451 453 included_suffixes=None,
452 454 result_html_prefix='',
453 455 result_html_suffix='<br>',
454 456 notebook_display_formatter=None,
455 457 terminal_display_formatter=None,
456 458 recursive=True):
457 459 """
458 460 See :class:`FileLink` for the ``path``, ``url_prefix``,
459 461 ``result_html_prefix`` and ``result_html_suffix`` parameters.
460 462
461 463 included_suffixes : list
462 464 Filename suffixes to include when formatting output [default: include
463 465 all files]
464 466
465 467 notebook_display_formatter : function
466 468 Used to format links for display in the notebook. See discussion of
467 469 formatter functions below.
468 470
469 471 terminal_display_formatter : function
470 472 Used to format links for display in the terminal. See discussion of
471 473 formatter functions below.
472 474
473 475 Formatter functions must be of the form::
474 476
475 477 f(dirname, fnames, included_suffixes)
476 478
477 479 dirname : str
478 480 The name of a directory
479 481 fnames : list
480 482 The files in that directory
481 483 included_suffixes : list
482 484 The file suffixes that should be included in the output (passing None
483 485 meansto include all suffixes in the output in the built-in formatters)
484 486 recursive : boolean
485 487 Whether to recurse into subdirectories. Default is True.
486 488
487 489 The function should return a list of lines that will be printed in the
488 490 notebook (if passing notebook_display_formatter) or the terminal (if
489 491 passing terminal_display_formatter). This function is iterated over for
490 492 each directory in self.path. Default formatters are in place, can be
491 493 passed here to support alternative formatting.
492 494
493 495 """
494 496 if isfile(path):
495 497 raise ValueError("Cannot display a file using FileLinks. "
496 498 "Use FileLink to display '%s'." % path)
497 499 self.included_suffixes = included_suffixes
498 500 # remove trailing slashes for more consistent output formatting
499 501 path = path.rstrip('/')
500 502
501 503 self.path = path
502 504 self.url_prefix = url_prefix
503 505 self.result_html_prefix = result_html_prefix
504 506 self.result_html_suffix = result_html_suffix
505 507
506 508 self.notebook_display_formatter = \
507 509 notebook_display_formatter or self._get_notebook_display_formatter()
508 510 self.terminal_display_formatter = \
509 511 terminal_display_formatter or self._get_terminal_display_formatter()
510 512
511 513 self.recursive = recursive
512 514
513 515 def _get_display_formatter(
514 516 self, dirname_output_format, fname_output_format, fp_format, fp_cleaner=None
515 517 ):
516 518 """generate built-in formatter function
517 519
518 520 this is used to define both the notebook and terminal built-in
519 521 formatters as they only differ by some wrapper text for each entry
520 522
521 523 dirname_output_format: string to use for formatting directory
522 524 names, dirname will be substituted for a single "%s" which
523 525 must appear in this string
524 526 fname_output_format: string to use for formatting file names,
525 527 if a single "%s" appears in the string, fname will be substituted
526 528 if two "%s" appear in the string, the path to fname will be
527 529 substituted for the first and fname will be substituted for the
528 530 second
529 531 fp_format: string to use for formatting filepaths, must contain
530 532 exactly two "%s" and the dirname will be substituted for the first
531 533 and fname will be substituted for the second
532 534 """
533 535 def f(dirname, fnames, included_suffixes=None):
534 536 result = []
535 537 # begin by figuring out which filenames, if any,
536 538 # are going to be displayed
537 539 display_fnames = []
538 540 for fname in fnames:
539 541 if (isfile(join(dirname,fname)) and
540 542 (included_suffixes is None or
541 543 splitext(fname)[1] in included_suffixes)):
542 544 display_fnames.append(fname)
543 545
544 546 if len(display_fnames) == 0:
545 547 # if there are no filenames to display, don't print anything
546 548 # (not even the directory name)
547 549 pass
548 550 else:
549 551 # otherwise print the formatted directory name followed by
550 552 # the formatted filenames
551 553 dirname_output_line = dirname_output_format % dirname
552 554 result.append(dirname_output_line)
553 555 for fname in display_fnames:
554 556 fp = fp_format % (dirname,fname)
555 557 if fp_cleaner is not None:
556 558 fp = fp_cleaner(fp)
557 559 try:
558 560 # output can include both a filepath and a filename...
559 561 fname_output_line = fname_output_format % (fp, fname)
560 562 except TypeError:
561 563 # ... or just a single filepath
562 564 fname_output_line = fname_output_format % fname
563 565 result.append(fname_output_line)
564 566 return result
565 567 return f
566 568
567 569 def _get_notebook_display_formatter(self,
568 570 spacer="&nbsp;&nbsp;"):
569 571 """ generate function to use for notebook formatting
570 572 """
571 573 dirname_output_format = \
572 574 self.result_html_prefix + "%s/" + self.result_html_suffix
573 575 fname_output_format = \
574 576 self.result_html_prefix + spacer + self.html_link_str + self.result_html_suffix
575 577 fp_format = self.url_prefix + '%s/%s'
576 578 if sep == "\\":
577 579 # Working on a platform where the path separator is "\", so
578 580 # must convert these to "/" for generating a URI
579 581 def fp_cleaner(fp):
580 582 # Replace all occurrences of backslash ("\") with a forward
581 583 # slash ("/") - this is necessary on windows when a path is
582 584 # provided as input, but we must link to a URI
583 585 return fp.replace('\\','/')
584 586 else:
585 587 fp_cleaner = None
586 588
587 589 return self._get_display_formatter(dirname_output_format,
588 590 fname_output_format,
589 591 fp_format,
590 592 fp_cleaner)
591 593
592 594 def _get_terminal_display_formatter(self,
593 595 spacer=" "):
594 596 """ generate function to use for terminal formatting
595 597 """
596 598 dirname_output_format = "%s/"
597 599 fname_output_format = spacer + "%s"
598 600 fp_format = '%s/%s'
599 601
600 602 return self._get_display_formatter(dirname_output_format,
601 603 fname_output_format,
602 604 fp_format)
603 605
604 606 def _format_path(self):
605 607 result_lines = []
606 608 if self.recursive:
607 609 walked_dir = list(walk(self.path))
608 610 else:
609 611 walked_dir = [next(walk(self.path))]
610 612 walked_dir.sort()
611 613 for dirname, subdirs, fnames in walked_dir:
612 614 result_lines += self.notebook_display_formatter(dirname, fnames, self.included_suffixes)
613 615 return '\n'.join(result_lines)
614 616
615 617 def __repr__(self):
616 618 """return newline-separated absolute paths
617 619 """
618 620 result_lines = []
619 621 if self.recursive:
620 622 walked_dir = list(walk(self.path))
621 623 else:
622 624 walked_dir = [next(walk(self.path))]
623 625 walked_dir.sort()
624 626 for dirname, subdirs, fnames in walked_dir:
625 627 result_lines += self.terminal_display_formatter(dirname, fnames, self.included_suffixes)
626 628 return '\n'.join(result_lines)
627 629
628 630
629 631 class Code(TextDisplayObject):
630 632 """Display syntax-highlighted source code.
631 633
632 634 This uses Pygments to highlight the code for HTML and Latex output.
633 635
634 636 Parameters
635 637 ----------
636 638 data : str
637 639 The code as a string
638 640 url : str
639 641 A URL to fetch the code from
640 642 filename : str
641 643 A local filename to load the code from
642 644 language : str
643 645 The short name of a Pygments lexer to use for highlighting.
644 646 If not specified, it will guess the lexer based on the filename
645 647 or the code. Available lexers: http://pygments.org/docs/lexers/
646 648 """
647 649 def __init__(self, data=None, url=None, filename=None, language=None):
648 650 self.language = language
649 651 super().__init__(data=data, url=url, filename=filename)
650 652
651 653 def _get_lexer(self):
652 654 if self.language:
653 655 from pygments.lexers import get_lexer_by_name
654 656 return get_lexer_by_name(self.language)
655 657 elif self.filename:
656 658 from pygments.lexers import get_lexer_for_filename
657 659 return get_lexer_for_filename(self.filename)
658 660 else:
659 661 from pygments.lexers import guess_lexer
660 662 return guess_lexer(self.data)
661 663
662 664 def __repr__(self):
663 665 return self.data
664 666
665 667 def _repr_html_(self):
666 668 from pygments import highlight
667 669 from pygments.formatters import HtmlFormatter
668 670 fmt = HtmlFormatter()
669 671 style = '<style>{}</style>'.format(fmt.get_style_defs('.output_html'))
670 672 return style + highlight(self.data, self._get_lexer(), fmt)
671 673
672 674 def _repr_latex_(self):
673 675 from pygments import highlight
674 676 from pygments.formatters import LatexFormatter
675 677 return highlight(self.data, self._get_lexer(), LatexFormatter())
@@ -1,46 +1,48 b''
1 1 # encoding: utf-8
2 2 """
3 3 Timezone utilities
4 4
5 5 Just UTC-awareness right now
6 6 """
7 7
8 8 #-----------------------------------------------------------------------------
9 9 # Copyright (C) 2013 The IPython Development Team
10 10 #
11 11 # Distributed under the terms of the BSD License. The full license is in
12 12 # the file COPYING, distributed as part of this software.
13 13 #-----------------------------------------------------------------------------
14 14
15 15 #-----------------------------------------------------------------------------
16 16 # Imports
17 17 #-----------------------------------------------------------------------------
18 18
19 19 from datetime import tzinfo, timedelta, datetime
20 20
21 21 #-----------------------------------------------------------------------------
22 22 # Code
23 23 #-----------------------------------------------------------------------------
24 24 # constant for zero offset
25 25 ZERO = timedelta(0)
26 26
27 27 class tzUTC(tzinfo):
28 28 """tzinfo object for UTC (zero offset)"""
29 29
30 30 def utcoffset(self, d):
31 31 return ZERO
32 32
33 33 def dst(self, d):
34 34 return ZERO
35 35
36 UTC = tzUTC()
36
37 UTC = tzUTC() # type: ignore[abstract]
38
37 39
38 40 def utc_aware(unaware):
39 41 """decorator for adding UTC tzinfo to datetime's utcfoo methods"""
40 42 def utc_method(*args, **kwargs):
41 43 dt = unaware(*args, **kwargs)
42 44 return dt.replace(tzinfo=UTC)
43 45 return utc_method
44 46
45 47 utcfromtimestamp = utc_aware(datetime.utcfromtimestamp)
46 48 utcnow = utc_aware(datetime.utcnow)
@@ -1,3 +1,32 b''
1 1 [build-system]
2 2 requires = ["setuptools >= 51.0.0"]
3 3 build-backend = "setuptools.build_meta"
4 [tool.mypy]
5 python_version = 3.8
6 ignore_missing_imports = true
7 follow_imports = 'silent'
8 exclude = [
9 'test_\.+\.py',
10 'IPython.utils.tests.test_wildcard',
11 'testing',
12 'tests',
13 'PyColorize.py',
14 '_process_win32_controller.py',
15 'IPython/core/application.py',
16 'IPython/core/completerlib.py',
17 'IPython/core/displaypub.py',
18 'IPython/core/historyapp.py',
19 #'IPython/core/interactiveshell.py',
20 'IPython/core/magic.py',
21 'IPython/core/profileapp.py',
22 'IPython/core/ultratb.py',
23 'IPython/lib/deepreload.py',
24 'IPython/lib/pretty.py',
25 'IPython/sphinxext/ipython_directive.py',
26 'IPython/terminal/ipapp.py',
27 'IPython/utils/_process_win32.py',
28 'IPython/utils/path.py',
29 'IPython/utils/timing.py',
30 'IPython/utils/text.py'
31 ]
32
@@ -1,4 +0,0 b''
1 [mypy]
2 python_version = 3.8
3 ignore_missing_imports = True
4 follow_imports = silent
General Comments 0
You need to be logged in to leave comments. Login now