##// END OF EJS Templates
Move Matplotlib backend resolution to Matplotlib
Ian Thomas -
Show More
@@ -1,3980 +1,3980
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Main IPython class."""
2 """Main IPython class."""
3
3
4 #-----------------------------------------------------------------------------
4 #-----------------------------------------------------------------------------
5 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de>
5 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de>
6 # Copyright (C) 2001-2007 Fernando Perez. <fperez@colorado.edu>
6 # Copyright (C) 2001-2007 Fernando Perez. <fperez@colorado.edu>
7 # Copyright (C) 2008-2011 The IPython Development Team
7 # Copyright (C) 2008-2011 The IPython Development Team
8 #
8 #
9 # Distributed under the terms of the BSD License. The full license is in
9 # Distributed under the terms of the BSD License. The full license is in
10 # the file COPYING, distributed as part of this software.
10 # the file COPYING, distributed as part of this software.
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12
12
13
13
14 import abc
14 import abc
15 import ast
15 import ast
16 import atexit
16 import atexit
17 import bdb
17 import bdb
18 import builtins as builtin_mod
18 import builtins as builtin_mod
19 import functools
19 import functools
20 import inspect
20 import inspect
21 import os
21 import os
22 import re
22 import re
23 import runpy
23 import runpy
24 import shutil
24 import shutil
25 import subprocess
25 import subprocess
26 import sys
26 import sys
27 import tempfile
27 import tempfile
28 import traceback
28 import traceback
29 import types
29 import types
30 import warnings
30 import warnings
31 from ast import stmt
31 from ast import stmt
32 from io import open as io_open
32 from io import open as io_open
33 from logging import error
33 from logging import error
34 from pathlib import Path
34 from pathlib import Path
35 from typing import Callable
35 from typing import Callable
36 from typing import List as ListType, Dict as DictType, Any as AnyType
36 from typing import List as ListType, Dict as DictType, Any as AnyType
37 from typing import Optional, Sequence, Tuple
37 from typing import Optional, Sequence, Tuple
38 from warnings import warn
38 from warnings import warn
39
39
40 try:
40 try:
41 from pickleshare import PickleShareDB
41 from pickleshare import PickleShareDB
42 except ModuleNotFoundError:
42 except ModuleNotFoundError:
43
43
44 class PickleShareDB: # type: ignore [no-redef]
44 class PickleShareDB: # type: ignore [no-redef]
45 _mock = True
45 _mock = True
46
46
47 def __init__(self, path):
47 def __init__(self, path):
48 pass
48 pass
49
49
50 def get(self, key, default=None):
50 def get(self, key, default=None):
51 warn(
51 warn(
52 f"This is now an optional IPython functionality, using {key} requires you to install the `pickleshare` library.",
52 f"This is now an optional IPython functionality, using {key} requires you to install the `pickleshare` library.",
53 stacklevel=2,
53 stacklevel=2,
54 )
54 )
55 return default
55 return default
56
56
57 def __getitem__(self, key):
57 def __getitem__(self, key):
58 warn(
58 warn(
59 f"This is now an optional IPython functionality, using {key} requires you to install the `pickleshare` library.",
59 f"This is now an optional IPython functionality, using {key} requires you to install the `pickleshare` library.",
60 stacklevel=2,
60 stacklevel=2,
61 )
61 )
62 return None
62 return None
63
63
64 def __setitem__(self, key, value):
64 def __setitem__(self, key, value):
65 warn(
65 warn(
66 f"This is now an optional IPython functionality, setting {key} requires you to install the `pickleshare` library.",
66 f"This is now an optional IPython functionality, setting {key} requires you to install the `pickleshare` library.",
67 stacklevel=2,
67 stacklevel=2,
68 )
68 )
69
69
70 def __delitem__(self, key):
70 def __delitem__(self, key):
71 warn(
71 warn(
72 f"This is now an optional IPython functionality, deleting {key} requires you to install the `pickleshare` library.",
72 f"This is now an optional IPython functionality, deleting {key} requires you to install the `pickleshare` library.",
73 stacklevel=2,
73 stacklevel=2,
74 )
74 )
75
75
76
76
77 from tempfile import TemporaryDirectory
77 from tempfile import TemporaryDirectory
78 from traitlets import (
78 from traitlets import (
79 Any,
79 Any,
80 Bool,
80 Bool,
81 CaselessStrEnum,
81 CaselessStrEnum,
82 Dict,
82 Dict,
83 Enum,
83 Enum,
84 Instance,
84 Instance,
85 Integer,
85 Integer,
86 List,
86 List,
87 Type,
87 Type,
88 Unicode,
88 Unicode,
89 default,
89 default,
90 observe,
90 observe,
91 validate,
91 validate,
92 )
92 )
93 from traitlets.config.configurable import SingletonConfigurable
93 from traitlets.config.configurable import SingletonConfigurable
94 from traitlets.utils.importstring import import_item
94 from traitlets.utils.importstring import import_item
95
95
96 import IPython.core.hooks
96 import IPython.core.hooks
97 from IPython.core import magic, oinspect, page, prefilter, ultratb
97 from IPython.core import magic, oinspect, page, prefilter, ultratb
98 from IPython.core.alias import Alias, AliasManager
98 from IPython.core.alias import Alias, AliasManager
99 from IPython.core.autocall import ExitAutocall
99 from IPython.core.autocall import ExitAutocall
100 from IPython.core.builtin_trap import BuiltinTrap
100 from IPython.core.builtin_trap import BuiltinTrap
101 from IPython.core.compilerop import CachingCompiler
101 from IPython.core.compilerop import CachingCompiler
102 from IPython.core.debugger import InterruptiblePdb
102 from IPython.core.debugger import InterruptiblePdb
103 from IPython.core.display_trap import DisplayTrap
103 from IPython.core.display_trap import DisplayTrap
104 from IPython.core.displayhook import DisplayHook
104 from IPython.core.displayhook import DisplayHook
105 from IPython.core.displaypub import DisplayPublisher
105 from IPython.core.displaypub import DisplayPublisher
106 from IPython.core.error import InputRejected, UsageError
106 from IPython.core.error import InputRejected, UsageError
107 from IPython.core.events import EventManager, available_events
107 from IPython.core.events import EventManager, available_events
108 from IPython.core.extensions import ExtensionManager
108 from IPython.core.extensions import ExtensionManager
109 from IPython.core.formatters import DisplayFormatter
109 from IPython.core.formatters import DisplayFormatter
110 from IPython.core.history import HistoryManager
110 from IPython.core.history import HistoryManager
111 from IPython.core.inputtransformer2 import ESC_MAGIC, ESC_MAGIC2
111 from IPython.core.inputtransformer2 import ESC_MAGIC, ESC_MAGIC2
112 from IPython.core.logger import Logger
112 from IPython.core.logger import Logger
113 from IPython.core.macro import Macro
113 from IPython.core.macro import Macro
114 from IPython.core.payload import PayloadManager
114 from IPython.core.payload import PayloadManager
115 from IPython.core.prefilter import PrefilterManager
115 from IPython.core.prefilter import PrefilterManager
116 from IPython.core.profiledir import ProfileDir
116 from IPython.core.profiledir import ProfileDir
117 from IPython.core.usage import default_banner
117 from IPython.core.usage import default_banner
118 from IPython.display import display
118 from IPython.display import display
119 from IPython.paths import get_ipython_dir
119 from IPython.paths import get_ipython_dir
120 from IPython.testing.skipdoctest import skip_doctest
120 from IPython.testing.skipdoctest import skip_doctest
121 from IPython.utils import PyColorize, io, openpy, py3compat
121 from IPython.utils import PyColorize, io, openpy, py3compat
122 from IPython.utils.decorators import undoc
122 from IPython.utils.decorators import undoc
123 from IPython.utils.io import ask_yes_no
123 from IPython.utils.io import ask_yes_no
124 from IPython.utils.ipstruct import Struct
124 from IPython.utils.ipstruct import Struct
125 from IPython.utils.path import ensure_dir_exists, get_home_dir, get_py_filename
125 from IPython.utils.path import ensure_dir_exists, get_home_dir, get_py_filename
126 from IPython.utils.process import getoutput, system
126 from IPython.utils.process import getoutput, system
127 from IPython.utils.strdispatch import StrDispatch
127 from IPython.utils.strdispatch import StrDispatch
128 from IPython.utils.syspathcontext import prepended_to_syspath
128 from IPython.utils.syspathcontext import prepended_to_syspath
129 from IPython.utils.text import DollarFormatter, LSString, SList, format_screen
129 from IPython.utils.text import DollarFormatter, LSString, SList, format_screen
130 from IPython.core.oinspect import OInfo
130 from IPython.core.oinspect import OInfo
131
131
132
132
133 sphinxify: Optional[Callable]
133 sphinxify: Optional[Callable]
134
134
135 try:
135 try:
136 import docrepr.sphinxify as sphx
136 import docrepr.sphinxify as sphx
137
137
138 def sphinxify(oinfo):
138 def sphinxify(oinfo):
139 wrapped_docstring = sphx.wrap_main_docstring(oinfo)
139 wrapped_docstring = sphx.wrap_main_docstring(oinfo)
140
140
141 def sphinxify_docstring(docstring):
141 def sphinxify_docstring(docstring):
142 with TemporaryDirectory() as dirname:
142 with TemporaryDirectory() as dirname:
143 return {
143 return {
144 "text/html": sphx.sphinxify(wrapped_docstring, dirname),
144 "text/html": sphx.sphinxify(wrapped_docstring, dirname),
145 "text/plain": docstring,
145 "text/plain": docstring,
146 }
146 }
147
147
148 return sphinxify_docstring
148 return sphinxify_docstring
149 except ImportError:
149 except ImportError:
150 sphinxify = None
150 sphinxify = None
151
151
152 if sys.version_info[:2] < (3, 11):
152 if sys.version_info[:2] < (3, 11):
153 from exceptiongroup import BaseExceptionGroup
153 from exceptiongroup import BaseExceptionGroup
154
154
155 class ProvisionalWarning(DeprecationWarning):
155 class ProvisionalWarning(DeprecationWarning):
156 """
156 """
157 Warning class for unstable features
157 Warning class for unstable features
158 """
158 """
159 pass
159 pass
160
160
161 from ast import Module
161 from ast import Module
162
162
163 _assign_nodes = (ast.AugAssign, ast.AnnAssign, ast.Assign)
163 _assign_nodes = (ast.AugAssign, ast.AnnAssign, ast.Assign)
164 _single_targets_nodes = (ast.AugAssign, ast.AnnAssign)
164 _single_targets_nodes = (ast.AugAssign, ast.AnnAssign)
165
165
166 #-----------------------------------------------------------------------------
166 #-----------------------------------------------------------------------------
167 # Await Helpers
167 # Await Helpers
168 #-----------------------------------------------------------------------------
168 #-----------------------------------------------------------------------------
169
169
170 # we still need to run things using the asyncio eventloop, but there is no
170 # we still need to run things using the asyncio eventloop, but there is no
171 # async integration
171 # async integration
172 from .async_helpers import (
172 from .async_helpers import (
173 _asyncio_runner,
173 _asyncio_runner,
174 _curio_runner,
174 _curio_runner,
175 _pseudo_sync_runner,
175 _pseudo_sync_runner,
176 _should_be_async,
176 _should_be_async,
177 _trio_runner,
177 _trio_runner,
178 )
178 )
179
179
180 #-----------------------------------------------------------------------------
180 #-----------------------------------------------------------------------------
181 # Globals
181 # Globals
182 #-----------------------------------------------------------------------------
182 #-----------------------------------------------------------------------------
183
183
184 # compiled regexps for autoindent management
184 # compiled regexps for autoindent management
185 dedent_re = re.compile(r'^\s+raise|^\s+return|^\s+pass')
185 dedent_re = re.compile(r'^\s+raise|^\s+return|^\s+pass')
186
186
187 #-----------------------------------------------------------------------------
187 #-----------------------------------------------------------------------------
188 # Utilities
188 # Utilities
189 #-----------------------------------------------------------------------------
189 #-----------------------------------------------------------------------------
190
190
191
191
192 def is_integer_string(s: str):
192 def is_integer_string(s: str):
193 """
193 """
194 Variant of "str.isnumeric()" that allow negative values and other ints.
194 Variant of "str.isnumeric()" that allow negative values and other ints.
195 """
195 """
196 try:
196 try:
197 int(s)
197 int(s)
198 return True
198 return True
199 except ValueError:
199 except ValueError:
200 return False
200 return False
201 raise ValueError("Unexpected error")
201 raise ValueError("Unexpected error")
202
202
203
203
204 @undoc
204 @undoc
205 def softspace(file, newvalue):
205 def softspace(file, newvalue):
206 """Copied from code.py, to remove the dependency"""
206 """Copied from code.py, to remove the dependency"""
207
207
208 oldvalue = 0
208 oldvalue = 0
209 try:
209 try:
210 oldvalue = file.softspace
210 oldvalue = file.softspace
211 except AttributeError:
211 except AttributeError:
212 pass
212 pass
213 try:
213 try:
214 file.softspace = newvalue
214 file.softspace = newvalue
215 except (AttributeError, TypeError):
215 except (AttributeError, TypeError):
216 # "attribute-less object" or "read-only attributes"
216 # "attribute-less object" or "read-only attributes"
217 pass
217 pass
218 return oldvalue
218 return oldvalue
219
219
220 @undoc
220 @undoc
221 def no_op(*a, **kw):
221 def no_op(*a, **kw):
222 pass
222 pass
223
223
224
224
225 class SpaceInInput(Exception): pass
225 class SpaceInInput(Exception): pass
226
226
227
227
228 class SeparateUnicode(Unicode):
228 class SeparateUnicode(Unicode):
229 r"""A Unicode subclass to validate separate_in, separate_out, etc.
229 r"""A Unicode subclass to validate separate_in, separate_out, etc.
230
230
231 This is a Unicode based trait that converts '0'->'' and ``'\\n'->'\n'``.
231 This is a Unicode based trait that converts '0'->'' and ``'\\n'->'\n'``.
232 """
232 """
233
233
234 def validate(self, obj, value):
234 def validate(self, obj, value):
235 if value == '0': value = ''
235 if value == '0': value = ''
236 value = value.replace('\\n','\n')
236 value = value.replace('\\n','\n')
237 return super(SeparateUnicode, self).validate(obj, value)
237 return super(SeparateUnicode, self).validate(obj, value)
238
238
239
239
240 @undoc
240 @undoc
241 class DummyMod(object):
241 class DummyMod(object):
242 """A dummy module used for IPython's interactive module when
242 """A dummy module used for IPython's interactive module when
243 a namespace must be assigned to the module's __dict__."""
243 a namespace must be assigned to the module's __dict__."""
244 __spec__ = None
244 __spec__ = None
245
245
246
246
247 class ExecutionInfo(object):
247 class ExecutionInfo(object):
248 """The arguments used for a call to :meth:`InteractiveShell.run_cell`
248 """The arguments used for a call to :meth:`InteractiveShell.run_cell`
249
249
250 Stores information about what is going to happen.
250 Stores information about what is going to happen.
251 """
251 """
252 raw_cell = None
252 raw_cell = None
253 store_history = False
253 store_history = False
254 silent = False
254 silent = False
255 shell_futures = True
255 shell_futures = True
256 cell_id = None
256 cell_id = None
257
257
258 def __init__(self, raw_cell, store_history, silent, shell_futures, cell_id):
258 def __init__(self, raw_cell, store_history, silent, shell_futures, cell_id):
259 self.raw_cell = raw_cell
259 self.raw_cell = raw_cell
260 self.store_history = store_history
260 self.store_history = store_history
261 self.silent = silent
261 self.silent = silent
262 self.shell_futures = shell_futures
262 self.shell_futures = shell_futures
263 self.cell_id = cell_id
263 self.cell_id = cell_id
264
264
265 def __repr__(self):
265 def __repr__(self):
266 name = self.__class__.__qualname__
266 name = self.__class__.__qualname__
267 raw_cell = (
267 raw_cell = (
268 (self.raw_cell[:50] + "..") if len(self.raw_cell) > 50 else self.raw_cell
268 (self.raw_cell[:50] + "..") if len(self.raw_cell) > 50 else self.raw_cell
269 )
269 )
270 return (
270 return (
271 '<%s object at %x, raw_cell="%s" store_history=%s silent=%s shell_futures=%s cell_id=%s>'
271 '<%s object at %x, raw_cell="%s" store_history=%s silent=%s shell_futures=%s cell_id=%s>'
272 % (
272 % (
273 name,
273 name,
274 id(self),
274 id(self),
275 raw_cell,
275 raw_cell,
276 self.store_history,
276 self.store_history,
277 self.silent,
277 self.silent,
278 self.shell_futures,
278 self.shell_futures,
279 self.cell_id,
279 self.cell_id,
280 )
280 )
281 )
281 )
282
282
283
283
284 class ExecutionResult:
284 class ExecutionResult:
285 """The result of a call to :meth:`InteractiveShell.run_cell`
285 """The result of a call to :meth:`InteractiveShell.run_cell`
286
286
287 Stores information about what took place.
287 Stores information about what took place.
288 """
288 """
289
289
290 execution_count: Optional[int] = None
290 execution_count: Optional[int] = None
291 error_before_exec: Optional[bool] = None
291 error_before_exec: Optional[bool] = None
292 error_in_exec: Optional[BaseException] = None
292 error_in_exec: Optional[BaseException] = None
293 info = None
293 info = None
294 result = None
294 result = None
295
295
296 def __init__(self, info):
296 def __init__(self, info):
297 self.info = info
297 self.info = info
298
298
299 @property
299 @property
300 def success(self):
300 def success(self):
301 return (self.error_before_exec is None) and (self.error_in_exec is None)
301 return (self.error_before_exec is None) and (self.error_in_exec is None)
302
302
303 def raise_error(self):
303 def raise_error(self):
304 """Reraises error if `success` is `False`, otherwise does nothing"""
304 """Reraises error if `success` is `False`, otherwise does nothing"""
305 if self.error_before_exec is not None:
305 if self.error_before_exec is not None:
306 raise self.error_before_exec
306 raise self.error_before_exec
307 if self.error_in_exec is not None:
307 if self.error_in_exec is not None:
308 raise self.error_in_exec
308 raise self.error_in_exec
309
309
310 def __repr__(self):
310 def __repr__(self):
311 name = self.__class__.__qualname__
311 name = self.__class__.__qualname__
312 return '<%s object at %x, execution_count=%s error_before_exec=%s error_in_exec=%s info=%s result=%s>' %\
312 return '<%s object at %x, execution_count=%s error_before_exec=%s error_in_exec=%s info=%s result=%s>' %\
313 (name, id(self), self.execution_count, self.error_before_exec, self.error_in_exec, repr(self.info), repr(self.result))
313 (name, id(self), self.execution_count, self.error_before_exec, self.error_in_exec, repr(self.info), repr(self.result))
314
314
315 @functools.wraps(io_open)
315 @functools.wraps(io_open)
316 def _modified_open(file, *args, **kwargs):
316 def _modified_open(file, *args, **kwargs):
317 if file in {0, 1, 2}:
317 if file in {0, 1, 2}:
318 raise ValueError(
318 raise ValueError(
319 f"IPython won't let you open fd={file} by default "
319 f"IPython won't let you open fd={file} by default "
320 "as it is likely to crash IPython. If you know what you are doing, "
320 "as it is likely to crash IPython. If you know what you are doing, "
321 "you can use builtins' open."
321 "you can use builtins' open."
322 )
322 )
323
323
324 return io_open(file, *args, **kwargs)
324 return io_open(file, *args, **kwargs)
325
325
326 class InteractiveShell(SingletonConfigurable):
326 class InteractiveShell(SingletonConfigurable):
327 """An enhanced, interactive shell for Python."""
327 """An enhanced, interactive shell for Python."""
328
328
329 _instance = None
329 _instance = None
330
330
331 ast_transformers: List[ast.NodeTransformer] = List(
331 ast_transformers: List[ast.NodeTransformer] = List(
332 [],
332 [],
333 help="""
333 help="""
334 A list of ast.NodeTransformer subclass instances, which will be applied
334 A list of ast.NodeTransformer subclass instances, which will be applied
335 to user input before code is run.
335 to user input before code is run.
336 """,
336 """,
337 ).tag(config=True)
337 ).tag(config=True)
338
338
339 autocall = Enum((0,1,2), default_value=0, help=
339 autocall = Enum((0,1,2), default_value=0, help=
340 """
340 """
341 Make IPython automatically call any callable object even if you didn't
341 Make IPython automatically call any callable object even if you didn't
342 type explicit parentheses. For example, 'str 43' becomes 'str(43)'
342 type explicit parentheses. For example, 'str 43' becomes 'str(43)'
343 automatically. The value can be '0' to disable the feature, '1' for
343 automatically. The value can be '0' to disable the feature, '1' for
344 'smart' autocall, where it is not applied if there are no more
344 'smart' autocall, where it is not applied if there are no more
345 arguments on the line, and '2' for 'full' autocall, where all callable
345 arguments on the line, and '2' for 'full' autocall, where all callable
346 objects are automatically called (even if no arguments are present).
346 objects are automatically called (even if no arguments are present).
347 """
347 """
348 ).tag(config=True)
348 ).tag(config=True)
349
349
350 autoindent = Bool(True, help=
350 autoindent = Bool(True, help=
351 """
351 """
352 Autoindent IPython code entered interactively.
352 Autoindent IPython code entered interactively.
353 """
353 """
354 ).tag(config=True)
354 ).tag(config=True)
355
355
356 autoawait = Bool(True, help=
356 autoawait = Bool(True, help=
357 """
357 """
358 Automatically run await statement in the top level repl.
358 Automatically run await statement in the top level repl.
359 """
359 """
360 ).tag(config=True)
360 ).tag(config=True)
361
361
362 loop_runner_map ={
362 loop_runner_map ={
363 'asyncio':(_asyncio_runner, True),
363 'asyncio':(_asyncio_runner, True),
364 'curio':(_curio_runner, True),
364 'curio':(_curio_runner, True),
365 'trio':(_trio_runner, True),
365 'trio':(_trio_runner, True),
366 'sync': (_pseudo_sync_runner, False)
366 'sync': (_pseudo_sync_runner, False)
367 }
367 }
368
368
369 loop_runner = Any(default_value="IPython.core.interactiveshell._asyncio_runner",
369 loop_runner = Any(default_value="IPython.core.interactiveshell._asyncio_runner",
370 allow_none=True,
370 allow_none=True,
371 help="""Select the loop runner that will be used to execute top-level asynchronous code"""
371 help="""Select the loop runner that will be used to execute top-level asynchronous code"""
372 ).tag(config=True)
372 ).tag(config=True)
373
373
374 @default('loop_runner')
374 @default('loop_runner')
375 def _default_loop_runner(self):
375 def _default_loop_runner(self):
376 return import_item("IPython.core.interactiveshell._asyncio_runner")
376 return import_item("IPython.core.interactiveshell._asyncio_runner")
377
377
378 @validate('loop_runner')
378 @validate('loop_runner')
379 def _import_runner(self, proposal):
379 def _import_runner(self, proposal):
380 if isinstance(proposal.value, str):
380 if isinstance(proposal.value, str):
381 if proposal.value in self.loop_runner_map:
381 if proposal.value in self.loop_runner_map:
382 runner, autoawait = self.loop_runner_map[proposal.value]
382 runner, autoawait = self.loop_runner_map[proposal.value]
383 self.autoawait = autoawait
383 self.autoawait = autoawait
384 return runner
384 return runner
385 runner = import_item(proposal.value)
385 runner = import_item(proposal.value)
386 if not callable(runner):
386 if not callable(runner):
387 raise ValueError('loop_runner must be callable')
387 raise ValueError('loop_runner must be callable')
388 return runner
388 return runner
389 if not callable(proposal.value):
389 if not callable(proposal.value):
390 raise ValueError('loop_runner must be callable')
390 raise ValueError('loop_runner must be callable')
391 return proposal.value
391 return proposal.value
392
392
393 automagic = Bool(True, help=
393 automagic = Bool(True, help=
394 """
394 """
395 Enable magic commands to be called without the leading %.
395 Enable magic commands to be called without the leading %.
396 """
396 """
397 ).tag(config=True)
397 ).tag(config=True)
398
398
399 banner1 = Unicode(default_banner,
399 banner1 = Unicode(default_banner,
400 help="""The part of the banner to be printed before the profile"""
400 help="""The part of the banner to be printed before the profile"""
401 ).tag(config=True)
401 ).tag(config=True)
402 banner2 = Unicode('',
402 banner2 = Unicode('',
403 help="""The part of the banner to be printed after the profile"""
403 help="""The part of the banner to be printed after the profile"""
404 ).tag(config=True)
404 ).tag(config=True)
405
405
406 cache_size = Integer(1000, help=
406 cache_size = Integer(1000, help=
407 """
407 """
408 Set the size of the output cache. The default is 1000, you can
408 Set the size of the output cache. The default is 1000, you can
409 change it permanently in your config file. Setting it to 0 completely
409 change it permanently in your config file. Setting it to 0 completely
410 disables the caching system, and the minimum value accepted is 3 (if
410 disables the caching system, and the minimum value accepted is 3 (if
411 you provide a value less than 3, it is reset to 0 and a warning is
411 you provide a value less than 3, it is reset to 0 and a warning is
412 issued). This limit is defined because otherwise you'll spend more
412 issued). This limit is defined because otherwise you'll spend more
413 time re-flushing a too small cache than working
413 time re-flushing a too small cache than working
414 """
414 """
415 ).tag(config=True)
415 ).tag(config=True)
416 color_info = Bool(True, help=
416 color_info = Bool(True, help=
417 """
417 """
418 Use colors for displaying information about objects. Because this
418 Use colors for displaying information about objects. Because this
419 information is passed through a pager (like 'less'), and some pagers
419 information is passed through a pager (like 'less'), and some pagers
420 get confused with color codes, this capability can be turned off.
420 get confused with color codes, this capability can be turned off.
421 """
421 """
422 ).tag(config=True)
422 ).tag(config=True)
423 colors = CaselessStrEnum(('Neutral', 'NoColor','LightBG','Linux'),
423 colors = CaselessStrEnum(('Neutral', 'NoColor','LightBG','Linux'),
424 default_value='Neutral',
424 default_value='Neutral',
425 help="Set the color scheme (NoColor, Neutral, Linux, or LightBG)."
425 help="Set the color scheme (NoColor, Neutral, Linux, or LightBG)."
426 ).tag(config=True)
426 ).tag(config=True)
427 debug = Bool(False).tag(config=True)
427 debug = Bool(False).tag(config=True)
428 disable_failing_post_execute = Bool(False,
428 disable_failing_post_execute = Bool(False,
429 help="Don't call post-execute functions that have failed in the past."
429 help="Don't call post-execute functions that have failed in the past."
430 ).tag(config=True)
430 ).tag(config=True)
431 display_formatter = Instance(DisplayFormatter, allow_none=True)
431 display_formatter = Instance(DisplayFormatter, allow_none=True)
432 displayhook_class = Type(DisplayHook)
432 displayhook_class = Type(DisplayHook)
433 display_pub_class = Type(DisplayPublisher)
433 display_pub_class = Type(DisplayPublisher)
434 compiler_class = Type(CachingCompiler)
434 compiler_class = Type(CachingCompiler)
435 inspector_class = Type(
435 inspector_class = Type(
436 oinspect.Inspector, help="Class to use to instantiate the shell inspector"
436 oinspect.Inspector, help="Class to use to instantiate the shell inspector"
437 ).tag(config=True)
437 ).tag(config=True)
438
438
439 sphinxify_docstring = Bool(False, help=
439 sphinxify_docstring = Bool(False, help=
440 """
440 """
441 Enables rich html representation of docstrings. (This requires the
441 Enables rich html representation of docstrings. (This requires the
442 docrepr module).
442 docrepr module).
443 """).tag(config=True)
443 """).tag(config=True)
444
444
445 @observe("sphinxify_docstring")
445 @observe("sphinxify_docstring")
446 def _sphinxify_docstring_changed(self, change):
446 def _sphinxify_docstring_changed(self, change):
447 if change['new']:
447 if change['new']:
448 warn("`sphinxify_docstring` is provisional since IPython 5.0 and might change in future versions." , ProvisionalWarning)
448 warn("`sphinxify_docstring` is provisional since IPython 5.0 and might change in future versions." , ProvisionalWarning)
449
449
450 enable_html_pager = Bool(False, help=
450 enable_html_pager = Bool(False, help=
451 """
451 """
452 (Provisional API) enables html representation in mime bundles sent
452 (Provisional API) enables html representation in mime bundles sent
453 to pagers.
453 to pagers.
454 """).tag(config=True)
454 """).tag(config=True)
455
455
456 @observe("enable_html_pager")
456 @observe("enable_html_pager")
457 def _enable_html_pager_changed(self, change):
457 def _enable_html_pager_changed(self, change):
458 if change['new']:
458 if change['new']:
459 warn("`enable_html_pager` is provisional since IPython 5.0 and might change in future versions.", ProvisionalWarning)
459 warn("`enable_html_pager` is provisional since IPython 5.0 and might change in future versions.", ProvisionalWarning)
460
460
461 data_pub_class = None
461 data_pub_class = None
462
462
463 exit_now = Bool(False)
463 exit_now = Bool(False)
464 exiter = Instance(ExitAutocall)
464 exiter = Instance(ExitAutocall)
465 @default('exiter')
465 @default('exiter')
466 def _exiter_default(self):
466 def _exiter_default(self):
467 return ExitAutocall(self)
467 return ExitAutocall(self)
468 # Monotonically increasing execution counter
468 # Monotonically increasing execution counter
469 execution_count = Integer(1)
469 execution_count = Integer(1)
470 filename = Unicode("<ipython console>")
470 filename = Unicode("<ipython console>")
471 ipython_dir= Unicode('').tag(config=True) # Set to get_ipython_dir() in __init__
471 ipython_dir= Unicode('').tag(config=True) # Set to get_ipython_dir() in __init__
472
472
473 # Used to transform cells before running them, and check whether code is complete
473 # Used to transform cells before running them, and check whether code is complete
474 input_transformer_manager = Instance('IPython.core.inputtransformer2.TransformerManager',
474 input_transformer_manager = Instance('IPython.core.inputtransformer2.TransformerManager',
475 ())
475 ())
476
476
477 @property
477 @property
478 def input_transformers_cleanup(self):
478 def input_transformers_cleanup(self):
479 return self.input_transformer_manager.cleanup_transforms
479 return self.input_transformer_manager.cleanup_transforms
480
480
481 input_transformers_post: List = List(
481 input_transformers_post: List = List(
482 [],
482 [],
483 help="A list of string input transformers, to be applied after IPython's "
483 help="A list of string input transformers, to be applied after IPython's "
484 "own input transformations."
484 "own input transformations."
485 )
485 )
486
486
487 @property
487 @property
488 def input_splitter(self):
488 def input_splitter(self):
489 """Make this available for backward compatibility (pre-7.0 release) with existing code.
489 """Make this available for backward compatibility (pre-7.0 release) with existing code.
490
490
491 For example, ipykernel ipykernel currently uses
491 For example, ipykernel ipykernel currently uses
492 `shell.input_splitter.check_complete`
492 `shell.input_splitter.check_complete`
493 """
493 """
494 from warnings import warn
494 from warnings import warn
495 warn("`input_splitter` is deprecated since IPython 7.0, prefer `input_transformer_manager`.",
495 warn("`input_splitter` is deprecated since IPython 7.0, prefer `input_transformer_manager`.",
496 DeprecationWarning, stacklevel=2
496 DeprecationWarning, stacklevel=2
497 )
497 )
498 return self.input_transformer_manager
498 return self.input_transformer_manager
499
499
500 logstart = Bool(False, help=
500 logstart = Bool(False, help=
501 """
501 """
502 Start logging to the default log file in overwrite mode.
502 Start logging to the default log file in overwrite mode.
503 Use `logappend` to specify a log file to **append** logs to.
503 Use `logappend` to specify a log file to **append** logs to.
504 """
504 """
505 ).tag(config=True)
505 ).tag(config=True)
506 logfile = Unicode('', help=
506 logfile = Unicode('', help=
507 """
507 """
508 The name of the logfile to use.
508 The name of the logfile to use.
509 """
509 """
510 ).tag(config=True)
510 ).tag(config=True)
511 logappend = Unicode('', help=
511 logappend = Unicode('', help=
512 """
512 """
513 Start logging to the given file in append mode.
513 Start logging to the given file in append mode.
514 Use `logfile` to specify a log file to **overwrite** logs to.
514 Use `logfile` to specify a log file to **overwrite** logs to.
515 """
515 """
516 ).tag(config=True)
516 ).tag(config=True)
517 object_info_string_level = Enum((0,1,2), default_value=0,
517 object_info_string_level = Enum((0,1,2), default_value=0,
518 ).tag(config=True)
518 ).tag(config=True)
519 pdb = Bool(False, help=
519 pdb = Bool(False, help=
520 """
520 """
521 Automatically call the pdb debugger after every exception.
521 Automatically call the pdb debugger after every exception.
522 """
522 """
523 ).tag(config=True)
523 ).tag(config=True)
524 display_page = Bool(False,
524 display_page = Bool(False,
525 help="""If True, anything that would be passed to the pager
525 help="""If True, anything that would be passed to the pager
526 will be displayed as regular output instead."""
526 will be displayed as regular output instead."""
527 ).tag(config=True)
527 ).tag(config=True)
528
528
529
529
530 show_rewritten_input = Bool(True,
530 show_rewritten_input = Bool(True,
531 help="Show rewritten input, e.g. for autocall."
531 help="Show rewritten input, e.g. for autocall."
532 ).tag(config=True)
532 ).tag(config=True)
533
533
534 quiet = Bool(False).tag(config=True)
534 quiet = Bool(False).tag(config=True)
535
535
536 history_length = Integer(10000,
536 history_length = Integer(10000,
537 help='Total length of command history'
537 help='Total length of command history'
538 ).tag(config=True)
538 ).tag(config=True)
539
539
540 history_load_length = Integer(1000, help=
540 history_load_length = Integer(1000, help=
541 """
541 """
542 The number of saved history entries to be loaded
542 The number of saved history entries to be loaded
543 into the history buffer at startup.
543 into the history buffer at startup.
544 """
544 """
545 ).tag(config=True)
545 ).tag(config=True)
546
546
547 ast_node_interactivity = Enum(['all', 'last', 'last_expr', 'none', 'last_expr_or_assign'],
547 ast_node_interactivity = Enum(['all', 'last', 'last_expr', 'none', 'last_expr_or_assign'],
548 default_value='last_expr',
548 default_value='last_expr',
549 help="""
549 help="""
550 'all', 'last', 'last_expr' or 'none', 'last_expr_or_assign' specifying
550 'all', 'last', 'last_expr' or 'none', 'last_expr_or_assign' specifying
551 which nodes should be run interactively (displaying output from expressions).
551 which nodes should be run interactively (displaying output from expressions).
552 """
552 """
553 ).tag(config=True)
553 ).tag(config=True)
554
554
555 warn_venv = Bool(
555 warn_venv = Bool(
556 True,
556 True,
557 help="Warn if running in a virtual environment with no IPython installed (so IPython from the global environment is used).",
557 help="Warn if running in a virtual environment with no IPython installed (so IPython from the global environment is used).",
558 ).tag(config=True)
558 ).tag(config=True)
559
559
560 # TODO: this part of prompt management should be moved to the frontends.
560 # TODO: this part of prompt management should be moved to the frontends.
561 # Use custom TraitTypes that convert '0'->'' and '\\n'->'\n'
561 # Use custom TraitTypes that convert '0'->'' and '\\n'->'\n'
562 separate_in = SeparateUnicode('\n').tag(config=True)
562 separate_in = SeparateUnicode('\n').tag(config=True)
563 separate_out = SeparateUnicode('').tag(config=True)
563 separate_out = SeparateUnicode('').tag(config=True)
564 separate_out2 = SeparateUnicode('').tag(config=True)
564 separate_out2 = SeparateUnicode('').tag(config=True)
565 wildcards_case_sensitive = Bool(True).tag(config=True)
565 wildcards_case_sensitive = Bool(True).tag(config=True)
566 xmode = CaselessStrEnum(('Context', 'Plain', 'Verbose', 'Minimal'),
566 xmode = CaselessStrEnum(('Context', 'Plain', 'Verbose', 'Minimal'),
567 default_value='Context',
567 default_value='Context',
568 help="Switch modes for the IPython exception handlers."
568 help="Switch modes for the IPython exception handlers."
569 ).tag(config=True)
569 ).tag(config=True)
570
570
571 # Subcomponents of InteractiveShell
571 # Subcomponents of InteractiveShell
572 alias_manager = Instance("IPython.core.alias.AliasManager", allow_none=True)
572 alias_manager = Instance("IPython.core.alias.AliasManager", allow_none=True)
573 prefilter_manager = Instance(
573 prefilter_manager = Instance(
574 "IPython.core.prefilter.PrefilterManager", allow_none=True
574 "IPython.core.prefilter.PrefilterManager", allow_none=True
575 )
575 )
576 builtin_trap = Instance("IPython.core.builtin_trap.BuiltinTrap")
576 builtin_trap = Instance("IPython.core.builtin_trap.BuiltinTrap")
577 display_trap = Instance("IPython.core.display_trap.DisplayTrap")
577 display_trap = Instance("IPython.core.display_trap.DisplayTrap")
578 extension_manager = Instance(
578 extension_manager = Instance(
579 "IPython.core.extensions.ExtensionManager", allow_none=True
579 "IPython.core.extensions.ExtensionManager", allow_none=True
580 )
580 )
581 payload_manager = Instance("IPython.core.payload.PayloadManager", allow_none=True)
581 payload_manager = Instance("IPython.core.payload.PayloadManager", allow_none=True)
582 history_manager = Instance(
582 history_manager = Instance(
583 "IPython.core.history.HistoryAccessorBase", allow_none=True
583 "IPython.core.history.HistoryAccessorBase", allow_none=True
584 )
584 )
585 magics_manager = Instance("IPython.core.magic.MagicsManager")
585 magics_manager = Instance("IPython.core.magic.MagicsManager")
586
586
587 profile_dir = Instance('IPython.core.application.ProfileDir', allow_none=True)
587 profile_dir = Instance('IPython.core.application.ProfileDir', allow_none=True)
588 @property
588 @property
589 def profile(self):
589 def profile(self):
590 if self.profile_dir is not None:
590 if self.profile_dir is not None:
591 name = os.path.basename(self.profile_dir.location)
591 name = os.path.basename(self.profile_dir.location)
592 return name.replace('profile_','')
592 return name.replace('profile_','')
593
593
594
594
595 # Private interface
595 # Private interface
596 _post_execute = Dict()
596 _post_execute = Dict()
597
597
598 # Tracks any GUI loop loaded for pylab
598 # Tracks any GUI loop loaded for pylab
599 pylab_gui_select = None
599 pylab_gui_select = None
600
600
601 last_execution_succeeded = Bool(True, help='Did last executed command succeeded')
601 last_execution_succeeded = Bool(True, help='Did last executed command succeeded')
602
602
603 last_execution_result = Instance('IPython.core.interactiveshell.ExecutionResult', help='Result of executing the last command', allow_none=True)
603 last_execution_result = Instance('IPython.core.interactiveshell.ExecutionResult', help='Result of executing the last command', allow_none=True)
604
604
605 def __init__(self, ipython_dir=None, profile_dir=None,
605 def __init__(self, ipython_dir=None, profile_dir=None,
606 user_module=None, user_ns=None,
606 user_module=None, user_ns=None,
607 custom_exceptions=((), None), **kwargs):
607 custom_exceptions=((), None), **kwargs):
608 # This is where traits with a config_key argument are updated
608 # This is where traits with a config_key argument are updated
609 # from the values on config.
609 # from the values on config.
610 super(InteractiveShell, self).__init__(**kwargs)
610 super(InteractiveShell, self).__init__(**kwargs)
611 if 'PromptManager' in self.config:
611 if 'PromptManager' in self.config:
612 warn('As of IPython 5.0 `PromptManager` config will have no effect'
612 warn('As of IPython 5.0 `PromptManager` config will have no effect'
613 ' and has been replaced by TerminalInteractiveShell.prompts_class')
613 ' and has been replaced by TerminalInteractiveShell.prompts_class')
614 self.configurables = [self]
614 self.configurables = [self]
615
615
616 # These are relatively independent and stateless
616 # These are relatively independent and stateless
617 self.init_ipython_dir(ipython_dir)
617 self.init_ipython_dir(ipython_dir)
618 self.init_profile_dir(profile_dir)
618 self.init_profile_dir(profile_dir)
619 self.init_instance_attrs()
619 self.init_instance_attrs()
620 self.init_environment()
620 self.init_environment()
621
621
622 # Check if we're in a virtualenv, and set up sys.path.
622 # Check if we're in a virtualenv, and set up sys.path.
623 self.init_virtualenv()
623 self.init_virtualenv()
624
624
625 # Create namespaces (user_ns, user_global_ns, etc.)
625 # Create namespaces (user_ns, user_global_ns, etc.)
626 self.init_create_namespaces(user_module, user_ns)
626 self.init_create_namespaces(user_module, user_ns)
627 # This has to be done after init_create_namespaces because it uses
627 # This has to be done after init_create_namespaces because it uses
628 # something in self.user_ns, but before init_sys_modules, which
628 # something in self.user_ns, but before init_sys_modules, which
629 # is the first thing to modify sys.
629 # is the first thing to modify sys.
630 # TODO: When we override sys.stdout and sys.stderr before this class
630 # TODO: When we override sys.stdout and sys.stderr before this class
631 # is created, we are saving the overridden ones here. Not sure if this
631 # is created, we are saving the overridden ones here. Not sure if this
632 # is what we want to do.
632 # is what we want to do.
633 self.save_sys_module_state()
633 self.save_sys_module_state()
634 self.init_sys_modules()
634 self.init_sys_modules()
635
635
636 # While we're trying to have each part of the code directly access what
636 # While we're trying to have each part of the code directly access what
637 # it needs without keeping redundant references to objects, we have too
637 # it needs without keeping redundant references to objects, we have too
638 # much legacy code that expects ip.db to exist.
638 # much legacy code that expects ip.db to exist.
639 self.db = PickleShareDB(os.path.join(self.profile_dir.location, 'db'))
639 self.db = PickleShareDB(os.path.join(self.profile_dir.location, 'db'))
640
640
641 self.init_history()
641 self.init_history()
642 self.init_encoding()
642 self.init_encoding()
643 self.init_prefilter()
643 self.init_prefilter()
644
644
645 self.init_syntax_highlighting()
645 self.init_syntax_highlighting()
646 self.init_hooks()
646 self.init_hooks()
647 self.init_events()
647 self.init_events()
648 self.init_pushd_popd_magic()
648 self.init_pushd_popd_magic()
649 self.init_user_ns()
649 self.init_user_ns()
650 self.init_logger()
650 self.init_logger()
651 self.init_builtins()
651 self.init_builtins()
652
652
653 # The following was in post_config_initialization
653 # The following was in post_config_initialization
654 self.init_inspector()
654 self.init_inspector()
655 self.raw_input_original = input
655 self.raw_input_original = input
656 self.init_completer()
656 self.init_completer()
657 # TODO: init_io() needs to happen before init_traceback handlers
657 # TODO: init_io() needs to happen before init_traceback handlers
658 # because the traceback handlers hardcode the stdout/stderr streams.
658 # because the traceback handlers hardcode the stdout/stderr streams.
659 # This logic in in debugger.Pdb and should eventually be changed.
659 # This logic in in debugger.Pdb and should eventually be changed.
660 self.init_io()
660 self.init_io()
661 self.init_traceback_handlers(custom_exceptions)
661 self.init_traceback_handlers(custom_exceptions)
662 self.init_prompts()
662 self.init_prompts()
663 self.init_display_formatter()
663 self.init_display_formatter()
664 self.init_display_pub()
664 self.init_display_pub()
665 self.init_data_pub()
665 self.init_data_pub()
666 self.init_displayhook()
666 self.init_displayhook()
667 self.init_magics()
667 self.init_magics()
668 self.init_alias()
668 self.init_alias()
669 self.init_logstart()
669 self.init_logstart()
670 self.init_pdb()
670 self.init_pdb()
671 self.init_extension_manager()
671 self.init_extension_manager()
672 self.init_payload()
672 self.init_payload()
673 self.events.trigger('shell_initialized', self)
673 self.events.trigger('shell_initialized', self)
674 atexit.register(self.atexit_operations)
674 atexit.register(self.atexit_operations)
675
675
676 # The trio runner is used for running Trio in the foreground thread. It
676 # The trio runner is used for running Trio in the foreground thread. It
677 # is different from `_trio_runner(async_fn)` in `async_helpers.py`
677 # is different from `_trio_runner(async_fn)` in `async_helpers.py`
678 # which calls `trio.run()` for every cell. This runner runs all cells
678 # which calls `trio.run()` for every cell. This runner runs all cells
679 # inside a single Trio event loop. If used, it is set from
679 # inside a single Trio event loop. If used, it is set from
680 # `ipykernel.kernelapp`.
680 # `ipykernel.kernelapp`.
681 self.trio_runner = None
681 self.trio_runner = None
682
682
683 def get_ipython(self):
683 def get_ipython(self):
684 """Return the currently running IPython instance."""
684 """Return the currently running IPython instance."""
685 return self
685 return self
686
686
687 #-------------------------------------------------------------------------
687 #-------------------------------------------------------------------------
688 # Trait changed handlers
688 # Trait changed handlers
689 #-------------------------------------------------------------------------
689 #-------------------------------------------------------------------------
690 @observe('ipython_dir')
690 @observe('ipython_dir')
691 def _ipython_dir_changed(self, change):
691 def _ipython_dir_changed(self, change):
692 ensure_dir_exists(change['new'])
692 ensure_dir_exists(change['new'])
693
693
694 def set_autoindent(self,value=None):
694 def set_autoindent(self,value=None):
695 """Set the autoindent flag.
695 """Set the autoindent flag.
696
696
697 If called with no arguments, it acts as a toggle."""
697 If called with no arguments, it acts as a toggle."""
698 if value is None:
698 if value is None:
699 self.autoindent = not self.autoindent
699 self.autoindent = not self.autoindent
700 else:
700 else:
701 self.autoindent = value
701 self.autoindent = value
702
702
703 def set_trio_runner(self, tr):
703 def set_trio_runner(self, tr):
704 self.trio_runner = tr
704 self.trio_runner = tr
705
705
706 #-------------------------------------------------------------------------
706 #-------------------------------------------------------------------------
707 # init_* methods called by __init__
707 # init_* methods called by __init__
708 #-------------------------------------------------------------------------
708 #-------------------------------------------------------------------------
709
709
710 def init_ipython_dir(self, ipython_dir):
710 def init_ipython_dir(self, ipython_dir):
711 if ipython_dir is not None:
711 if ipython_dir is not None:
712 self.ipython_dir = ipython_dir
712 self.ipython_dir = ipython_dir
713 return
713 return
714
714
715 self.ipython_dir = get_ipython_dir()
715 self.ipython_dir = get_ipython_dir()
716
716
717 def init_profile_dir(self, profile_dir):
717 def init_profile_dir(self, profile_dir):
718 if profile_dir is not None:
718 if profile_dir is not None:
719 self.profile_dir = profile_dir
719 self.profile_dir = profile_dir
720 return
720 return
721 self.profile_dir = ProfileDir.create_profile_dir_by_name(
721 self.profile_dir = ProfileDir.create_profile_dir_by_name(
722 self.ipython_dir, "default"
722 self.ipython_dir, "default"
723 )
723 )
724
724
725 def init_instance_attrs(self):
725 def init_instance_attrs(self):
726 self.more = False
726 self.more = False
727
727
728 # command compiler
728 # command compiler
729 self.compile = self.compiler_class()
729 self.compile = self.compiler_class()
730
730
731 # Make an empty namespace, which extension writers can rely on both
731 # Make an empty namespace, which extension writers can rely on both
732 # existing and NEVER being used by ipython itself. This gives them a
732 # existing and NEVER being used by ipython itself. This gives them a
733 # convenient location for storing additional information and state
733 # convenient location for storing additional information and state
734 # their extensions may require, without fear of collisions with other
734 # their extensions may require, without fear of collisions with other
735 # ipython names that may develop later.
735 # ipython names that may develop later.
736 self.meta = Struct()
736 self.meta = Struct()
737
737
738 # Temporary files used for various purposes. Deleted at exit.
738 # Temporary files used for various purposes. Deleted at exit.
739 # The files here are stored with Path from Pathlib
739 # The files here are stored with Path from Pathlib
740 self.tempfiles = []
740 self.tempfiles = []
741 self.tempdirs = []
741 self.tempdirs = []
742
742
743 # keep track of where we started running (mainly for crash post-mortem)
743 # keep track of where we started running (mainly for crash post-mortem)
744 # This is not being used anywhere currently.
744 # This is not being used anywhere currently.
745 self.starting_dir = os.getcwd()
745 self.starting_dir = os.getcwd()
746
746
747 # Indentation management
747 # Indentation management
748 self.indent_current_nsp = 0
748 self.indent_current_nsp = 0
749
749
750 # Dict to track post-execution functions that have been registered
750 # Dict to track post-execution functions that have been registered
751 self._post_execute = {}
751 self._post_execute = {}
752
752
753 def init_environment(self):
753 def init_environment(self):
754 """Any changes we need to make to the user's environment."""
754 """Any changes we need to make to the user's environment."""
755 pass
755 pass
756
756
757 def init_encoding(self):
757 def init_encoding(self):
758 # Get system encoding at startup time. Certain terminals (like Emacs
758 # Get system encoding at startup time. Certain terminals (like Emacs
759 # under Win32 have it set to None, and we need to have a known valid
759 # under Win32 have it set to None, and we need to have a known valid
760 # encoding to use in the raw_input() method
760 # encoding to use in the raw_input() method
761 try:
761 try:
762 self.stdin_encoding = sys.stdin.encoding or 'ascii'
762 self.stdin_encoding = sys.stdin.encoding or 'ascii'
763 except AttributeError:
763 except AttributeError:
764 self.stdin_encoding = 'ascii'
764 self.stdin_encoding = 'ascii'
765
765
766
766
767 @observe('colors')
767 @observe('colors')
768 def init_syntax_highlighting(self, changes=None):
768 def init_syntax_highlighting(self, changes=None):
769 # Python source parser/formatter for syntax highlighting
769 # Python source parser/formatter for syntax highlighting
770 pyformat = PyColorize.Parser(style=self.colors, parent=self).format
770 pyformat = PyColorize.Parser(style=self.colors, parent=self).format
771 self.pycolorize = lambda src: pyformat(src,'str')
771 self.pycolorize = lambda src: pyformat(src,'str')
772
772
773 def refresh_style(self):
773 def refresh_style(self):
774 # No-op here, used in subclass
774 # No-op here, used in subclass
775 pass
775 pass
776
776
777 def init_pushd_popd_magic(self):
777 def init_pushd_popd_magic(self):
778 # for pushd/popd management
778 # for pushd/popd management
779 self.home_dir = get_home_dir()
779 self.home_dir = get_home_dir()
780
780
781 self.dir_stack = []
781 self.dir_stack = []
782
782
783 def init_logger(self):
783 def init_logger(self):
784 self.logger = Logger(self.home_dir, logfname='ipython_log.py',
784 self.logger = Logger(self.home_dir, logfname='ipython_log.py',
785 logmode='rotate')
785 logmode='rotate')
786
786
787 def init_logstart(self):
787 def init_logstart(self):
788 """Initialize logging in case it was requested at the command line.
788 """Initialize logging in case it was requested at the command line.
789 """
789 """
790 if self.logappend:
790 if self.logappend:
791 self.magic('logstart %s append' % self.logappend)
791 self.magic('logstart %s append' % self.logappend)
792 elif self.logfile:
792 elif self.logfile:
793 self.magic('logstart %s' % self.logfile)
793 self.magic('logstart %s' % self.logfile)
794 elif self.logstart:
794 elif self.logstart:
795 self.magic('logstart')
795 self.magic('logstart')
796
796
797
797
798 def init_builtins(self):
798 def init_builtins(self):
799 # A single, static flag that we set to True. Its presence indicates
799 # A single, static flag that we set to True. Its presence indicates
800 # that an IPython shell has been created, and we make no attempts at
800 # that an IPython shell has been created, and we make no attempts at
801 # removing on exit or representing the existence of more than one
801 # removing on exit or representing the existence of more than one
802 # IPython at a time.
802 # IPython at a time.
803 builtin_mod.__dict__['__IPYTHON__'] = True
803 builtin_mod.__dict__['__IPYTHON__'] = True
804 builtin_mod.__dict__['display'] = display
804 builtin_mod.__dict__['display'] = display
805
805
806 self.builtin_trap = BuiltinTrap(shell=self)
806 self.builtin_trap = BuiltinTrap(shell=self)
807
807
808 @observe('colors')
808 @observe('colors')
809 def init_inspector(self, changes=None):
809 def init_inspector(self, changes=None):
810 # Object inspector
810 # Object inspector
811 self.inspector = self.inspector_class(
811 self.inspector = self.inspector_class(
812 oinspect.InspectColors,
812 oinspect.InspectColors,
813 PyColorize.ANSICodeColors,
813 PyColorize.ANSICodeColors,
814 self.colors,
814 self.colors,
815 self.object_info_string_level,
815 self.object_info_string_level,
816 )
816 )
817
817
818 def init_io(self):
818 def init_io(self):
819 # implemented in subclasses, TerminalInteractiveShell does call
819 # implemented in subclasses, TerminalInteractiveShell does call
820 # colorama.init().
820 # colorama.init().
821 pass
821 pass
822
822
823 def init_prompts(self):
823 def init_prompts(self):
824 # Set system prompts, so that scripts can decide if they are running
824 # Set system prompts, so that scripts can decide if they are running
825 # interactively.
825 # interactively.
826 sys.ps1 = 'In : '
826 sys.ps1 = 'In : '
827 sys.ps2 = '...: '
827 sys.ps2 = '...: '
828 sys.ps3 = 'Out: '
828 sys.ps3 = 'Out: '
829
829
830 def init_display_formatter(self):
830 def init_display_formatter(self):
831 self.display_formatter = DisplayFormatter(parent=self)
831 self.display_formatter = DisplayFormatter(parent=self)
832 self.configurables.append(self.display_formatter)
832 self.configurables.append(self.display_formatter)
833
833
834 def init_display_pub(self):
834 def init_display_pub(self):
835 self.display_pub = self.display_pub_class(parent=self, shell=self)
835 self.display_pub = self.display_pub_class(parent=self, shell=self)
836 self.configurables.append(self.display_pub)
836 self.configurables.append(self.display_pub)
837
837
838 def init_data_pub(self):
838 def init_data_pub(self):
839 if not self.data_pub_class:
839 if not self.data_pub_class:
840 self.data_pub = None
840 self.data_pub = None
841 return
841 return
842 self.data_pub = self.data_pub_class(parent=self)
842 self.data_pub = self.data_pub_class(parent=self)
843 self.configurables.append(self.data_pub)
843 self.configurables.append(self.data_pub)
844
844
845 def init_displayhook(self):
845 def init_displayhook(self):
846 # Initialize displayhook, set in/out prompts and printing system
846 # Initialize displayhook, set in/out prompts and printing system
847 self.displayhook = self.displayhook_class(
847 self.displayhook = self.displayhook_class(
848 parent=self,
848 parent=self,
849 shell=self,
849 shell=self,
850 cache_size=self.cache_size,
850 cache_size=self.cache_size,
851 )
851 )
852 self.configurables.append(self.displayhook)
852 self.configurables.append(self.displayhook)
853 # This is a context manager that installs/revmoes the displayhook at
853 # This is a context manager that installs/revmoes the displayhook at
854 # the appropriate time.
854 # the appropriate time.
855 self.display_trap = DisplayTrap(hook=self.displayhook)
855 self.display_trap = DisplayTrap(hook=self.displayhook)
856
856
857 @staticmethod
857 @staticmethod
858 def get_path_links(p: Path):
858 def get_path_links(p: Path):
859 """Gets path links including all symlinks
859 """Gets path links including all symlinks
860
860
861 Examples
861 Examples
862 --------
862 --------
863 In [1]: from IPython.core.interactiveshell import InteractiveShell
863 In [1]: from IPython.core.interactiveshell import InteractiveShell
864
864
865 In [2]: import sys, pathlib
865 In [2]: import sys, pathlib
866
866
867 In [3]: paths = InteractiveShell.get_path_links(pathlib.Path(sys.executable))
867 In [3]: paths = InteractiveShell.get_path_links(pathlib.Path(sys.executable))
868
868
869 In [4]: len(paths) == len(set(paths))
869 In [4]: len(paths) == len(set(paths))
870 Out[4]: True
870 Out[4]: True
871
871
872 In [5]: bool(paths)
872 In [5]: bool(paths)
873 Out[5]: True
873 Out[5]: True
874 """
874 """
875 paths = [p]
875 paths = [p]
876 while p.is_symlink():
876 while p.is_symlink():
877 new_path = Path(os.readlink(p))
877 new_path = Path(os.readlink(p))
878 if not new_path.is_absolute():
878 if not new_path.is_absolute():
879 new_path = p.parent / new_path
879 new_path = p.parent / new_path
880 p = new_path
880 p = new_path
881 paths.append(p)
881 paths.append(p)
882 return paths
882 return paths
883
883
884 def init_virtualenv(self):
884 def init_virtualenv(self):
885 """Add the current virtualenv to sys.path so the user can import modules from it.
885 """Add the current virtualenv to sys.path so the user can import modules from it.
886 This isn't perfect: it doesn't use the Python interpreter with which the
886 This isn't perfect: it doesn't use the Python interpreter with which the
887 virtualenv was built, and it ignores the --no-site-packages option. A
887 virtualenv was built, and it ignores the --no-site-packages option. A
888 warning will appear suggesting the user installs IPython in the
888 warning will appear suggesting the user installs IPython in the
889 virtualenv, but for many cases, it probably works well enough.
889 virtualenv, but for many cases, it probably works well enough.
890
890
891 Adapted from code snippets online.
891 Adapted from code snippets online.
892
892
893 http://blog.ufsoft.org/2009/1/29/ipython-and-virtualenv
893 http://blog.ufsoft.org/2009/1/29/ipython-and-virtualenv
894 """
894 """
895 if 'VIRTUAL_ENV' not in os.environ:
895 if 'VIRTUAL_ENV' not in os.environ:
896 # Not in a virtualenv
896 # Not in a virtualenv
897 return
897 return
898 elif os.environ["VIRTUAL_ENV"] == "":
898 elif os.environ["VIRTUAL_ENV"] == "":
899 warn("Virtual env path set to '', please check if this is intended.")
899 warn("Virtual env path set to '', please check if this is intended.")
900 return
900 return
901
901
902 p = Path(sys.executable)
902 p = Path(sys.executable)
903 p_venv = Path(os.environ["VIRTUAL_ENV"])
903 p_venv = Path(os.environ["VIRTUAL_ENV"])
904
904
905 # fallback venv detection:
905 # fallback venv detection:
906 # stdlib venv may symlink sys.executable, so we can't use realpath.
906 # stdlib venv may symlink sys.executable, so we can't use realpath.
907 # but others can symlink *to* the venv Python, so we can't just use sys.executable.
907 # but others can symlink *to* the venv Python, so we can't just use sys.executable.
908 # So we just check every item in the symlink tree (generally <= 3)
908 # So we just check every item in the symlink tree (generally <= 3)
909 paths = self.get_path_links(p)
909 paths = self.get_path_links(p)
910
910
911 # In Cygwin paths like "c:\..." and '\cygdrive\c\...' are possible
911 # In Cygwin paths like "c:\..." and '\cygdrive\c\...' are possible
912 if p_venv.parts[1] == "cygdrive":
912 if p_venv.parts[1] == "cygdrive":
913 drive_name = p_venv.parts[2]
913 drive_name = p_venv.parts[2]
914 p_venv = (drive_name + ":/") / Path(*p_venv.parts[3:])
914 p_venv = (drive_name + ":/") / Path(*p_venv.parts[3:])
915
915
916 if any(p_venv == p.parents[1] for p in paths):
916 if any(p_venv == p.parents[1] for p in paths):
917 # Our exe is inside or has access to the virtualenv, don't need to do anything.
917 # Our exe is inside or has access to the virtualenv, don't need to do anything.
918 return
918 return
919
919
920 if sys.platform == "win32":
920 if sys.platform == "win32":
921 virtual_env = str(Path(os.environ["VIRTUAL_ENV"], "Lib", "site-packages"))
921 virtual_env = str(Path(os.environ["VIRTUAL_ENV"], "Lib", "site-packages"))
922 else:
922 else:
923 virtual_env_path = Path(
923 virtual_env_path = Path(
924 os.environ["VIRTUAL_ENV"], "lib", "python{}.{}", "site-packages"
924 os.environ["VIRTUAL_ENV"], "lib", "python{}.{}", "site-packages"
925 )
925 )
926 p_ver = sys.version_info[:2]
926 p_ver = sys.version_info[:2]
927
927
928 # Predict version from py[thon]-x.x in the $VIRTUAL_ENV
928 # Predict version from py[thon]-x.x in the $VIRTUAL_ENV
929 re_m = re.search(r"\bpy(?:thon)?([23])\.(\d+)\b", os.environ["VIRTUAL_ENV"])
929 re_m = re.search(r"\bpy(?:thon)?([23])\.(\d+)\b", os.environ["VIRTUAL_ENV"])
930 if re_m:
930 if re_m:
931 predicted_path = Path(str(virtual_env_path).format(*re_m.groups()))
931 predicted_path = Path(str(virtual_env_path).format(*re_m.groups()))
932 if predicted_path.exists():
932 if predicted_path.exists():
933 p_ver = re_m.groups()
933 p_ver = re_m.groups()
934
934
935 virtual_env = str(virtual_env_path).format(*p_ver)
935 virtual_env = str(virtual_env_path).format(*p_ver)
936 if self.warn_venv:
936 if self.warn_venv:
937 warn(
937 warn(
938 "Attempting to work in a virtualenv. If you encounter problems, "
938 "Attempting to work in a virtualenv. If you encounter problems, "
939 "please install IPython inside the virtualenv."
939 "please install IPython inside the virtualenv."
940 )
940 )
941 import site
941 import site
942 sys.path.insert(0, virtual_env)
942 sys.path.insert(0, virtual_env)
943 site.addsitedir(virtual_env)
943 site.addsitedir(virtual_env)
944
944
945 #-------------------------------------------------------------------------
945 #-------------------------------------------------------------------------
946 # Things related to injections into the sys module
946 # Things related to injections into the sys module
947 #-------------------------------------------------------------------------
947 #-------------------------------------------------------------------------
948
948
949 def save_sys_module_state(self):
949 def save_sys_module_state(self):
950 """Save the state of hooks in the sys module.
950 """Save the state of hooks in the sys module.
951
951
952 This has to be called after self.user_module is created.
952 This has to be called after self.user_module is created.
953 """
953 """
954 self._orig_sys_module_state = {'stdin': sys.stdin,
954 self._orig_sys_module_state = {'stdin': sys.stdin,
955 'stdout': sys.stdout,
955 'stdout': sys.stdout,
956 'stderr': sys.stderr,
956 'stderr': sys.stderr,
957 'excepthook': sys.excepthook}
957 'excepthook': sys.excepthook}
958 self._orig_sys_modules_main_name = self.user_module.__name__
958 self._orig_sys_modules_main_name = self.user_module.__name__
959 self._orig_sys_modules_main_mod = sys.modules.get(self.user_module.__name__)
959 self._orig_sys_modules_main_mod = sys.modules.get(self.user_module.__name__)
960
960
961 def restore_sys_module_state(self):
961 def restore_sys_module_state(self):
962 """Restore the state of the sys module."""
962 """Restore the state of the sys module."""
963 try:
963 try:
964 for k, v in self._orig_sys_module_state.items():
964 for k, v in self._orig_sys_module_state.items():
965 setattr(sys, k, v)
965 setattr(sys, k, v)
966 except AttributeError:
966 except AttributeError:
967 pass
967 pass
968 # Reset what what done in self.init_sys_modules
968 # Reset what what done in self.init_sys_modules
969 if self._orig_sys_modules_main_mod is not None:
969 if self._orig_sys_modules_main_mod is not None:
970 sys.modules[self._orig_sys_modules_main_name] = self._orig_sys_modules_main_mod
970 sys.modules[self._orig_sys_modules_main_name] = self._orig_sys_modules_main_mod
971
971
972 #-------------------------------------------------------------------------
972 #-------------------------------------------------------------------------
973 # Things related to the banner
973 # Things related to the banner
974 #-------------------------------------------------------------------------
974 #-------------------------------------------------------------------------
975
975
976 @property
976 @property
977 def banner(self):
977 def banner(self):
978 banner = self.banner1
978 banner = self.banner1
979 if self.profile and self.profile != 'default':
979 if self.profile and self.profile != 'default':
980 banner += '\nIPython profile: %s\n' % self.profile
980 banner += '\nIPython profile: %s\n' % self.profile
981 if self.banner2:
981 if self.banner2:
982 banner += '\n' + self.banner2
982 banner += '\n' + self.banner2
983 return banner
983 return banner
984
984
985 def show_banner(self, banner=None):
985 def show_banner(self, banner=None):
986 if banner is None:
986 if banner is None:
987 banner = self.banner
987 banner = self.banner
988 sys.stdout.write(banner)
988 sys.stdout.write(banner)
989
989
990 #-------------------------------------------------------------------------
990 #-------------------------------------------------------------------------
991 # Things related to hooks
991 # Things related to hooks
992 #-------------------------------------------------------------------------
992 #-------------------------------------------------------------------------
993
993
994 def init_hooks(self):
994 def init_hooks(self):
995 # hooks holds pointers used for user-side customizations
995 # hooks holds pointers used for user-side customizations
996 self.hooks = Struct()
996 self.hooks = Struct()
997
997
998 self.strdispatchers = {}
998 self.strdispatchers = {}
999
999
1000 # Set all default hooks, defined in the IPython.hooks module.
1000 # Set all default hooks, defined in the IPython.hooks module.
1001 hooks = IPython.core.hooks
1001 hooks = IPython.core.hooks
1002 for hook_name in hooks.__all__:
1002 for hook_name in hooks.__all__:
1003 # default hooks have priority 100, i.e. low; user hooks should have
1003 # default hooks have priority 100, i.e. low; user hooks should have
1004 # 0-100 priority
1004 # 0-100 priority
1005 self.set_hook(hook_name, getattr(hooks, hook_name), 100)
1005 self.set_hook(hook_name, getattr(hooks, hook_name), 100)
1006
1006
1007 if self.display_page:
1007 if self.display_page:
1008 self.set_hook('show_in_pager', page.as_hook(page.display_page), 90)
1008 self.set_hook('show_in_pager', page.as_hook(page.display_page), 90)
1009
1009
1010 def set_hook(self, name, hook, priority=50, str_key=None, re_key=None):
1010 def set_hook(self, name, hook, priority=50, str_key=None, re_key=None):
1011 """set_hook(name,hook) -> sets an internal IPython hook.
1011 """set_hook(name,hook) -> sets an internal IPython hook.
1012
1012
1013 IPython exposes some of its internal API as user-modifiable hooks. By
1013 IPython exposes some of its internal API as user-modifiable hooks. By
1014 adding your function to one of these hooks, you can modify IPython's
1014 adding your function to one of these hooks, you can modify IPython's
1015 behavior to call at runtime your own routines."""
1015 behavior to call at runtime your own routines."""
1016
1016
1017 # At some point in the future, this should validate the hook before it
1017 # At some point in the future, this should validate the hook before it
1018 # accepts it. Probably at least check that the hook takes the number
1018 # accepts it. Probably at least check that the hook takes the number
1019 # of args it's supposed to.
1019 # of args it's supposed to.
1020
1020
1021 f = types.MethodType(hook,self)
1021 f = types.MethodType(hook,self)
1022
1022
1023 # check if the hook is for strdispatcher first
1023 # check if the hook is for strdispatcher first
1024 if str_key is not None:
1024 if str_key is not None:
1025 sdp = self.strdispatchers.get(name, StrDispatch())
1025 sdp = self.strdispatchers.get(name, StrDispatch())
1026 sdp.add_s(str_key, f, priority )
1026 sdp.add_s(str_key, f, priority )
1027 self.strdispatchers[name] = sdp
1027 self.strdispatchers[name] = sdp
1028 return
1028 return
1029 if re_key is not None:
1029 if re_key is not None:
1030 sdp = self.strdispatchers.get(name, StrDispatch())
1030 sdp = self.strdispatchers.get(name, StrDispatch())
1031 sdp.add_re(re.compile(re_key), f, priority )
1031 sdp.add_re(re.compile(re_key), f, priority )
1032 self.strdispatchers[name] = sdp
1032 self.strdispatchers[name] = sdp
1033 return
1033 return
1034
1034
1035 dp = getattr(self.hooks, name, None)
1035 dp = getattr(self.hooks, name, None)
1036 if name not in IPython.core.hooks.__all__:
1036 if name not in IPython.core.hooks.__all__:
1037 print("Warning! Hook '%s' is not one of %s" % \
1037 print("Warning! Hook '%s' is not one of %s" % \
1038 (name, IPython.core.hooks.__all__ ))
1038 (name, IPython.core.hooks.__all__ ))
1039
1039
1040 if name in IPython.core.hooks.deprecated:
1040 if name in IPython.core.hooks.deprecated:
1041 alternative = IPython.core.hooks.deprecated[name]
1041 alternative = IPython.core.hooks.deprecated[name]
1042 raise ValueError(
1042 raise ValueError(
1043 "Hook {} has been deprecated since IPython 5.0. Use {} instead.".format(
1043 "Hook {} has been deprecated since IPython 5.0. Use {} instead.".format(
1044 name, alternative
1044 name, alternative
1045 )
1045 )
1046 )
1046 )
1047
1047
1048 if not dp:
1048 if not dp:
1049 dp = IPython.core.hooks.CommandChainDispatcher()
1049 dp = IPython.core.hooks.CommandChainDispatcher()
1050
1050
1051 try:
1051 try:
1052 dp.add(f,priority)
1052 dp.add(f,priority)
1053 except AttributeError:
1053 except AttributeError:
1054 # it was not commandchain, plain old func - replace
1054 # it was not commandchain, plain old func - replace
1055 dp = f
1055 dp = f
1056
1056
1057 setattr(self.hooks,name, dp)
1057 setattr(self.hooks,name, dp)
1058
1058
1059 #-------------------------------------------------------------------------
1059 #-------------------------------------------------------------------------
1060 # Things related to events
1060 # Things related to events
1061 #-------------------------------------------------------------------------
1061 #-------------------------------------------------------------------------
1062
1062
1063 def init_events(self):
1063 def init_events(self):
1064 self.events = EventManager(self, available_events)
1064 self.events = EventManager(self, available_events)
1065
1065
1066 self.events.register("pre_execute", self._clear_warning_registry)
1066 self.events.register("pre_execute", self._clear_warning_registry)
1067
1067
1068 def register_post_execute(self, func):
1068 def register_post_execute(self, func):
1069 """DEPRECATED: Use ip.events.register('post_run_cell', func)
1069 """DEPRECATED: Use ip.events.register('post_run_cell', func)
1070
1070
1071 Register a function for calling after code execution.
1071 Register a function for calling after code execution.
1072 """
1072 """
1073 raise ValueError(
1073 raise ValueError(
1074 "ip.register_post_execute is deprecated since IPython 1.0, use "
1074 "ip.register_post_execute is deprecated since IPython 1.0, use "
1075 "ip.events.register('post_run_cell', func) instead."
1075 "ip.events.register('post_run_cell', func) instead."
1076 )
1076 )
1077
1077
1078 def _clear_warning_registry(self):
1078 def _clear_warning_registry(self):
1079 # clear the warning registry, so that different code blocks with
1079 # clear the warning registry, so that different code blocks with
1080 # overlapping line number ranges don't cause spurious suppression of
1080 # overlapping line number ranges don't cause spurious suppression of
1081 # warnings (see gh-6611 for details)
1081 # warnings (see gh-6611 for details)
1082 if "__warningregistry__" in self.user_global_ns:
1082 if "__warningregistry__" in self.user_global_ns:
1083 del self.user_global_ns["__warningregistry__"]
1083 del self.user_global_ns["__warningregistry__"]
1084
1084
1085 #-------------------------------------------------------------------------
1085 #-------------------------------------------------------------------------
1086 # Things related to the "main" module
1086 # Things related to the "main" module
1087 #-------------------------------------------------------------------------
1087 #-------------------------------------------------------------------------
1088
1088
1089 def new_main_mod(self, filename, modname):
1089 def new_main_mod(self, filename, modname):
1090 """Return a new 'main' module object for user code execution.
1090 """Return a new 'main' module object for user code execution.
1091
1091
1092 ``filename`` should be the path of the script which will be run in the
1092 ``filename`` should be the path of the script which will be run in the
1093 module. Requests with the same filename will get the same module, with
1093 module. Requests with the same filename will get the same module, with
1094 its namespace cleared.
1094 its namespace cleared.
1095
1095
1096 ``modname`` should be the module name - normally either '__main__' or
1096 ``modname`` should be the module name - normally either '__main__' or
1097 the basename of the file without the extension.
1097 the basename of the file without the extension.
1098
1098
1099 When scripts are executed via %run, we must keep a reference to their
1099 When scripts are executed via %run, we must keep a reference to their
1100 __main__ module around so that Python doesn't
1100 __main__ module around so that Python doesn't
1101 clear it, rendering references to module globals useless.
1101 clear it, rendering references to module globals useless.
1102
1102
1103 This method keeps said reference in a private dict, keyed by the
1103 This method keeps said reference in a private dict, keyed by the
1104 absolute path of the script. This way, for multiple executions of the
1104 absolute path of the script. This way, for multiple executions of the
1105 same script we only keep one copy of the namespace (the last one),
1105 same script we only keep one copy of the namespace (the last one),
1106 thus preventing memory leaks from old references while allowing the
1106 thus preventing memory leaks from old references while allowing the
1107 objects from the last execution to be accessible.
1107 objects from the last execution to be accessible.
1108 """
1108 """
1109 filename = os.path.abspath(filename)
1109 filename = os.path.abspath(filename)
1110 try:
1110 try:
1111 main_mod = self._main_mod_cache[filename]
1111 main_mod = self._main_mod_cache[filename]
1112 except KeyError:
1112 except KeyError:
1113 main_mod = self._main_mod_cache[filename] = types.ModuleType(
1113 main_mod = self._main_mod_cache[filename] = types.ModuleType(
1114 modname,
1114 modname,
1115 doc="Module created for script run in IPython")
1115 doc="Module created for script run in IPython")
1116 else:
1116 else:
1117 main_mod.__dict__.clear()
1117 main_mod.__dict__.clear()
1118 main_mod.__name__ = modname
1118 main_mod.__name__ = modname
1119
1119
1120 main_mod.__file__ = filename
1120 main_mod.__file__ = filename
1121 # It seems pydoc (and perhaps others) needs any module instance to
1121 # It seems pydoc (and perhaps others) needs any module instance to
1122 # implement a __nonzero__ method
1122 # implement a __nonzero__ method
1123 main_mod.__nonzero__ = lambda : True
1123 main_mod.__nonzero__ = lambda : True
1124
1124
1125 return main_mod
1125 return main_mod
1126
1126
1127 def clear_main_mod_cache(self):
1127 def clear_main_mod_cache(self):
1128 """Clear the cache of main modules.
1128 """Clear the cache of main modules.
1129
1129
1130 Mainly for use by utilities like %reset.
1130 Mainly for use by utilities like %reset.
1131
1131
1132 Examples
1132 Examples
1133 --------
1133 --------
1134 In [15]: import IPython
1134 In [15]: import IPython
1135
1135
1136 In [16]: m = _ip.new_main_mod(IPython.__file__, 'IPython')
1136 In [16]: m = _ip.new_main_mod(IPython.__file__, 'IPython')
1137
1137
1138 In [17]: len(_ip._main_mod_cache) > 0
1138 In [17]: len(_ip._main_mod_cache) > 0
1139 Out[17]: True
1139 Out[17]: True
1140
1140
1141 In [18]: _ip.clear_main_mod_cache()
1141 In [18]: _ip.clear_main_mod_cache()
1142
1142
1143 In [19]: len(_ip._main_mod_cache) == 0
1143 In [19]: len(_ip._main_mod_cache) == 0
1144 Out[19]: True
1144 Out[19]: True
1145 """
1145 """
1146 self._main_mod_cache.clear()
1146 self._main_mod_cache.clear()
1147
1147
1148 #-------------------------------------------------------------------------
1148 #-------------------------------------------------------------------------
1149 # Things related to debugging
1149 # Things related to debugging
1150 #-------------------------------------------------------------------------
1150 #-------------------------------------------------------------------------
1151
1151
1152 def init_pdb(self):
1152 def init_pdb(self):
1153 # Set calling of pdb on exceptions
1153 # Set calling of pdb on exceptions
1154 # self.call_pdb is a property
1154 # self.call_pdb is a property
1155 self.call_pdb = self.pdb
1155 self.call_pdb = self.pdb
1156
1156
1157 def _get_call_pdb(self):
1157 def _get_call_pdb(self):
1158 return self._call_pdb
1158 return self._call_pdb
1159
1159
1160 def _set_call_pdb(self,val):
1160 def _set_call_pdb(self,val):
1161
1161
1162 if val not in (0,1,False,True):
1162 if val not in (0,1,False,True):
1163 raise ValueError('new call_pdb value must be boolean')
1163 raise ValueError('new call_pdb value must be boolean')
1164
1164
1165 # store value in instance
1165 # store value in instance
1166 self._call_pdb = val
1166 self._call_pdb = val
1167
1167
1168 # notify the actual exception handlers
1168 # notify the actual exception handlers
1169 self.InteractiveTB.call_pdb = val
1169 self.InteractiveTB.call_pdb = val
1170
1170
1171 call_pdb = property(_get_call_pdb,_set_call_pdb,None,
1171 call_pdb = property(_get_call_pdb,_set_call_pdb,None,
1172 'Control auto-activation of pdb at exceptions')
1172 'Control auto-activation of pdb at exceptions')
1173
1173
1174 def debugger(self,force=False):
1174 def debugger(self,force=False):
1175 """Call the pdb debugger.
1175 """Call the pdb debugger.
1176
1176
1177 Keywords:
1177 Keywords:
1178
1178
1179 - force(False): by default, this routine checks the instance call_pdb
1179 - force(False): by default, this routine checks the instance call_pdb
1180 flag and does not actually invoke the debugger if the flag is false.
1180 flag and does not actually invoke the debugger if the flag is false.
1181 The 'force' option forces the debugger to activate even if the flag
1181 The 'force' option forces the debugger to activate even if the flag
1182 is false.
1182 is false.
1183 """
1183 """
1184
1184
1185 if not (force or self.call_pdb):
1185 if not (force or self.call_pdb):
1186 return
1186 return
1187
1187
1188 if not hasattr(sys,'last_traceback'):
1188 if not hasattr(sys,'last_traceback'):
1189 error('No traceback has been produced, nothing to debug.')
1189 error('No traceback has been produced, nothing to debug.')
1190 return
1190 return
1191
1191
1192 self.InteractiveTB.debugger(force=True)
1192 self.InteractiveTB.debugger(force=True)
1193
1193
1194 #-------------------------------------------------------------------------
1194 #-------------------------------------------------------------------------
1195 # Things related to IPython's various namespaces
1195 # Things related to IPython's various namespaces
1196 #-------------------------------------------------------------------------
1196 #-------------------------------------------------------------------------
1197 default_user_namespaces = True
1197 default_user_namespaces = True
1198
1198
1199 def init_create_namespaces(self, user_module=None, user_ns=None):
1199 def init_create_namespaces(self, user_module=None, user_ns=None):
1200 # Create the namespace where the user will operate. user_ns is
1200 # Create the namespace where the user will operate. user_ns is
1201 # normally the only one used, and it is passed to the exec calls as
1201 # normally the only one used, and it is passed to the exec calls as
1202 # the locals argument. But we do carry a user_global_ns namespace
1202 # the locals argument. But we do carry a user_global_ns namespace
1203 # given as the exec 'globals' argument, This is useful in embedding
1203 # given as the exec 'globals' argument, This is useful in embedding
1204 # situations where the ipython shell opens in a context where the
1204 # situations where the ipython shell opens in a context where the
1205 # distinction between locals and globals is meaningful. For
1205 # distinction between locals and globals is meaningful. For
1206 # non-embedded contexts, it is just the same object as the user_ns dict.
1206 # non-embedded contexts, it is just the same object as the user_ns dict.
1207
1207
1208 # FIXME. For some strange reason, __builtins__ is showing up at user
1208 # FIXME. For some strange reason, __builtins__ is showing up at user
1209 # level as a dict instead of a module. This is a manual fix, but I
1209 # level as a dict instead of a module. This is a manual fix, but I
1210 # should really track down where the problem is coming from. Alex
1210 # should really track down where the problem is coming from. Alex
1211 # Schmolck reported this problem first.
1211 # Schmolck reported this problem first.
1212
1212
1213 # A useful post by Alex Martelli on this topic:
1213 # A useful post by Alex Martelli on this topic:
1214 # Re: inconsistent value from __builtins__
1214 # Re: inconsistent value from __builtins__
1215 # Von: Alex Martelli <aleaxit@yahoo.com>
1215 # Von: Alex Martelli <aleaxit@yahoo.com>
1216 # Datum: Freitag 01 Oktober 2004 04:45:34 nachmittags/abends
1216 # Datum: Freitag 01 Oktober 2004 04:45:34 nachmittags/abends
1217 # Gruppen: comp.lang.python
1217 # Gruppen: comp.lang.python
1218
1218
1219 # Michael Hohn <hohn@hooknose.lbl.gov> wrote:
1219 # Michael Hohn <hohn@hooknose.lbl.gov> wrote:
1220 # > >>> print type(builtin_check.get_global_binding('__builtins__'))
1220 # > >>> print type(builtin_check.get_global_binding('__builtins__'))
1221 # > <type 'dict'>
1221 # > <type 'dict'>
1222 # > >>> print type(__builtins__)
1222 # > >>> print type(__builtins__)
1223 # > <type 'module'>
1223 # > <type 'module'>
1224 # > Is this difference in return value intentional?
1224 # > Is this difference in return value intentional?
1225
1225
1226 # Well, it's documented that '__builtins__' can be either a dictionary
1226 # Well, it's documented that '__builtins__' can be either a dictionary
1227 # or a module, and it's been that way for a long time. Whether it's
1227 # or a module, and it's been that way for a long time. Whether it's
1228 # intentional (or sensible), I don't know. In any case, the idea is
1228 # intentional (or sensible), I don't know. In any case, the idea is
1229 # that if you need to access the built-in namespace directly, you
1229 # that if you need to access the built-in namespace directly, you
1230 # should start with "import __builtin__" (note, no 's') which will
1230 # should start with "import __builtin__" (note, no 's') which will
1231 # definitely give you a module. Yeah, it's somewhat confusing:-(.
1231 # definitely give you a module. Yeah, it's somewhat confusing:-(.
1232
1232
1233 # These routines return a properly built module and dict as needed by
1233 # These routines return a properly built module and dict as needed by
1234 # the rest of the code, and can also be used by extension writers to
1234 # the rest of the code, and can also be used by extension writers to
1235 # generate properly initialized namespaces.
1235 # generate properly initialized namespaces.
1236 if (user_ns is not None) or (user_module is not None):
1236 if (user_ns is not None) or (user_module is not None):
1237 self.default_user_namespaces = False
1237 self.default_user_namespaces = False
1238 self.user_module, self.user_ns = self.prepare_user_module(user_module, user_ns)
1238 self.user_module, self.user_ns = self.prepare_user_module(user_module, user_ns)
1239
1239
1240 # A record of hidden variables we have added to the user namespace, so
1240 # A record of hidden variables we have added to the user namespace, so
1241 # we can list later only variables defined in actual interactive use.
1241 # we can list later only variables defined in actual interactive use.
1242 self.user_ns_hidden = {}
1242 self.user_ns_hidden = {}
1243
1243
1244 # Now that FakeModule produces a real module, we've run into a nasty
1244 # Now that FakeModule produces a real module, we've run into a nasty
1245 # problem: after script execution (via %run), the module where the user
1245 # problem: after script execution (via %run), the module where the user
1246 # code ran is deleted. Now that this object is a true module (needed
1246 # code ran is deleted. Now that this object is a true module (needed
1247 # so doctest and other tools work correctly), the Python module
1247 # so doctest and other tools work correctly), the Python module
1248 # teardown mechanism runs over it, and sets to None every variable
1248 # teardown mechanism runs over it, and sets to None every variable
1249 # present in that module. Top-level references to objects from the
1249 # present in that module. Top-level references to objects from the
1250 # script survive, because the user_ns is updated with them. However,
1250 # script survive, because the user_ns is updated with them. However,
1251 # calling functions defined in the script that use other things from
1251 # calling functions defined in the script that use other things from
1252 # the script will fail, because the function's closure had references
1252 # the script will fail, because the function's closure had references
1253 # to the original objects, which are now all None. So we must protect
1253 # to the original objects, which are now all None. So we must protect
1254 # these modules from deletion by keeping a cache.
1254 # these modules from deletion by keeping a cache.
1255 #
1255 #
1256 # To avoid keeping stale modules around (we only need the one from the
1256 # To avoid keeping stale modules around (we only need the one from the
1257 # last run), we use a dict keyed with the full path to the script, so
1257 # last run), we use a dict keyed with the full path to the script, so
1258 # only the last version of the module is held in the cache. Note,
1258 # only the last version of the module is held in the cache. Note,
1259 # however, that we must cache the module *namespace contents* (their
1259 # however, that we must cache the module *namespace contents* (their
1260 # __dict__). Because if we try to cache the actual modules, old ones
1260 # __dict__). Because if we try to cache the actual modules, old ones
1261 # (uncached) could be destroyed while still holding references (such as
1261 # (uncached) could be destroyed while still holding references (such as
1262 # those held by GUI objects that tend to be long-lived)>
1262 # those held by GUI objects that tend to be long-lived)>
1263 #
1263 #
1264 # The %reset command will flush this cache. See the cache_main_mod()
1264 # The %reset command will flush this cache. See the cache_main_mod()
1265 # and clear_main_mod_cache() methods for details on use.
1265 # and clear_main_mod_cache() methods for details on use.
1266
1266
1267 # This is the cache used for 'main' namespaces
1267 # This is the cache used for 'main' namespaces
1268 self._main_mod_cache = {}
1268 self._main_mod_cache = {}
1269
1269
1270 # A table holding all the namespaces IPython deals with, so that
1270 # A table holding all the namespaces IPython deals with, so that
1271 # introspection facilities can search easily.
1271 # introspection facilities can search easily.
1272 self.ns_table = {'user_global':self.user_module.__dict__,
1272 self.ns_table = {'user_global':self.user_module.__dict__,
1273 'user_local':self.user_ns,
1273 'user_local':self.user_ns,
1274 'builtin':builtin_mod.__dict__
1274 'builtin':builtin_mod.__dict__
1275 }
1275 }
1276
1276
1277 @property
1277 @property
1278 def user_global_ns(self):
1278 def user_global_ns(self):
1279 return self.user_module.__dict__
1279 return self.user_module.__dict__
1280
1280
1281 def prepare_user_module(self, user_module=None, user_ns=None):
1281 def prepare_user_module(self, user_module=None, user_ns=None):
1282 """Prepare the module and namespace in which user code will be run.
1282 """Prepare the module and namespace in which user code will be run.
1283
1283
1284 When IPython is started normally, both parameters are None: a new module
1284 When IPython is started normally, both parameters are None: a new module
1285 is created automatically, and its __dict__ used as the namespace.
1285 is created automatically, and its __dict__ used as the namespace.
1286
1286
1287 If only user_module is provided, its __dict__ is used as the namespace.
1287 If only user_module is provided, its __dict__ is used as the namespace.
1288 If only user_ns is provided, a dummy module is created, and user_ns
1288 If only user_ns is provided, a dummy module is created, and user_ns
1289 becomes the global namespace. If both are provided (as they may be
1289 becomes the global namespace. If both are provided (as they may be
1290 when embedding), user_ns is the local namespace, and user_module
1290 when embedding), user_ns is the local namespace, and user_module
1291 provides the global namespace.
1291 provides the global namespace.
1292
1292
1293 Parameters
1293 Parameters
1294 ----------
1294 ----------
1295 user_module : module, optional
1295 user_module : module, optional
1296 The current user module in which IPython is being run. If None,
1296 The current user module in which IPython is being run. If None,
1297 a clean module will be created.
1297 a clean module will be created.
1298 user_ns : dict, optional
1298 user_ns : dict, optional
1299 A namespace in which to run interactive commands.
1299 A namespace in which to run interactive commands.
1300
1300
1301 Returns
1301 Returns
1302 -------
1302 -------
1303 A tuple of user_module and user_ns, each properly initialised.
1303 A tuple of user_module and user_ns, each properly initialised.
1304 """
1304 """
1305 if user_module is None and user_ns is not None:
1305 if user_module is None and user_ns is not None:
1306 user_ns.setdefault("__name__", "__main__")
1306 user_ns.setdefault("__name__", "__main__")
1307 user_module = DummyMod()
1307 user_module = DummyMod()
1308 user_module.__dict__ = user_ns
1308 user_module.__dict__ = user_ns
1309
1309
1310 if user_module is None:
1310 if user_module is None:
1311 user_module = types.ModuleType("__main__",
1311 user_module = types.ModuleType("__main__",
1312 doc="Automatically created module for IPython interactive environment")
1312 doc="Automatically created module for IPython interactive environment")
1313
1313
1314 # We must ensure that __builtin__ (without the final 's') is always
1314 # We must ensure that __builtin__ (without the final 's') is always
1315 # available and pointing to the __builtin__ *module*. For more details:
1315 # available and pointing to the __builtin__ *module*. For more details:
1316 # http://mail.python.org/pipermail/python-dev/2001-April/014068.html
1316 # http://mail.python.org/pipermail/python-dev/2001-April/014068.html
1317 user_module.__dict__.setdefault('__builtin__', builtin_mod)
1317 user_module.__dict__.setdefault('__builtin__', builtin_mod)
1318 user_module.__dict__.setdefault('__builtins__', builtin_mod)
1318 user_module.__dict__.setdefault('__builtins__', builtin_mod)
1319
1319
1320 if user_ns is None:
1320 if user_ns is None:
1321 user_ns = user_module.__dict__
1321 user_ns = user_module.__dict__
1322
1322
1323 return user_module, user_ns
1323 return user_module, user_ns
1324
1324
1325 def init_sys_modules(self):
1325 def init_sys_modules(self):
1326 # We need to insert into sys.modules something that looks like a
1326 # We need to insert into sys.modules something that looks like a
1327 # module but which accesses the IPython namespace, for shelve and
1327 # module but which accesses the IPython namespace, for shelve and
1328 # pickle to work interactively. Normally they rely on getting
1328 # pickle to work interactively. Normally they rely on getting
1329 # everything out of __main__, but for embedding purposes each IPython
1329 # everything out of __main__, but for embedding purposes each IPython
1330 # instance has its own private namespace, so we can't go shoving
1330 # instance has its own private namespace, so we can't go shoving
1331 # everything into __main__.
1331 # everything into __main__.
1332
1332
1333 # note, however, that we should only do this for non-embedded
1333 # note, however, that we should only do this for non-embedded
1334 # ipythons, which really mimic the __main__.__dict__ with their own
1334 # ipythons, which really mimic the __main__.__dict__ with their own
1335 # namespace. Embedded instances, on the other hand, should not do
1335 # namespace. Embedded instances, on the other hand, should not do
1336 # this because they need to manage the user local/global namespaces
1336 # this because they need to manage the user local/global namespaces
1337 # only, but they live within a 'normal' __main__ (meaning, they
1337 # only, but they live within a 'normal' __main__ (meaning, they
1338 # shouldn't overtake the execution environment of the script they're
1338 # shouldn't overtake the execution environment of the script they're
1339 # embedded in).
1339 # embedded in).
1340
1340
1341 # This is overridden in the InteractiveShellEmbed subclass to a no-op.
1341 # This is overridden in the InteractiveShellEmbed subclass to a no-op.
1342 main_name = self.user_module.__name__
1342 main_name = self.user_module.__name__
1343 sys.modules[main_name] = self.user_module
1343 sys.modules[main_name] = self.user_module
1344
1344
1345 def init_user_ns(self):
1345 def init_user_ns(self):
1346 """Initialize all user-visible namespaces to their minimum defaults.
1346 """Initialize all user-visible namespaces to their minimum defaults.
1347
1347
1348 Certain history lists are also initialized here, as they effectively
1348 Certain history lists are also initialized here, as they effectively
1349 act as user namespaces.
1349 act as user namespaces.
1350
1350
1351 Notes
1351 Notes
1352 -----
1352 -----
1353 All data structures here are only filled in, they are NOT reset by this
1353 All data structures here are only filled in, they are NOT reset by this
1354 method. If they were not empty before, data will simply be added to
1354 method. If they were not empty before, data will simply be added to
1355 them.
1355 them.
1356 """
1356 """
1357 # This function works in two parts: first we put a few things in
1357 # This function works in two parts: first we put a few things in
1358 # user_ns, and we sync that contents into user_ns_hidden so that these
1358 # user_ns, and we sync that contents into user_ns_hidden so that these
1359 # initial variables aren't shown by %who. After the sync, we add the
1359 # initial variables aren't shown by %who. After the sync, we add the
1360 # rest of what we *do* want the user to see with %who even on a new
1360 # rest of what we *do* want the user to see with %who even on a new
1361 # session (probably nothing, so they really only see their own stuff)
1361 # session (probably nothing, so they really only see their own stuff)
1362
1362
1363 # The user dict must *always* have a __builtin__ reference to the
1363 # The user dict must *always* have a __builtin__ reference to the
1364 # Python standard __builtin__ namespace, which must be imported.
1364 # Python standard __builtin__ namespace, which must be imported.
1365 # This is so that certain operations in prompt evaluation can be
1365 # This is so that certain operations in prompt evaluation can be
1366 # reliably executed with builtins. Note that we can NOT use
1366 # reliably executed with builtins. Note that we can NOT use
1367 # __builtins__ (note the 's'), because that can either be a dict or a
1367 # __builtins__ (note the 's'), because that can either be a dict or a
1368 # module, and can even mutate at runtime, depending on the context
1368 # module, and can even mutate at runtime, depending on the context
1369 # (Python makes no guarantees on it). In contrast, __builtin__ is
1369 # (Python makes no guarantees on it). In contrast, __builtin__ is
1370 # always a module object, though it must be explicitly imported.
1370 # always a module object, though it must be explicitly imported.
1371
1371
1372 # For more details:
1372 # For more details:
1373 # http://mail.python.org/pipermail/python-dev/2001-April/014068.html
1373 # http://mail.python.org/pipermail/python-dev/2001-April/014068.html
1374 ns = {}
1374 ns = {}
1375
1375
1376 # make global variables for user access to the histories
1376 # make global variables for user access to the histories
1377 ns['_ih'] = self.history_manager.input_hist_parsed
1377 ns['_ih'] = self.history_manager.input_hist_parsed
1378 ns['_oh'] = self.history_manager.output_hist
1378 ns['_oh'] = self.history_manager.output_hist
1379 ns['_dh'] = self.history_manager.dir_hist
1379 ns['_dh'] = self.history_manager.dir_hist
1380
1380
1381 # user aliases to input and output histories. These shouldn't show up
1381 # user aliases to input and output histories. These shouldn't show up
1382 # in %who, as they can have very large reprs.
1382 # in %who, as they can have very large reprs.
1383 ns['In'] = self.history_manager.input_hist_parsed
1383 ns['In'] = self.history_manager.input_hist_parsed
1384 ns['Out'] = self.history_manager.output_hist
1384 ns['Out'] = self.history_manager.output_hist
1385
1385
1386 # Store myself as the public api!!!
1386 # Store myself as the public api!!!
1387 ns['get_ipython'] = self.get_ipython
1387 ns['get_ipython'] = self.get_ipython
1388
1388
1389 ns['exit'] = self.exiter
1389 ns['exit'] = self.exiter
1390 ns['quit'] = self.exiter
1390 ns['quit'] = self.exiter
1391 ns["open"] = _modified_open
1391 ns["open"] = _modified_open
1392
1392
1393 # Sync what we've added so far to user_ns_hidden so these aren't seen
1393 # Sync what we've added so far to user_ns_hidden so these aren't seen
1394 # by %who
1394 # by %who
1395 self.user_ns_hidden.update(ns)
1395 self.user_ns_hidden.update(ns)
1396
1396
1397 # Anything put into ns now would show up in %who. Think twice before
1397 # Anything put into ns now would show up in %who. Think twice before
1398 # putting anything here, as we really want %who to show the user their
1398 # putting anything here, as we really want %who to show the user their
1399 # stuff, not our variables.
1399 # stuff, not our variables.
1400
1400
1401 # Finally, update the real user's namespace
1401 # Finally, update the real user's namespace
1402 self.user_ns.update(ns)
1402 self.user_ns.update(ns)
1403
1403
1404 @property
1404 @property
1405 def all_ns_refs(self):
1405 def all_ns_refs(self):
1406 """Get a list of references to all the namespace dictionaries in which
1406 """Get a list of references to all the namespace dictionaries in which
1407 IPython might store a user-created object.
1407 IPython might store a user-created object.
1408
1408
1409 Note that this does not include the displayhook, which also caches
1409 Note that this does not include the displayhook, which also caches
1410 objects from the output."""
1410 objects from the output."""
1411 return [self.user_ns, self.user_global_ns, self.user_ns_hidden] + \
1411 return [self.user_ns, self.user_global_ns, self.user_ns_hidden] + \
1412 [m.__dict__ for m in self._main_mod_cache.values()]
1412 [m.__dict__ for m in self._main_mod_cache.values()]
1413
1413
1414 def reset(self, new_session=True, aggressive=False):
1414 def reset(self, new_session=True, aggressive=False):
1415 """Clear all internal namespaces, and attempt to release references to
1415 """Clear all internal namespaces, and attempt to release references to
1416 user objects.
1416 user objects.
1417
1417
1418 If new_session is True, a new history session will be opened.
1418 If new_session is True, a new history session will be opened.
1419 """
1419 """
1420 # Clear histories
1420 # Clear histories
1421 assert self.history_manager is not None
1421 assert self.history_manager is not None
1422 self.history_manager.reset(new_session)
1422 self.history_manager.reset(new_session)
1423 # Reset counter used to index all histories
1423 # Reset counter used to index all histories
1424 if new_session:
1424 if new_session:
1425 self.execution_count = 1
1425 self.execution_count = 1
1426
1426
1427 # Reset last execution result
1427 # Reset last execution result
1428 self.last_execution_succeeded = True
1428 self.last_execution_succeeded = True
1429 self.last_execution_result = None
1429 self.last_execution_result = None
1430
1430
1431 # Flush cached output items
1431 # Flush cached output items
1432 if self.displayhook.do_full_cache:
1432 if self.displayhook.do_full_cache:
1433 self.displayhook.flush()
1433 self.displayhook.flush()
1434
1434
1435 # The main execution namespaces must be cleared very carefully,
1435 # The main execution namespaces must be cleared very carefully,
1436 # skipping the deletion of the builtin-related keys, because doing so
1436 # skipping the deletion of the builtin-related keys, because doing so
1437 # would cause errors in many object's __del__ methods.
1437 # would cause errors in many object's __del__ methods.
1438 if self.user_ns is not self.user_global_ns:
1438 if self.user_ns is not self.user_global_ns:
1439 self.user_ns.clear()
1439 self.user_ns.clear()
1440 ns = self.user_global_ns
1440 ns = self.user_global_ns
1441 drop_keys = set(ns.keys())
1441 drop_keys = set(ns.keys())
1442 drop_keys.discard('__builtin__')
1442 drop_keys.discard('__builtin__')
1443 drop_keys.discard('__builtins__')
1443 drop_keys.discard('__builtins__')
1444 drop_keys.discard('__name__')
1444 drop_keys.discard('__name__')
1445 for k in drop_keys:
1445 for k in drop_keys:
1446 del ns[k]
1446 del ns[k]
1447
1447
1448 self.user_ns_hidden.clear()
1448 self.user_ns_hidden.clear()
1449
1449
1450 # Restore the user namespaces to minimal usability
1450 # Restore the user namespaces to minimal usability
1451 self.init_user_ns()
1451 self.init_user_ns()
1452 if aggressive and not hasattr(self, "_sys_modules_keys"):
1452 if aggressive and not hasattr(self, "_sys_modules_keys"):
1453 print("Cannot restore sys.module, no snapshot")
1453 print("Cannot restore sys.module, no snapshot")
1454 elif aggressive:
1454 elif aggressive:
1455 print("culling sys module...")
1455 print("culling sys module...")
1456 current_keys = set(sys.modules.keys())
1456 current_keys = set(sys.modules.keys())
1457 for k in current_keys - self._sys_modules_keys:
1457 for k in current_keys - self._sys_modules_keys:
1458 if k.startswith("multiprocessing"):
1458 if k.startswith("multiprocessing"):
1459 continue
1459 continue
1460 del sys.modules[k]
1460 del sys.modules[k]
1461
1461
1462 # Restore the default and user aliases
1462 # Restore the default and user aliases
1463 self.alias_manager.clear_aliases()
1463 self.alias_manager.clear_aliases()
1464 self.alias_manager.init_aliases()
1464 self.alias_manager.init_aliases()
1465
1465
1466 # Now define aliases that only make sense on the terminal, because they
1466 # Now define aliases that only make sense on the terminal, because they
1467 # need direct access to the console in a way that we can't emulate in
1467 # need direct access to the console in a way that we can't emulate in
1468 # GUI or web frontend
1468 # GUI or web frontend
1469 if os.name == 'posix':
1469 if os.name == 'posix':
1470 for cmd in ('clear', 'more', 'less', 'man'):
1470 for cmd in ('clear', 'more', 'less', 'man'):
1471 if cmd not in self.magics_manager.magics['line']:
1471 if cmd not in self.magics_manager.magics['line']:
1472 self.alias_manager.soft_define_alias(cmd, cmd)
1472 self.alias_manager.soft_define_alias(cmd, cmd)
1473
1473
1474 # Flush the private list of module references kept for script
1474 # Flush the private list of module references kept for script
1475 # execution protection
1475 # execution protection
1476 self.clear_main_mod_cache()
1476 self.clear_main_mod_cache()
1477
1477
1478 def del_var(self, varname, by_name=False):
1478 def del_var(self, varname, by_name=False):
1479 """Delete a variable from the various namespaces, so that, as
1479 """Delete a variable from the various namespaces, so that, as
1480 far as possible, we're not keeping any hidden references to it.
1480 far as possible, we're not keeping any hidden references to it.
1481
1481
1482 Parameters
1482 Parameters
1483 ----------
1483 ----------
1484 varname : str
1484 varname : str
1485 The name of the variable to delete.
1485 The name of the variable to delete.
1486 by_name : bool
1486 by_name : bool
1487 If True, delete variables with the given name in each
1487 If True, delete variables with the given name in each
1488 namespace. If False (default), find the variable in the user
1488 namespace. If False (default), find the variable in the user
1489 namespace, and delete references to it.
1489 namespace, and delete references to it.
1490 """
1490 """
1491 if varname in ('__builtin__', '__builtins__'):
1491 if varname in ('__builtin__', '__builtins__'):
1492 raise ValueError("Refusing to delete %s" % varname)
1492 raise ValueError("Refusing to delete %s" % varname)
1493
1493
1494 ns_refs = self.all_ns_refs
1494 ns_refs = self.all_ns_refs
1495
1495
1496 if by_name: # Delete by name
1496 if by_name: # Delete by name
1497 for ns in ns_refs:
1497 for ns in ns_refs:
1498 try:
1498 try:
1499 del ns[varname]
1499 del ns[varname]
1500 except KeyError:
1500 except KeyError:
1501 pass
1501 pass
1502 else: # Delete by object
1502 else: # Delete by object
1503 try:
1503 try:
1504 obj = self.user_ns[varname]
1504 obj = self.user_ns[varname]
1505 except KeyError as e:
1505 except KeyError as e:
1506 raise NameError("name '%s' is not defined" % varname) from e
1506 raise NameError("name '%s' is not defined" % varname) from e
1507 # Also check in output history
1507 # Also check in output history
1508 assert self.history_manager is not None
1508 assert self.history_manager is not None
1509 ns_refs.append(self.history_manager.output_hist)
1509 ns_refs.append(self.history_manager.output_hist)
1510 for ns in ns_refs:
1510 for ns in ns_refs:
1511 to_delete = [n for n, o in ns.items() if o is obj]
1511 to_delete = [n for n, o in ns.items() if o is obj]
1512 for name in to_delete:
1512 for name in to_delete:
1513 del ns[name]
1513 del ns[name]
1514
1514
1515 # Ensure it is removed from the last execution result
1515 # Ensure it is removed from the last execution result
1516 if self.last_execution_result.result is obj:
1516 if self.last_execution_result.result is obj:
1517 self.last_execution_result = None
1517 self.last_execution_result = None
1518
1518
1519 # displayhook keeps extra references, but not in a dictionary
1519 # displayhook keeps extra references, but not in a dictionary
1520 for name in ('_', '__', '___'):
1520 for name in ('_', '__', '___'):
1521 if getattr(self.displayhook, name) is obj:
1521 if getattr(self.displayhook, name) is obj:
1522 setattr(self.displayhook, name, None)
1522 setattr(self.displayhook, name, None)
1523
1523
1524 def reset_selective(self, regex=None):
1524 def reset_selective(self, regex=None):
1525 """Clear selective variables from internal namespaces based on a
1525 """Clear selective variables from internal namespaces based on a
1526 specified regular expression.
1526 specified regular expression.
1527
1527
1528 Parameters
1528 Parameters
1529 ----------
1529 ----------
1530 regex : string or compiled pattern, optional
1530 regex : string or compiled pattern, optional
1531 A regular expression pattern that will be used in searching
1531 A regular expression pattern that will be used in searching
1532 variable names in the users namespaces.
1532 variable names in the users namespaces.
1533 """
1533 """
1534 if regex is not None:
1534 if regex is not None:
1535 try:
1535 try:
1536 m = re.compile(regex)
1536 m = re.compile(regex)
1537 except TypeError as e:
1537 except TypeError as e:
1538 raise TypeError('regex must be a string or compiled pattern') from e
1538 raise TypeError('regex must be a string or compiled pattern') from e
1539 # Search for keys in each namespace that match the given regex
1539 # Search for keys in each namespace that match the given regex
1540 # If a match is found, delete the key/value pair.
1540 # If a match is found, delete the key/value pair.
1541 for ns in self.all_ns_refs:
1541 for ns in self.all_ns_refs:
1542 for var in ns:
1542 for var in ns:
1543 if m.search(var):
1543 if m.search(var):
1544 del ns[var]
1544 del ns[var]
1545
1545
1546 def push(self, variables, interactive=True):
1546 def push(self, variables, interactive=True):
1547 """Inject a group of variables into the IPython user namespace.
1547 """Inject a group of variables into the IPython user namespace.
1548
1548
1549 Parameters
1549 Parameters
1550 ----------
1550 ----------
1551 variables : dict, str or list/tuple of str
1551 variables : dict, str or list/tuple of str
1552 The variables to inject into the user's namespace. If a dict, a
1552 The variables to inject into the user's namespace. If a dict, a
1553 simple update is done. If a str, the string is assumed to have
1553 simple update is done. If a str, the string is assumed to have
1554 variable names separated by spaces. A list/tuple of str can also
1554 variable names separated by spaces. A list/tuple of str can also
1555 be used to give the variable names. If just the variable names are
1555 be used to give the variable names. If just the variable names are
1556 give (list/tuple/str) then the variable values looked up in the
1556 give (list/tuple/str) then the variable values looked up in the
1557 callers frame.
1557 callers frame.
1558 interactive : bool
1558 interactive : bool
1559 If True (default), the variables will be listed with the ``who``
1559 If True (default), the variables will be listed with the ``who``
1560 magic.
1560 magic.
1561 """
1561 """
1562 vdict = None
1562 vdict = None
1563
1563
1564 # We need a dict of name/value pairs to do namespace updates.
1564 # We need a dict of name/value pairs to do namespace updates.
1565 if isinstance(variables, dict):
1565 if isinstance(variables, dict):
1566 vdict = variables
1566 vdict = variables
1567 elif isinstance(variables, (str, list, tuple)):
1567 elif isinstance(variables, (str, list, tuple)):
1568 if isinstance(variables, str):
1568 if isinstance(variables, str):
1569 vlist = variables.split()
1569 vlist = variables.split()
1570 else:
1570 else:
1571 vlist = variables
1571 vlist = variables
1572 vdict = {}
1572 vdict = {}
1573 cf = sys._getframe(1)
1573 cf = sys._getframe(1)
1574 for name in vlist:
1574 for name in vlist:
1575 try:
1575 try:
1576 vdict[name] = eval(name, cf.f_globals, cf.f_locals)
1576 vdict[name] = eval(name, cf.f_globals, cf.f_locals)
1577 except:
1577 except:
1578 print('Could not get variable %s from %s' %
1578 print('Could not get variable %s from %s' %
1579 (name,cf.f_code.co_name))
1579 (name,cf.f_code.co_name))
1580 else:
1580 else:
1581 raise ValueError('variables must be a dict/str/list/tuple')
1581 raise ValueError('variables must be a dict/str/list/tuple')
1582
1582
1583 # Propagate variables to user namespace
1583 # Propagate variables to user namespace
1584 self.user_ns.update(vdict)
1584 self.user_ns.update(vdict)
1585
1585
1586 # And configure interactive visibility
1586 # And configure interactive visibility
1587 user_ns_hidden = self.user_ns_hidden
1587 user_ns_hidden = self.user_ns_hidden
1588 if interactive:
1588 if interactive:
1589 for name in vdict:
1589 for name in vdict:
1590 user_ns_hidden.pop(name, None)
1590 user_ns_hidden.pop(name, None)
1591 else:
1591 else:
1592 user_ns_hidden.update(vdict)
1592 user_ns_hidden.update(vdict)
1593
1593
1594 def drop_by_id(self, variables):
1594 def drop_by_id(self, variables):
1595 """Remove a dict of variables from the user namespace, if they are the
1595 """Remove a dict of variables from the user namespace, if they are the
1596 same as the values in the dictionary.
1596 same as the values in the dictionary.
1597
1597
1598 This is intended for use by extensions: variables that they've added can
1598 This is intended for use by extensions: variables that they've added can
1599 be taken back out if they are unloaded, without removing any that the
1599 be taken back out if they are unloaded, without removing any that the
1600 user has overwritten.
1600 user has overwritten.
1601
1601
1602 Parameters
1602 Parameters
1603 ----------
1603 ----------
1604 variables : dict
1604 variables : dict
1605 A dictionary mapping object names (as strings) to the objects.
1605 A dictionary mapping object names (as strings) to the objects.
1606 """
1606 """
1607 for name, obj in variables.items():
1607 for name, obj in variables.items():
1608 if name in self.user_ns and self.user_ns[name] is obj:
1608 if name in self.user_ns and self.user_ns[name] is obj:
1609 del self.user_ns[name]
1609 del self.user_ns[name]
1610 self.user_ns_hidden.pop(name, None)
1610 self.user_ns_hidden.pop(name, None)
1611
1611
1612 #-------------------------------------------------------------------------
1612 #-------------------------------------------------------------------------
1613 # Things related to object introspection
1613 # Things related to object introspection
1614 #-------------------------------------------------------------------------
1614 #-------------------------------------------------------------------------
1615 @staticmethod
1615 @staticmethod
1616 def _find_parts(oname: str) -> Tuple[bool, ListType[str]]:
1616 def _find_parts(oname: str) -> Tuple[bool, ListType[str]]:
1617 """
1617 """
1618 Given an object name, return a list of parts of this object name.
1618 Given an object name, return a list of parts of this object name.
1619
1619
1620 Basically split on docs when using attribute access,
1620 Basically split on docs when using attribute access,
1621 and extract the value when using square bracket.
1621 and extract the value when using square bracket.
1622
1622
1623
1623
1624 For example foo.bar[3].baz[x] -> foo, bar, 3, baz, x
1624 For example foo.bar[3].baz[x] -> foo, bar, 3, baz, x
1625
1625
1626
1626
1627 Returns
1627 Returns
1628 -------
1628 -------
1629 parts_ok: bool
1629 parts_ok: bool
1630 wether we were properly able to parse parts.
1630 wether we were properly able to parse parts.
1631 parts: list of str
1631 parts: list of str
1632 extracted parts
1632 extracted parts
1633
1633
1634
1634
1635
1635
1636 """
1636 """
1637 raw_parts = oname.split(".")
1637 raw_parts = oname.split(".")
1638 parts = []
1638 parts = []
1639 parts_ok = True
1639 parts_ok = True
1640 for p in raw_parts:
1640 for p in raw_parts:
1641 if p.endswith("]"):
1641 if p.endswith("]"):
1642 var, *indices = p.split("[")
1642 var, *indices = p.split("[")
1643 if not var.isidentifier():
1643 if not var.isidentifier():
1644 parts_ok = False
1644 parts_ok = False
1645 break
1645 break
1646 parts.append(var)
1646 parts.append(var)
1647 for ind in indices:
1647 for ind in indices:
1648 if ind[-1] != "]" and not is_integer_string(ind[:-1]):
1648 if ind[-1] != "]" and not is_integer_string(ind[:-1]):
1649 parts_ok = False
1649 parts_ok = False
1650 break
1650 break
1651 parts.append(ind[:-1])
1651 parts.append(ind[:-1])
1652 continue
1652 continue
1653
1653
1654 if not p.isidentifier():
1654 if not p.isidentifier():
1655 parts_ok = False
1655 parts_ok = False
1656 parts.append(p)
1656 parts.append(p)
1657
1657
1658 return parts_ok, parts
1658 return parts_ok, parts
1659
1659
1660 def _ofind(
1660 def _ofind(
1661 self, oname: str, namespaces: Optional[Sequence[Tuple[str, AnyType]]] = None
1661 self, oname: str, namespaces: Optional[Sequence[Tuple[str, AnyType]]] = None
1662 ) -> OInfo:
1662 ) -> OInfo:
1663 """Find an object in the available namespaces.
1663 """Find an object in the available namespaces.
1664
1664
1665
1665
1666 Returns
1666 Returns
1667 -------
1667 -------
1668 OInfo with fields:
1668 OInfo with fields:
1669 - ismagic
1669 - ismagic
1670 - isalias
1670 - isalias
1671 - found
1671 - found
1672 - obj
1672 - obj
1673 - namespac
1673 - namespac
1674 - parent
1674 - parent
1675
1675
1676 Has special code to detect magic functions.
1676 Has special code to detect magic functions.
1677 """
1677 """
1678 oname = oname.strip()
1678 oname = oname.strip()
1679 parts_ok, parts = self._find_parts(oname)
1679 parts_ok, parts = self._find_parts(oname)
1680
1680
1681 if (
1681 if (
1682 not oname.startswith(ESC_MAGIC)
1682 not oname.startswith(ESC_MAGIC)
1683 and not oname.startswith(ESC_MAGIC2)
1683 and not oname.startswith(ESC_MAGIC2)
1684 and not parts_ok
1684 and not parts_ok
1685 ):
1685 ):
1686 return OInfo(
1686 return OInfo(
1687 ismagic=False,
1687 ismagic=False,
1688 isalias=False,
1688 isalias=False,
1689 found=False,
1689 found=False,
1690 obj=None,
1690 obj=None,
1691 namespace=None,
1691 namespace=None,
1692 parent=None,
1692 parent=None,
1693 )
1693 )
1694
1694
1695 if namespaces is None:
1695 if namespaces is None:
1696 # Namespaces to search in:
1696 # Namespaces to search in:
1697 # Put them in a list. The order is important so that we
1697 # Put them in a list. The order is important so that we
1698 # find things in the same order that Python finds them.
1698 # find things in the same order that Python finds them.
1699 namespaces = [ ('Interactive', self.user_ns),
1699 namespaces = [ ('Interactive', self.user_ns),
1700 ('Interactive (global)', self.user_global_ns),
1700 ('Interactive (global)', self.user_global_ns),
1701 ('Python builtin', builtin_mod.__dict__),
1701 ('Python builtin', builtin_mod.__dict__),
1702 ]
1702 ]
1703
1703
1704 ismagic = False
1704 ismagic = False
1705 isalias = False
1705 isalias = False
1706 found = False
1706 found = False
1707 ospace = None
1707 ospace = None
1708 parent = None
1708 parent = None
1709 obj = None
1709 obj = None
1710
1710
1711
1711
1712 # Look for the given name by splitting it in parts. If the head is
1712 # Look for the given name by splitting it in parts. If the head is
1713 # found, then we look for all the remaining parts as members, and only
1713 # found, then we look for all the remaining parts as members, and only
1714 # declare success if we can find them all.
1714 # declare success if we can find them all.
1715 oname_parts = parts
1715 oname_parts = parts
1716 oname_head, oname_rest = oname_parts[0],oname_parts[1:]
1716 oname_head, oname_rest = oname_parts[0],oname_parts[1:]
1717 for nsname,ns in namespaces:
1717 for nsname,ns in namespaces:
1718 try:
1718 try:
1719 obj = ns[oname_head]
1719 obj = ns[oname_head]
1720 except KeyError:
1720 except KeyError:
1721 continue
1721 continue
1722 else:
1722 else:
1723 for idx, part in enumerate(oname_rest):
1723 for idx, part in enumerate(oname_rest):
1724 try:
1724 try:
1725 parent = obj
1725 parent = obj
1726 # The last part is looked up in a special way to avoid
1726 # The last part is looked up in a special way to avoid
1727 # descriptor invocation as it may raise or have side
1727 # descriptor invocation as it may raise or have side
1728 # effects.
1728 # effects.
1729 if idx == len(oname_rest) - 1:
1729 if idx == len(oname_rest) - 1:
1730 obj = self._getattr_property(obj, part)
1730 obj = self._getattr_property(obj, part)
1731 else:
1731 else:
1732 if is_integer_string(part):
1732 if is_integer_string(part):
1733 obj = obj[int(part)]
1733 obj = obj[int(part)]
1734 else:
1734 else:
1735 obj = getattr(obj, part)
1735 obj = getattr(obj, part)
1736 except:
1736 except:
1737 # Blanket except b/c some badly implemented objects
1737 # Blanket except b/c some badly implemented objects
1738 # allow __getattr__ to raise exceptions other than
1738 # allow __getattr__ to raise exceptions other than
1739 # AttributeError, which then crashes IPython.
1739 # AttributeError, which then crashes IPython.
1740 break
1740 break
1741 else:
1741 else:
1742 # If we finish the for loop (no break), we got all members
1742 # If we finish the for loop (no break), we got all members
1743 found = True
1743 found = True
1744 ospace = nsname
1744 ospace = nsname
1745 break # namespace loop
1745 break # namespace loop
1746
1746
1747 # Try to see if it's magic
1747 # Try to see if it's magic
1748 if not found:
1748 if not found:
1749 obj = None
1749 obj = None
1750 if oname.startswith(ESC_MAGIC2):
1750 if oname.startswith(ESC_MAGIC2):
1751 oname = oname.lstrip(ESC_MAGIC2)
1751 oname = oname.lstrip(ESC_MAGIC2)
1752 obj = self.find_cell_magic(oname)
1752 obj = self.find_cell_magic(oname)
1753 elif oname.startswith(ESC_MAGIC):
1753 elif oname.startswith(ESC_MAGIC):
1754 oname = oname.lstrip(ESC_MAGIC)
1754 oname = oname.lstrip(ESC_MAGIC)
1755 obj = self.find_line_magic(oname)
1755 obj = self.find_line_magic(oname)
1756 else:
1756 else:
1757 # search without prefix, so run? will find %run?
1757 # search without prefix, so run? will find %run?
1758 obj = self.find_line_magic(oname)
1758 obj = self.find_line_magic(oname)
1759 if obj is None:
1759 if obj is None:
1760 obj = self.find_cell_magic(oname)
1760 obj = self.find_cell_magic(oname)
1761 if obj is not None:
1761 if obj is not None:
1762 found = True
1762 found = True
1763 ospace = 'IPython internal'
1763 ospace = 'IPython internal'
1764 ismagic = True
1764 ismagic = True
1765 isalias = isinstance(obj, Alias)
1765 isalias = isinstance(obj, Alias)
1766
1766
1767 # Last try: special-case some literals like '', [], {}, etc:
1767 # Last try: special-case some literals like '', [], {}, etc:
1768 if not found and oname_head in ["''",'""','[]','{}','()']:
1768 if not found and oname_head in ["''",'""','[]','{}','()']:
1769 obj = eval(oname_head)
1769 obj = eval(oname_head)
1770 found = True
1770 found = True
1771 ospace = 'Interactive'
1771 ospace = 'Interactive'
1772
1772
1773 return OInfo(
1773 return OInfo(
1774 obj=obj,
1774 obj=obj,
1775 found=found,
1775 found=found,
1776 parent=parent,
1776 parent=parent,
1777 ismagic=ismagic,
1777 ismagic=ismagic,
1778 isalias=isalias,
1778 isalias=isalias,
1779 namespace=ospace,
1779 namespace=ospace,
1780 )
1780 )
1781
1781
1782 @staticmethod
1782 @staticmethod
1783 def _getattr_property(obj, attrname):
1783 def _getattr_property(obj, attrname):
1784 """Property-aware getattr to use in object finding.
1784 """Property-aware getattr to use in object finding.
1785
1785
1786 If attrname represents a property, return it unevaluated (in case it has
1786 If attrname represents a property, return it unevaluated (in case it has
1787 side effects or raises an error.
1787 side effects or raises an error.
1788
1788
1789 """
1789 """
1790 if not isinstance(obj, type):
1790 if not isinstance(obj, type):
1791 try:
1791 try:
1792 # `getattr(type(obj), attrname)` is not guaranteed to return
1792 # `getattr(type(obj), attrname)` is not guaranteed to return
1793 # `obj`, but does so for property:
1793 # `obj`, but does so for property:
1794 #
1794 #
1795 # property.__get__(self, None, cls) -> self
1795 # property.__get__(self, None, cls) -> self
1796 #
1796 #
1797 # The universal alternative is to traverse the mro manually
1797 # The universal alternative is to traverse the mro manually
1798 # searching for attrname in class dicts.
1798 # searching for attrname in class dicts.
1799 if is_integer_string(attrname):
1799 if is_integer_string(attrname):
1800 return obj[int(attrname)]
1800 return obj[int(attrname)]
1801 else:
1801 else:
1802 attr = getattr(type(obj), attrname)
1802 attr = getattr(type(obj), attrname)
1803 except AttributeError:
1803 except AttributeError:
1804 pass
1804 pass
1805 else:
1805 else:
1806 # This relies on the fact that data descriptors (with both
1806 # This relies on the fact that data descriptors (with both
1807 # __get__ & __set__ magic methods) take precedence over
1807 # __get__ & __set__ magic methods) take precedence over
1808 # instance-level attributes:
1808 # instance-level attributes:
1809 #
1809 #
1810 # class A(object):
1810 # class A(object):
1811 # @property
1811 # @property
1812 # def foobar(self): return 123
1812 # def foobar(self): return 123
1813 # a = A()
1813 # a = A()
1814 # a.__dict__['foobar'] = 345
1814 # a.__dict__['foobar'] = 345
1815 # a.foobar # == 123
1815 # a.foobar # == 123
1816 #
1816 #
1817 # So, a property may be returned right away.
1817 # So, a property may be returned right away.
1818 if isinstance(attr, property):
1818 if isinstance(attr, property):
1819 return attr
1819 return attr
1820
1820
1821 # Nothing helped, fall back.
1821 # Nothing helped, fall back.
1822 return getattr(obj, attrname)
1822 return getattr(obj, attrname)
1823
1823
1824 def _object_find(self, oname, namespaces=None) -> OInfo:
1824 def _object_find(self, oname, namespaces=None) -> OInfo:
1825 """Find an object and return a struct with info about it."""
1825 """Find an object and return a struct with info about it."""
1826 return self._ofind(oname, namespaces)
1826 return self._ofind(oname, namespaces)
1827
1827
1828 def _inspect(self, meth, oname: str, namespaces=None, **kw):
1828 def _inspect(self, meth, oname: str, namespaces=None, **kw):
1829 """Generic interface to the inspector system.
1829 """Generic interface to the inspector system.
1830
1830
1831 This function is meant to be called by pdef, pdoc & friends.
1831 This function is meant to be called by pdef, pdoc & friends.
1832 """
1832 """
1833 info: OInfo = self._object_find(oname, namespaces)
1833 info: OInfo = self._object_find(oname, namespaces)
1834 if self.sphinxify_docstring:
1834 if self.sphinxify_docstring:
1835 if sphinxify is None:
1835 if sphinxify is None:
1836 raise ImportError("Module ``docrepr`` required but missing")
1836 raise ImportError("Module ``docrepr`` required but missing")
1837 docformat = sphinxify(self.object_inspect(oname))
1837 docformat = sphinxify(self.object_inspect(oname))
1838 else:
1838 else:
1839 docformat = None
1839 docformat = None
1840 if info.found or hasattr(info.parent, oinspect.HOOK_NAME):
1840 if info.found or hasattr(info.parent, oinspect.HOOK_NAME):
1841 pmethod = getattr(self.inspector, meth)
1841 pmethod = getattr(self.inspector, meth)
1842 # TODO: only apply format_screen to the plain/text repr of the mime
1842 # TODO: only apply format_screen to the plain/text repr of the mime
1843 # bundle.
1843 # bundle.
1844 formatter = format_screen if info.ismagic else docformat
1844 formatter = format_screen if info.ismagic else docformat
1845 if meth == 'pdoc':
1845 if meth == 'pdoc':
1846 pmethod(info.obj, oname, formatter)
1846 pmethod(info.obj, oname, formatter)
1847 elif meth == 'pinfo':
1847 elif meth == 'pinfo':
1848 pmethod(
1848 pmethod(
1849 info.obj,
1849 info.obj,
1850 oname,
1850 oname,
1851 formatter,
1851 formatter,
1852 info,
1852 info,
1853 enable_html_pager=self.enable_html_pager,
1853 enable_html_pager=self.enable_html_pager,
1854 **kw,
1854 **kw,
1855 )
1855 )
1856 else:
1856 else:
1857 pmethod(info.obj, oname)
1857 pmethod(info.obj, oname)
1858 else:
1858 else:
1859 print('Object `%s` not found.' % oname)
1859 print('Object `%s` not found.' % oname)
1860 return 'not found' # so callers can take other action
1860 return 'not found' # so callers can take other action
1861
1861
1862 def object_inspect(self, oname, detail_level=0):
1862 def object_inspect(self, oname, detail_level=0):
1863 """Get object info about oname"""
1863 """Get object info about oname"""
1864 with self.builtin_trap:
1864 with self.builtin_trap:
1865 info = self._object_find(oname)
1865 info = self._object_find(oname)
1866 if info.found:
1866 if info.found:
1867 return self.inspector.info(info.obj, oname, info=info,
1867 return self.inspector.info(info.obj, oname, info=info,
1868 detail_level=detail_level
1868 detail_level=detail_level
1869 )
1869 )
1870 else:
1870 else:
1871 return oinspect.object_info(name=oname, found=False)
1871 return oinspect.object_info(name=oname, found=False)
1872
1872
1873 def object_inspect_text(self, oname, detail_level=0):
1873 def object_inspect_text(self, oname, detail_level=0):
1874 """Get object info as formatted text"""
1874 """Get object info as formatted text"""
1875 return self.object_inspect_mime(oname, detail_level)['text/plain']
1875 return self.object_inspect_mime(oname, detail_level)['text/plain']
1876
1876
1877 def object_inspect_mime(self, oname, detail_level=0, omit_sections=()):
1877 def object_inspect_mime(self, oname, detail_level=0, omit_sections=()):
1878 """Get object info as a mimebundle of formatted representations.
1878 """Get object info as a mimebundle of formatted representations.
1879
1879
1880 A mimebundle is a dictionary, keyed by mime-type.
1880 A mimebundle is a dictionary, keyed by mime-type.
1881 It must always have the key `'text/plain'`.
1881 It must always have the key `'text/plain'`.
1882 """
1882 """
1883 with self.builtin_trap:
1883 with self.builtin_trap:
1884 info = self._object_find(oname)
1884 info = self._object_find(oname)
1885 if info.found:
1885 if info.found:
1886 docformat = (
1886 docformat = (
1887 sphinxify(self.object_inspect(oname))
1887 sphinxify(self.object_inspect(oname))
1888 if self.sphinxify_docstring
1888 if self.sphinxify_docstring
1889 else None
1889 else None
1890 )
1890 )
1891 return self.inspector._get_info(
1891 return self.inspector._get_info(
1892 info.obj,
1892 info.obj,
1893 oname,
1893 oname,
1894 info=info,
1894 info=info,
1895 detail_level=detail_level,
1895 detail_level=detail_level,
1896 formatter=docformat,
1896 formatter=docformat,
1897 omit_sections=omit_sections,
1897 omit_sections=omit_sections,
1898 )
1898 )
1899 else:
1899 else:
1900 raise KeyError(oname)
1900 raise KeyError(oname)
1901
1901
1902 #-------------------------------------------------------------------------
1902 #-------------------------------------------------------------------------
1903 # Things related to history management
1903 # Things related to history management
1904 #-------------------------------------------------------------------------
1904 #-------------------------------------------------------------------------
1905
1905
1906 def init_history(self):
1906 def init_history(self):
1907 """Sets up the command history, and starts regular autosaves."""
1907 """Sets up the command history, and starts regular autosaves."""
1908 self.history_manager = HistoryManager(shell=self, parent=self)
1908 self.history_manager = HistoryManager(shell=self, parent=self)
1909 self.configurables.append(self.history_manager)
1909 self.configurables.append(self.history_manager)
1910
1910
1911 #-------------------------------------------------------------------------
1911 #-------------------------------------------------------------------------
1912 # Things related to exception handling and tracebacks (not debugging)
1912 # Things related to exception handling and tracebacks (not debugging)
1913 #-------------------------------------------------------------------------
1913 #-------------------------------------------------------------------------
1914
1914
1915 debugger_cls = InterruptiblePdb
1915 debugger_cls = InterruptiblePdb
1916
1916
1917 def init_traceback_handlers(self, custom_exceptions):
1917 def init_traceback_handlers(self, custom_exceptions):
1918 # Syntax error handler.
1918 # Syntax error handler.
1919 self.SyntaxTB = ultratb.SyntaxTB(color_scheme='NoColor', parent=self)
1919 self.SyntaxTB = ultratb.SyntaxTB(color_scheme='NoColor', parent=self)
1920
1920
1921 # The interactive one is initialized with an offset, meaning we always
1921 # The interactive one is initialized with an offset, meaning we always
1922 # want to remove the topmost item in the traceback, which is our own
1922 # want to remove the topmost item in the traceback, which is our own
1923 # internal code. Valid modes: ['Plain','Context','Verbose','Minimal']
1923 # internal code. Valid modes: ['Plain','Context','Verbose','Minimal']
1924 self.InteractiveTB = ultratb.AutoFormattedTB(mode = 'Plain',
1924 self.InteractiveTB = ultratb.AutoFormattedTB(mode = 'Plain',
1925 color_scheme='NoColor',
1925 color_scheme='NoColor',
1926 tb_offset = 1,
1926 tb_offset = 1,
1927 debugger_cls=self.debugger_cls, parent=self)
1927 debugger_cls=self.debugger_cls, parent=self)
1928
1928
1929 # The instance will store a pointer to the system-wide exception hook,
1929 # The instance will store a pointer to the system-wide exception hook,
1930 # so that runtime code (such as magics) can access it. This is because
1930 # so that runtime code (such as magics) can access it. This is because
1931 # during the read-eval loop, it may get temporarily overwritten.
1931 # during the read-eval loop, it may get temporarily overwritten.
1932 self.sys_excepthook = sys.excepthook
1932 self.sys_excepthook = sys.excepthook
1933
1933
1934 # and add any custom exception handlers the user may have specified
1934 # and add any custom exception handlers the user may have specified
1935 self.set_custom_exc(*custom_exceptions)
1935 self.set_custom_exc(*custom_exceptions)
1936
1936
1937 # Set the exception mode
1937 # Set the exception mode
1938 self.InteractiveTB.set_mode(mode=self.xmode)
1938 self.InteractiveTB.set_mode(mode=self.xmode)
1939
1939
1940 def set_custom_exc(self, exc_tuple, handler):
1940 def set_custom_exc(self, exc_tuple, handler):
1941 """set_custom_exc(exc_tuple, handler)
1941 """set_custom_exc(exc_tuple, handler)
1942
1942
1943 Set a custom exception handler, which will be called if any of the
1943 Set a custom exception handler, which will be called if any of the
1944 exceptions in exc_tuple occur in the mainloop (specifically, in the
1944 exceptions in exc_tuple occur in the mainloop (specifically, in the
1945 run_code() method).
1945 run_code() method).
1946
1946
1947 Parameters
1947 Parameters
1948 ----------
1948 ----------
1949 exc_tuple : tuple of exception classes
1949 exc_tuple : tuple of exception classes
1950 A *tuple* of exception classes, for which to call the defined
1950 A *tuple* of exception classes, for which to call the defined
1951 handler. It is very important that you use a tuple, and NOT A
1951 handler. It is very important that you use a tuple, and NOT A
1952 LIST here, because of the way Python's except statement works. If
1952 LIST here, because of the way Python's except statement works. If
1953 you only want to trap a single exception, use a singleton tuple::
1953 you only want to trap a single exception, use a singleton tuple::
1954
1954
1955 exc_tuple == (MyCustomException,)
1955 exc_tuple == (MyCustomException,)
1956
1956
1957 handler : callable
1957 handler : callable
1958 handler must have the following signature::
1958 handler must have the following signature::
1959
1959
1960 def my_handler(self, etype, value, tb, tb_offset=None):
1960 def my_handler(self, etype, value, tb, tb_offset=None):
1961 ...
1961 ...
1962 return structured_traceback
1962 return structured_traceback
1963
1963
1964 Your handler must return a structured traceback (a list of strings),
1964 Your handler must return a structured traceback (a list of strings),
1965 or None.
1965 or None.
1966
1966
1967 This will be made into an instance method (via types.MethodType)
1967 This will be made into an instance method (via types.MethodType)
1968 of IPython itself, and it will be called if any of the exceptions
1968 of IPython itself, and it will be called if any of the exceptions
1969 listed in the exc_tuple are caught. If the handler is None, an
1969 listed in the exc_tuple are caught. If the handler is None, an
1970 internal basic one is used, which just prints basic info.
1970 internal basic one is used, which just prints basic info.
1971
1971
1972 To protect IPython from crashes, if your handler ever raises an
1972 To protect IPython from crashes, if your handler ever raises an
1973 exception or returns an invalid result, it will be immediately
1973 exception or returns an invalid result, it will be immediately
1974 disabled.
1974 disabled.
1975
1975
1976 Notes
1976 Notes
1977 -----
1977 -----
1978 WARNING: by putting in your own exception handler into IPython's main
1978 WARNING: by putting in your own exception handler into IPython's main
1979 execution loop, you run a very good chance of nasty crashes. This
1979 execution loop, you run a very good chance of nasty crashes. This
1980 facility should only be used if you really know what you are doing.
1980 facility should only be used if you really know what you are doing.
1981 """
1981 """
1982
1982
1983 if not isinstance(exc_tuple, tuple):
1983 if not isinstance(exc_tuple, tuple):
1984 raise TypeError("The custom exceptions must be given as a tuple.")
1984 raise TypeError("The custom exceptions must be given as a tuple.")
1985
1985
1986 def dummy_handler(self, etype, value, tb, tb_offset=None):
1986 def dummy_handler(self, etype, value, tb, tb_offset=None):
1987 print('*** Simple custom exception handler ***')
1987 print('*** Simple custom exception handler ***')
1988 print('Exception type :', etype)
1988 print('Exception type :', etype)
1989 print('Exception value:', value)
1989 print('Exception value:', value)
1990 print('Traceback :', tb)
1990 print('Traceback :', tb)
1991
1991
1992 def validate_stb(stb):
1992 def validate_stb(stb):
1993 """validate structured traceback return type
1993 """validate structured traceback return type
1994
1994
1995 return type of CustomTB *should* be a list of strings, but allow
1995 return type of CustomTB *should* be a list of strings, but allow
1996 single strings or None, which are harmless.
1996 single strings or None, which are harmless.
1997
1997
1998 This function will *always* return a list of strings,
1998 This function will *always* return a list of strings,
1999 and will raise a TypeError if stb is inappropriate.
1999 and will raise a TypeError if stb is inappropriate.
2000 """
2000 """
2001 msg = "CustomTB must return list of strings, not %r" % stb
2001 msg = "CustomTB must return list of strings, not %r" % stb
2002 if stb is None:
2002 if stb is None:
2003 return []
2003 return []
2004 elif isinstance(stb, str):
2004 elif isinstance(stb, str):
2005 return [stb]
2005 return [stb]
2006 elif not isinstance(stb, list):
2006 elif not isinstance(stb, list):
2007 raise TypeError(msg)
2007 raise TypeError(msg)
2008 # it's a list
2008 # it's a list
2009 for line in stb:
2009 for line in stb:
2010 # check every element
2010 # check every element
2011 if not isinstance(line, str):
2011 if not isinstance(line, str):
2012 raise TypeError(msg)
2012 raise TypeError(msg)
2013 return stb
2013 return stb
2014
2014
2015 if handler is None:
2015 if handler is None:
2016 wrapped = dummy_handler
2016 wrapped = dummy_handler
2017 else:
2017 else:
2018 def wrapped(self,etype,value,tb,tb_offset=None):
2018 def wrapped(self,etype,value,tb,tb_offset=None):
2019 """wrap CustomTB handler, to protect IPython from user code
2019 """wrap CustomTB handler, to protect IPython from user code
2020
2020
2021 This makes it harder (but not impossible) for custom exception
2021 This makes it harder (but not impossible) for custom exception
2022 handlers to crash IPython.
2022 handlers to crash IPython.
2023 """
2023 """
2024 try:
2024 try:
2025 stb = handler(self,etype,value,tb,tb_offset=tb_offset)
2025 stb = handler(self,etype,value,tb,tb_offset=tb_offset)
2026 return validate_stb(stb)
2026 return validate_stb(stb)
2027 except:
2027 except:
2028 # clear custom handler immediately
2028 # clear custom handler immediately
2029 self.set_custom_exc((), None)
2029 self.set_custom_exc((), None)
2030 print("Custom TB Handler failed, unregistering", file=sys.stderr)
2030 print("Custom TB Handler failed, unregistering", file=sys.stderr)
2031 # show the exception in handler first
2031 # show the exception in handler first
2032 stb = self.InteractiveTB.structured_traceback(*sys.exc_info())
2032 stb = self.InteractiveTB.structured_traceback(*sys.exc_info())
2033 print(self.InteractiveTB.stb2text(stb))
2033 print(self.InteractiveTB.stb2text(stb))
2034 print("The original exception:")
2034 print("The original exception:")
2035 stb = self.InteractiveTB.structured_traceback(
2035 stb = self.InteractiveTB.structured_traceback(
2036 (etype,value,tb), tb_offset=tb_offset
2036 (etype,value,tb), tb_offset=tb_offset
2037 )
2037 )
2038 return stb
2038 return stb
2039
2039
2040 self.CustomTB = types.MethodType(wrapped,self)
2040 self.CustomTB = types.MethodType(wrapped,self)
2041 self.custom_exceptions = exc_tuple
2041 self.custom_exceptions = exc_tuple
2042
2042
2043 def excepthook(self, etype, value, tb):
2043 def excepthook(self, etype, value, tb):
2044 """One more defense for GUI apps that call sys.excepthook.
2044 """One more defense for GUI apps that call sys.excepthook.
2045
2045
2046 GUI frameworks like wxPython trap exceptions and call
2046 GUI frameworks like wxPython trap exceptions and call
2047 sys.excepthook themselves. I guess this is a feature that
2047 sys.excepthook themselves. I guess this is a feature that
2048 enables them to keep running after exceptions that would
2048 enables them to keep running after exceptions that would
2049 otherwise kill their mainloop. This is a bother for IPython
2049 otherwise kill their mainloop. This is a bother for IPython
2050 which expects to catch all of the program exceptions with a try:
2050 which expects to catch all of the program exceptions with a try:
2051 except: statement.
2051 except: statement.
2052
2052
2053 Normally, IPython sets sys.excepthook to a CrashHandler instance, so if
2053 Normally, IPython sets sys.excepthook to a CrashHandler instance, so if
2054 any app directly invokes sys.excepthook, it will look to the user like
2054 any app directly invokes sys.excepthook, it will look to the user like
2055 IPython crashed. In order to work around this, we can disable the
2055 IPython crashed. In order to work around this, we can disable the
2056 CrashHandler and replace it with this excepthook instead, which prints a
2056 CrashHandler and replace it with this excepthook instead, which prints a
2057 regular traceback using our InteractiveTB. In this fashion, apps which
2057 regular traceback using our InteractiveTB. In this fashion, apps which
2058 call sys.excepthook will generate a regular-looking exception from
2058 call sys.excepthook will generate a regular-looking exception from
2059 IPython, and the CrashHandler will only be triggered by real IPython
2059 IPython, and the CrashHandler will only be triggered by real IPython
2060 crashes.
2060 crashes.
2061
2061
2062 This hook should be used sparingly, only in places which are not likely
2062 This hook should be used sparingly, only in places which are not likely
2063 to be true IPython errors.
2063 to be true IPython errors.
2064 """
2064 """
2065 self.showtraceback((etype, value, tb), tb_offset=0)
2065 self.showtraceback((etype, value, tb), tb_offset=0)
2066
2066
2067 def _get_exc_info(self, exc_tuple=None):
2067 def _get_exc_info(self, exc_tuple=None):
2068 """get exc_info from a given tuple, sys.exc_info() or sys.last_type etc.
2068 """get exc_info from a given tuple, sys.exc_info() or sys.last_type etc.
2069
2069
2070 Ensures sys.last_type,value,traceback hold the exc_info we found,
2070 Ensures sys.last_type,value,traceback hold the exc_info we found,
2071 from whichever source.
2071 from whichever source.
2072
2072
2073 raises ValueError if none of these contain any information
2073 raises ValueError if none of these contain any information
2074 """
2074 """
2075 if exc_tuple is None:
2075 if exc_tuple is None:
2076 etype, value, tb = sys.exc_info()
2076 etype, value, tb = sys.exc_info()
2077 else:
2077 else:
2078 etype, value, tb = exc_tuple
2078 etype, value, tb = exc_tuple
2079
2079
2080 if etype is None:
2080 if etype is None:
2081 if hasattr(sys, 'last_type'):
2081 if hasattr(sys, 'last_type'):
2082 etype, value, tb = sys.last_type, sys.last_value, \
2082 etype, value, tb = sys.last_type, sys.last_value, \
2083 sys.last_traceback
2083 sys.last_traceback
2084
2084
2085 if etype is None:
2085 if etype is None:
2086 raise ValueError("No exception to find")
2086 raise ValueError("No exception to find")
2087
2087
2088 # Now store the exception info in sys.last_type etc.
2088 # Now store the exception info in sys.last_type etc.
2089 # WARNING: these variables are somewhat deprecated and not
2089 # WARNING: these variables are somewhat deprecated and not
2090 # necessarily safe to use in a threaded environment, but tools
2090 # necessarily safe to use in a threaded environment, but tools
2091 # like pdb depend on their existence, so let's set them. If we
2091 # like pdb depend on their existence, so let's set them. If we
2092 # find problems in the field, we'll need to revisit their use.
2092 # find problems in the field, we'll need to revisit their use.
2093 sys.last_type = etype
2093 sys.last_type = etype
2094 sys.last_value = value
2094 sys.last_value = value
2095 sys.last_traceback = tb
2095 sys.last_traceback = tb
2096
2096
2097 return etype, value, tb
2097 return etype, value, tb
2098
2098
2099 def show_usage_error(self, exc):
2099 def show_usage_error(self, exc):
2100 """Show a short message for UsageErrors
2100 """Show a short message for UsageErrors
2101
2101
2102 These are special exceptions that shouldn't show a traceback.
2102 These are special exceptions that shouldn't show a traceback.
2103 """
2103 """
2104 print("UsageError: %s" % exc, file=sys.stderr)
2104 print("UsageError: %s" % exc, file=sys.stderr)
2105
2105
2106 def get_exception_only(self, exc_tuple=None):
2106 def get_exception_only(self, exc_tuple=None):
2107 """
2107 """
2108 Return as a string (ending with a newline) the exception that
2108 Return as a string (ending with a newline) the exception that
2109 just occurred, without any traceback.
2109 just occurred, without any traceback.
2110 """
2110 """
2111 etype, value, tb = self._get_exc_info(exc_tuple)
2111 etype, value, tb = self._get_exc_info(exc_tuple)
2112 msg = traceback.format_exception_only(etype, value)
2112 msg = traceback.format_exception_only(etype, value)
2113 return ''.join(msg)
2113 return ''.join(msg)
2114
2114
2115 def showtraceback(self, exc_tuple=None, filename=None, tb_offset=None,
2115 def showtraceback(self, exc_tuple=None, filename=None, tb_offset=None,
2116 exception_only=False, running_compiled_code=False):
2116 exception_only=False, running_compiled_code=False):
2117 """Display the exception that just occurred.
2117 """Display the exception that just occurred.
2118
2118
2119 If nothing is known about the exception, this is the method which
2119 If nothing is known about the exception, this is the method which
2120 should be used throughout the code for presenting user tracebacks,
2120 should be used throughout the code for presenting user tracebacks,
2121 rather than directly invoking the InteractiveTB object.
2121 rather than directly invoking the InteractiveTB object.
2122
2122
2123 A specific showsyntaxerror() also exists, but this method can take
2123 A specific showsyntaxerror() also exists, but this method can take
2124 care of calling it if needed, so unless you are explicitly catching a
2124 care of calling it if needed, so unless you are explicitly catching a
2125 SyntaxError exception, don't try to analyze the stack manually and
2125 SyntaxError exception, don't try to analyze the stack manually and
2126 simply call this method."""
2126 simply call this method."""
2127
2127
2128 try:
2128 try:
2129 try:
2129 try:
2130 etype, value, tb = self._get_exc_info(exc_tuple)
2130 etype, value, tb = self._get_exc_info(exc_tuple)
2131 except ValueError:
2131 except ValueError:
2132 print('No traceback available to show.', file=sys.stderr)
2132 print('No traceback available to show.', file=sys.stderr)
2133 return
2133 return
2134
2134
2135 if issubclass(etype, SyntaxError):
2135 if issubclass(etype, SyntaxError):
2136 # Though this won't be called by syntax errors in the input
2136 # Though this won't be called by syntax errors in the input
2137 # line, there may be SyntaxError cases with imported code.
2137 # line, there may be SyntaxError cases with imported code.
2138 self.showsyntaxerror(filename, running_compiled_code)
2138 self.showsyntaxerror(filename, running_compiled_code)
2139 elif etype is UsageError:
2139 elif etype is UsageError:
2140 self.show_usage_error(value)
2140 self.show_usage_error(value)
2141 else:
2141 else:
2142 if exception_only:
2142 if exception_only:
2143 stb = ['An exception has occurred, use %tb to see '
2143 stb = ['An exception has occurred, use %tb to see '
2144 'the full traceback.\n']
2144 'the full traceback.\n']
2145 stb.extend(self.InteractiveTB.get_exception_only(etype,
2145 stb.extend(self.InteractiveTB.get_exception_only(etype,
2146 value))
2146 value))
2147 else:
2147 else:
2148
2148
2149 def contains_exceptiongroup(val):
2149 def contains_exceptiongroup(val):
2150 if val is None:
2150 if val is None:
2151 return False
2151 return False
2152 return isinstance(
2152 return isinstance(
2153 val, BaseExceptionGroup
2153 val, BaseExceptionGroup
2154 ) or contains_exceptiongroup(val.__context__)
2154 ) or contains_exceptiongroup(val.__context__)
2155
2155
2156 if contains_exceptiongroup(value):
2156 if contains_exceptiongroup(value):
2157 # fall back to native exception formatting until ultratb
2157 # fall back to native exception formatting until ultratb
2158 # supports exception groups
2158 # supports exception groups
2159 traceback.print_exc()
2159 traceback.print_exc()
2160 else:
2160 else:
2161 try:
2161 try:
2162 # Exception classes can customise their traceback - we
2162 # Exception classes can customise their traceback - we
2163 # use this in IPython.parallel for exceptions occurring
2163 # use this in IPython.parallel for exceptions occurring
2164 # in the engines. This should return a list of strings.
2164 # in the engines. This should return a list of strings.
2165 if hasattr(value, "_render_traceback_"):
2165 if hasattr(value, "_render_traceback_"):
2166 stb = value._render_traceback_()
2166 stb = value._render_traceback_()
2167 else:
2167 else:
2168 stb = self.InteractiveTB.structured_traceback(
2168 stb = self.InteractiveTB.structured_traceback(
2169 etype, value, tb, tb_offset=tb_offset
2169 etype, value, tb, tb_offset=tb_offset
2170 )
2170 )
2171
2171
2172 except Exception:
2172 except Exception:
2173 print(
2173 print(
2174 "Unexpected exception formatting exception. Falling back to standard exception"
2174 "Unexpected exception formatting exception. Falling back to standard exception"
2175 )
2175 )
2176 traceback.print_exc()
2176 traceback.print_exc()
2177 return None
2177 return None
2178
2178
2179 self._showtraceback(etype, value, stb)
2179 self._showtraceback(etype, value, stb)
2180 if self.call_pdb:
2180 if self.call_pdb:
2181 # drop into debugger
2181 # drop into debugger
2182 self.debugger(force=True)
2182 self.debugger(force=True)
2183 return
2183 return
2184
2184
2185 # Actually show the traceback
2185 # Actually show the traceback
2186 self._showtraceback(etype, value, stb)
2186 self._showtraceback(etype, value, stb)
2187
2187
2188 except KeyboardInterrupt:
2188 except KeyboardInterrupt:
2189 print('\n' + self.get_exception_only(), file=sys.stderr)
2189 print('\n' + self.get_exception_only(), file=sys.stderr)
2190
2190
2191 def _showtraceback(self, etype, evalue, stb: str):
2191 def _showtraceback(self, etype, evalue, stb: str):
2192 """Actually show a traceback.
2192 """Actually show a traceback.
2193
2193
2194 Subclasses may override this method to put the traceback on a different
2194 Subclasses may override this method to put the traceback on a different
2195 place, like a side channel.
2195 place, like a side channel.
2196 """
2196 """
2197 val = self.InteractiveTB.stb2text(stb)
2197 val = self.InteractiveTB.stb2text(stb)
2198 try:
2198 try:
2199 print(val)
2199 print(val)
2200 except UnicodeEncodeError:
2200 except UnicodeEncodeError:
2201 print(val.encode("utf-8", "backslashreplace").decode())
2201 print(val.encode("utf-8", "backslashreplace").decode())
2202
2202
2203 def showsyntaxerror(self, filename=None, running_compiled_code=False):
2203 def showsyntaxerror(self, filename=None, running_compiled_code=False):
2204 """Display the syntax error that just occurred.
2204 """Display the syntax error that just occurred.
2205
2205
2206 This doesn't display a stack trace because there isn't one.
2206 This doesn't display a stack trace because there isn't one.
2207
2207
2208 If a filename is given, it is stuffed in the exception instead
2208 If a filename is given, it is stuffed in the exception instead
2209 of what was there before (because Python's parser always uses
2209 of what was there before (because Python's parser always uses
2210 "<string>" when reading from a string).
2210 "<string>" when reading from a string).
2211
2211
2212 If the syntax error occurred when running a compiled code (i.e. running_compile_code=True),
2212 If the syntax error occurred when running a compiled code (i.e. running_compile_code=True),
2213 longer stack trace will be displayed.
2213 longer stack trace will be displayed.
2214 """
2214 """
2215 etype, value, last_traceback = self._get_exc_info()
2215 etype, value, last_traceback = self._get_exc_info()
2216
2216
2217 if filename and issubclass(etype, SyntaxError):
2217 if filename and issubclass(etype, SyntaxError):
2218 try:
2218 try:
2219 value.filename = filename
2219 value.filename = filename
2220 except:
2220 except:
2221 # Not the format we expect; leave it alone
2221 # Not the format we expect; leave it alone
2222 pass
2222 pass
2223
2223
2224 # If the error occurred when executing compiled code, we should provide full stacktrace.
2224 # If the error occurred when executing compiled code, we should provide full stacktrace.
2225 elist = traceback.extract_tb(last_traceback) if running_compiled_code else []
2225 elist = traceback.extract_tb(last_traceback) if running_compiled_code else []
2226 stb = self.SyntaxTB.structured_traceback(etype, value, elist)
2226 stb = self.SyntaxTB.structured_traceback(etype, value, elist)
2227 self._showtraceback(etype, value, stb)
2227 self._showtraceback(etype, value, stb)
2228
2228
2229 # This is overridden in TerminalInteractiveShell to show a message about
2229 # This is overridden in TerminalInteractiveShell to show a message about
2230 # the %paste magic.
2230 # the %paste magic.
2231 def showindentationerror(self):
2231 def showindentationerror(self):
2232 """Called by _run_cell when there's an IndentationError in code entered
2232 """Called by _run_cell when there's an IndentationError in code entered
2233 at the prompt.
2233 at the prompt.
2234
2234
2235 This is overridden in TerminalInteractiveShell to show a message about
2235 This is overridden in TerminalInteractiveShell to show a message about
2236 the %paste magic."""
2236 the %paste magic."""
2237 self.showsyntaxerror()
2237 self.showsyntaxerror()
2238
2238
2239 @skip_doctest
2239 @skip_doctest
2240 def set_next_input(self, s, replace=False):
2240 def set_next_input(self, s, replace=False):
2241 """ Sets the 'default' input string for the next command line.
2241 """ Sets the 'default' input string for the next command line.
2242
2242
2243 Example::
2243 Example::
2244
2244
2245 In [1]: _ip.set_next_input("Hello Word")
2245 In [1]: _ip.set_next_input("Hello Word")
2246 In [2]: Hello Word_ # cursor is here
2246 In [2]: Hello Word_ # cursor is here
2247 """
2247 """
2248 self.rl_next_input = s
2248 self.rl_next_input = s
2249
2249
2250 def _indent_current_str(self):
2250 def _indent_current_str(self):
2251 """return the current level of indentation as a string"""
2251 """return the current level of indentation as a string"""
2252 return self.input_splitter.get_indent_spaces() * ' '
2252 return self.input_splitter.get_indent_spaces() * ' '
2253
2253
2254 #-------------------------------------------------------------------------
2254 #-------------------------------------------------------------------------
2255 # Things related to text completion
2255 # Things related to text completion
2256 #-------------------------------------------------------------------------
2256 #-------------------------------------------------------------------------
2257
2257
2258 def init_completer(self):
2258 def init_completer(self):
2259 """Initialize the completion machinery.
2259 """Initialize the completion machinery.
2260
2260
2261 This creates completion machinery that can be used by client code,
2261 This creates completion machinery that can be used by client code,
2262 either interactively in-process (typically triggered by the readline
2262 either interactively in-process (typically triggered by the readline
2263 library), programmatically (such as in test suites) or out-of-process
2263 library), programmatically (such as in test suites) or out-of-process
2264 (typically over the network by remote frontends).
2264 (typically over the network by remote frontends).
2265 """
2265 """
2266 from IPython.core.completer import IPCompleter
2266 from IPython.core.completer import IPCompleter
2267 from IPython.core.completerlib import (
2267 from IPython.core.completerlib import (
2268 cd_completer,
2268 cd_completer,
2269 magic_run_completer,
2269 magic_run_completer,
2270 module_completer,
2270 module_completer,
2271 reset_completer,
2271 reset_completer,
2272 )
2272 )
2273
2273
2274 self.Completer = IPCompleter(shell=self,
2274 self.Completer = IPCompleter(shell=self,
2275 namespace=self.user_ns,
2275 namespace=self.user_ns,
2276 global_namespace=self.user_global_ns,
2276 global_namespace=self.user_global_ns,
2277 parent=self,
2277 parent=self,
2278 )
2278 )
2279 self.configurables.append(self.Completer)
2279 self.configurables.append(self.Completer)
2280
2280
2281 # Add custom completers to the basic ones built into IPCompleter
2281 # Add custom completers to the basic ones built into IPCompleter
2282 sdisp = self.strdispatchers.get('complete_command', StrDispatch())
2282 sdisp = self.strdispatchers.get('complete_command', StrDispatch())
2283 self.strdispatchers['complete_command'] = sdisp
2283 self.strdispatchers['complete_command'] = sdisp
2284 self.Completer.custom_completers = sdisp
2284 self.Completer.custom_completers = sdisp
2285
2285
2286 self.set_hook('complete_command', module_completer, str_key = 'import')
2286 self.set_hook('complete_command', module_completer, str_key = 'import')
2287 self.set_hook('complete_command', module_completer, str_key = 'from')
2287 self.set_hook('complete_command', module_completer, str_key = 'from')
2288 self.set_hook('complete_command', module_completer, str_key = '%aimport')
2288 self.set_hook('complete_command', module_completer, str_key = '%aimport')
2289 self.set_hook('complete_command', magic_run_completer, str_key = '%run')
2289 self.set_hook('complete_command', magic_run_completer, str_key = '%run')
2290 self.set_hook('complete_command', cd_completer, str_key = '%cd')
2290 self.set_hook('complete_command', cd_completer, str_key = '%cd')
2291 self.set_hook('complete_command', reset_completer, str_key = '%reset')
2291 self.set_hook('complete_command', reset_completer, str_key = '%reset')
2292
2292
2293 @skip_doctest
2293 @skip_doctest
2294 def complete(self, text, line=None, cursor_pos=None):
2294 def complete(self, text, line=None, cursor_pos=None):
2295 """Return the completed text and a list of completions.
2295 """Return the completed text and a list of completions.
2296
2296
2297 Parameters
2297 Parameters
2298 ----------
2298 ----------
2299 text : string
2299 text : string
2300 A string of text to be completed on. It can be given as empty and
2300 A string of text to be completed on. It can be given as empty and
2301 instead a line/position pair are given. In this case, the
2301 instead a line/position pair are given. In this case, the
2302 completer itself will split the line like readline does.
2302 completer itself will split the line like readline does.
2303 line : string, optional
2303 line : string, optional
2304 The complete line that text is part of.
2304 The complete line that text is part of.
2305 cursor_pos : int, optional
2305 cursor_pos : int, optional
2306 The position of the cursor on the input line.
2306 The position of the cursor on the input line.
2307
2307
2308 Returns
2308 Returns
2309 -------
2309 -------
2310 text : string
2310 text : string
2311 The actual text that was completed.
2311 The actual text that was completed.
2312 matches : list
2312 matches : list
2313 A sorted list with all possible completions.
2313 A sorted list with all possible completions.
2314
2314
2315 Notes
2315 Notes
2316 -----
2316 -----
2317 The optional arguments allow the completion to take more context into
2317 The optional arguments allow the completion to take more context into
2318 account, and are part of the low-level completion API.
2318 account, and are part of the low-level completion API.
2319
2319
2320 This is a wrapper around the completion mechanism, similar to what
2320 This is a wrapper around the completion mechanism, similar to what
2321 readline does at the command line when the TAB key is hit. By
2321 readline does at the command line when the TAB key is hit. By
2322 exposing it as a method, it can be used by other non-readline
2322 exposing it as a method, it can be used by other non-readline
2323 environments (such as GUIs) for text completion.
2323 environments (such as GUIs) for text completion.
2324
2324
2325 Examples
2325 Examples
2326 --------
2326 --------
2327 In [1]: x = 'hello'
2327 In [1]: x = 'hello'
2328
2328
2329 In [2]: _ip.complete('x.l')
2329 In [2]: _ip.complete('x.l')
2330 Out[2]: ('x.l', ['x.ljust', 'x.lower', 'x.lstrip'])
2330 Out[2]: ('x.l', ['x.ljust', 'x.lower', 'x.lstrip'])
2331 """
2331 """
2332
2332
2333 # Inject names into __builtin__ so we can complete on the added names.
2333 # Inject names into __builtin__ so we can complete on the added names.
2334 with self.builtin_trap:
2334 with self.builtin_trap:
2335 return self.Completer.complete(text, line, cursor_pos)
2335 return self.Completer.complete(text, line, cursor_pos)
2336
2336
2337 def set_custom_completer(self, completer, pos=0) -> None:
2337 def set_custom_completer(self, completer, pos=0) -> None:
2338 """Adds a new custom completer function.
2338 """Adds a new custom completer function.
2339
2339
2340 The position argument (defaults to 0) is the index in the completers
2340 The position argument (defaults to 0) is the index in the completers
2341 list where you want the completer to be inserted.
2341 list where you want the completer to be inserted.
2342
2342
2343 `completer` should have the following signature::
2343 `completer` should have the following signature::
2344
2344
2345 def completion(self: Completer, text: string) -> List[str]:
2345 def completion(self: Completer, text: string) -> List[str]:
2346 raise NotImplementedError
2346 raise NotImplementedError
2347
2347
2348 It will be bound to the current Completer instance and pass some text
2348 It will be bound to the current Completer instance and pass some text
2349 and return a list with current completions to suggest to the user.
2349 and return a list with current completions to suggest to the user.
2350 """
2350 """
2351
2351
2352 newcomp = types.MethodType(completer, self.Completer)
2352 newcomp = types.MethodType(completer, self.Completer)
2353 self.Completer.custom_matchers.insert(pos,newcomp)
2353 self.Completer.custom_matchers.insert(pos,newcomp)
2354
2354
2355 def set_completer_frame(self, frame=None):
2355 def set_completer_frame(self, frame=None):
2356 """Set the frame of the completer."""
2356 """Set the frame of the completer."""
2357 if frame:
2357 if frame:
2358 self.Completer.namespace = frame.f_locals
2358 self.Completer.namespace = frame.f_locals
2359 self.Completer.global_namespace = frame.f_globals
2359 self.Completer.global_namespace = frame.f_globals
2360 else:
2360 else:
2361 self.Completer.namespace = self.user_ns
2361 self.Completer.namespace = self.user_ns
2362 self.Completer.global_namespace = self.user_global_ns
2362 self.Completer.global_namespace = self.user_global_ns
2363
2363
2364 #-------------------------------------------------------------------------
2364 #-------------------------------------------------------------------------
2365 # Things related to magics
2365 # Things related to magics
2366 #-------------------------------------------------------------------------
2366 #-------------------------------------------------------------------------
2367
2367
2368 def init_magics(self):
2368 def init_magics(self):
2369 from IPython.core import magics as m
2369 from IPython.core import magics as m
2370 self.magics_manager = magic.MagicsManager(shell=self,
2370 self.magics_manager = magic.MagicsManager(shell=self,
2371 parent=self,
2371 parent=self,
2372 user_magics=m.UserMagics(self))
2372 user_magics=m.UserMagics(self))
2373 self.configurables.append(self.magics_manager)
2373 self.configurables.append(self.magics_manager)
2374
2374
2375 # Expose as public API from the magics manager
2375 # Expose as public API from the magics manager
2376 self.register_magics = self.magics_manager.register
2376 self.register_magics = self.magics_manager.register
2377
2377
2378 self.register_magics(m.AutoMagics, m.BasicMagics, m.CodeMagics,
2378 self.register_magics(m.AutoMagics, m.BasicMagics, m.CodeMagics,
2379 m.ConfigMagics, m.DisplayMagics, m.ExecutionMagics,
2379 m.ConfigMagics, m.DisplayMagics, m.ExecutionMagics,
2380 m.ExtensionMagics, m.HistoryMagics, m.LoggingMagics,
2380 m.ExtensionMagics, m.HistoryMagics, m.LoggingMagics,
2381 m.NamespaceMagics, m.OSMagics, m.PackagingMagics,
2381 m.NamespaceMagics, m.OSMagics, m.PackagingMagics,
2382 m.PylabMagics, m.ScriptMagics,
2382 m.PylabMagics, m.ScriptMagics,
2383 )
2383 )
2384 self.register_magics(m.AsyncMagics)
2384 self.register_magics(m.AsyncMagics)
2385
2385
2386 # Register Magic Aliases
2386 # Register Magic Aliases
2387 mman = self.magics_manager
2387 mman = self.magics_manager
2388 # FIXME: magic aliases should be defined by the Magics classes
2388 # FIXME: magic aliases should be defined by the Magics classes
2389 # or in MagicsManager, not here
2389 # or in MagicsManager, not here
2390 mman.register_alias('ed', 'edit')
2390 mman.register_alias('ed', 'edit')
2391 mman.register_alias('hist', 'history')
2391 mman.register_alias('hist', 'history')
2392 mman.register_alias('rep', 'recall')
2392 mman.register_alias('rep', 'recall')
2393 mman.register_alias('SVG', 'svg', 'cell')
2393 mman.register_alias('SVG', 'svg', 'cell')
2394 mman.register_alias('HTML', 'html', 'cell')
2394 mman.register_alias('HTML', 'html', 'cell')
2395 mman.register_alias('file', 'writefile', 'cell')
2395 mman.register_alias('file', 'writefile', 'cell')
2396
2396
2397 # FIXME: Move the color initialization to the DisplayHook, which
2397 # FIXME: Move the color initialization to the DisplayHook, which
2398 # should be split into a prompt manager and displayhook. We probably
2398 # should be split into a prompt manager and displayhook. We probably
2399 # even need a centralize colors management object.
2399 # even need a centralize colors management object.
2400 self.run_line_magic('colors', self.colors)
2400 self.run_line_magic('colors', self.colors)
2401
2401
2402 # Defined here so that it's included in the documentation
2402 # Defined here so that it's included in the documentation
2403 @functools.wraps(magic.MagicsManager.register_function)
2403 @functools.wraps(magic.MagicsManager.register_function)
2404 def register_magic_function(self, func, magic_kind='line', magic_name=None):
2404 def register_magic_function(self, func, magic_kind='line', magic_name=None):
2405 self.magics_manager.register_function(
2405 self.magics_manager.register_function(
2406 func, magic_kind=magic_kind, magic_name=magic_name
2406 func, magic_kind=magic_kind, magic_name=magic_name
2407 )
2407 )
2408
2408
2409 def _find_with_lazy_load(self, /, type_, magic_name: str):
2409 def _find_with_lazy_load(self, /, type_, magic_name: str):
2410 """
2410 """
2411 Try to find a magic potentially lazy-loading it.
2411 Try to find a magic potentially lazy-loading it.
2412
2412
2413 Parameters
2413 Parameters
2414 ----------
2414 ----------
2415
2415
2416 type_: "line"|"cell"
2416 type_: "line"|"cell"
2417 the type of magics we are trying to find/lazy load.
2417 the type of magics we are trying to find/lazy load.
2418 magic_name: str
2418 magic_name: str
2419 The name of the magic we are trying to find/lazy load
2419 The name of the magic we are trying to find/lazy load
2420
2420
2421
2421
2422 Note that this may have any side effects
2422 Note that this may have any side effects
2423 """
2423 """
2424 finder = {"line": self.find_line_magic, "cell": self.find_cell_magic}[type_]
2424 finder = {"line": self.find_line_magic, "cell": self.find_cell_magic}[type_]
2425 fn = finder(magic_name)
2425 fn = finder(magic_name)
2426 if fn is not None:
2426 if fn is not None:
2427 return fn
2427 return fn
2428 lazy = self.magics_manager.lazy_magics.get(magic_name)
2428 lazy = self.magics_manager.lazy_magics.get(magic_name)
2429 if lazy is None:
2429 if lazy is None:
2430 return None
2430 return None
2431
2431
2432 self.run_line_magic("load_ext", lazy)
2432 self.run_line_magic("load_ext", lazy)
2433 res = finder(magic_name)
2433 res = finder(magic_name)
2434 return res
2434 return res
2435
2435
2436 def run_line_magic(self, magic_name: str, line: str, _stack_depth=1):
2436 def run_line_magic(self, magic_name: str, line: str, _stack_depth=1):
2437 """Execute the given line magic.
2437 """Execute the given line magic.
2438
2438
2439 Parameters
2439 Parameters
2440 ----------
2440 ----------
2441 magic_name : str
2441 magic_name : str
2442 Name of the desired magic function, without '%' prefix.
2442 Name of the desired magic function, without '%' prefix.
2443 line : str
2443 line : str
2444 The rest of the input line as a single string.
2444 The rest of the input line as a single string.
2445 _stack_depth : int
2445 _stack_depth : int
2446 If run_line_magic() is called from magic() then _stack_depth=2.
2446 If run_line_magic() is called from magic() then _stack_depth=2.
2447 This is added to ensure backward compatibility for use of 'get_ipython().magic()'
2447 This is added to ensure backward compatibility for use of 'get_ipython().magic()'
2448 """
2448 """
2449 fn = self._find_with_lazy_load("line", magic_name)
2449 fn = self._find_with_lazy_load("line", magic_name)
2450 if fn is None:
2450 if fn is None:
2451 lazy = self.magics_manager.lazy_magics.get(magic_name)
2451 lazy = self.magics_manager.lazy_magics.get(magic_name)
2452 if lazy:
2452 if lazy:
2453 self.run_line_magic("load_ext", lazy)
2453 self.run_line_magic("load_ext", lazy)
2454 fn = self.find_line_magic(magic_name)
2454 fn = self.find_line_magic(magic_name)
2455 if fn is None:
2455 if fn is None:
2456 cm = self.find_cell_magic(magic_name)
2456 cm = self.find_cell_magic(magic_name)
2457 etpl = "Line magic function `%%%s` not found%s."
2457 etpl = "Line magic function `%%%s` not found%s."
2458 extra = '' if cm is None else (' (But cell magic `%%%%%s` exists, '
2458 extra = '' if cm is None else (' (But cell magic `%%%%%s` exists, '
2459 'did you mean that instead?)' % magic_name )
2459 'did you mean that instead?)' % magic_name )
2460 raise UsageError(etpl % (magic_name, extra))
2460 raise UsageError(etpl % (magic_name, extra))
2461 else:
2461 else:
2462 # Note: this is the distance in the stack to the user's frame.
2462 # Note: this is the distance in the stack to the user's frame.
2463 # This will need to be updated if the internal calling logic gets
2463 # This will need to be updated if the internal calling logic gets
2464 # refactored, or else we'll be expanding the wrong variables.
2464 # refactored, or else we'll be expanding the wrong variables.
2465
2465
2466 # Determine stack_depth depending on where run_line_magic() has been called
2466 # Determine stack_depth depending on where run_line_magic() has been called
2467 stack_depth = _stack_depth
2467 stack_depth = _stack_depth
2468 if getattr(fn, magic.MAGIC_NO_VAR_EXPAND_ATTR, False):
2468 if getattr(fn, magic.MAGIC_NO_VAR_EXPAND_ATTR, False):
2469 # magic has opted out of var_expand
2469 # magic has opted out of var_expand
2470 magic_arg_s = line
2470 magic_arg_s = line
2471 else:
2471 else:
2472 magic_arg_s = self.var_expand(line, stack_depth)
2472 magic_arg_s = self.var_expand(line, stack_depth)
2473 # Put magic args in a list so we can call with f(*a) syntax
2473 # Put magic args in a list so we can call with f(*a) syntax
2474 args = [magic_arg_s]
2474 args = [magic_arg_s]
2475 kwargs = {}
2475 kwargs = {}
2476 # Grab local namespace if we need it:
2476 # Grab local namespace if we need it:
2477 if getattr(fn, "needs_local_scope", False):
2477 if getattr(fn, "needs_local_scope", False):
2478 kwargs['local_ns'] = self.get_local_scope(stack_depth)
2478 kwargs['local_ns'] = self.get_local_scope(stack_depth)
2479 with self.builtin_trap:
2479 with self.builtin_trap:
2480 result = fn(*args, **kwargs)
2480 result = fn(*args, **kwargs)
2481
2481
2482 # The code below prevents the output from being displayed
2482 # The code below prevents the output from being displayed
2483 # when using magics with decorator @output_can_be_silenced
2483 # when using magics with decorator @output_can_be_silenced
2484 # when the last Python token in the expression is a ';'.
2484 # when the last Python token in the expression is a ';'.
2485 if getattr(fn, magic.MAGIC_OUTPUT_CAN_BE_SILENCED, False):
2485 if getattr(fn, magic.MAGIC_OUTPUT_CAN_BE_SILENCED, False):
2486 if DisplayHook.semicolon_at_end_of_expression(magic_arg_s):
2486 if DisplayHook.semicolon_at_end_of_expression(magic_arg_s):
2487 return None
2487 return None
2488
2488
2489 return result
2489 return result
2490
2490
2491 def get_local_scope(self, stack_depth):
2491 def get_local_scope(self, stack_depth):
2492 """Get local scope at given stack depth.
2492 """Get local scope at given stack depth.
2493
2493
2494 Parameters
2494 Parameters
2495 ----------
2495 ----------
2496 stack_depth : int
2496 stack_depth : int
2497 Depth relative to calling frame
2497 Depth relative to calling frame
2498 """
2498 """
2499 return sys._getframe(stack_depth + 1).f_locals
2499 return sys._getframe(stack_depth + 1).f_locals
2500
2500
2501 def run_cell_magic(self, magic_name, line, cell):
2501 def run_cell_magic(self, magic_name, line, cell):
2502 """Execute the given cell magic.
2502 """Execute the given cell magic.
2503
2503
2504 Parameters
2504 Parameters
2505 ----------
2505 ----------
2506 magic_name : str
2506 magic_name : str
2507 Name of the desired magic function, without '%' prefix.
2507 Name of the desired magic function, without '%' prefix.
2508 line : str
2508 line : str
2509 The rest of the first input line as a single string.
2509 The rest of the first input line as a single string.
2510 cell : str
2510 cell : str
2511 The body of the cell as a (possibly multiline) string.
2511 The body of the cell as a (possibly multiline) string.
2512 """
2512 """
2513 fn = self._find_with_lazy_load("cell", magic_name)
2513 fn = self._find_with_lazy_load("cell", magic_name)
2514 if fn is None:
2514 if fn is None:
2515 lm = self.find_line_magic(magic_name)
2515 lm = self.find_line_magic(magic_name)
2516 etpl = "Cell magic `%%{0}` not found{1}."
2516 etpl = "Cell magic `%%{0}` not found{1}."
2517 extra = '' if lm is None else (' (But line magic `%{0}` exists, '
2517 extra = '' if lm is None else (' (But line magic `%{0}` exists, '
2518 'did you mean that instead?)'.format(magic_name))
2518 'did you mean that instead?)'.format(magic_name))
2519 raise UsageError(etpl.format(magic_name, extra))
2519 raise UsageError(etpl.format(magic_name, extra))
2520 elif cell == '':
2520 elif cell == '':
2521 message = '%%{0} is a cell magic, but the cell body is empty.'.format(magic_name)
2521 message = '%%{0} is a cell magic, but the cell body is empty.'.format(magic_name)
2522 if self.find_line_magic(magic_name) is not None:
2522 if self.find_line_magic(magic_name) is not None:
2523 message += ' Did you mean the line magic %{0} (single %)?'.format(magic_name)
2523 message += ' Did you mean the line magic %{0} (single %)?'.format(magic_name)
2524 raise UsageError(message)
2524 raise UsageError(message)
2525 else:
2525 else:
2526 # Note: this is the distance in the stack to the user's frame.
2526 # Note: this is the distance in the stack to the user's frame.
2527 # This will need to be updated if the internal calling logic gets
2527 # This will need to be updated if the internal calling logic gets
2528 # refactored, or else we'll be expanding the wrong variables.
2528 # refactored, or else we'll be expanding the wrong variables.
2529 stack_depth = 2
2529 stack_depth = 2
2530 if getattr(fn, magic.MAGIC_NO_VAR_EXPAND_ATTR, False):
2530 if getattr(fn, magic.MAGIC_NO_VAR_EXPAND_ATTR, False):
2531 # magic has opted out of var_expand
2531 # magic has opted out of var_expand
2532 magic_arg_s = line
2532 magic_arg_s = line
2533 else:
2533 else:
2534 magic_arg_s = self.var_expand(line, stack_depth)
2534 magic_arg_s = self.var_expand(line, stack_depth)
2535 kwargs = {}
2535 kwargs = {}
2536 if getattr(fn, "needs_local_scope", False):
2536 if getattr(fn, "needs_local_scope", False):
2537 kwargs['local_ns'] = self.user_ns
2537 kwargs['local_ns'] = self.user_ns
2538
2538
2539 with self.builtin_trap:
2539 with self.builtin_trap:
2540 args = (magic_arg_s, cell)
2540 args = (magic_arg_s, cell)
2541 result = fn(*args, **kwargs)
2541 result = fn(*args, **kwargs)
2542
2542
2543 # The code below prevents the output from being displayed
2543 # The code below prevents the output from being displayed
2544 # when using magics with decorator @output_can_be_silenced
2544 # when using magics with decorator @output_can_be_silenced
2545 # when the last Python token in the expression is a ';'.
2545 # when the last Python token in the expression is a ';'.
2546 if getattr(fn, magic.MAGIC_OUTPUT_CAN_BE_SILENCED, False):
2546 if getattr(fn, magic.MAGIC_OUTPUT_CAN_BE_SILENCED, False):
2547 if DisplayHook.semicolon_at_end_of_expression(cell):
2547 if DisplayHook.semicolon_at_end_of_expression(cell):
2548 return None
2548 return None
2549
2549
2550 return result
2550 return result
2551
2551
2552 def find_line_magic(self, magic_name):
2552 def find_line_magic(self, magic_name):
2553 """Find and return a line magic by name.
2553 """Find and return a line magic by name.
2554
2554
2555 Returns None if the magic isn't found."""
2555 Returns None if the magic isn't found."""
2556 return self.magics_manager.magics['line'].get(magic_name)
2556 return self.magics_manager.magics['line'].get(magic_name)
2557
2557
2558 def find_cell_magic(self, magic_name):
2558 def find_cell_magic(self, magic_name):
2559 """Find and return a cell magic by name.
2559 """Find and return a cell magic by name.
2560
2560
2561 Returns None if the magic isn't found."""
2561 Returns None if the magic isn't found."""
2562 return self.magics_manager.magics['cell'].get(magic_name)
2562 return self.magics_manager.magics['cell'].get(magic_name)
2563
2563
2564 def find_magic(self, magic_name, magic_kind='line'):
2564 def find_magic(self, magic_name, magic_kind='line'):
2565 """Find and return a magic of the given type by name.
2565 """Find and return a magic of the given type by name.
2566
2566
2567 Returns None if the magic isn't found."""
2567 Returns None if the magic isn't found."""
2568 return self.magics_manager.magics[magic_kind].get(magic_name)
2568 return self.magics_manager.magics[magic_kind].get(magic_name)
2569
2569
2570 def magic(self, arg_s):
2570 def magic(self, arg_s):
2571 """
2571 """
2572 DEPRECATED
2572 DEPRECATED
2573
2573
2574 Deprecated since IPython 0.13 (warning added in
2574 Deprecated since IPython 0.13 (warning added in
2575 8.1), use run_line_magic(magic_name, parameter_s).
2575 8.1), use run_line_magic(magic_name, parameter_s).
2576
2576
2577 Call a magic function by name.
2577 Call a magic function by name.
2578
2578
2579 Input: a string containing the name of the magic function to call and
2579 Input: a string containing the name of the magic function to call and
2580 any additional arguments to be passed to the magic.
2580 any additional arguments to be passed to the magic.
2581
2581
2582 magic('name -opt foo bar') is equivalent to typing at the ipython
2582 magic('name -opt foo bar') is equivalent to typing at the ipython
2583 prompt:
2583 prompt:
2584
2584
2585 In[1]: %name -opt foo bar
2585 In[1]: %name -opt foo bar
2586
2586
2587 To call a magic without arguments, simply use magic('name').
2587 To call a magic without arguments, simply use magic('name').
2588
2588
2589 This provides a proper Python function to call IPython's magics in any
2589 This provides a proper Python function to call IPython's magics in any
2590 valid Python code you can type at the interpreter, including loops and
2590 valid Python code you can type at the interpreter, including loops and
2591 compound statements.
2591 compound statements.
2592 """
2592 """
2593 warnings.warn(
2593 warnings.warn(
2594 "`magic(...)` is deprecated since IPython 0.13 (warning added in "
2594 "`magic(...)` is deprecated since IPython 0.13 (warning added in "
2595 "8.1), use run_line_magic(magic_name, parameter_s).",
2595 "8.1), use run_line_magic(magic_name, parameter_s).",
2596 DeprecationWarning,
2596 DeprecationWarning,
2597 stacklevel=2,
2597 stacklevel=2,
2598 )
2598 )
2599 # TODO: should we issue a loud deprecation warning here?
2599 # TODO: should we issue a loud deprecation warning here?
2600 magic_name, _, magic_arg_s = arg_s.partition(' ')
2600 magic_name, _, magic_arg_s = arg_s.partition(' ')
2601 magic_name = magic_name.lstrip(prefilter.ESC_MAGIC)
2601 magic_name = magic_name.lstrip(prefilter.ESC_MAGIC)
2602 return self.run_line_magic(magic_name, magic_arg_s, _stack_depth=2)
2602 return self.run_line_magic(magic_name, magic_arg_s, _stack_depth=2)
2603
2603
2604 #-------------------------------------------------------------------------
2604 #-------------------------------------------------------------------------
2605 # Things related to macros
2605 # Things related to macros
2606 #-------------------------------------------------------------------------
2606 #-------------------------------------------------------------------------
2607
2607
2608 def define_macro(self, name, themacro):
2608 def define_macro(self, name, themacro):
2609 """Define a new macro
2609 """Define a new macro
2610
2610
2611 Parameters
2611 Parameters
2612 ----------
2612 ----------
2613 name : str
2613 name : str
2614 The name of the macro.
2614 The name of the macro.
2615 themacro : str or Macro
2615 themacro : str or Macro
2616 The action to do upon invoking the macro. If a string, a new
2616 The action to do upon invoking the macro. If a string, a new
2617 Macro object is created by passing the string to it.
2617 Macro object is created by passing the string to it.
2618 """
2618 """
2619
2619
2620 from IPython.core import macro
2620 from IPython.core import macro
2621
2621
2622 if isinstance(themacro, str):
2622 if isinstance(themacro, str):
2623 themacro = macro.Macro(themacro)
2623 themacro = macro.Macro(themacro)
2624 if not isinstance(themacro, macro.Macro):
2624 if not isinstance(themacro, macro.Macro):
2625 raise ValueError('A macro must be a string or a Macro instance.')
2625 raise ValueError('A macro must be a string or a Macro instance.')
2626 self.user_ns[name] = themacro
2626 self.user_ns[name] = themacro
2627
2627
2628 #-------------------------------------------------------------------------
2628 #-------------------------------------------------------------------------
2629 # Things related to the running of system commands
2629 # Things related to the running of system commands
2630 #-------------------------------------------------------------------------
2630 #-------------------------------------------------------------------------
2631
2631
2632 def system_piped(self, cmd):
2632 def system_piped(self, cmd):
2633 """Call the given cmd in a subprocess, piping stdout/err
2633 """Call the given cmd in a subprocess, piping stdout/err
2634
2634
2635 Parameters
2635 Parameters
2636 ----------
2636 ----------
2637 cmd : str
2637 cmd : str
2638 Command to execute (can not end in '&', as background processes are
2638 Command to execute (can not end in '&', as background processes are
2639 not supported. Should not be a command that expects input
2639 not supported. Should not be a command that expects input
2640 other than simple text.
2640 other than simple text.
2641 """
2641 """
2642 if cmd.rstrip().endswith('&'):
2642 if cmd.rstrip().endswith('&'):
2643 # this is *far* from a rigorous test
2643 # this is *far* from a rigorous test
2644 # We do not support backgrounding processes because we either use
2644 # We do not support backgrounding processes because we either use
2645 # pexpect or pipes to read from. Users can always just call
2645 # pexpect or pipes to read from. Users can always just call
2646 # os.system() or use ip.system=ip.system_raw
2646 # os.system() or use ip.system=ip.system_raw
2647 # if they really want a background process.
2647 # if they really want a background process.
2648 raise OSError("Background processes not supported.")
2648 raise OSError("Background processes not supported.")
2649
2649
2650 # we explicitly do NOT return the subprocess status code, because
2650 # we explicitly do NOT return the subprocess status code, because
2651 # a non-None value would trigger :func:`sys.displayhook` calls.
2651 # a non-None value would trigger :func:`sys.displayhook` calls.
2652 # Instead, we store the exit_code in user_ns.
2652 # Instead, we store the exit_code in user_ns.
2653 self.user_ns['_exit_code'] = system(self.var_expand(cmd, depth=1))
2653 self.user_ns['_exit_code'] = system(self.var_expand(cmd, depth=1))
2654
2654
2655 def system_raw(self, cmd):
2655 def system_raw(self, cmd):
2656 """Call the given cmd in a subprocess using os.system on Windows or
2656 """Call the given cmd in a subprocess using os.system on Windows or
2657 subprocess.call using the system shell on other platforms.
2657 subprocess.call using the system shell on other platforms.
2658
2658
2659 Parameters
2659 Parameters
2660 ----------
2660 ----------
2661 cmd : str
2661 cmd : str
2662 Command to execute.
2662 Command to execute.
2663 """
2663 """
2664 cmd = self.var_expand(cmd, depth=1)
2664 cmd = self.var_expand(cmd, depth=1)
2665 # warn if there is an IPython magic alternative.
2665 # warn if there is an IPython magic alternative.
2666 if cmd == "":
2666 if cmd == "":
2667 main_cmd = ""
2667 main_cmd = ""
2668 else:
2668 else:
2669 main_cmd = cmd.split()[0]
2669 main_cmd = cmd.split()[0]
2670 has_magic_alternatives = ("pip", "conda", "cd")
2670 has_magic_alternatives = ("pip", "conda", "cd")
2671
2671
2672 if main_cmd in has_magic_alternatives:
2672 if main_cmd in has_magic_alternatives:
2673 warnings.warn(
2673 warnings.warn(
2674 (
2674 (
2675 "You executed the system command !{0} which may not work "
2675 "You executed the system command !{0} which may not work "
2676 "as expected. Try the IPython magic %{0} instead."
2676 "as expected. Try the IPython magic %{0} instead."
2677 ).format(main_cmd)
2677 ).format(main_cmd)
2678 )
2678 )
2679
2679
2680 # protect os.system from UNC paths on Windows, which it can't handle:
2680 # protect os.system from UNC paths on Windows, which it can't handle:
2681 if sys.platform == 'win32':
2681 if sys.platform == 'win32':
2682 from IPython.utils._process_win32 import AvoidUNCPath
2682 from IPython.utils._process_win32 import AvoidUNCPath
2683 with AvoidUNCPath() as path:
2683 with AvoidUNCPath() as path:
2684 if path is not None:
2684 if path is not None:
2685 cmd = '"pushd %s &&"%s' % (path, cmd)
2685 cmd = '"pushd %s &&"%s' % (path, cmd)
2686 try:
2686 try:
2687 ec = os.system(cmd)
2687 ec = os.system(cmd)
2688 except KeyboardInterrupt:
2688 except KeyboardInterrupt:
2689 print('\n' + self.get_exception_only(), file=sys.stderr)
2689 print('\n' + self.get_exception_only(), file=sys.stderr)
2690 ec = -2
2690 ec = -2
2691 else:
2691 else:
2692 # For posix the result of the subprocess.call() below is an exit
2692 # For posix the result of the subprocess.call() below is an exit
2693 # code, which by convention is zero for success, positive for
2693 # code, which by convention is zero for success, positive for
2694 # program failure. Exit codes above 128 are reserved for signals,
2694 # program failure. Exit codes above 128 are reserved for signals,
2695 # and the formula for converting a signal to an exit code is usually
2695 # and the formula for converting a signal to an exit code is usually
2696 # signal_number+128. To more easily differentiate between exit
2696 # signal_number+128. To more easily differentiate between exit
2697 # codes and signals, ipython uses negative numbers. For instance
2697 # codes and signals, ipython uses negative numbers. For instance
2698 # since control-c is signal 2 but exit code 130, ipython's
2698 # since control-c is signal 2 but exit code 130, ipython's
2699 # _exit_code variable will read -2. Note that some shells like
2699 # _exit_code variable will read -2. Note that some shells like
2700 # csh and fish don't follow sh/bash conventions for exit codes.
2700 # csh and fish don't follow sh/bash conventions for exit codes.
2701 executable = os.environ.get('SHELL', None)
2701 executable = os.environ.get('SHELL', None)
2702 try:
2702 try:
2703 # Use env shell instead of default /bin/sh
2703 # Use env shell instead of default /bin/sh
2704 ec = subprocess.call(cmd, shell=True, executable=executable)
2704 ec = subprocess.call(cmd, shell=True, executable=executable)
2705 except KeyboardInterrupt:
2705 except KeyboardInterrupt:
2706 # intercept control-C; a long traceback is not useful here
2706 # intercept control-C; a long traceback is not useful here
2707 print('\n' + self.get_exception_only(), file=sys.stderr)
2707 print('\n' + self.get_exception_only(), file=sys.stderr)
2708 ec = 130
2708 ec = 130
2709 if ec > 128:
2709 if ec > 128:
2710 ec = -(ec - 128)
2710 ec = -(ec - 128)
2711
2711
2712 # We explicitly do NOT return the subprocess status code, because
2712 # We explicitly do NOT return the subprocess status code, because
2713 # a non-None value would trigger :func:`sys.displayhook` calls.
2713 # a non-None value would trigger :func:`sys.displayhook` calls.
2714 # Instead, we store the exit_code in user_ns. Note the semantics
2714 # Instead, we store the exit_code in user_ns. Note the semantics
2715 # of _exit_code: for control-c, _exit_code == -signal.SIGNIT,
2715 # of _exit_code: for control-c, _exit_code == -signal.SIGNIT,
2716 # but raising SystemExit(_exit_code) will give status 254!
2716 # but raising SystemExit(_exit_code) will give status 254!
2717 self.user_ns['_exit_code'] = ec
2717 self.user_ns['_exit_code'] = ec
2718
2718
2719 # use piped system by default, because it is better behaved
2719 # use piped system by default, because it is better behaved
2720 system = system_piped
2720 system = system_piped
2721
2721
2722 def getoutput(self, cmd, split=True, depth=0):
2722 def getoutput(self, cmd, split=True, depth=0):
2723 """Get output (possibly including stderr) from a subprocess.
2723 """Get output (possibly including stderr) from a subprocess.
2724
2724
2725 Parameters
2725 Parameters
2726 ----------
2726 ----------
2727 cmd : str
2727 cmd : str
2728 Command to execute (can not end in '&', as background processes are
2728 Command to execute (can not end in '&', as background processes are
2729 not supported.
2729 not supported.
2730 split : bool, optional
2730 split : bool, optional
2731 If True, split the output into an IPython SList. Otherwise, an
2731 If True, split the output into an IPython SList. Otherwise, an
2732 IPython LSString is returned. These are objects similar to normal
2732 IPython LSString is returned. These are objects similar to normal
2733 lists and strings, with a few convenience attributes for easier
2733 lists and strings, with a few convenience attributes for easier
2734 manipulation of line-based output. You can use '?' on them for
2734 manipulation of line-based output. You can use '?' on them for
2735 details.
2735 details.
2736 depth : int, optional
2736 depth : int, optional
2737 How many frames above the caller are the local variables which should
2737 How many frames above the caller are the local variables which should
2738 be expanded in the command string? The default (0) assumes that the
2738 be expanded in the command string? The default (0) assumes that the
2739 expansion variables are in the stack frame calling this function.
2739 expansion variables are in the stack frame calling this function.
2740 """
2740 """
2741 if cmd.rstrip().endswith('&'):
2741 if cmd.rstrip().endswith('&'):
2742 # this is *far* from a rigorous test
2742 # this is *far* from a rigorous test
2743 raise OSError("Background processes not supported.")
2743 raise OSError("Background processes not supported.")
2744 out = getoutput(self.var_expand(cmd, depth=depth+1))
2744 out = getoutput(self.var_expand(cmd, depth=depth+1))
2745 if split:
2745 if split:
2746 out = SList(out.splitlines())
2746 out = SList(out.splitlines())
2747 else:
2747 else:
2748 out = LSString(out)
2748 out = LSString(out)
2749 return out
2749 return out
2750
2750
2751 #-------------------------------------------------------------------------
2751 #-------------------------------------------------------------------------
2752 # Things related to aliases
2752 # Things related to aliases
2753 #-------------------------------------------------------------------------
2753 #-------------------------------------------------------------------------
2754
2754
2755 def init_alias(self):
2755 def init_alias(self):
2756 self.alias_manager = AliasManager(shell=self, parent=self)
2756 self.alias_manager = AliasManager(shell=self, parent=self)
2757 self.configurables.append(self.alias_manager)
2757 self.configurables.append(self.alias_manager)
2758
2758
2759 #-------------------------------------------------------------------------
2759 #-------------------------------------------------------------------------
2760 # Things related to extensions
2760 # Things related to extensions
2761 #-------------------------------------------------------------------------
2761 #-------------------------------------------------------------------------
2762
2762
2763 def init_extension_manager(self):
2763 def init_extension_manager(self):
2764 self.extension_manager = ExtensionManager(shell=self, parent=self)
2764 self.extension_manager = ExtensionManager(shell=self, parent=self)
2765 self.configurables.append(self.extension_manager)
2765 self.configurables.append(self.extension_manager)
2766
2766
2767 #-------------------------------------------------------------------------
2767 #-------------------------------------------------------------------------
2768 # Things related to payloads
2768 # Things related to payloads
2769 #-------------------------------------------------------------------------
2769 #-------------------------------------------------------------------------
2770
2770
2771 def init_payload(self):
2771 def init_payload(self):
2772 self.payload_manager = PayloadManager(parent=self)
2772 self.payload_manager = PayloadManager(parent=self)
2773 self.configurables.append(self.payload_manager)
2773 self.configurables.append(self.payload_manager)
2774
2774
2775 #-------------------------------------------------------------------------
2775 #-------------------------------------------------------------------------
2776 # Things related to the prefilter
2776 # Things related to the prefilter
2777 #-------------------------------------------------------------------------
2777 #-------------------------------------------------------------------------
2778
2778
2779 def init_prefilter(self):
2779 def init_prefilter(self):
2780 self.prefilter_manager = PrefilterManager(shell=self, parent=self)
2780 self.prefilter_manager = PrefilterManager(shell=self, parent=self)
2781 self.configurables.append(self.prefilter_manager)
2781 self.configurables.append(self.prefilter_manager)
2782 # Ultimately this will be refactored in the new interpreter code, but
2782 # Ultimately this will be refactored in the new interpreter code, but
2783 # for now, we should expose the main prefilter method (there's legacy
2783 # for now, we should expose the main prefilter method (there's legacy
2784 # code out there that may rely on this).
2784 # code out there that may rely on this).
2785 self.prefilter = self.prefilter_manager.prefilter_lines
2785 self.prefilter = self.prefilter_manager.prefilter_lines
2786
2786
2787 def auto_rewrite_input(self, cmd):
2787 def auto_rewrite_input(self, cmd):
2788 """Print to the screen the rewritten form of the user's command.
2788 """Print to the screen the rewritten form of the user's command.
2789
2789
2790 This shows visual feedback by rewriting input lines that cause
2790 This shows visual feedback by rewriting input lines that cause
2791 automatic calling to kick in, like::
2791 automatic calling to kick in, like::
2792
2792
2793 /f x
2793 /f x
2794
2794
2795 into::
2795 into::
2796
2796
2797 ------> f(x)
2797 ------> f(x)
2798
2798
2799 after the user's input prompt. This helps the user understand that the
2799 after the user's input prompt. This helps the user understand that the
2800 input line was transformed automatically by IPython.
2800 input line was transformed automatically by IPython.
2801 """
2801 """
2802 if not self.show_rewritten_input:
2802 if not self.show_rewritten_input:
2803 return
2803 return
2804
2804
2805 # This is overridden in TerminalInteractiveShell to use fancy prompts
2805 # This is overridden in TerminalInteractiveShell to use fancy prompts
2806 print("------> " + cmd)
2806 print("------> " + cmd)
2807
2807
2808 #-------------------------------------------------------------------------
2808 #-------------------------------------------------------------------------
2809 # Things related to extracting values/expressions from kernel and user_ns
2809 # Things related to extracting values/expressions from kernel and user_ns
2810 #-------------------------------------------------------------------------
2810 #-------------------------------------------------------------------------
2811
2811
2812 def _user_obj_error(self):
2812 def _user_obj_error(self):
2813 """return simple exception dict
2813 """return simple exception dict
2814
2814
2815 for use in user_expressions
2815 for use in user_expressions
2816 """
2816 """
2817
2817
2818 etype, evalue, tb = self._get_exc_info()
2818 etype, evalue, tb = self._get_exc_info()
2819 stb = self.InteractiveTB.get_exception_only(etype, evalue)
2819 stb = self.InteractiveTB.get_exception_only(etype, evalue)
2820
2820
2821 exc_info = {
2821 exc_info = {
2822 "status": "error",
2822 "status": "error",
2823 "traceback": stb,
2823 "traceback": stb,
2824 "ename": etype.__name__,
2824 "ename": etype.__name__,
2825 "evalue": py3compat.safe_unicode(evalue),
2825 "evalue": py3compat.safe_unicode(evalue),
2826 }
2826 }
2827
2827
2828 return exc_info
2828 return exc_info
2829
2829
2830 def _format_user_obj(self, obj):
2830 def _format_user_obj(self, obj):
2831 """format a user object to display dict
2831 """format a user object to display dict
2832
2832
2833 for use in user_expressions
2833 for use in user_expressions
2834 """
2834 """
2835
2835
2836 data, md = self.display_formatter.format(obj)
2836 data, md = self.display_formatter.format(obj)
2837 value = {
2837 value = {
2838 'status' : 'ok',
2838 'status' : 'ok',
2839 'data' : data,
2839 'data' : data,
2840 'metadata' : md,
2840 'metadata' : md,
2841 }
2841 }
2842 return value
2842 return value
2843
2843
2844 def user_expressions(self, expressions):
2844 def user_expressions(self, expressions):
2845 """Evaluate a dict of expressions in the user's namespace.
2845 """Evaluate a dict of expressions in the user's namespace.
2846
2846
2847 Parameters
2847 Parameters
2848 ----------
2848 ----------
2849 expressions : dict
2849 expressions : dict
2850 A dict with string keys and string values. The expression values
2850 A dict with string keys and string values. The expression values
2851 should be valid Python expressions, each of which will be evaluated
2851 should be valid Python expressions, each of which will be evaluated
2852 in the user namespace.
2852 in the user namespace.
2853
2853
2854 Returns
2854 Returns
2855 -------
2855 -------
2856 A dict, keyed like the input expressions dict, with the rich mime-typed
2856 A dict, keyed like the input expressions dict, with the rich mime-typed
2857 display_data of each value.
2857 display_data of each value.
2858 """
2858 """
2859 out = {}
2859 out = {}
2860 user_ns = self.user_ns
2860 user_ns = self.user_ns
2861 global_ns = self.user_global_ns
2861 global_ns = self.user_global_ns
2862
2862
2863 for key, expr in expressions.items():
2863 for key, expr in expressions.items():
2864 try:
2864 try:
2865 value = self._format_user_obj(eval(expr, global_ns, user_ns))
2865 value = self._format_user_obj(eval(expr, global_ns, user_ns))
2866 except:
2866 except:
2867 value = self._user_obj_error()
2867 value = self._user_obj_error()
2868 out[key] = value
2868 out[key] = value
2869 return out
2869 return out
2870
2870
2871 #-------------------------------------------------------------------------
2871 #-------------------------------------------------------------------------
2872 # Things related to the running of code
2872 # Things related to the running of code
2873 #-------------------------------------------------------------------------
2873 #-------------------------------------------------------------------------
2874
2874
2875 def ex(self, cmd):
2875 def ex(self, cmd):
2876 """Execute a normal python statement in user namespace."""
2876 """Execute a normal python statement in user namespace."""
2877 with self.builtin_trap:
2877 with self.builtin_trap:
2878 exec(cmd, self.user_global_ns, self.user_ns)
2878 exec(cmd, self.user_global_ns, self.user_ns)
2879
2879
2880 def ev(self, expr):
2880 def ev(self, expr):
2881 """Evaluate python expression expr in user namespace.
2881 """Evaluate python expression expr in user namespace.
2882
2882
2883 Returns the result of evaluation
2883 Returns the result of evaluation
2884 """
2884 """
2885 with self.builtin_trap:
2885 with self.builtin_trap:
2886 return eval(expr, self.user_global_ns, self.user_ns)
2886 return eval(expr, self.user_global_ns, self.user_ns)
2887
2887
2888 def safe_execfile(self, fname, *where, exit_ignore=False, raise_exceptions=False, shell_futures=False):
2888 def safe_execfile(self, fname, *where, exit_ignore=False, raise_exceptions=False, shell_futures=False):
2889 """A safe version of the builtin execfile().
2889 """A safe version of the builtin execfile().
2890
2890
2891 This version will never throw an exception, but instead print
2891 This version will never throw an exception, but instead print
2892 helpful error messages to the screen. This only works on pure
2892 helpful error messages to the screen. This only works on pure
2893 Python files with the .py extension.
2893 Python files with the .py extension.
2894
2894
2895 Parameters
2895 Parameters
2896 ----------
2896 ----------
2897 fname : string
2897 fname : string
2898 The name of the file to be executed.
2898 The name of the file to be executed.
2899 *where : tuple
2899 *where : tuple
2900 One or two namespaces, passed to execfile() as (globals,locals).
2900 One or two namespaces, passed to execfile() as (globals,locals).
2901 If only one is given, it is passed as both.
2901 If only one is given, it is passed as both.
2902 exit_ignore : bool (False)
2902 exit_ignore : bool (False)
2903 If True, then silence SystemExit for non-zero status (it is always
2903 If True, then silence SystemExit for non-zero status (it is always
2904 silenced for zero status, as it is so common).
2904 silenced for zero status, as it is so common).
2905 raise_exceptions : bool (False)
2905 raise_exceptions : bool (False)
2906 If True raise exceptions everywhere. Meant for testing.
2906 If True raise exceptions everywhere. Meant for testing.
2907 shell_futures : bool (False)
2907 shell_futures : bool (False)
2908 If True, the code will share future statements with the interactive
2908 If True, the code will share future statements with the interactive
2909 shell. It will both be affected by previous __future__ imports, and
2909 shell. It will both be affected by previous __future__ imports, and
2910 any __future__ imports in the code will affect the shell. If False,
2910 any __future__ imports in the code will affect the shell. If False,
2911 __future__ imports are not shared in either direction.
2911 __future__ imports are not shared in either direction.
2912
2912
2913 """
2913 """
2914 fname = Path(fname).expanduser().resolve()
2914 fname = Path(fname).expanduser().resolve()
2915
2915
2916 # Make sure we can open the file
2916 # Make sure we can open the file
2917 try:
2917 try:
2918 with fname.open("rb"):
2918 with fname.open("rb"):
2919 pass
2919 pass
2920 except:
2920 except:
2921 warn('Could not open file <%s> for safe execution.' % fname)
2921 warn('Could not open file <%s> for safe execution.' % fname)
2922 return
2922 return
2923
2923
2924 # Find things also in current directory. This is needed to mimic the
2924 # Find things also in current directory. This is needed to mimic the
2925 # behavior of running a script from the system command line, where
2925 # behavior of running a script from the system command line, where
2926 # Python inserts the script's directory into sys.path
2926 # Python inserts the script's directory into sys.path
2927 dname = str(fname.parent)
2927 dname = str(fname.parent)
2928
2928
2929 with prepended_to_syspath(dname), self.builtin_trap:
2929 with prepended_to_syspath(dname), self.builtin_trap:
2930 try:
2930 try:
2931 glob, loc = (where + (None, ))[:2]
2931 glob, loc = (where + (None, ))[:2]
2932 py3compat.execfile(
2932 py3compat.execfile(
2933 fname, glob, loc,
2933 fname, glob, loc,
2934 self.compile if shell_futures else None)
2934 self.compile if shell_futures else None)
2935 except SystemExit as status:
2935 except SystemExit as status:
2936 # If the call was made with 0 or None exit status (sys.exit(0)
2936 # If the call was made with 0 or None exit status (sys.exit(0)
2937 # or sys.exit() ), don't bother showing a traceback, as both of
2937 # or sys.exit() ), don't bother showing a traceback, as both of
2938 # these are considered normal by the OS:
2938 # these are considered normal by the OS:
2939 # > python -c'import sys;sys.exit(0)'; echo $?
2939 # > python -c'import sys;sys.exit(0)'; echo $?
2940 # 0
2940 # 0
2941 # > python -c'import sys;sys.exit()'; echo $?
2941 # > python -c'import sys;sys.exit()'; echo $?
2942 # 0
2942 # 0
2943 # For other exit status, we show the exception unless
2943 # For other exit status, we show the exception unless
2944 # explicitly silenced, but only in short form.
2944 # explicitly silenced, but only in short form.
2945 if status.code:
2945 if status.code:
2946 if raise_exceptions:
2946 if raise_exceptions:
2947 raise
2947 raise
2948 if not exit_ignore:
2948 if not exit_ignore:
2949 self.showtraceback(exception_only=True)
2949 self.showtraceback(exception_only=True)
2950 except:
2950 except:
2951 if raise_exceptions:
2951 if raise_exceptions:
2952 raise
2952 raise
2953 # tb offset is 2 because we wrap execfile
2953 # tb offset is 2 because we wrap execfile
2954 self.showtraceback(tb_offset=2)
2954 self.showtraceback(tb_offset=2)
2955
2955
2956 def safe_execfile_ipy(self, fname, shell_futures=False, raise_exceptions=False):
2956 def safe_execfile_ipy(self, fname, shell_futures=False, raise_exceptions=False):
2957 """Like safe_execfile, but for .ipy or .ipynb files with IPython syntax.
2957 """Like safe_execfile, but for .ipy or .ipynb files with IPython syntax.
2958
2958
2959 Parameters
2959 Parameters
2960 ----------
2960 ----------
2961 fname : str
2961 fname : str
2962 The name of the file to execute. The filename must have a
2962 The name of the file to execute. The filename must have a
2963 .ipy or .ipynb extension.
2963 .ipy or .ipynb extension.
2964 shell_futures : bool (False)
2964 shell_futures : bool (False)
2965 If True, the code will share future statements with the interactive
2965 If True, the code will share future statements with the interactive
2966 shell. It will both be affected by previous __future__ imports, and
2966 shell. It will both be affected by previous __future__ imports, and
2967 any __future__ imports in the code will affect the shell. If False,
2967 any __future__ imports in the code will affect the shell. If False,
2968 __future__ imports are not shared in either direction.
2968 __future__ imports are not shared in either direction.
2969 raise_exceptions : bool (False)
2969 raise_exceptions : bool (False)
2970 If True raise exceptions everywhere. Meant for testing.
2970 If True raise exceptions everywhere. Meant for testing.
2971 """
2971 """
2972 fname = Path(fname).expanduser().resolve()
2972 fname = Path(fname).expanduser().resolve()
2973
2973
2974 # Make sure we can open the file
2974 # Make sure we can open the file
2975 try:
2975 try:
2976 with fname.open("rb"):
2976 with fname.open("rb"):
2977 pass
2977 pass
2978 except:
2978 except:
2979 warn('Could not open file <%s> for safe execution.' % fname)
2979 warn('Could not open file <%s> for safe execution.' % fname)
2980 return
2980 return
2981
2981
2982 # Find things also in current directory. This is needed to mimic the
2982 # Find things also in current directory. This is needed to mimic the
2983 # behavior of running a script from the system command line, where
2983 # behavior of running a script from the system command line, where
2984 # Python inserts the script's directory into sys.path
2984 # Python inserts the script's directory into sys.path
2985 dname = str(fname.parent)
2985 dname = str(fname.parent)
2986
2986
2987 def get_cells():
2987 def get_cells():
2988 """generator for sequence of code blocks to run"""
2988 """generator for sequence of code blocks to run"""
2989 if fname.suffix == ".ipynb":
2989 if fname.suffix == ".ipynb":
2990 from nbformat import read
2990 from nbformat import read
2991 nb = read(fname, as_version=4)
2991 nb = read(fname, as_version=4)
2992 if not nb.cells:
2992 if not nb.cells:
2993 return
2993 return
2994 for cell in nb.cells:
2994 for cell in nb.cells:
2995 if cell.cell_type == 'code':
2995 if cell.cell_type == 'code':
2996 yield cell.source
2996 yield cell.source
2997 else:
2997 else:
2998 yield fname.read_text(encoding="utf-8")
2998 yield fname.read_text(encoding="utf-8")
2999
2999
3000 with prepended_to_syspath(dname):
3000 with prepended_to_syspath(dname):
3001 try:
3001 try:
3002 for cell in get_cells():
3002 for cell in get_cells():
3003 result = self.run_cell(cell, silent=True, shell_futures=shell_futures)
3003 result = self.run_cell(cell, silent=True, shell_futures=shell_futures)
3004 if raise_exceptions:
3004 if raise_exceptions:
3005 result.raise_error()
3005 result.raise_error()
3006 elif not result.success:
3006 elif not result.success:
3007 break
3007 break
3008 except:
3008 except:
3009 if raise_exceptions:
3009 if raise_exceptions:
3010 raise
3010 raise
3011 self.showtraceback()
3011 self.showtraceback()
3012 warn('Unknown failure executing file: <%s>' % fname)
3012 warn('Unknown failure executing file: <%s>' % fname)
3013
3013
3014 def safe_run_module(self, mod_name, where):
3014 def safe_run_module(self, mod_name, where):
3015 """A safe version of runpy.run_module().
3015 """A safe version of runpy.run_module().
3016
3016
3017 This version will never throw an exception, but instead print
3017 This version will never throw an exception, but instead print
3018 helpful error messages to the screen.
3018 helpful error messages to the screen.
3019
3019
3020 `SystemExit` exceptions with status code 0 or None are ignored.
3020 `SystemExit` exceptions with status code 0 or None are ignored.
3021
3021
3022 Parameters
3022 Parameters
3023 ----------
3023 ----------
3024 mod_name : string
3024 mod_name : string
3025 The name of the module to be executed.
3025 The name of the module to be executed.
3026 where : dict
3026 where : dict
3027 The globals namespace.
3027 The globals namespace.
3028 """
3028 """
3029 try:
3029 try:
3030 try:
3030 try:
3031 where.update(
3031 where.update(
3032 runpy.run_module(str(mod_name), run_name="__main__",
3032 runpy.run_module(str(mod_name), run_name="__main__",
3033 alter_sys=True)
3033 alter_sys=True)
3034 )
3034 )
3035 except SystemExit as status:
3035 except SystemExit as status:
3036 if status.code:
3036 if status.code:
3037 raise
3037 raise
3038 except:
3038 except:
3039 self.showtraceback()
3039 self.showtraceback()
3040 warn('Unknown failure executing module: <%s>' % mod_name)
3040 warn('Unknown failure executing module: <%s>' % mod_name)
3041
3041
3042 def run_cell(
3042 def run_cell(
3043 self,
3043 self,
3044 raw_cell,
3044 raw_cell,
3045 store_history=False,
3045 store_history=False,
3046 silent=False,
3046 silent=False,
3047 shell_futures=True,
3047 shell_futures=True,
3048 cell_id=None,
3048 cell_id=None,
3049 ):
3049 ):
3050 """Run a complete IPython cell.
3050 """Run a complete IPython cell.
3051
3051
3052 Parameters
3052 Parameters
3053 ----------
3053 ----------
3054 raw_cell : str
3054 raw_cell : str
3055 The code (including IPython code such as %magic functions) to run.
3055 The code (including IPython code such as %magic functions) to run.
3056 store_history : bool
3056 store_history : bool
3057 If True, the raw and translated cell will be stored in IPython's
3057 If True, the raw and translated cell will be stored in IPython's
3058 history. For user code calling back into IPython's machinery, this
3058 history. For user code calling back into IPython's machinery, this
3059 should be set to False.
3059 should be set to False.
3060 silent : bool
3060 silent : bool
3061 If True, avoid side-effects, such as implicit displayhooks and
3061 If True, avoid side-effects, such as implicit displayhooks and
3062 and logging. silent=True forces store_history=False.
3062 and logging. silent=True forces store_history=False.
3063 shell_futures : bool
3063 shell_futures : bool
3064 If True, the code will share future statements with the interactive
3064 If True, the code will share future statements with the interactive
3065 shell. It will both be affected by previous __future__ imports, and
3065 shell. It will both be affected by previous __future__ imports, and
3066 any __future__ imports in the code will affect the shell. If False,
3066 any __future__ imports in the code will affect the shell. If False,
3067 __future__ imports are not shared in either direction.
3067 __future__ imports are not shared in either direction.
3068
3068
3069 Returns
3069 Returns
3070 -------
3070 -------
3071 result : :class:`ExecutionResult`
3071 result : :class:`ExecutionResult`
3072 """
3072 """
3073 result = None
3073 result = None
3074 try:
3074 try:
3075 result = self._run_cell(
3075 result = self._run_cell(
3076 raw_cell, store_history, silent, shell_futures, cell_id
3076 raw_cell, store_history, silent, shell_futures, cell_id
3077 )
3077 )
3078 finally:
3078 finally:
3079 self.events.trigger('post_execute')
3079 self.events.trigger('post_execute')
3080 if not silent:
3080 if not silent:
3081 self.events.trigger('post_run_cell', result)
3081 self.events.trigger('post_run_cell', result)
3082 return result
3082 return result
3083
3083
3084 def _run_cell(
3084 def _run_cell(
3085 self,
3085 self,
3086 raw_cell: str,
3086 raw_cell: str,
3087 store_history: bool,
3087 store_history: bool,
3088 silent: bool,
3088 silent: bool,
3089 shell_futures: bool,
3089 shell_futures: bool,
3090 cell_id: str,
3090 cell_id: str,
3091 ) -> ExecutionResult:
3091 ) -> ExecutionResult:
3092 """Internal method to run a complete IPython cell."""
3092 """Internal method to run a complete IPython cell."""
3093
3093
3094 # we need to avoid calling self.transform_cell multiple time on the same thing
3094 # we need to avoid calling self.transform_cell multiple time on the same thing
3095 # so we need to store some results:
3095 # so we need to store some results:
3096 preprocessing_exc_tuple = None
3096 preprocessing_exc_tuple = None
3097 try:
3097 try:
3098 transformed_cell = self.transform_cell(raw_cell)
3098 transformed_cell = self.transform_cell(raw_cell)
3099 except Exception:
3099 except Exception:
3100 transformed_cell = raw_cell
3100 transformed_cell = raw_cell
3101 preprocessing_exc_tuple = sys.exc_info()
3101 preprocessing_exc_tuple = sys.exc_info()
3102
3102
3103 assert transformed_cell is not None
3103 assert transformed_cell is not None
3104 coro = self.run_cell_async(
3104 coro = self.run_cell_async(
3105 raw_cell,
3105 raw_cell,
3106 store_history=store_history,
3106 store_history=store_history,
3107 silent=silent,
3107 silent=silent,
3108 shell_futures=shell_futures,
3108 shell_futures=shell_futures,
3109 transformed_cell=transformed_cell,
3109 transformed_cell=transformed_cell,
3110 preprocessing_exc_tuple=preprocessing_exc_tuple,
3110 preprocessing_exc_tuple=preprocessing_exc_tuple,
3111 cell_id=cell_id,
3111 cell_id=cell_id,
3112 )
3112 )
3113
3113
3114 # run_cell_async is async, but may not actually need an eventloop.
3114 # run_cell_async is async, but may not actually need an eventloop.
3115 # when this is the case, we want to run it using the pseudo_sync_runner
3115 # when this is the case, we want to run it using the pseudo_sync_runner
3116 # so that code can invoke eventloops (for example via the %run , and
3116 # so that code can invoke eventloops (for example via the %run , and
3117 # `%paste` magic.
3117 # `%paste` magic.
3118 if self.trio_runner:
3118 if self.trio_runner:
3119 runner = self.trio_runner
3119 runner = self.trio_runner
3120 elif self.should_run_async(
3120 elif self.should_run_async(
3121 raw_cell,
3121 raw_cell,
3122 transformed_cell=transformed_cell,
3122 transformed_cell=transformed_cell,
3123 preprocessing_exc_tuple=preprocessing_exc_tuple,
3123 preprocessing_exc_tuple=preprocessing_exc_tuple,
3124 ):
3124 ):
3125 runner = self.loop_runner
3125 runner = self.loop_runner
3126 else:
3126 else:
3127 runner = _pseudo_sync_runner
3127 runner = _pseudo_sync_runner
3128
3128
3129 try:
3129 try:
3130 result = runner(coro)
3130 result = runner(coro)
3131 except BaseException as e:
3131 except BaseException as e:
3132 info = ExecutionInfo(
3132 info = ExecutionInfo(
3133 raw_cell, store_history, silent, shell_futures, cell_id
3133 raw_cell, store_history, silent, shell_futures, cell_id
3134 )
3134 )
3135 result = ExecutionResult(info)
3135 result = ExecutionResult(info)
3136 result.error_in_exec = e
3136 result.error_in_exec = e
3137 self.showtraceback(running_compiled_code=True)
3137 self.showtraceback(running_compiled_code=True)
3138 finally:
3138 finally:
3139 return result
3139 return result
3140
3140
3141 def should_run_async(
3141 def should_run_async(
3142 self, raw_cell: str, *, transformed_cell=None, preprocessing_exc_tuple=None
3142 self, raw_cell: str, *, transformed_cell=None, preprocessing_exc_tuple=None
3143 ) -> bool:
3143 ) -> bool:
3144 """Return whether a cell should be run asynchronously via a coroutine runner
3144 """Return whether a cell should be run asynchronously via a coroutine runner
3145
3145
3146 Parameters
3146 Parameters
3147 ----------
3147 ----------
3148 raw_cell : str
3148 raw_cell : str
3149 The code to be executed
3149 The code to be executed
3150
3150
3151 Returns
3151 Returns
3152 -------
3152 -------
3153 result: bool
3153 result: bool
3154 Whether the code needs to be run with a coroutine runner or not
3154 Whether the code needs to be run with a coroutine runner or not
3155 .. versionadded:: 7.0
3155 .. versionadded:: 7.0
3156 """
3156 """
3157 if not self.autoawait:
3157 if not self.autoawait:
3158 return False
3158 return False
3159 if preprocessing_exc_tuple is not None:
3159 if preprocessing_exc_tuple is not None:
3160 return False
3160 return False
3161 assert preprocessing_exc_tuple is None
3161 assert preprocessing_exc_tuple is None
3162 if transformed_cell is None:
3162 if transformed_cell is None:
3163 warnings.warn(
3163 warnings.warn(
3164 "`should_run_async` will not call `transform_cell`"
3164 "`should_run_async` will not call `transform_cell`"
3165 " automatically in the future. Please pass the result to"
3165 " automatically in the future. Please pass the result to"
3166 " `transformed_cell` argument and any exception that happen"
3166 " `transformed_cell` argument and any exception that happen"
3167 " during the"
3167 " during the"
3168 "transform in `preprocessing_exc_tuple` in"
3168 "transform in `preprocessing_exc_tuple` in"
3169 " IPython 7.17 and above.",
3169 " IPython 7.17 and above.",
3170 DeprecationWarning,
3170 DeprecationWarning,
3171 stacklevel=2,
3171 stacklevel=2,
3172 )
3172 )
3173 try:
3173 try:
3174 cell = self.transform_cell(raw_cell)
3174 cell = self.transform_cell(raw_cell)
3175 except Exception:
3175 except Exception:
3176 # any exception during transform will be raised
3176 # any exception during transform will be raised
3177 # prior to execution
3177 # prior to execution
3178 return False
3178 return False
3179 else:
3179 else:
3180 cell = transformed_cell
3180 cell = transformed_cell
3181 return _should_be_async(cell)
3181 return _should_be_async(cell)
3182
3182
3183 async def run_cell_async(
3183 async def run_cell_async(
3184 self,
3184 self,
3185 raw_cell: str,
3185 raw_cell: str,
3186 store_history=False,
3186 store_history=False,
3187 silent=False,
3187 silent=False,
3188 shell_futures=True,
3188 shell_futures=True,
3189 *,
3189 *,
3190 transformed_cell: Optional[str] = None,
3190 transformed_cell: Optional[str] = None,
3191 preprocessing_exc_tuple: Optional[AnyType] = None,
3191 preprocessing_exc_tuple: Optional[AnyType] = None,
3192 cell_id=None,
3192 cell_id=None,
3193 ) -> ExecutionResult:
3193 ) -> ExecutionResult:
3194 """Run a complete IPython cell asynchronously.
3194 """Run a complete IPython cell asynchronously.
3195
3195
3196 Parameters
3196 Parameters
3197 ----------
3197 ----------
3198 raw_cell : str
3198 raw_cell : str
3199 The code (including IPython code such as %magic functions) to run.
3199 The code (including IPython code such as %magic functions) to run.
3200 store_history : bool
3200 store_history : bool
3201 If True, the raw and translated cell will be stored in IPython's
3201 If True, the raw and translated cell will be stored in IPython's
3202 history. For user code calling back into IPython's machinery, this
3202 history. For user code calling back into IPython's machinery, this
3203 should be set to False.
3203 should be set to False.
3204 silent : bool
3204 silent : bool
3205 If True, avoid side-effects, such as implicit displayhooks and
3205 If True, avoid side-effects, such as implicit displayhooks and
3206 and logging. silent=True forces store_history=False.
3206 and logging. silent=True forces store_history=False.
3207 shell_futures : bool
3207 shell_futures : bool
3208 If True, the code will share future statements with the interactive
3208 If True, the code will share future statements with the interactive
3209 shell. It will both be affected by previous __future__ imports, and
3209 shell. It will both be affected by previous __future__ imports, and
3210 any __future__ imports in the code will affect the shell. If False,
3210 any __future__ imports in the code will affect the shell. If False,
3211 __future__ imports are not shared in either direction.
3211 __future__ imports are not shared in either direction.
3212 transformed_cell: str
3212 transformed_cell: str
3213 cell that was passed through transformers
3213 cell that was passed through transformers
3214 preprocessing_exc_tuple:
3214 preprocessing_exc_tuple:
3215 trace if the transformation failed.
3215 trace if the transformation failed.
3216
3216
3217 Returns
3217 Returns
3218 -------
3218 -------
3219 result : :class:`ExecutionResult`
3219 result : :class:`ExecutionResult`
3220
3220
3221 .. versionadded:: 7.0
3221 .. versionadded:: 7.0
3222 """
3222 """
3223 info = ExecutionInfo(raw_cell, store_history, silent, shell_futures, cell_id)
3223 info = ExecutionInfo(raw_cell, store_history, silent, shell_futures, cell_id)
3224 result = ExecutionResult(info)
3224 result = ExecutionResult(info)
3225
3225
3226 if (not raw_cell) or raw_cell.isspace():
3226 if (not raw_cell) or raw_cell.isspace():
3227 self.last_execution_succeeded = True
3227 self.last_execution_succeeded = True
3228 self.last_execution_result = result
3228 self.last_execution_result = result
3229 return result
3229 return result
3230
3230
3231 if silent:
3231 if silent:
3232 store_history = False
3232 store_history = False
3233
3233
3234 if store_history:
3234 if store_history:
3235 result.execution_count = self.execution_count
3235 result.execution_count = self.execution_count
3236
3236
3237 def error_before_exec(value):
3237 def error_before_exec(value):
3238 if store_history:
3238 if store_history:
3239 self.execution_count += 1
3239 self.execution_count += 1
3240 result.error_before_exec = value
3240 result.error_before_exec = value
3241 self.last_execution_succeeded = False
3241 self.last_execution_succeeded = False
3242 self.last_execution_result = result
3242 self.last_execution_result = result
3243 return result
3243 return result
3244
3244
3245 self.events.trigger('pre_execute')
3245 self.events.trigger('pre_execute')
3246 if not silent:
3246 if not silent:
3247 self.events.trigger('pre_run_cell', info)
3247 self.events.trigger('pre_run_cell', info)
3248
3248
3249 if transformed_cell is None:
3249 if transformed_cell is None:
3250 warnings.warn(
3250 warnings.warn(
3251 "`run_cell_async` will not call `transform_cell`"
3251 "`run_cell_async` will not call `transform_cell`"
3252 " automatically in the future. Please pass the result to"
3252 " automatically in the future. Please pass the result to"
3253 " `transformed_cell` argument and any exception that happen"
3253 " `transformed_cell` argument and any exception that happen"
3254 " during the"
3254 " during the"
3255 "transform in `preprocessing_exc_tuple` in"
3255 "transform in `preprocessing_exc_tuple` in"
3256 " IPython 7.17 and above.",
3256 " IPython 7.17 and above.",
3257 DeprecationWarning,
3257 DeprecationWarning,
3258 stacklevel=2,
3258 stacklevel=2,
3259 )
3259 )
3260 # If any of our input transformation (input_transformer_manager or
3260 # If any of our input transformation (input_transformer_manager or
3261 # prefilter_manager) raises an exception, we store it in this variable
3261 # prefilter_manager) raises an exception, we store it in this variable
3262 # so that we can display the error after logging the input and storing
3262 # so that we can display the error after logging the input and storing
3263 # it in the history.
3263 # it in the history.
3264 try:
3264 try:
3265 cell = self.transform_cell(raw_cell)
3265 cell = self.transform_cell(raw_cell)
3266 except Exception:
3266 except Exception:
3267 preprocessing_exc_tuple = sys.exc_info()
3267 preprocessing_exc_tuple = sys.exc_info()
3268 cell = raw_cell # cell has to exist so it can be stored/logged
3268 cell = raw_cell # cell has to exist so it can be stored/logged
3269 else:
3269 else:
3270 preprocessing_exc_tuple = None
3270 preprocessing_exc_tuple = None
3271 else:
3271 else:
3272 if preprocessing_exc_tuple is None:
3272 if preprocessing_exc_tuple is None:
3273 cell = transformed_cell
3273 cell = transformed_cell
3274 else:
3274 else:
3275 cell = raw_cell
3275 cell = raw_cell
3276
3276
3277 # Do NOT store paste/cpaste magic history
3277 # Do NOT store paste/cpaste magic history
3278 if "get_ipython().run_line_magic(" in cell and "paste" in cell:
3278 if "get_ipython().run_line_magic(" in cell and "paste" in cell:
3279 store_history = False
3279 store_history = False
3280
3280
3281 # Store raw and processed history
3281 # Store raw and processed history
3282 if store_history:
3282 if store_history:
3283 assert self.history_manager is not None
3283 assert self.history_manager is not None
3284 self.history_manager.store_inputs(self.execution_count, cell, raw_cell)
3284 self.history_manager.store_inputs(self.execution_count, cell, raw_cell)
3285 if not silent:
3285 if not silent:
3286 self.logger.log(cell, raw_cell)
3286 self.logger.log(cell, raw_cell)
3287
3287
3288 # Display the exception if input processing failed.
3288 # Display the exception if input processing failed.
3289 if preprocessing_exc_tuple is not None:
3289 if preprocessing_exc_tuple is not None:
3290 self.showtraceback(preprocessing_exc_tuple)
3290 self.showtraceback(preprocessing_exc_tuple)
3291 if store_history:
3291 if store_history:
3292 self.execution_count += 1
3292 self.execution_count += 1
3293 return error_before_exec(preprocessing_exc_tuple[1])
3293 return error_before_exec(preprocessing_exc_tuple[1])
3294
3294
3295 # Our own compiler remembers the __future__ environment. If we want to
3295 # Our own compiler remembers the __future__ environment. If we want to
3296 # run code with a separate __future__ environment, use the default
3296 # run code with a separate __future__ environment, use the default
3297 # compiler
3297 # compiler
3298 compiler = self.compile if shell_futures else self.compiler_class()
3298 compiler = self.compile if shell_futures else self.compiler_class()
3299
3299
3300 with self.builtin_trap:
3300 with self.builtin_trap:
3301 cell_name = compiler.cache(cell, self.execution_count, raw_code=raw_cell)
3301 cell_name = compiler.cache(cell, self.execution_count, raw_code=raw_cell)
3302
3302
3303 with self.display_trap:
3303 with self.display_trap:
3304 # Compile to bytecode
3304 # Compile to bytecode
3305 try:
3305 try:
3306 code_ast = compiler.ast_parse(cell, filename=cell_name)
3306 code_ast = compiler.ast_parse(cell, filename=cell_name)
3307 except self.custom_exceptions as e:
3307 except self.custom_exceptions as e:
3308 etype, value, tb = sys.exc_info()
3308 etype, value, tb = sys.exc_info()
3309 self.CustomTB(etype, value, tb)
3309 self.CustomTB(etype, value, tb)
3310 return error_before_exec(e)
3310 return error_before_exec(e)
3311 except IndentationError as e:
3311 except IndentationError as e:
3312 self.showindentationerror()
3312 self.showindentationerror()
3313 return error_before_exec(e)
3313 return error_before_exec(e)
3314 except (OverflowError, SyntaxError, ValueError, TypeError,
3314 except (OverflowError, SyntaxError, ValueError, TypeError,
3315 MemoryError) as e:
3315 MemoryError) as e:
3316 self.showsyntaxerror()
3316 self.showsyntaxerror()
3317 return error_before_exec(e)
3317 return error_before_exec(e)
3318
3318
3319 # Apply AST transformations
3319 # Apply AST transformations
3320 try:
3320 try:
3321 code_ast = self.transform_ast(code_ast)
3321 code_ast = self.transform_ast(code_ast)
3322 except InputRejected as e:
3322 except InputRejected as e:
3323 self.showtraceback()
3323 self.showtraceback()
3324 return error_before_exec(e)
3324 return error_before_exec(e)
3325
3325
3326 # Give the displayhook a reference to our ExecutionResult so it
3326 # Give the displayhook a reference to our ExecutionResult so it
3327 # can fill in the output value.
3327 # can fill in the output value.
3328 self.displayhook.exec_result = result
3328 self.displayhook.exec_result = result
3329
3329
3330 # Execute the user code
3330 # Execute the user code
3331 interactivity = "none" if silent else self.ast_node_interactivity
3331 interactivity = "none" if silent else self.ast_node_interactivity
3332
3332
3333
3333
3334 has_raised = await self.run_ast_nodes(code_ast.body, cell_name,
3334 has_raised = await self.run_ast_nodes(code_ast.body, cell_name,
3335 interactivity=interactivity, compiler=compiler, result=result)
3335 interactivity=interactivity, compiler=compiler, result=result)
3336
3336
3337 self.last_execution_succeeded = not has_raised
3337 self.last_execution_succeeded = not has_raised
3338 self.last_execution_result = result
3338 self.last_execution_result = result
3339
3339
3340 # Reset this so later displayed values do not modify the
3340 # Reset this so later displayed values do not modify the
3341 # ExecutionResult
3341 # ExecutionResult
3342 self.displayhook.exec_result = None
3342 self.displayhook.exec_result = None
3343
3343
3344 if store_history:
3344 if store_history:
3345 assert self.history_manager is not None
3345 assert self.history_manager is not None
3346 # Write output to the database. Does nothing unless
3346 # Write output to the database. Does nothing unless
3347 # history output logging is enabled.
3347 # history output logging is enabled.
3348 self.history_manager.store_output(self.execution_count)
3348 self.history_manager.store_output(self.execution_count)
3349 # Each cell is a *single* input, regardless of how many lines it has
3349 # Each cell is a *single* input, regardless of how many lines it has
3350 self.execution_count += 1
3350 self.execution_count += 1
3351
3351
3352 return result
3352 return result
3353
3353
3354 def transform_cell(self, raw_cell):
3354 def transform_cell(self, raw_cell):
3355 """Transform an input cell before parsing it.
3355 """Transform an input cell before parsing it.
3356
3356
3357 Static transformations, implemented in IPython.core.inputtransformer2,
3357 Static transformations, implemented in IPython.core.inputtransformer2,
3358 deal with things like ``%magic`` and ``!system`` commands.
3358 deal with things like ``%magic`` and ``!system`` commands.
3359 These run on all input.
3359 These run on all input.
3360 Dynamic transformations, for things like unescaped magics and the exit
3360 Dynamic transformations, for things like unescaped magics and the exit
3361 autocall, depend on the state of the interpreter.
3361 autocall, depend on the state of the interpreter.
3362 These only apply to single line inputs.
3362 These only apply to single line inputs.
3363
3363
3364 These string-based transformations are followed by AST transformations;
3364 These string-based transformations are followed by AST transformations;
3365 see :meth:`transform_ast`.
3365 see :meth:`transform_ast`.
3366 """
3366 """
3367 # Static input transformations
3367 # Static input transformations
3368 cell = self.input_transformer_manager.transform_cell(raw_cell)
3368 cell = self.input_transformer_manager.transform_cell(raw_cell)
3369
3369
3370 if len(cell.splitlines()) == 1:
3370 if len(cell.splitlines()) == 1:
3371 # Dynamic transformations - only applied for single line commands
3371 # Dynamic transformations - only applied for single line commands
3372 with self.builtin_trap:
3372 with self.builtin_trap:
3373 # use prefilter_lines to handle trailing newlines
3373 # use prefilter_lines to handle trailing newlines
3374 # restore trailing newline for ast.parse
3374 # restore trailing newline for ast.parse
3375 cell = self.prefilter_manager.prefilter_lines(cell) + '\n'
3375 cell = self.prefilter_manager.prefilter_lines(cell) + '\n'
3376
3376
3377 lines = cell.splitlines(keepends=True)
3377 lines = cell.splitlines(keepends=True)
3378 for transform in self.input_transformers_post:
3378 for transform in self.input_transformers_post:
3379 lines = transform(lines)
3379 lines = transform(lines)
3380 cell = ''.join(lines)
3380 cell = ''.join(lines)
3381
3381
3382 return cell
3382 return cell
3383
3383
3384 def transform_ast(self, node):
3384 def transform_ast(self, node):
3385 """Apply the AST transformations from self.ast_transformers
3385 """Apply the AST transformations from self.ast_transformers
3386
3386
3387 Parameters
3387 Parameters
3388 ----------
3388 ----------
3389 node : ast.Node
3389 node : ast.Node
3390 The root node to be transformed. Typically called with the ast.Module
3390 The root node to be transformed. Typically called with the ast.Module
3391 produced by parsing user input.
3391 produced by parsing user input.
3392
3392
3393 Returns
3393 Returns
3394 -------
3394 -------
3395 An ast.Node corresponding to the node it was called with. Note that it
3395 An ast.Node corresponding to the node it was called with. Note that it
3396 may also modify the passed object, so don't rely on references to the
3396 may also modify the passed object, so don't rely on references to the
3397 original AST.
3397 original AST.
3398 """
3398 """
3399 for transformer in self.ast_transformers:
3399 for transformer in self.ast_transformers:
3400 try:
3400 try:
3401 node = transformer.visit(node)
3401 node = transformer.visit(node)
3402 except InputRejected:
3402 except InputRejected:
3403 # User-supplied AST transformers can reject an input by raising
3403 # User-supplied AST transformers can reject an input by raising
3404 # an InputRejected. Short-circuit in this case so that we
3404 # an InputRejected. Short-circuit in this case so that we
3405 # don't unregister the transform.
3405 # don't unregister the transform.
3406 raise
3406 raise
3407 except Exception as e:
3407 except Exception as e:
3408 warn(
3408 warn(
3409 "AST transformer %r threw an error. It will be unregistered. %s"
3409 "AST transformer %r threw an error. It will be unregistered. %s"
3410 % (transformer, e)
3410 % (transformer, e)
3411 )
3411 )
3412 self.ast_transformers.remove(transformer)
3412 self.ast_transformers.remove(transformer)
3413
3413
3414 if self.ast_transformers:
3414 if self.ast_transformers:
3415 ast.fix_missing_locations(node)
3415 ast.fix_missing_locations(node)
3416 return node
3416 return node
3417
3417
3418 async def run_ast_nodes(
3418 async def run_ast_nodes(
3419 self,
3419 self,
3420 nodelist: ListType[stmt],
3420 nodelist: ListType[stmt],
3421 cell_name: str,
3421 cell_name: str,
3422 interactivity="last_expr",
3422 interactivity="last_expr",
3423 compiler=compile,
3423 compiler=compile,
3424 result=None,
3424 result=None,
3425 ):
3425 ):
3426 """Run a sequence of AST nodes. The execution mode depends on the
3426 """Run a sequence of AST nodes. The execution mode depends on the
3427 interactivity parameter.
3427 interactivity parameter.
3428
3428
3429 Parameters
3429 Parameters
3430 ----------
3430 ----------
3431 nodelist : list
3431 nodelist : list
3432 A sequence of AST nodes to run.
3432 A sequence of AST nodes to run.
3433 cell_name : str
3433 cell_name : str
3434 Will be passed to the compiler as the filename of the cell. Typically
3434 Will be passed to the compiler as the filename of the cell. Typically
3435 the value returned by ip.compile.cache(cell).
3435 the value returned by ip.compile.cache(cell).
3436 interactivity : str
3436 interactivity : str
3437 'all', 'last', 'last_expr' , 'last_expr_or_assign' or 'none',
3437 'all', 'last', 'last_expr' , 'last_expr_or_assign' or 'none',
3438 specifying which nodes should be run interactively (displaying output
3438 specifying which nodes should be run interactively (displaying output
3439 from expressions). 'last_expr' will run the last node interactively
3439 from expressions). 'last_expr' will run the last node interactively
3440 only if it is an expression (i.e. expressions in loops or other blocks
3440 only if it is an expression (i.e. expressions in loops or other blocks
3441 are not displayed) 'last_expr_or_assign' will run the last expression
3441 are not displayed) 'last_expr_or_assign' will run the last expression
3442 or the last assignment. Other values for this parameter will raise a
3442 or the last assignment. Other values for this parameter will raise a
3443 ValueError.
3443 ValueError.
3444
3444
3445 compiler : callable
3445 compiler : callable
3446 A function with the same interface as the built-in compile(), to turn
3446 A function with the same interface as the built-in compile(), to turn
3447 the AST nodes into code objects. Default is the built-in compile().
3447 the AST nodes into code objects. Default is the built-in compile().
3448 result : ExecutionResult, optional
3448 result : ExecutionResult, optional
3449 An object to store exceptions that occur during execution.
3449 An object to store exceptions that occur during execution.
3450
3450
3451 Returns
3451 Returns
3452 -------
3452 -------
3453 True if an exception occurred while running code, False if it finished
3453 True if an exception occurred while running code, False if it finished
3454 running.
3454 running.
3455 """
3455 """
3456 if not nodelist:
3456 if not nodelist:
3457 return
3457 return
3458
3458
3459
3459
3460 if interactivity == 'last_expr_or_assign':
3460 if interactivity == 'last_expr_or_assign':
3461 if isinstance(nodelist[-1], _assign_nodes):
3461 if isinstance(nodelist[-1], _assign_nodes):
3462 asg = nodelist[-1]
3462 asg = nodelist[-1]
3463 if isinstance(asg, ast.Assign) and len(asg.targets) == 1:
3463 if isinstance(asg, ast.Assign) and len(asg.targets) == 1:
3464 target = asg.targets[0]
3464 target = asg.targets[0]
3465 elif isinstance(asg, _single_targets_nodes):
3465 elif isinstance(asg, _single_targets_nodes):
3466 target = asg.target
3466 target = asg.target
3467 else:
3467 else:
3468 target = None
3468 target = None
3469 if isinstance(target, ast.Name):
3469 if isinstance(target, ast.Name):
3470 nnode = ast.Expr(ast.Name(target.id, ast.Load()))
3470 nnode = ast.Expr(ast.Name(target.id, ast.Load()))
3471 ast.fix_missing_locations(nnode)
3471 ast.fix_missing_locations(nnode)
3472 nodelist.append(nnode)
3472 nodelist.append(nnode)
3473 interactivity = 'last_expr'
3473 interactivity = 'last_expr'
3474
3474
3475 _async = False
3475 _async = False
3476 if interactivity == 'last_expr':
3476 if interactivity == 'last_expr':
3477 if isinstance(nodelist[-1], ast.Expr):
3477 if isinstance(nodelist[-1], ast.Expr):
3478 interactivity = "last"
3478 interactivity = "last"
3479 else:
3479 else:
3480 interactivity = "none"
3480 interactivity = "none"
3481
3481
3482 if interactivity == 'none':
3482 if interactivity == 'none':
3483 to_run_exec, to_run_interactive = nodelist, []
3483 to_run_exec, to_run_interactive = nodelist, []
3484 elif interactivity == 'last':
3484 elif interactivity == 'last':
3485 to_run_exec, to_run_interactive = nodelist[:-1], nodelist[-1:]
3485 to_run_exec, to_run_interactive = nodelist[:-1], nodelist[-1:]
3486 elif interactivity == 'all':
3486 elif interactivity == 'all':
3487 to_run_exec, to_run_interactive = [], nodelist
3487 to_run_exec, to_run_interactive = [], nodelist
3488 else:
3488 else:
3489 raise ValueError("Interactivity was %r" % interactivity)
3489 raise ValueError("Interactivity was %r" % interactivity)
3490
3490
3491 try:
3491 try:
3492
3492
3493 def compare(code):
3493 def compare(code):
3494 is_async = inspect.CO_COROUTINE & code.co_flags == inspect.CO_COROUTINE
3494 is_async = inspect.CO_COROUTINE & code.co_flags == inspect.CO_COROUTINE
3495 return is_async
3495 return is_async
3496
3496
3497 # refactor that to just change the mod constructor.
3497 # refactor that to just change the mod constructor.
3498 to_run = []
3498 to_run = []
3499 for node in to_run_exec:
3499 for node in to_run_exec:
3500 to_run.append((node, "exec"))
3500 to_run.append((node, "exec"))
3501
3501
3502 for node in to_run_interactive:
3502 for node in to_run_interactive:
3503 to_run.append((node, "single"))
3503 to_run.append((node, "single"))
3504
3504
3505 for node, mode in to_run:
3505 for node, mode in to_run:
3506 if mode == "exec":
3506 if mode == "exec":
3507 mod = Module([node], [])
3507 mod = Module([node], [])
3508 elif mode == "single":
3508 elif mode == "single":
3509 mod = ast.Interactive([node]) # type: ignore
3509 mod = ast.Interactive([node]) # type: ignore
3510 with compiler.extra_flags(
3510 with compiler.extra_flags(
3511 getattr(ast, "PyCF_ALLOW_TOP_LEVEL_AWAIT", 0x0)
3511 getattr(ast, "PyCF_ALLOW_TOP_LEVEL_AWAIT", 0x0)
3512 if self.autoawait
3512 if self.autoawait
3513 else 0x0
3513 else 0x0
3514 ):
3514 ):
3515 code = compiler(mod, cell_name, mode)
3515 code = compiler(mod, cell_name, mode)
3516 asy = compare(code)
3516 asy = compare(code)
3517 if await self.run_code(code, result, async_=asy):
3517 if await self.run_code(code, result, async_=asy):
3518 return True
3518 return True
3519
3519
3520 # Flush softspace
3520 # Flush softspace
3521 if softspace(sys.stdout, 0):
3521 if softspace(sys.stdout, 0):
3522 print()
3522 print()
3523
3523
3524 except:
3524 except:
3525 # It's possible to have exceptions raised here, typically by
3525 # It's possible to have exceptions raised here, typically by
3526 # compilation of odd code (such as a naked 'return' outside a
3526 # compilation of odd code (such as a naked 'return' outside a
3527 # function) that did parse but isn't valid. Typically the exception
3527 # function) that did parse but isn't valid. Typically the exception
3528 # is a SyntaxError, but it's safest just to catch anything and show
3528 # is a SyntaxError, but it's safest just to catch anything and show
3529 # the user a traceback.
3529 # the user a traceback.
3530
3530
3531 # We do only one try/except outside the loop to minimize the impact
3531 # We do only one try/except outside the loop to minimize the impact
3532 # on runtime, and also because if any node in the node list is
3532 # on runtime, and also because if any node in the node list is
3533 # broken, we should stop execution completely.
3533 # broken, we should stop execution completely.
3534 if result:
3534 if result:
3535 result.error_before_exec = sys.exc_info()[1]
3535 result.error_before_exec = sys.exc_info()[1]
3536 self.showtraceback()
3536 self.showtraceback()
3537 return True
3537 return True
3538
3538
3539 return False
3539 return False
3540
3540
3541 async def run_code(self, code_obj, result=None, *, async_=False):
3541 async def run_code(self, code_obj, result=None, *, async_=False):
3542 """Execute a code object.
3542 """Execute a code object.
3543
3543
3544 When an exception occurs, self.showtraceback() is called to display a
3544 When an exception occurs, self.showtraceback() is called to display a
3545 traceback.
3545 traceback.
3546
3546
3547 Parameters
3547 Parameters
3548 ----------
3548 ----------
3549 code_obj : code object
3549 code_obj : code object
3550 A compiled code object, to be executed
3550 A compiled code object, to be executed
3551 result : ExecutionResult, optional
3551 result : ExecutionResult, optional
3552 An object to store exceptions that occur during execution.
3552 An object to store exceptions that occur during execution.
3553 async_ : Bool (Experimental)
3553 async_ : Bool (Experimental)
3554 Attempt to run top-level asynchronous code in a default loop.
3554 Attempt to run top-level asynchronous code in a default loop.
3555
3555
3556 Returns
3556 Returns
3557 -------
3557 -------
3558 False : successful execution.
3558 False : successful execution.
3559 True : an error occurred.
3559 True : an error occurred.
3560 """
3560 """
3561 # special value to say that anything above is IPython and should be
3561 # special value to say that anything above is IPython and should be
3562 # hidden.
3562 # hidden.
3563 __tracebackhide__ = "__ipython_bottom__"
3563 __tracebackhide__ = "__ipython_bottom__"
3564 # Set our own excepthook in case the user code tries to call it
3564 # Set our own excepthook in case the user code tries to call it
3565 # directly, so that the IPython crash handler doesn't get triggered
3565 # directly, so that the IPython crash handler doesn't get triggered
3566 old_excepthook, sys.excepthook = sys.excepthook, self.excepthook
3566 old_excepthook, sys.excepthook = sys.excepthook, self.excepthook
3567
3567
3568 # we save the original sys.excepthook in the instance, in case config
3568 # we save the original sys.excepthook in the instance, in case config
3569 # code (such as magics) needs access to it.
3569 # code (such as magics) needs access to it.
3570 self.sys_excepthook = old_excepthook
3570 self.sys_excepthook = old_excepthook
3571 outflag = True # happens in more places, so it's easier as default
3571 outflag = True # happens in more places, so it's easier as default
3572 try:
3572 try:
3573 try:
3573 try:
3574 if async_:
3574 if async_:
3575 await eval(code_obj, self.user_global_ns, self.user_ns)
3575 await eval(code_obj, self.user_global_ns, self.user_ns)
3576 else:
3576 else:
3577 exec(code_obj, self.user_global_ns, self.user_ns)
3577 exec(code_obj, self.user_global_ns, self.user_ns)
3578 finally:
3578 finally:
3579 # Reset our crash handler in place
3579 # Reset our crash handler in place
3580 sys.excepthook = old_excepthook
3580 sys.excepthook = old_excepthook
3581 except SystemExit as e:
3581 except SystemExit as e:
3582 if result is not None:
3582 if result is not None:
3583 result.error_in_exec = e
3583 result.error_in_exec = e
3584 self.showtraceback(exception_only=True)
3584 self.showtraceback(exception_only=True)
3585 warn("To exit: use 'exit', 'quit', or Ctrl-D.", stacklevel=1)
3585 warn("To exit: use 'exit', 'quit', or Ctrl-D.", stacklevel=1)
3586 except bdb.BdbQuit:
3586 except bdb.BdbQuit:
3587 etype, value, tb = sys.exc_info()
3587 etype, value, tb = sys.exc_info()
3588 if result is not None:
3588 if result is not None:
3589 result.error_in_exec = value
3589 result.error_in_exec = value
3590 # the BdbQuit stops here
3590 # the BdbQuit stops here
3591 except self.custom_exceptions:
3591 except self.custom_exceptions:
3592 etype, value, tb = sys.exc_info()
3592 etype, value, tb = sys.exc_info()
3593 if result is not None:
3593 if result is not None:
3594 result.error_in_exec = value
3594 result.error_in_exec = value
3595 self.CustomTB(etype, value, tb)
3595 self.CustomTB(etype, value, tb)
3596 except:
3596 except:
3597 if result is not None:
3597 if result is not None:
3598 result.error_in_exec = sys.exc_info()[1]
3598 result.error_in_exec = sys.exc_info()[1]
3599 self.showtraceback(running_compiled_code=True)
3599 self.showtraceback(running_compiled_code=True)
3600 else:
3600 else:
3601 outflag = False
3601 outflag = False
3602 return outflag
3602 return outflag
3603
3603
3604 # For backwards compatibility
3604 # For backwards compatibility
3605 runcode = run_code
3605 runcode = run_code
3606
3606
3607 def check_complete(self, code: str) -> Tuple[str, str]:
3607 def check_complete(self, code: str) -> Tuple[str, str]:
3608 """Return whether a block of code is ready to execute, or should be continued
3608 """Return whether a block of code is ready to execute, or should be continued
3609
3609
3610 Parameters
3610 Parameters
3611 ----------
3611 ----------
3612 code : string
3612 code : string
3613 Python input code, which can be multiline.
3613 Python input code, which can be multiline.
3614
3614
3615 Returns
3615 Returns
3616 -------
3616 -------
3617 status : str
3617 status : str
3618 One of 'complete', 'incomplete', or 'invalid' if source is not a
3618 One of 'complete', 'incomplete', or 'invalid' if source is not a
3619 prefix of valid code.
3619 prefix of valid code.
3620 indent : str
3620 indent : str
3621 When status is 'incomplete', this is some whitespace to insert on
3621 When status is 'incomplete', this is some whitespace to insert on
3622 the next line of the prompt.
3622 the next line of the prompt.
3623 """
3623 """
3624 status, nspaces = self.input_transformer_manager.check_complete(code)
3624 status, nspaces = self.input_transformer_manager.check_complete(code)
3625 return status, ' ' * (nspaces or 0)
3625 return status, ' ' * (nspaces or 0)
3626
3626
3627 #-------------------------------------------------------------------------
3627 #-------------------------------------------------------------------------
3628 # Things related to GUI support and pylab
3628 # Things related to GUI support and pylab
3629 #-------------------------------------------------------------------------
3629 #-------------------------------------------------------------------------
3630
3630
3631 active_eventloop: Optional[str] = None
3631 active_eventloop: Optional[str] = None
3632
3632
3633 def enable_gui(self, gui=None):
3633 def enable_gui(self, gui=None):
3634 raise NotImplementedError('Implement enable_gui in a subclass')
3634 raise NotImplementedError('Implement enable_gui in a subclass')
3635
3635
3636 def enable_matplotlib(self, gui=None):
3636 def enable_matplotlib(self, gui=None):
3637 """Enable interactive matplotlib and inline figure support.
3637 """Enable interactive matplotlib and inline figure support.
3638
3638
3639 This takes the following steps:
3639 This takes the following steps:
3640
3640
3641 1. select the appropriate eventloop and matplotlib backend
3641 1. select the appropriate eventloop and matplotlib backend
3642 2. set up matplotlib for interactive use with that backend
3642 2. set up matplotlib for interactive use with that backend
3643 3. configure formatters for inline figure display
3643 3. configure formatters for inline figure display
3644 4. enable the selected gui eventloop
3644 4. enable the selected gui eventloop
3645
3645
3646 Parameters
3646 Parameters
3647 ----------
3647 ----------
3648 gui : optional, string
3648 gui : optional, string
3649 If given, dictates the choice of matplotlib GUI backend to use
3649 If given, dictates the choice of matplotlib GUI backend to use
3650 (should be one of IPython's supported backends, 'qt', 'osx', 'tk',
3650 (should be one of IPython's supported backends, 'qt', 'osx', 'tk',
3651 'gtk', 'wx' or 'inline'), otherwise we use the default chosen by
3651 'gtk', 'wx' or 'inline'), otherwise we use the default chosen by
3652 matplotlib (as dictated by the matplotlib build-time options plus the
3652 matplotlib (as dictated by the matplotlib build-time options plus the
3653 user's matplotlibrc configuration file). Note that not all backends
3653 user's matplotlibrc configuration file). Note that not all backends
3654 make sense in all contexts, for example a terminal ipython can't
3654 make sense in all contexts, for example a terminal ipython can't
3655 display figures inline.
3655 display figures inline.
3656 """
3656 """
3657 from IPython.core import pylabtools as pt
3657 from IPython.core import pylabtools as pt
3658 gui, backend = pt.find_gui_and_backend(gui, self.pylab_gui_select)
3658 gui, backend = pt.find_gui_and_backend(gui, self.pylab_gui_select)
3659
3659
3660 if gui != 'inline':
3660 if gui != None:
3661 # If we have our first gui selection, store it
3661 # If we have our first gui selection, store it
3662 if self.pylab_gui_select is None:
3662 if self.pylab_gui_select is None:
3663 self.pylab_gui_select = gui
3663 self.pylab_gui_select = gui
3664 # Otherwise if they are different
3664 # Otherwise if they are different
3665 elif gui != self.pylab_gui_select:
3665 elif gui != self.pylab_gui_select:
3666 print('Warning: Cannot change to a different GUI toolkit: %s.'
3666 print('Warning: Cannot change to a different GUI toolkit: %s.'
3667 ' Using %s instead.' % (gui, self.pylab_gui_select))
3667 ' Using %s instead.' % (gui, self.pylab_gui_select))
3668 gui, backend = pt.find_gui_and_backend(self.pylab_gui_select)
3668 gui, backend = pt.find_gui_and_backend(self.pylab_gui_select)
3669
3669
3670 pt.activate_matplotlib(backend)
3670 pt.activate_matplotlib(backend)
3671
3671
3672 from matplotlib_inline.backend_inline import configure_inline_support
3672 from matplotlib_inline.backend_inline import configure_inline_support
3673
3673
3674 configure_inline_support(self, backend)
3674 configure_inline_support(self, backend)
3675
3675
3676 # Now we must activate the gui pylab wants to use, and fix %run to take
3676 # Now we must activate the gui pylab wants to use, and fix %run to take
3677 # plot updates into account
3677 # plot updates into account
3678 self.enable_gui(gui)
3678 self.enable_gui(gui)
3679 self.magics_manager.registry['ExecutionMagics'].default_runner = \
3679 self.magics_manager.registry['ExecutionMagics'].default_runner = \
3680 pt.mpl_runner(self.safe_execfile)
3680 pt.mpl_runner(self.safe_execfile)
3681
3681
3682 return gui, backend
3682 return gui, backend
3683
3683
3684 def enable_pylab(self, gui=None, import_all=True, welcome_message=False):
3684 def enable_pylab(self, gui=None, import_all=True, welcome_message=False):
3685 """Activate pylab support at runtime.
3685 """Activate pylab support at runtime.
3686
3686
3687 This turns on support for matplotlib, preloads into the interactive
3687 This turns on support for matplotlib, preloads into the interactive
3688 namespace all of numpy and pylab, and configures IPython to correctly
3688 namespace all of numpy and pylab, and configures IPython to correctly
3689 interact with the GUI event loop. The GUI backend to be used can be
3689 interact with the GUI event loop. The GUI backend to be used can be
3690 optionally selected with the optional ``gui`` argument.
3690 optionally selected with the optional ``gui`` argument.
3691
3691
3692 This method only adds preloading the namespace to InteractiveShell.enable_matplotlib.
3692 This method only adds preloading the namespace to InteractiveShell.enable_matplotlib.
3693
3693
3694 Parameters
3694 Parameters
3695 ----------
3695 ----------
3696 gui : optional, string
3696 gui : optional, string
3697 If given, dictates the choice of matplotlib GUI backend to use
3697 If given, dictates the choice of matplotlib GUI backend to use
3698 (should be one of IPython's supported backends, 'qt', 'osx', 'tk',
3698 (should be one of IPython's supported backends, 'qt', 'osx', 'tk',
3699 'gtk', 'wx' or 'inline'), otherwise we use the default chosen by
3699 'gtk', 'wx' or 'inline'), otherwise we use the default chosen by
3700 matplotlib (as dictated by the matplotlib build-time options plus the
3700 matplotlib (as dictated by the matplotlib build-time options plus the
3701 user's matplotlibrc configuration file). Note that not all backends
3701 user's matplotlibrc configuration file). Note that not all backends
3702 make sense in all contexts, for example a terminal ipython can't
3702 make sense in all contexts, for example a terminal ipython can't
3703 display figures inline.
3703 display figures inline.
3704 import_all : optional, bool, default: True
3704 import_all : optional, bool, default: True
3705 Whether to do `from numpy import *` and `from pylab import *`
3705 Whether to do `from numpy import *` and `from pylab import *`
3706 in addition to module imports.
3706 in addition to module imports.
3707 welcome_message : deprecated
3707 welcome_message : deprecated
3708 This argument is ignored, no welcome message will be displayed.
3708 This argument is ignored, no welcome message will be displayed.
3709 """
3709 """
3710 from IPython.core.pylabtools import import_pylab
3710 from IPython.core.pylabtools import import_pylab
3711
3711
3712 gui, backend = self.enable_matplotlib(gui)
3712 gui, backend = self.enable_matplotlib(gui)
3713
3713
3714 # We want to prevent the loading of pylab to pollute the user's
3714 # We want to prevent the loading of pylab to pollute the user's
3715 # namespace as shown by the %who* magics, so we execute the activation
3715 # namespace as shown by the %who* magics, so we execute the activation
3716 # code in an empty namespace, and we update *both* user_ns and
3716 # code in an empty namespace, and we update *both* user_ns and
3717 # user_ns_hidden with this information.
3717 # user_ns_hidden with this information.
3718 ns = {}
3718 ns = {}
3719 import_pylab(ns, import_all)
3719 import_pylab(ns, import_all)
3720 # warn about clobbered names
3720 # warn about clobbered names
3721 ignored = {"__builtins__"}
3721 ignored = {"__builtins__"}
3722 both = set(ns).intersection(self.user_ns).difference(ignored)
3722 both = set(ns).intersection(self.user_ns).difference(ignored)
3723 clobbered = [ name for name in both if self.user_ns[name] is not ns[name] ]
3723 clobbered = [ name for name in both if self.user_ns[name] is not ns[name] ]
3724 self.user_ns.update(ns)
3724 self.user_ns.update(ns)
3725 self.user_ns_hidden.update(ns)
3725 self.user_ns_hidden.update(ns)
3726 return gui, backend, clobbered
3726 return gui, backend, clobbered
3727
3727
3728 #-------------------------------------------------------------------------
3728 #-------------------------------------------------------------------------
3729 # Utilities
3729 # Utilities
3730 #-------------------------------------------------------------------------
3730 #-------------------------------------------------------------------------
3731
3731
3732 def var_expand(self, cmd, depth=0, formatter=DollarFormatter()):
3732 def var_expand(self, cmd, depth=0, formatter=DollarFormatter()):
3733 """Expand python variables in a string.
3733 """Expand python variables in a string.
3734
3734
3735 The depth argument indicates how many frames above the caller should
3735 The depth argument indicates how many frames above the caller should
3736 be walked to look for the local namespace where to expand variables.
3736 be walked to look for the local namespace where to expand variables.
3737
3737
3738 The global namespace for expansion is always the user's interactive
3738 The global namespace for expansion is always the user's interactive
3739 namespace.
3739 namespace.
3740 """
3740 """
3741 ns = self.user_ns.copy()
3741 ns = self.user_ns.copy()
3742 try:
3742 try:
3743 frame = sys._getframe(depth+1)
3743 frame = sys._getframe(depth+1)
3744 except ValueError:
3744 except ValueError:
3745 # This is thrown if there aren't that many frames on the stack,
3745 # This is thrown if there aren't that many frames on the stack,
3746 # e.g. if a script called run_line_magic() directly.
3746 # e.g. if a script called run_line_magic() directly.
3747 pass
3747 pass
3748 else:
3748 else:
3749 ns.update(frame.f_locals)
3749 ns.update(frame.f_locals)
3750
3750
3751 try:
3751 try:
3752 # We have to use .vformat() here, because 'self' is a valid and common
3752 # We have to use .vformat() here, because 'self' is a valid and common
3753 # name, and expanding **ns for .format() would make it collide with
3753 # name, and expanding **ns for .format() would make it collide with
3754 # the 'self' argument of the method.
3754 # the 'self' argument of the method.
3755 cmd = formatter.vformat(cmd, args=[], kwargs=ns)
3755 cmd = formatter.vformat(cmd, args=[], kwargs=ns)
3756 except Exception:
3756 except Exception:
3757 # if formatter couldn't format, just let it go untransformed
3757 # if formatter couldn't format, just let it go untransformed
3758 pass
3758 pass
3759 return cmd
3759 return cmd
3760
3760
3761 def mktempfile(self, data=None, prefix='ipython_edit_'):
3761 def mktempfile(self, data=None, prefix='ipython_edit_'):
3762 """Make a new tempfile and return its filename.
3762 """Make a new tempfile and return its filename.
3763
3763
3764 This makes a call to tempfile.mkstemp (created in a tempfile.mkdtemp),
3764 This makes a call to tempfile.mkstemp (created in a tempfile.mkdtemp),
3765 but it registers the created filename internally so ipython cleans it up
3765 but it registers the created filename internally so ipython cleans it up
3766 at exit time.
3766 at exit time.
3767
3767
3768 Optional inputs:
3768 Optional inputs:
3769
3769
3770 - data(None): if data is given, it gets written out to the temp file
3770 - data(None): if data is given, it gets written out to the temp file
3771 immediately, and the file is closed again."""
3771 immediately, and the file is closed again."""
3772
3772
3773 dir_path = Path(tempfile.mkdtemp(prefix=prefix))
3773 dir_path = Path(tempfile.mkdtemp(prefix=prefix))
3774 self.tempdirs.append(dir_path)
3774 self.tempdirs.append(dir_path)
3775
3775
3776 handle, filename = tempfile.mkstemp(".py", prefix, dir=str(dir_path))
3776 handle, filename = tempfile.mkstemp(".py", prefix, dir=str(dir_path))
3777 os.close(handle) # On Windows, there can only be one open handle on a file
3777 os.close(handle) # On Windows, there can only be one open handle on a file
3778
3778
3779 file_path = Path(filename)
3779 file_path = Path(filename)
3780 self.tempfiles.append(file_path)
3780 self.tempfiles.append(file_path)
3781
3781
3782 if data:
3782 if data:
3783 file_path.write_text(data, encoding="utf-8")
3783 file_path.write_text(data, encoding="utf-8")
3784 return filename
3784 return filename
3785
3785
3786 def ask_yes_no(self, prompt, default=None, interrupt=None):
3786 def ask_yes_no(self, prompt, default=None, interrupt=None):
3787 if self.quiet:
3787 if self.quiet:
3788 return True
3788 return True
3789 return ask_yes_no(prompt,default,interrupt)
3789 return ask_yes_no(prompt,default,interrupt)
3790
3790
3791 def show_usage(self):
3791 def show_usage(self):
3792 """Show a usage message"""
3792 """Show a usage message"""
3793 page.page(IPython.core.usage.interactive_usage)
3793 page.page(IPython.core.usage.interactive_usage)
3794
3794
3795 def extract_input_lines(self, range_str, raw=False):
3795 def extract_input_lines(self, range_str, raw=False):
3796 """Return as a string a set of input history slices.
3796 """Return as a string a set of input history slices.
3797
3797
3798 Parameters
3798 Parameters
3799 ----------
3799 ----------
3800 range_str : str
3800 range_str : str
3801 The set of slices is given as a string, like "~5/6-~4/2 4:8 9",
3801 The set of slices is given as a string, like "~5/6-~4/2 4:8 9",
3802 since this function is for use by magic functions which get their
3802 since this function is for use by magic functions which get their
3803 arguments as strings. The number before the / is the session
3803 arguments as strings. The number before the / is the session
3804 number: ~n goes n back from the current session.
3804 number: ~n goes n back from the current session.
3805
3805
3806 If empty string is given, returns history of current session
3806 If empty string is given, returns history of current session
3807 without the last input.
3807 without the last input.
3808
3808
3809 raw : bool, optional
3809 raw : bool, optional
3810 By default, the processed input is used. If this is true, the raw
3810 By default, the processed input is used. If this is true, the raw
3811 input history is used instead.
3811 input history is used instead.
3812
3812
3813 Notes
3813 Notes
3814 -----
3814 -----
3815 Slices can be described with two notations:
3815 Slices can be described with two notations:
3816
3816
3817 * ``N:M`` -> standard python form, means including items N...(M-1).
3817 * ``N:M`` -> standard python form, means including items N...(M-1).
3818 * ``N-M`` -> include items N..M (closed endpoint).
3818 * ``N-M`` -> include items N..M (closed endpoint).
3819 """
3819 """
3820 lines = self.history_manager.get_range_by_str(range_str, raw=raw)
3820 lines = self.history_manager.get_range_by_str(range_str, raw=raw)
3821 text = "\n".join(x for _, _, x in lines)
3821 text = "\n".join(x for _, _, x in lines)
3822
3822
3823 # Skip the last line, as it's probably the magic that called this
3823 # Skip the last line, as it's probably the magic that called this
3824 if not range_str:
3824 if not range_str:
3825 if "\n" not in text:
3825 if "\n" not in text:
3826 text = ""
3826 text = ""
3827 else:
3827 else:
3828 text = text[: text.rfind("\n")]
3828 text = text[: text.rfind("\n")]
3829
3829
3830 return text
3830 return text
3831
3831
3832 def find_user_code(self, target, raw=True, py_only=False, skip_encoding_cookie=True, search_ns=False):
3832 def find_user_code(self, target, raw=True, py_only=False, skip_encoding_cookie=True, search_ns=False):
3833 """Get a code string from history, file, url, or a string or macro.
3833 """Get a code string from history, file, url, or a string or macro.
3834
3834
3835 This is mainly used by magic functions.
3835 This is mainly used by magic functions.
3836
3836
3837 Parameters
3837 Parameters
3838 ----------
3838 ----------
3839 target : str
3839 target : str
3840 A string specifying code to retrieve. This will be tried respectively
3840 A string specifying code to retrieve. This will be tried respectively
3841 as: ranges of input history (see %history for syntax), url,
3841 as: ranges of input history (see %history for syntax), url,
3842 corresponding .py file, filename, or an expression evaluating to a
3842 corresponding .py file, filename, or an expression evaluating to a
3843 string or Macro in the user namespace.
3843 string or Macro in the user namespace.
3844
3844
3845 If empty string is given, returns complete history of current
3845 If empty string is given, returns complete history of current
3846 session, without the last line.
3846 session, without the last line.
3847
3847
3848 raw : bool
3848 raw : bool
3849 If true (default), retrieve raw history. Has no effect on the other
3849 If true (default), retrieve raw history. Has no effect on the other
3850 retrieval mechanisms.
3850 retrieval mechanisms.
3851
3851
3852 py_only : bool (default False)
3852 py_only : bool (default False)
3853 Only try to fetch python code, do not try alternative methods to decode file
3853 Only try to fetch python code, do not try alternative methods to decode file
3854 if unicode fails.
3854 if unicode fails.
3855
3855
3856 Returns
3856 Returns
3857 -------
3857 -------
3858 A string of code.
3858 A string of code.
3859 ValueError is raised if nothing is found, and TypeError if it evaluates
3859 ValueError is raised if nothing is found, and TypeError if it evaluates
3860 to an object of another type. In each case, .args[0] is a printable
3860 to an object of another type. In each case, .args[0] is a printable
3861 message.
3861 message.
3862 """
3862 """
3863 code = self.extract_input_lines(target, raw=raw) # Grab history
3863 code = self.extract_input_lines(target, raw=raw) # Grab history
3864 if code:
3864 if code:
3865 return code
3865 return code
3866 try:
3866 try:
3867 if target.startswith(('http://', 'https://')):
3867 if target.startswith(('http://', 'https://')):
3868 return openpy.read_py_url(target, skip_encoding_cookie=skip_encoding_cookie)
3868 return openpy.read_py_url(target, skip_encoding_cookie=skip_encoding_cookie)
3869 except UnicodeDecodeError as e:
3869 except UnicodeDecodeError as e:
3870 if not py_only :
3870 if not py_only :
3871 # Deferred import
3871 # Deferred import
3872 from urllib.request import urlopen
3872 from urllib.request import urlopen
3873 response = urlopen(target)
3873 response = urlopen(target)
3874 return response.read().decode('latin1')
3874 return response.read().decode('latin1')
3875 raise ValueError(("'%s' seem to be unreadable.") % target) from e
3875 raise ValueError(("'%s' seem to be unreadable.") % target) from e
3876
3876
3877 potential_target = [target]
3877 potential_target = [target]
3878 try :
3878 try :
3879 potential_target.insert(0,get_py_filename(target))
3879 potential_target.insert(0,get_py_filename(target))
3880 except IOError:
3880 except IOError:
3881 pass
3881 pass
3882
3882
3883 for tgt in potential_target :
3883 for tgt in potential_target :
3884 if os.path.isfile(tgt): # Read file
3884 if os.path.isfile(tgt): # Read file
3885 try :
3885 try :
3886 return openpy.read_py_file(tgt, skip_encoding_cookie=skip_encoding_cookie)
3886 return openpy.read_py_file(tgt, skip_encoding_cookie=skip_encoding_cookie)
3887 except UnicodeDecodeError as e:
3887 except UnicodeDecodeError as e:
3888 if not py_only :
3888 if not py_only :
3889 with io_open(tgt,'r', encoding='latin1') as f :
3889 with io_open(tgt,'r', encoding='latin1') as f :
3890 return f.read()
3890 return f.read()
3891 raise ValueError(("'%s' seem to be unreadable.") % target) from e
3891 raise ValueError(("'%s' seem to be unreadable.") % target) from e
3892 elif os.path.isdir(os.path.expanduser(tgt)):
3892 elif os.path.isdir(os.path.expanduser(tgt)):
3893 raise ValueError("'%s' is a directory, not a regular file." % target)
3893 raise ValueError("'%s' is a directory, not a regular file." % target)
3894
3894
3895 if search_ns:
3895 if search_ns:
3896 # Inspect namespace to load object source
3896 # Inspect namespace to load object source
3897 object_info = self.object_inspect(target, detail_level=1)
3897 object_info = self.object_inspect(target, detail_level=1)
3898 if object_info['found'] and object_info['source']:
3898 if object_info['found'] and object_info['source']:
3899 return object_info['source']
3899 return object_info['source']
3900
3900
3901 try: # User namespace
3901 try: # User namespace
3902 codeobj = eval(target, self.user_ns)
3902 codeobj = eval(target, self.user_ns)
3903 except Exception as e:
3903 except Exception as e:
3904 raise ValueError(("'%s' was not found in history, as a file, url, "
3904 raise ValueError(("'%s' was not found in history, as a file, url, "
3905 "nor in the user namespace.") % target) from e
3905 "nor in the user namespace.") % target) from e
3906
3906
3907 if isinstance(codeobj, str):
3907 if isinstance(codeobj, str):
3908 return codeobj
3908 return codeobj
3909 elif isinstance(codeobj, Macro):
3909 elif isinstance(codeobj, Macro):
3910 return codeobj.value
3910 return codeobj.value
3911
3911
3912 raise TypeError("%s is neither a string nor a macro." % target,
3912 raise TypeError("%s is neither a string nor a macro." % target,
3913 codeobj)
3913 codeobj)
3914
3914
3915 def _atexit_once(self):
3915 def _atexit_once(self):
3916 """
3916 """
3917 At exist operation that need to be called at most once.
3917 At exist operation that need to be called at most once.
3918 Second call to this function per instance will do nothing.
3918 Second call to this function per instance will do nothing.
3919 """
3919 """
3920
3920
3921 if not getattr(self, "_atexit_once_called", False):
3921 if not getattr(self, "_atexit_once_called", False):
3922 self._atexit_once_called = True
3922 self._atexit_once_called = True
3923 # Clear all user namespaces to release all references cleanly.
3923 # Clear all user namespaces to release all references cleanly.
3924 self.reset(new_session=False)
3924 self.reset(new_session=False)
3925 # Close the history session (this stores the end time and line count)
3925 # Close the history session (this stores the end time and line count)
3926 # this must be *before* the tempfile cleanup, in case of temporary
3926 # this must be *before* the tempfile cleanup, in case of temporary
3927 # history db
3927 # history db
3928 self.history_manager.end_session()
3928 self.history_manager.end_session()
3929 self.history_manager = None
3929 self.history_manager = None
3930
3930
3931 #-------------------------------------------------------------------------
3931 #-------------------------------------------------------------------------
3932 # Things related to IPython exiting
3932 # Things related to IPython exiting
3933 #-------------------------------------------------------------------------
3933 #-------------------------------------------------------------------------
3934 def atexit_operations(self):
3934 def atexit_operations(self):
3935 """This will be executed at the time of exit.
3935 """This will be executed at the time of exit.
3936
3936
3937 Cleanup operations and saving of persistent data that is done
3937 Cleanup operations and saving of persistent data that is done
3938 unconditionally by IPython should be performed here.
3938 unconditionally by IPython should be performed here.
3939
3939
3940 For things that may depend on startup flags or platform specifics (such
3940 For things that may depend on startup flags or platform specifics (such
3941 as having readline or not), register a separate atexit function in the
3941 as having readline or not), register a separate atexit function in the
3942 code that has the appropriate information, rather than trying to
3942 code that has the appropriate information, rather than trying to
3943 clutter
3943 clutter
3944 """
3944 """
3945 self._atexit_once()
3945 self._atexit_once()
3946
3946
3947 # Cleanup all tempfiles and folders left around
3947 # Cleanup all tempfiles and folders left around
3948 for tfile in self.tempfiles:
3948 for tfile in self.tempfiles:
3949 try:
3949 try:
3950 tfile.unlink()
3950 tfile.unlink()
3951 self.tempfiles.remove(tfile)
3951 self.tempfiles.remove(tfile)
3952 except FileNotFoundError:
3952 except FileNotFoundError:
3953 pass
3953 pass
3954 del self.tempfiles
3954 del self.tempfiles
3955 for tdir in self.tempdirs:
3955 for tdir in self.tempdirs:
3956 try:
3956 try:
3957 shutil.rmtree(tdir)
3957 shutil.rmtree(tdir)
3958 self.tempdirs.remove(tdir)
3958 self.tempdirs.remove(tdir)
3959 except FileNotFoundError:
3959 except FileNotFoundError:
3960 pass
3960 pass
3961 del self.tempdirs
3961 del self.tempdirs
3962
3962
3963 # Restore user's cursor
3963 # Restore user's cursor
3964 if hasattr(self, "editing_mode") and self.editing_mode == "vi":
3964 if hasattr(self, "editing_mode") and self.editing_mode == "vi":
3965 sys.stdout.write("\x1b[0 q")
3965 sys.stdout.write("\x1b[0 q")
3966 sys.stdout.flush()
3966 sys.stdout.flush()
3967
3967
3968 def cleanup(self):
3968 def cleanup(self):
3969 self.restore_sys_module_state()
3969 self.restore_sys_module_state()
3970
3970
3971
3971
3972 # Overridden in terminal subclass to change prompts
3972 # Overridden in terminal subclass to change prompts
3973 def switch_doctest_mode(self, mode):
3973 def switch_doctest_mode(self, mode):
3974 pass
3974 pass
3975
3975
3976
3976
3977 class InteractiveShellABC(metaclass=abc.ABCMeta):
3977 class InteractiveShellABC(metaclass=abc.ABCMeta):
3978 """An abstract base class for InteractiveShell."""
3978 """An abstract base class for InteractiveShell."""
3979
3979
3980 InteractiveShellABC.register(InteractiveShell)
3980 InteractiveShellABC.register(InteractiveShell)
@@ -1,169 +1,174
1 """Implementation of magic functions for matplotlib/pylab support.
1 """Implementation of magic functions for matplotlib/pylab support.
2 """
2 """
3 #-----------------------------------------------------------------------------
3 #-----------------------------------------------------------------------------
4 # Copyright (c) 2012 The IPython Development Team.
4 # Copyright (c) 2012 The IPython Development Team.
5 #
5 #
6 # Distributed under the terms of the Modified BSD License.
6 # Distributed under the terms of the Modified BSD License.
7 #
7 #
8 # The full license is in the file COPYING.txt, distributed with this software.
8 # The full license is in the file COPYING.txt, distributed with this software.
9 #-----------------------------------------------------------------------------
9 #-----------------------------------------------------------------------------
10
10
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12 # Imports
12 # Imports
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14
14
15 # Our own packages
15 # Our own packages
16 from traitlets.config.application import Application
16 from traitlets.config.application import Application
17 from IPython.core import magic_arguments
17 from IPython.core import magic_arguments
18 from IPython.core.magic import Magics, magics_class, line_magic
18 from IPython.core.magic import Magics, magics_class, line_magic
19 from IPython.testing.skipdoctest import skip_doctest
19 from IPython.testing.skipdoctest import skip_doctest
20 from warnings import warn
20 from warnings import warn
21 from IPython.core.pylabtools import backends
22
21
23 #-----------------------------------------------------------------------------
22 #-----------------------------------------------------------------------------
24 # Magic implementation classes
23 # Magic implementation classes
25 #-----------------------------------------------------------------------------
24 #-----------------------------------------------------------------------------
26
25
27 magic_gui_arg = magic_arguments.argument(
26 magic_gui_arg = magic_arguments.argument(
28 'gui', nargs='?',
27 'gui', nargs='?',
29 help="""Name of the matplotlib backend to use %s.
28 help="""Name of the matplotlib backend to use such as 'qt' or 'widget'.
30 If given, the corresponding matplotlib backend is used,
29 If given, the corresponding matplotlib backend is used,
31 otherwise it will be matplotlib's default
30 otherwise it will be matplotlib's default
32 (which you can set in your matplotlib config file).
31 (which you can set in your matplotlib config file).
33 """ % str(tuple(sorted(backends.keys())))
32 """
34 )
33 )
35
34
36
35
37 @magics_class
36 @magics_class
38 class PylabMagics(Magics):
37 class PylabMagics(Magics):
39 """Magics related to matplotlib's pylab support"""
38 """Magics related to matplotlib's pylab support"""
40
39
41 @skip_doctest
40 @skip_doctest
42 @line_magic
41 @line_magic
43 @magic_arguments.magic_arguments()
42 @magic_arguments.magic_arguments()
44 @magic_arguments.argument('-l', '--list', action='store_true',
43 @magic_arguments.argument('-l', '--list', action='store_true',
45 help='Show available matplotlib backends')
44 help='Show available matplotlib backends')
46 @magic_gui_arg
45 @magic_gui_arg
47 def matplotlib(self, line=''):
46 def matplotlib(self, line=''):
48 """Set up matplotlib to work interactively.
47 """Set up matplotlib to work interactively.
49
48
50 This function lets you activate matplotlib interactive support
49 This function lets you activate matplotlib interactive support
51 at any point during an IPython session. It does not import anything
50 at any point during an IPython session. It does not import anything
52 into the interactive namespace.
51 into the interactive namespace.
53
52
54 If you are using the inline matplotlib backend in the IPython Notebook
53 If you are using the inline matplotlib backend in the IPython Notebook
55 you can set which figure formats are enabled using the following::
54 you can set which figure formats are enabled using the following::
56
55
57 In [1]: from matplotlib_inline.backend_inline import set_matplotlib_formats
56 In [1]: from matplotlib_inline.backend_inline import set_matplotlib_formats
58
57
59 In [2]: set_matplotlib_formats('pdf', 'svg')
58 In [2]: set_matplotlib_formats('pdf', 'svg')
60
59
61 The default for inline figures sets `bbox_inches` to 'tight'. This can
60 The default for inline figures sets `bbox_inches` to 'tight'. This can
62 cause discrepancies between the displayed image and the identical
61 cause discrepancies between the displayed image and the identical
63 image created using `savefig`. This behavior can be disabled using the
62 image created using `savefig`. This behavior can be disabled using the
64 `%config` magic::
63 `%config` magic::
65
64
66 In [3]: %config InlineBackend.print_figure_kwargs = {'bbox_inches':None}
65 In [3]: %config InlineBackend.print_figure_kwargs = {'bbox_inches':None}
67
66
68 In addition, see the docstrings of
67 In addition, see the docstrings of
69 `matplotlib_inline.backend_inline.set_matplotlib_formats` and
68 `matplotlib_inline.backend_inline.set_matplotlib_formats` and
70 `matplotlib_inline.backend_inline.set_matplotlib_close` for more information on
69 `matplotlib_inline.backend_inline.set_matplotlib_close` for more information on
71 changing additional behaviors of the inline backend.
70 changing additional behaviors of the inline backend.
72
71
73 Examples
72 Examples
74 --------
73 --------
75 To enable the inline backend for usage with the IPython Notebook::
74 To enable the inline backend for usage with the IPython Notebook::
76
75
77 In [1]: %matplotlib inline
76 In [1]: %matplotlib inline
78
77
79 In this case, where the matplotlib default is TkAgg::
78 In this case, where the matplotlib default is TkAgg::
80
79
81 In [2]: %matplotlib
80 In [2]: %matplotlib
82 Using matplotlib backend: TkAgg
81 Using matplotlib backend: TkAgg
83
82
84 But you can explicitly request a different GUI backend::
83 But you can explicitly request a different GUI backend::
85
84
86 In [3]: %matplotlib qt
85 In [3]: %matplotlib qt
87
86
88 You can list the available backends using the -l/--list option::
87 You can list the available backends using the -l/--list option::
89
88
90 In [4]: %matplotlib --list
89 In [4]: %matplotlib --list
91 Available matplotlib backends: ['osx', 'qt4', 'qt5', 'gtk3', 'gtk4', 'notebook', 'wx', 'qt', 'nbagg',
90 Available matplotlib backends: ['osx', 'qt4', 'qt5', 'gtk3', 'gtk4', 'notebook', 'wx', 'qt', 'nbagg',
92 'gtk', 'tk', 'inline']
91 'gtk', 'tk', 'inline']
93 """
92 """
94 args = magic_arguments.parse_argstring(self.matplotlib, line)
93 args = magic_arguments.parse_argstring(self.matplotlib, line)
95 if args.list:
94 if args.list:
96 backends_list = list(backends.keys())
95 from IPython.core.pylabtools import _matplotlib_manages_backends
96 if _matplotlib_manages_backends():
97 from matplotlib.backends.registry import backend_registry
98 backends_list = backend_registry.list_all()
99 else:
100 from IPython.core.pylabtools import backends
101 backends_list = list(backends.keys())
97 print("Available matplotlib backends: %s" % backends_list)
102 print("Available matplotlib backends: %s" % backends_list)
98 else:
103 else:
99 gui, backend = self.shell.enable_matplotlib(args.gui.lower() if isinstance(args.gui, str) else args.gui)
104 gui, backend = self.shell.enable_matplotlib(args.gui.lower() if isinstance(args.gui, str) else args.gui)
100 self._show_matplotlib_backend(args.gui, backend)
105 self._show_matplotlib_backend(args.gui, backend)
101
106
102 @skip_doctest
107 @skip_doctest
103 @line_magic
108 @line_magic
104 @magic_arguments.magic_arguments()
109 @magic_arguments.magic_arguments()
105 @magic_arguments.argument(
110 @magic_arguments.argument(
106 '--no-import-all', action='store_true', default=None,
111 '--no-import-all', action='store_true', default=None,
107 help="""Prevent IPython from performing ``import *`` into the interactive namespace.
112 help="""Prevent IPython from performing ``import *`` into the interactive namespace.
108
113
109 You can govern the default behavior of this flag with the
114 You can govern the default behavior of this flag with the
110 InteractiveShellApp.pylab_import_all configurable.
115 InteractiveShellApp.pylab_import_all configurable.
111 """
116 """
112 )
117 )
113 @magic_gui_arg
118 @magic_gui_arg
114 def pylab(self, line=''):
119 def pylab(self, line=''):
115 """Load numpy and matplotlib to work interactively.
120 """Load numpy and matplotlib to work interactively.
116
121
117 This function lets you activate pylab (matplotlib, numpy and
122 This function lets you activate pylab (matplotlib, numpy and
118 interactive support) at any point during an IPython session.
123 interactive support) at any point during an IPython session.
119
124
120 %pylab makes the following imports::
125 %pylab makes the following imports::
121
126
122 import numpy
127 import numpy
123 import matplotlib
128 import matplotlib
124 from matplotlib import pylab, mlab, pyplot
129 from matplotlib import pylab, mlab, pyplot
125 np = numpy
130 np = numpy
126 plt = pyplot
131 plt = pyplot
127
132
128 from IPython.display import display
133 from IPython.display import display
129 from IPython.core.pylabtools import figsize, getfigs
134 from IPython.core.pylabtools import figsize, getfigs
130
135
131 from pylab import *
136 from pylab import *
132 from numpy import *
137 from numpy import *
133
138
134 If you pass `--no-import-all`, the last two `*` imports will be excluded.
139 If you pass `--no-import-all`, the last two `*` imports will be excluded.
135
140
136 See the %matplotlib magic for more details about activating matplotlib
141 See the %matplotlib magic for more details about activating matplotlib
137 without affecting the interactive namespace.
142 without affecting the interactive namespace.
138 """
143 """
139 args = magic_arguments.parse_argstring(self.pylab, line)
144 args = magic_arguments.parse_argstring(self.pylab, line)
140 if args.no_import_all is None:
145 if args.no_import_all is None:
141 # get default from Application
146 # get default from Application
142 if Application.initialized():
147 if Application.initialized():
143 app = Application.instance()
148 app = Application.instance()
144 try:
149 try:
145 import_all = app.pylab_import_all
150 import_all = app.pylab_import_all
146 except AttributeError:
151 except AttributeError:
147 import_all = True
152 import_all = True
148 else:
153 else:
149 # nothing specified, no app - default True
154 # nothing specified, no app - default True
150 import_all = True
155 import_all = True
151 else:
156 else:
152 # invert no-import flag
157 # invert no-import flag
153 import_all = not args.no_import_all
158 import_all = not args.no_import_all
154
159
155 gui, backend, clobbered = self.shell.enable_pylab(args.gui, import_all=import_all)
160 gui, backend, clobbered = self.shell.enable_pylab(args.gui, import_all=import_all)
156 self._show_matplotlib_backend(args.gui, backend)
161 self._show_matplotlib_backend(args.gui, backend)
157 print(
162 print(
158 "%pylab is deprecated, use %matplotlib inline and import the required libraries."
163 "%pylab is deprecated, use %matplotlib inline and import the required libraries."
159 )
164 )
160 print("Populating the interactive namespace from numpy and matplotlib")
165 print("Populating the interactive namespace from numpy and matplotlib")
161 if clobbered:
166 if clobbered:
162 warn("pylab import has clobbered these variables: %s" % clobbered +
167 warn("pylab import has clobbered these variables: %s" % clobbered +
163 "\n`%matplotlib` prevents importing * from pylab and numpy"
168 "\n`%matplotlib` prevents importing * from pylab and numpy"
164 )
169 )
165
170
166 def _show_matplotlib_backend(self, gui, backend):
171 def _show_matplotlib_backend(self, gui, backend):
167 """show matplotlib message backend message"""
172 """show matplotlib message backend message"""
168 if not gui or gui == 'auto':
173 if not gui or gui == 'auto':
169 print("Using matplotlib backend: %s" % backend)
174 print("Using matplotlib backend: %s" % backend)
@@ -1,433 +1,470
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Pylab (matplotlib) support utilities."""
2 """Pylab (matplotlib) support utilities."""
3
3
4 # Copyright (c) IPython Development Team.
4 # Copyright (c) IPython Development Team.
5 # Distributed under the terms of the Modified BSD License.
5 # Distributed under the terms of the Modified BSD License.
6
6
7 from io import BytesIO
7 from io import BytesIO
8 from binascii import b2a_base64
8 from binascii import b2a_base64
9 from functools import partial
9 from functools import partial
10 import warnings
10 import warnings
11
11
12 from IPython.core.display import _pngxy
12 from IPython.core.display import _pngxy
13 from IPython.utils.decorators import flag_calls
13 from IPython.utils.decorators import flag_calls
14
14
15 # If user specifies a GUI, that dictates the backend, otherwise we read the
15
16 # user's mpl default from the mpl rc structure
16 # Matplotlib backend resolution functionality moved from IPython to Matplotlib
17 backends = {
17 # in IPython 8.23 and Matplotlib 3.9. Need to keep `backends` and `backend2gui`
18 # here for earlier Matplotlib and for external backend libraries such as
19 # mplcairo that might rely upon it.
20 _deprecated_backends = {
18 "tk": "TkAgg",
21 "tk": "TkAgg",
19 "gtk": "GTKAgg",
22 "gtk": "GTKAgg",
20 "gtk3": "GTK3Agg",
23 "gtk3": "GTK3Agg",
21 "gtk4": "GTK4Agg",
24 "gtk4": "GTK4Agg",
22 "wx": "WXAgg",
25 "wx": "WXAgg",
23 "qt4": "Qt4Agg",
26 "qt4": "Qt4Agg",
24 "qt5": "Qt5Agg",
27 "qt5": "Qt5Agg",
25 "qt6": "QtAgg",
28 "qt6": "QtAgg",
26 "qt": "QtAgg",
29 "qt": "QtAgg",
27 "osx": "MacOSX",
30 "osx": "MacOSX",
28 "nbagg": "nbAgg",
31 "nbagg": "nbAgg",
29 "webagg": "WebAgg",
32 "webagg": "WebAgg",
30 "notebook": "nbAgg",
33 "notebook": "nbAgg",
31 "agg": "agg",
34 "agg": "agg",
32 "svg": "svg",
35 "svg": "svg",
33 "pdf": "pdf",
36 "pdf": "pdf",
34 "ps": "ps",
37 "ps": "ps",
35 "inline": "module://matplotlib_inline.backend_inline",
38 "inline": "module://matplotlib_inline.backend_inline",
36 "ipympl": "module://ipympl.backend_nbagg",
39 "ipympl": "module://ipympl.backend_nbagg",
37 "widget": "module://ipympl.backend_nbagg",
40 "widget": "module://ipympl.backend_nbagg",
38 }
41 }
39
42
40 # We also need a reverse backends2guis mapping that will properly choose which
43 # We also need a reverse backends2guis mapping that will properly choose which
41 # GUI support to activate based on the desired matplotlib backend. For the
44 # GUI support to activate based on the desired matplotlib backend. For the
42 # most part it's just a reverse of the above dict, but we also need to add a
45 # most part it's just a reverse of the above dict, but we also need to add a
43 # few others that map to the same GUI manually:
46 # few others that map to the same GUI manually:
44 backend2gui = dict(zip(backends.values(), backends.keys()))
47 _deprecated_backend2gui = dict(zip(_deprecated_backends.values(), _deprecated_backends.keys()))
45 # In the reverse mapping, there are a few extra valid matplotlib backends that
48 # In the reverse mapping, there are a few extra valid matplotlib backends that
46 # map to the same GUI support
49 # map to the same GUI support
47 backend2gui["GTK"] = backend2gui["GTKCairo"] = "gtk"
50 _deprecated_backend2gui["GTK"] = _deprecated_backend2gui["GTKCairo"] = "gtk"
48 backend2gui["GTK3Cairo"] = "gtk3"
51 _deprecated_backend2gui["GTK3Cairo"] = "gtk3"
49 backend2gui["GTK4Cairo"] = "gtk4"
52 _deprecated_backend2gui["GTK4Cairo"] = "gtk4"
50 backend2gui["WX"] = "wx"
53 _deprecated_backend2gui["WX"] = "wx"
51 backend2gui["CocoaAgg"] = "osx"
54 _deprecated_backend2gui["CocoaAgg"] = "osx"
52 # There needs to be a hysteresis here as the new QtAgg Matplotlib backend
55 # There needs to be a hysteresis here as the new QtAgg Matplotlib backend
53 # supports either Qt5 or Qt6 and the IPython qt event loop support Qt4, Qt5,
56 # supports either Qt5 or Qt6 and the IPython qt event loop support Qt4, Qt5,
54 # and Qt6.
57 # and Qt6.
55 backend2gui["QtAgg"] = "qt"
58 _deprecated_backend2gui["QtAgg"] = "qt"
56 backend2gui["Qt4Agg"] = "qt4"
59 _deprecated_backend2gui["Qt4Agg"] = "qt4"
57 backend2gui["Qt5Agg"] = "qt5"
60 _deprecated_backend2gui["Qt5Agg"] = "qt5"
58
61
59 # And some backends that don't need GUI integration
62 # And some backends that don't need GUI integration
60 del backend2gui["nbAgg"]
63 del _deprecated_backend2gui["nbAgg"]
61 del backend2gui["agg"]
64 del _deprecated_backend2gui["agg"]
62 del backend2gui["svg"]
65 del _deprecated_backend2gui["svg"]
63 del backend2gui["pdf"]
66 del _deprecated_backend2gui["pdf"]
64 del backend2gui["ps"]
67 del _deprecated_backend2gui["ps"]
65 del backend2gui["module://matplotlib_inline.backend_inline"]
68 del _deprecated_backend2gui["module://matplotlib_inline.backend_inline"]
66 del backend2gui["module://ipympl.backend_nbagg"]
69 del _deprecated_backend2gui["module://ipympl.backend_nbagg"]
70
71
72 # Deprecated attributes backends and backend2gui mostly following PEP 562.
73 def __getattr__(name):
74 if name in ("backends", "backend2gui"):
75 warnings.warn(f"{name} is deprecated", DeprecationWarning)
76 return globals()[f"_deprecated_{name}"]
77 raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
78
67
79
68 #-----------------------------------------------------------------------------
80 #-----------------------------------------------------------------------------
69 # Matplotlib utilities
81 # Matplotlib utilities
70 #-----------------------------------------------------------------------------
82 #-----------------------------------------------------------------------------
71
83
72
84
73 def getfigs(*fig_nums):
85 def getfigs(*fig_nums):
74 """Get a list of matplotlib figures by figure numbers.
86 """Get a list of matplotlib figures by figure numbers.
75
87
76 If no arguments are given, all available figures are returned. If the
88 If no arguments are given, all available figures are returned. If the
77 argument list contains references to invalid figures, a warning is printed
89 argument list contains references to invalid figures, a warning is printed
78 but the function continues pasting further figures.
90 but the function continues pasting further figures.
79
91
80 Parameters
92 Parameters
81 ----------
93 ----------
82 figs : tuple
94 figs : tuple
83 A tuple of ints giving the figure numbers of the figures to return.
95 A tuple of ints giving the figure numbers of the figures to return.
84 """
96 """
85 from matplotlib._pylab_helpers import Gcf
97 from matplotlib._pylab_helpers import Gcf
86 if not fig_nums:
98 if not fig_nums:
87 fig_managers = Gcf.get_all_fig_managers()
99 fig_managers = Gcf.get_all_fig_managers()
88 return [fm.canvas.figure for fm in fig_managers]
100 return [fm.canvas.figure for fm in fig_managers]
89 else:
101 else:
90 figs = []
102 figs = []
91 for num in fig_nums:
103 for num in fig_nums:
92 f = Gcf.figs.get(num)
104 f = Gcf.figs.get(num)
93 if f is None:
105 if f is None:
94 print('Warning: figure %s not available.' % num)
106 print('Warning: figure %s not available.' % num)
95 else:
107 else:
96 figs.append(f.canvas.figure)
108 figs.append(f.canvas.figure)
97 return figs
109 return figs
98
110
99
111
100 def figsize(sizex, sizey):
112 def figsize(sizex, sizey):
101 """Set the default figure size to be [sizex, sizey].
113 """Set the default figure size to be [sizex, sizey].
102
114
103 This is just an easy to remember, convenience wrapper that sets::
115 This is just an easy to remember, convenience wrapper that sets::
104
116
105 matplotlib.rcParams['figure.figsize'] = [sizex, sizey]
117 matplotlib.rcParams['figure.figsize'] = [sizex, sizey]
106 """
118 """
107 import matplotlib
119 import matplotlib
108 matplotlib.rcParams['figure.figsize'] = [sizex, sizey]
120 matplotlib.rcParams['figure.figsize'] = [sizex, sizey]
109
121
110
122
111 def print_figure(fig, fmt="png", bbox_inches="tight", base64=False, **kwargs):
123 def print_figure(fig, fmt="png", bbox_inches="tight", base64=False, **kwargs):
112 """Print a figure to an image, and return the resulting file data
124 """Print a figure to an image, and return the resulting file data
113
125
114 Returned data will be bytes unless ``fmt='svg'``,
126 Returned data will be bytes unless ``fmt='svg'``,
115 in which case it will be unicode.
127 in which case it will be unicode.
116
128
117 Any keyword args are passed to fig.canvas.print_figure,
129 Any keyword args are passed to fig.canvas.print_figure,
118 such as ``quality`` or ``bbox_inches``.
130 such as ``quality`` or ``bbox_inches``.
119
131
120 If `base64` is True, return base64-encoded str instead of raw bytes
132 If `base64` is True, return base64-encoded str instead of raw bytes
121 for binary-encoded image formats
133 for binary-encoded image formats
122
134
123 .. versionadded:: 7.29
135 .. versionadded:: 7.29
124 base64 argument
136 base64 argument
125 """
137 """
126 # When there's an empty figure, we shouldn't return anything, otherwise we
138 # When there's an empty figure, we shouldn't return anything, otherwise we
127 # get big blank areas in the qt console.
139 # get big blank areas in the qt console.
128 if not fig.axes and not fig.lines:
140 if not fig.axes and not fig.lines:
129 return
141 return
130
142
131 dpi = fig.dpi
143 dpi = fig.dpi
132 if fmt == 'retina':
144 if fmt == 'retina':
133 dpi = dpi * 2
145 dpi = dpi * 2
134 fmt = 'png'
146 fmt = 'png'
135
147
136 # build keyword args
148 # build keyword args
137 kw = {
149 kw = {
138 "format":fmt,
150 "format":fmt,
139 "facecolor":fig.get_facecolor(),
151 "facecolor":fig.get_facecolor(),
140 "edgecolor":fig.get_edgecolor(),
152 "edgecolor":fig.get_edgecolor(),
141 "dpi":dpi,
153 "dpi":dpi,
142 "bbox_inches":bbox_inches,
154 "bbox_inches":bbox_inches,
143 }
155 }
144 # **kwargs get higher priority
156 # **kwargs get higher priority
145 kw.update(kwargs)
157 kw.update(kwargs)
146
158
147 bytes_io = BytesIO()
159 bytes_io = BytesIO()
148 if fig.canvas is None:
160 if fig.canvas is None:
149 from matplotlib.backend_bases import FigureCanvasBase
161 from matplotlib.backend_bases import FigureCanvasBase
150 FigureCanvasBase(fig)
162 FigureCanvasBase(fig)
151
163
152 fig.canvas.print_figure(bytes_io, **kw)
164 fig.canvas.print_figure(bytes_io, **kw)
153 data = bytes_io.getvalue()
165 data = bytes_io.getvalue()
154 if fmt == 'svg':
166 if fmt == 'svg':
155 data = data.decode('utf-8')
167 data = data.decode('utf-8')
156 elif base64:
168 elif base64:
157 data = b2a_base64(data, newline=False).decode("ascii")
169 data = b2a_base64(data, newline=False).decode("ascii")
158 return data
170 return data
159
171
160 def retina_figure(fig, base64=False, **kwargs):
172 def retina_figure(fig, base64=False, **kwargs):
161 """format a figure as a pixel-doubled (retina) PNG
173 """format a figure as a pixel-doubled (retina) PNG
162
174
163 If `base64` is True, return base64-encoded str instead of raw bytes
175 If `base64` is True, return base64-encoded str instead of raw bytes
164 for binary-encoded image formats
176 for binary-encoded image formats
165
177
166 .. versionadded:: 7.29
178 .. versionadded:: 7.29
167 base64 argument
179 base64 argument
168 """
180 """
169 pngdata = print_figure(fig, fmt="retina", base64=False, **kwargs)
181 pngdata = print_figure(fig, fmt="retina", base64=False, **kwargs)
170 # Make sure that retina_figure acts just like print_figure and returns
182 # Make sure that retina_figure acts just like print_figure and returns
171 # None when the figure is empty.
183 # None when the figure is empty.
172 if pngdata is None:
184 if pngdata is None:
173 return
185 return
174 w, h = _pngxy(pngdata)
186 w, h = _pngxy(pngdata)
175 metadata = {"width": w//2, "height":h//2}
187 metadata = {"width": w//2, "height":h//2}
176 if base64:
188 if base64:
177 pngdata = b2a_base64(pngdata, newline=False).decode("ascii")
189 pngdata = b2a_base64(pngdata, newline=False).decode("ascii")
178 return pngdata, metadata
190 return pngdata, metadata
179
191
180
192
181 # We need a little factory function here to create the closure where
193 # We need a little factory function here to create the closure where
182 # safe_execfile can live.
194 # safe_execfile can live.
183 def mpl_runner(safe_execfile):
195 def mpl_runner(safe_execfile):
184 """Factory to return a matplotlib-enabled runner for %run.
196 """Factory to return a matplotlib-enabled runner for %run.
185
197
186 Parameters
198 Parameters
187 ----------
199 ----------
188 safe_execfile : function
200 safe_execfile : function
189 This must be a function with the same interface as the
201 This must be a function with the same interface as the
190 :meth:`safe_execfile` method of IPython.
202 :meth:`safe_execfile` method of IPython.
191
203
192 Returns
204 Returns
193 -------
205 -------
194 A function suitable for use as the ``runner`` argument of the %run magic
206 A function suitable for use as the ``runner`` argument of the %run magic
195 function.
207 function.
196 """
208 """
197
209
198 def mpl_execfile(fname,*where,**kw):
210 def mpl_execfile(fname,*where,**kw):
199 """matplotlib-aware wrapper around safe_execfile.
211 """matplotlib-aware wrapper around safe_execfile.
200
212
201 Its interface is identical to that of the :func:`execfile` builtin.
213 Its interface is identical to that of the :func:`execfile` builtin.
202
214
203 This is ultimately a call to execfile(), but wrapped in safeties to
215 This is ultimately a call to execfile(), but wrapped in safeties to
204 properly handle interactive rendering."""
216 properly handle interactive rendering."""
205
217
206 import matplotlib
218 import matplotlib
207 import matplotlib.pyplot as plt
219 import matplotlib.pyplot as plt
208
220
209 #print '*** Matplotlib runner ***' # dbg
221 #print '*** Matplotlib runner ***' # dbg
210 # turn off rendering until end of script
222 # turn off rendering until end of script
211 with matplotlib.rc_context({"interactive": False}):
223 with matplotlib.rc_context({"interactive": False}):
212 safe_execfile(fname, *where, **kw)
224 safe_execfile(fname, *where, **kw)
213
225
214 if matplotlib.is_interactive():
226 if matplotlib.is_interactive():
215 plt.show()
227 plt.show()
216
228
217 # make rendering call now, if the user tried to do it
229 # make rendering call now, if the user tried to do it
218 if plt.draw_if_interactive.called:
230 if plt.draw_if_interactive.called:
219 plt.draw()
231 plt.draw()
220 plt.draw_if_interactive.called = False
232 plt.draw_if_interactive.called = False
221
233
222 # re-draw everything that is stale
234 # re-draw everything that is stale
223 try:
235 try:
224 da = plt.draw_all
236 da = plt.draw_all
225 except AttributeError:
237 except AttributeError:
226 pass
238 pass
227 else:
239 else:
228 da()
240 da()
229
241
230 return mpl_execfile
242 return mpl_execfile
231
243
232
244
233 def _reshow_nbagg_figure(fig):
245 def _reshow_nbagg_figure(fig):
234 """reshow an nbagg figure"""
246 """reshow an nbagg figure"""
235 try:
247 try:
236 reshow = fig.canvas.manager.reshow
248 reshow = fig.canvas.manager.reshow
237 except AttributeError as e:
249 except AttributeError as e:
238 raise NotImplementedError() from e
250 raise NotImplementedError() from e
239 else:
251 else:
240 reshow()
252 reshow()
241
253
242
254
243 def select_figure_formats(shell, formats, **kwargs):
255 def select_figure_formats(shell, formats, **kwargs):
244 """Select figure formats for the inline backend.
256 """Select figure formats for the inline backend.
245
257
246 Parameters
258 Parameters
247 ----------
259 ----------
248 shell : InteractiveShell
260 shell : InteractiveShell
249 The main IPython instance.
261 The main IPython instance.
250 formats : str or set
262 formats : str or set
251 One or a set of figure formats to enable: 'png', 'retina', 'jpeg', 'svg', 'pdf'.
263 One or a set of figure formats to enable: 'png', 'retina', 'jpeg', 'svg', 'pdf'.
252 **kwargs : any
264 **kwargs : any
253 Extra keyword arguments to be passed to fig.canvas.print_figure.
265 Extra keyword arguments to be passed to fig.canvas.print_figure.
254 """
266 """
255 import matplotlib
267 import matplotlib
256 from matplotlib.figure import Figure
268 from matplotlib.figure import Figure
257
269
258 svg_formatter = shell.display_formatter.formatters['image/svg+xml']
270 svg_formatter = shell.display_formatter.formatters['image/svg+xml']
259 png_formatter = shell.display_formatter.formatters['image/png']
271 png_formatter = shell.display_formatter.formatters['image/png']
260 jpg_formatter = shell.display_formatter.formatters['image/jpeg']
272 jpg_formatter = shell.display_formatter.formatters['image/jpeg']
261 pdf_formatter = shell.display_formatter.formatters['application/pdf']
273 pdf_formatter = shell.display_formatter.formatters['application/pdf']
262
274
263 if isinstance(formats, str):
275 if isinstance(formats, str):
264 formats = {formats}
276 formats = {formats}
265 # cast in case of list / tuple
277 # cast in case of list / tuple
266 formats = set(formats)
278 formats = set(formats)
267
279
268 [ f.pop(Figure, None) for f in shell.display_formatter.formatters.values() ]
280 [ f.pop(Figure, None) for f in shell.display_formatter.formatters.values() ]
269 mplbackend = matplotlib.get_backend().lower()
281 mplbackend = matplotlib.get_backend().lower()
270 if mplbackend == 'nbagg' or mplbackend == 'module://ipympl.backend_nbagg':
282 if mplbackend in ('nbagg', 'ipympl', 'widget', 'module://ipympl.backend_nbagg'):
271 formatter = shell.display_formatter.ipython_display_formatter
283 formatter = shell.display_formatter.ipython_display_formatter
272 formatter.for_type(Figure, _reshow_nbagg_figure)
284 formatter.for_type(Figure, _reshow_nbagg_figure)
273
285
274 supported = {'png', 'png2x', 'retina', 'jpg', 'jpeg', 'svg', 'pdf'}
286 supported = {'png', 'png2x', 'retina', 'jpg', 'jpeg', 'svg', 'pdf'}
275 bad = formats.difference(supported)
287 bad = formats.difference(supported)
276 if bad:
288 if bad:
277 bs = "%s" % ','.join([repr(f) for f in bad])
289 bs = "%s" % ','.join([repr(f) for f in bad])
278 gs = "%s" % ','.join([repr(f) for f in supported])
290 gs = "%s" % ','.join([repr(f) for f in supported])
279 raise ValueError("supported formats are: %s not %s" % (gs, bs))
291 raise ValueError("supported formats are: %s not %s" % (gs, bs))
280
292
281 if "png" in formats:
293 if "png" in formats:
282 png_formatter.for_type(
294 png_formatter.for_type(
283 Figure, partial(print_figure, fmt="png", base64=True, **kwargs)
295 Figure, partial(print_figure, fmt="png", base64=True, **kwargs)
284 )
296 )
285 if "retina" in formats or "png2x" in formats:
297 if "retina" in formats or "png2x" in formats:
286 png_formatter.for_type(Figure, partial(retina_figure, base64=True, **kwargs))
298 png_formatter.for_type(Figure, partial(retina_figure, base64=True, **kwargs))
287 if "jpg" in formats or "jpeg" in formats:
299 if "jpg" in formats or "jpeg" in formats:
288 jpg_formatter.for_type(
300 jpg_formatter.for_type(
289 Figure, partial(print_figure, fmt="jpg", base64=True, **kwargs)
301 Figure, partial(print_figure, fmt="jpg", base64=True, **kwargs)
290 )
302 )
291 if "svg" in formats:
303 if "svg" in formats:
292 svg_formatter.for_type(Figure, partial(print_figure, fmt="svg", **kwargs))
304 svg_formatter.for_type(Figure, partial(print_figure, fmt="svg", **kwargs))
293 if "pdf" in formats:
305 if "pdf" in formats:
294 pdf_formatter.for_type(
306 pdf_formatter.for_type(
295 Figure, partial(print_figure, fmt="pdf", base64=True, **kwargs)
307 Figure, partial(print_figure, fmt="pdf", base64=True, **kwargs)
296 )
308 )
297
309
298 #-----------------------------------------------------------------------------
310 #-----------------------------------------------------------------------------
299 # Code for initializing matplotlib and importing pylab
311 # Code for initializing matplotlib and importing pylab
300 #-----------------------------------------------------------------------------
312 #-----------------------------------------------------------------------------
301
313
302
314
303 def find_gui_and_backend(gui=None, gui_select=None):
315 def find_gui_and_backend(gui=None, gui_select=None):
304 """Given a gui string return the gui and mpl backend.
316 """Given a gui string return the gui and mpl backend.
305
317
306 Parameters
318 Parameters
307 ----------
319 ----------
308 gui : str
320 gui : str
309 Can be one of ('tk','gtk','wx','qt','qt4','inline','agg').
321 Can be one of ('tk','gtk','wx','qt','qt4','inline','agg').
310 gui_select : str
322 gui_select : str
311 Can be one of ('tk','gtk','wx','qt','qt4','inline').
323 Can be one of ('tk','gtk','wx','qt','qt4','inline').
312 This is any gui already selected by the shell.
324 This is any gui already selected by the shell.
313
325
314 Returns
326 Returns
315 -------
327 -------
316 A tuple of (gui, backend) where backend is one of ('TkAgg','GTKAgg',
328 A tuple of (gui, backend) where backend is one of ('TkAgg','GTKAgg',
317 'WXAgg','Qt4Agg','module://matplotlib_inline.backend_inline','agg').
329 'WXAgg','Qt4Agg','module://matplotlib_inline.backend_inline','agg').
318 """
330 """
319
331
320 import matplotlib
332 import matplotlib
333 if _matplotlib_manages_backends():
334 backend_registry = matplotlib.backends.registry.backend_registry
335
336 # gui argument may be a gui event loop or may be a backend name.
337 if gui in ("auto", None):
338 backend = matplotlib.rcParamsOrig['backend']
339 backend, gui = backend_registry.resolve_backend(backend)
340 else:
341 backend, gui = backend_registry.resolve_gui_or_backend(gui)
321
342
322 has_unified_qt_backend = getattr(matplotlib, "__version_info__", (0, 0)) >= (3, 5)
343 return gui, backend
323
344
345 # Fallback to previous behaviour (Matplotlib < 3.9)
346 mpl_version_info = getattr(matplotlib, "__version_info__", (0, 0))
347 has_unified_qt_backend = mpl_version_info >= (3, 5)
348
349 from IPython.core.pylabtools import backends
324 backends_ = dict(backends)
350 backends_ = dict(backends)
325 if not has_unified_qt_backend:
351 if not has_unified_qt_backend:
326 backends_["qt"] = "qt5agg"
352 backends_["qt"] = "qt5agg"
327
353
328 if gui and gui != 'auto':
354 if gui and gui != 'auto':
329 # select backend based on requested gui
355 # select backend based on requested gui
330 backend = backends_[gui]
356 backend = backends_[gui]
331 if gui == 'agg':
357 if gui == 'agg':
332 gui = None
358 gui = None
333 else:
359 else:
334 # We need to read the backend from the original data structure, *not*
360 # We need to read the backend from the original data structure, *not*
335 # from mpl.rcParams, since a prior invocation of %matplotlib may have
361 # from mpl.rcParams, since a prior invocation of %matplotlib may have
336 # overwritten that.
362 # overwritten that.
337 # WARNING: this assumes matplotlib 1.1 or newer!!
363 # WARNING: this assumes matplotlib 1.1 or newer!!
338 backend = matplotlib.rcParamsOrig['backend']
364 backend = matplotlib.rcParamsOrig['backend']
339 # In this case, we need to find what the appropriate gui selection call
365 # In this case, we need to find what the appropriate gui selection call
340 # should be for IPython, so we can activate inputhook accordingly
366 # should be for IPython, so we can activate inputhook accordingly
367 from IPython.core.pylabtools import backend2gui
341 gui = backend2gui.get(backend, None)
368 gui = backend2gui.get(backend, None)
342
369
343 # If we have already had a gui active, we need it and inline are the
370 # If we have already had a gui active, we need it and inline are the
344 # ones allowed.
371 # ones allowed.
345 if gui_select and gui != gui_select:
372 if gui_select and gui != gui_select:
346 gui = gui_select
373 gui = gui_select
347 backend = backends_[gui]
374 backend = backends_[gui]
348
375
376 # Since IPython 8.23.0 use None for no gui event loop rather than "inline".
377 if gui == "inline":
378 gui = None
379
349 return gui, backend
380 return gui, backend
350
381
351
382
352 def activate_matplotlib(backend):
383 def activate_matplotlib(backend):
353 """Activate the given backend and set interactive to True."""
384 """Activate the given backend and set interactive to True."""
354
385
355 import matplotlib
386 import matplotlib
356 matplotlib.interactive(True)
387 matplotlib.interactive(True)
357
388
358 # Matplotlib had a bug where even switch_backend could not force
389 # Matplotlib had a bug where even switch_backend could not force
359 # the rcParam to update. This needs to be set *before* the module
390 # the rcParam to update. This needs to be set *before* the module
360 # magic of switch_backend().
391 # magic of switch_backend().
361 matplotlib.rcParams['backend'] = backend
392 matplotlib.rcParams['backend'] = backend
362
393
363 # Due to circular imports, pyplot may be only partially initialised
394 # Due to circular imports, pyplot may be only partially initialised
364 # when this function runs.
395 # when this function runs.
365 # So avoid needing matplotlib attribute-lookup to access pyplot.
396 # So avoid needing matplotlib attribute-lookup to access pyplot.
366 from matplotlib import pyplot as plt
397 from matplotlib import pyplot as plt
367
398
368 plt.switch_backend(backend)
399 plt.switch_backend(backend)
369
400
370 plt.show._needmain = False
401 plt.show._needmain = False
371 # We need to detect at runtime whether show() is called by the user.
402 # We need to detect at runtime whether show() is called by the user.
372 # For this, we wrap it into a decorator which adds a 'called' flag.
403 # For this, we wrap it into a decorator which adds a 'called' flag.
373 plt.draw_if_interactive = flag_calls(plt.draw_if_interactive)
404 plt.draw_if_interactive = flag_calls(plt.draw_if_interactive)
374
405
375
406
376 def import_pylab(user_ns, import_all=True):
407 def import_pylab(user_ns, import_all=True):
377 """Populate the namespace with pylab-related values.
408 """Populate the namespace with pylab-related values.
378
409
379 Imports matplotlib, pylab, numpy, and everything from pylab and numpy.
410 Imports matplotlib, pylab, numpy, and everything from pylab and numpy.
380
411
381 Also imports a few names from IPython (figsize, display, getfigs)
412 Also imports a few names from IPython (figsize, display, getfigs)
382
413
383 """
414 """
384
415
385 # Import numpy as np/pyplot as plt are conventions we're trying to
416 # Import numpy as np/pyplot as plt are conventions we're trying to
386 # somewhat standardize on. Making them available to users by default
417 # somewhat standardize on. Making them available to users by default
387 # will greatly help this.
418 # will greatly help this.
388 s = ("import numpy\n"
419 s = ("import numpy\n"
389 "import matplotlib\n"
420 "import matplotlib\n"
390 "from matplotlib import pylab, mlab, pyplot\n"
421 "from matplotlib import pylab, mlab, pyplot\n"
391 "np = numpy\n"
422 "np = numpy\n"
392 "plt = pyplot\n"
423 "plt = pyplot\n"
393 )
424 )
394 exec(s, user_ns)
425 exec(s, user_ns)
395
426
396 if import_all:
427 if import_all:
397 s = ("from matplotlib.pylab import *\n"
428 s = ("from matplotlib.pylab import *\n"
398 "from numpy import *\n")
429 "from numpy import *\n")
399 exec(s, user_ns)
430 exec(s, user_ns)
400
431
401 # IPython symbols to add
432 # IPython symbols to add
402 user_ns['figsize'] = figsize
433 user_ns['figsize'] = figsize
403 from IPython.display import display
434 from IPython.display import display
404 # Add display and getfigs to the user's namespace
435 # Add display and getfigs to the user's namespace
405 user_ns['display'] = display
436 user_ns['display'] = display
406 user_ns['getfigs'] = getfigs
437 user_ns['getfigs'] = getfigs
407
438
408
439
409 def configure_inline_support(shell, backend):
440 def configure_inline_support(shell, backend):
410 """
441 """
411 .. deprecated:: 7.23
442 .. deprecated:: 7.23
412
443
413 use `matplotlib_inline.backend_inline.configure_inline_support()`
444 use `matplotlib_inline.backend_inline.configure_inline_support()`
414
445
415 Configure an IPython shell object for matplotlib use.
446 Configure an IPython shell object for matplotlib use.
416
447
417 Parameters
448 Parameters
418 ----------
449 ----------
419 shell : InteractiveShell instance
450 shell : InteractiveShell instance
420 backend : matplotlib backend
451 backend : matplotlib backend
421 """
452 """
422 warnings.warn(
453 warnings.warn(
423 "`configure_inline_support` is deprecated since IPython 7.23, directly "
454 "`configure_inline_support` is deprecated since IPython 7.23, directly "
424 "use `matplotlib_inline.backend_inline.configure_inline_support()`",
455 "use `matplotlib_inline.backend_inline.configure_inline_support()`",
425 DeprecationWarning,
456 DeprecationWarning,
426 stacklevel=2,
457 stacklevel=2,
427 )
458 )
428
459
429 from matplotlib_inline.backend_inline import (
460 from matplotlib_inline.backend_inline import (
430 configure_inline_support as configure_inline_support_orig,
461 configure_inline_support as configure_inline_support_orig,
431 )
462 )
432
463
433 configure_inline_support_orig(shell, backend)
464 configure_inline_support_orig(shell, backend)
465
466
467 def _matplotlib_manages_backends():
468 import matplotlib
469 mpl_version_info = getattr(matplotlib, "__version_info__", (0, 0))
470 return mpl_version_info >= (3, 9)
@@ -1,451 +1,450
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 A mixin for :class:`~IPython.core.application.Application` classes that
3 A mixin for :class:`~IPython.core.application.Application` classes that
4 launch InteractiveShell instances, load extensions, etc.
4 launch InteractiveShell instances, load extensions, etc.
5 """
5 """
6
6
7 # Copyright (c) IPython Development Team.
7 # Copyright (c) IPython Development Team.
8 # Distributed under the terms of the Modified BSD License.
8 # Distributed under the terms of the Modified BSD License.
9
9
10 import glob
10 import glob
11 from itertools import chain
11 from itertools import chain
12 import os
12 import os
13 import sys
13 import sys
14
14
15 from traitlets.config.application import boolean_flag
15 from traitlets.config.application import boolean_flag
16 from traitlets.config.configurable import Configurable
16 from traitlets.config.configurable import Configurable
17 from traitlets.config.loader import Config
17 from traitlets.config.loader import Config
18 from IPython.core.application import SYSTEM_CONFIG_DIRS, ENV_CONFIG_DIRS
18 from IPython.core.application import SYSTEM_CONFIG_DIRS, ENV_CONFIG_DIRS
19 from IPython.core import pylabtools
19 from IPython.core import pylabtools
20 from IPython.utils.contexts import preserve_keys
20 from IPython.utils.contexts import preserve_keys
21 from IPython.utils.path import filefind
21 from IPython.utils.path import filefind
22 from traitlets import (
22 from traitlets import (
23 Unicode, Instance, List, Bool, CaselessStrEnum, observe,
23 Unicode, Instance, List, Bool, CaselessStrEnum, observe,
24 DottedObjectName,
24 DottedObjectName,
25 )
25 )
26 from IPython.terminal import pt_inputhooks
26 from IPython.terminal import pt_inputhooks
27
27
28 #-----------------------------------------------------------------------------
28 #-----------------------------------------------------------------------------
29 # Aliases and Flags
29 # Aliases and Flags
30 #-----------------------------------------------------------------------------
30 #-----------------------------------------------------------------------------
31
31
32 gui_keys = tuple(sorted(pt_inputhooks.backends) + sorted(pt_inputhooks.aliases))
32 gui_keys = tuple(sorted(pt_inputhooks.backends) + sorted(pt_inputhooks.aliases))
33
33
34 backend_keys = sorted(pylabtools.backends.keys())
34 backend_keys = []
35 backend_keys.insert(0, 'auto')
36
35
37 shell_flags = {}
36 shell_flags = {}
38
37
39 addflag = lambda *args: shell_flags.update(boolean_flag(*args))
38 addflag = lambda *args: shell_flags.update(boolean_flag(*args))
40 addflag('autoindent', 'InteractiveShell.autoindent',
39 addflag('autoindent', 'InteractiveShell.autoindent',
41 'Turn on autoindenting.', 'Turn off autoindenting.'
40 'Turn on autoindenting.', 'Turn off autoindenting.'
42 )
41 )
43 addflag('automagic', 'InteractiveShell.automagic',
42 addflag('automagic', 'InteractiveShell.automagic',
44 """Turn on the auto calling of magic commands. Type %%magic at the
43 """Turn on the auto calling of magic commands. Type %%magic at the
45 IPython prompt for more information.""",
44 IPython prompt for more information.""",
46 'Turn off the auto calling of magic commands.'
45 'Turn off the auto calling of magic commands.'
47 )
46 )
48 addflag('pdb', 'InteractiveShell.pdb',
47 addflag('pdb', 'InteractiveShell.pdb',
49 "Enable auto calling the pdb debugger after every exception.",
48 "Enable auto calling the pdb debugger after every exception.",
50 "Disable auto calling the pdb debugger after every exception."
49 "Disable auto calling the pdb debugger after every exception."
51 )
50 )
52 addflag('pprint', 'PlainTextFormatter.pprint',
51 addflag('pprint', 'PlainTextFormatter.pprint',
53 "Enable auto pretty printing of results.",
52 "Enable auto pretty printing of results.",
54 "Disable auto pretty printing of results."
53 "Disable auto pretty printing of results."
55 )
54 )
56 addflag('color-info', 'InteractiveShell.color_info',
55 addflag('color-info', 'InteractiveShell.color_info',
57 """IPython can display information about objects via a set of functions,
56 """IPython can display information about objects via a set of functions,
58 and optionally can use colors for this, syntax highlighting
57 and optionally can use colors for this, syntax highlighting
59 source code and various other elements. This is on by default, but can cause
58 source code and various other elements. This is on by default, but can cause
60 problems with some pagers. If you see such problems, you can disable the
59 problems with some pagers. If you see such problems, you can disable the
61 colours.""",
60 colours.""",
62 "Disable using colors for info related things."
61 "Disable using colors for info related things."
63 )
62 )
64 addflag('ignore-cwd', 'InteractiveShellApp.ignore_cwd',
63 addflag('ignore-cwd', 'InteractiveShellApp.ignore_cwd',
65 "Exclude the current working directory from sys.path",
64 "Exclude the current working directory from sys.path",
66 "Include the current working directory in sys.path",
65 "Include the current working directory in sys.path",
67 )
66 )
68 nosep_config = Config()
67 nosep_config = Config()
69 nosep_config.InteractiveShell.separate_in = ''
68 nosep_config.InteractiveShell.separate_in = ''
70 nosep_config.InteractiveShell.separate_out = ''
69 nosep_config.InteractiveShell.separate_out = ''
71 nosep_config.InteractiveShell.separate_out2 = ''
70 nosep_config.InteractiveShell.separate_out2 = ''
72
71
73 shell_flags['nosep']=(nosep_config, "Eliminate all spacing between prompts.")
72 shell_flags['nosep']=(nosep_config, "Eliminate all spacing between prompts.")
74 shell_flags['pylab'] = (
73 shell_flags['pylab'] = (
75 {'InteractiveShellApp' : {'pylab' : 'auto'}},
74 {'InteractiveShellApp' : {'pylab' : 'auto'}},
76 """Pre-load matplotlib and numpy for interactive use with
75 """Pre-load matplotlib and numpy for interactive use with
77 the default matplotlib backend."""
76 the default matplotlib backend."""
78 )
77 )
79 shell_flags['matplotlib'] = (
78 shell_flags['matplotlib'] = (
80 {'InteractiveShellApp' : {'matplotlib' : 'auto'}},
79 {'InteractiveShellApp' : {'matplotlib' : 'auto'}},
81 """Configure matplotlib for interactive use with
80 """Configure matplotlib for interactive use with
82 the default matplotlib backend."""
81 the default matplotlib backend."""
83 )
82 )
84
83
85 # it's possible we don't want short aliases for *all* of these:
84 # it's possible we don't want short aliases for *all* of these:
86 shell_aliases = dict(
85 shell_aliases = dict(
87 autocall='InteractiveShell.autocall',
86 autocall='InteractiveShell.autocall',
88 colors='InteractiveShell.colors',
87 colors='InteractiveShell.colors',
89 logfile='InteractiveShell.logfile',
88 logfile='InteractiveShell.logfile',
90 logappend='InteractiveShell.logappend',
89 logappend='InteractiveShell.logappend',
91 c='InteractiveShellApp.code_to_run',
90 c='InteractiveShellApp.code_to_run',
92 m='InteractiveShellApp.module_to_run',
91 m='InteractiveShellApp.module_to_run',
93 ext="InteractiveShellApp.extra_extensions",
92 ext="InteractiveShellApp.extra_extensions",
94 gui='InteractiveShellApp.gui',
93 gui='InteractiveShellApp.gui',
95 pylab='InteractiveShellApp.pylab',
94 pylab='InteractiveShellApp.pylab',
96 matplotlib='InteractiveShellApp.matplotlib',
95 matplotlib='InteractiveShellApp.matplotlib',
97 )
96 )
98 shell_aliases['cache-size'] = 'InteractiveShell.cache_size'
97 shell_aliases['cache-size'] = 'InteractiveShell.cache_size'
99
98
100 #-----------------------------------------------------------------------------
99 #-----------------------------------------------------------------------------
101 # Main classes and functions
100 # Main classes and functions
102 #-----------------------------------------------------------------------------
101 #-----------------------------------------------------------------------------
103
102
104 class InteractiveShellApp(Configurable):
103 class InteractiveShellApp(Configurable):
105 """A Mixin for applications that start InteractiveShell instances.
104 """A Mixin for applications that start InteractiveShell instances.
106
105
107 Provides configurables for loading extensions and executing files
106 Provides configurables for loading extensions and executing files
108 as part of configuring a Shell environment.
107 as part of configuring a Shell environment.
109
108
110 The following methods should be called by the :meth:`initialize` method
109 The following methods should be called by the :meth:`initialize` method
111 of the subclass:
110 of the subclass:
112
111
113 - :meth:`init_path`
112 - :meth:`init_path`
114 - :meth:`init_shell` (to be implemented by the subclass)
113 - :meth:`init_shell` (to be implemented by the subclass)
115 - :meth:`init_gui_pylab`
114 - :meth:`init_gui_pylab`
116 - :meth:`init_extensions`
115 - :meth:`init_extensions`
117 - :meth:`init_code`
116 - :meth:`init_code`
118 """
117 """
119 extensions = List(Unicode(),
118 extensions = List(Unicode(),
120 help="A list of dotted module names of IPython extensions to load."
119 help="A list of dotted module names of IPython extensions to load."
121 ).tag(config=True)
120 ).tag(config=True)
122
121
123 extra_extensions = List(
122 extra_extensions = List(
124 DottedObjectName(),
123 DottedObjectName(),
125 help="""
124 help="""
126 Dotted module name(s) of one or more IPython extensions to load.
125 Dotted module name(s) of one or more IPython extensions to load.
127
126
128 For specifying extra extensions to load on the command-line.
127 For specifying extra extensions to load on the command-line.
129
128
130 .. versionadded:: 7.10
129 .. versionadded:: 7.10
131 """,
130 """,
132 ).tag(config=True)
131 ).tag(config=True)
133
132
134 reraise_ipython_extension_failures = Bool(False,
133 reraise_ipython_extension_failures = Bool(False,
135 help="Reraise exceptions encountered loading IPython extensions?",
134 help="Reraise exceptions encountered loading IPython extensions?",
136 ).tag(config=True)
135 ).tag(config=True)
137
136
138 # Extensions that are always loaded (not configurable)
137 # Extensions that are always loaded (not configurable)
139 default_extensions = List(Unicode(), [u'storemagic']).tag(config=False)
138 default_extensions = List(Unicode(), [u'storemagic']).tag(config=False)
140
139
141 hide_initial_ns = Bool(True,
140 hide_initial_ns = Bool(True,
142 help="""Should variables loaded at startup (by startup files, exec_lines, etc.)
141 help="""Should variables loaded at startup (by startup files, exec_lines, etc.)
143 be hidden from tools like %who?"""
142 be hidden from tools like %who?"""
144 ).tag(config=True)
143 ).tag(config=True)
145
144
146 exec_files = List(Unicode(),
145 exec_files = List(Unicode(),
147 help="""List of files to run at IPython startup."""
146 help="""List of files to run at IPython startup."""
148 ).tag(config=True)
147 ).tag(config=True)
149 exec_PYTHONSTARTUP = Bool(True,
148 exec_PYTHONSTARTUP = Bool(True,
150 help="""Run the file referenced by the PYTHONSTARTUP environment
149 help="""Run the file referenced by the PYTHONSTARTUP environment
151 variable at IPython startup."""
150 variable at IPython startup."""
152 ).tag(config=True)
151 ).tag(config=True)
153 file_to_run = Unicode('',
152 file_to_run = Unicode('',
154 help="""A file to be run""").tag(config=True)
153 help="""A file to be run""").tag(config=True)
155
154
156 exec_lines = List(Unicode(),
155 exec_lines = List(Unicode(),
157 help="""lines of code to run at IPython startup."""
156 help="""lines of code to run at IPython startup."""
158 ).tag(config=True)
157 ).tag(config=True)
159 code_to_run = Unicode('',
158 code_to_run = Unicode('',
160 help="Execute the given command string."
159 help="Execute the given command string."
161 ).tag(config=True)
160 ).tag(config=True)
162 module_to_run = Unicode('',
161 module_to_run = Unicode('',
163 help="Run the module as a script."
162 help="Run the module as a script."
164 ).tag(config=True)
163 ).tag(config=True)
165 gui = CaselessStrEnum(gui_keys, allow_none=True,
164 gui = CaselessStrEnum(gui_keys, allow_none=True,
166 help="Enable GUI event loop integration with any of {0}.".format(gui_keys)
165 help="Enable GUI event loop integration with any of {0}.".format(gui_keys)
167 ).tag(config=True)
166 ).tag(config=True)
168 matplotlib = CaselessStrEnum(backend_keys, allow_none=True,
167 matplotlib = CaselessStrEnum(backend_keys, allow_none=True,
169 help="""Configure matplotlib for interactive use with
168 help="""Configure matplotlib for interactive use with
170 the default matplotlib backend."""
169 the default matplotlib backend."""
171 ).tag(config=True)
170 ).tag(config=True)
172 pylab = CaselessStrEnum(backend_keys, allow_none=True,
171 pylab = CaselessStrEnum(backend_keys, allow_none=True,
173 help="""Pre-load matplotlib and numpy for interactive use,
172 help="""Pre-load matplotlib and numpy for interactive use,
174 selecting a particular matplotlib backend and loop integration.
173 selecting a particular matplotlib backend and loop integration.
175 """
174 """
176 ).tag(config=True)
175 ).tag(config=True)
177 pylab_import_all = Bool(True,
176 pylab_import_all = Bool(True,
178 help="""If true, IPython will populate the user namespace with numpy, pylab, etc.
177 help="""If true, IPython will populate the user namespace with numpy, pylab, etc.
179 and an ``import *`` is done from numpy and pylab, when using pylab mode.
178 and an ``import *`` is done from numpy and pylab, when using pylab mode.
180
179
181 When False, pylab mode should not import any names into the user namespace.
180 When False, pylab mode should not import any names into the user namespace.
182 """
181 """
183 ).tag(config=True)
182 ).tag(config=True)
184 ignore_cwd = Bool(
183 ignore_cwd = Bool(
185 False,
184 False,
186 help="""If True, IPython will not add the current working directory to sys.path.
185 help="""If True, IPython will not add the current working directory to sys.path.
187 When False, the current working directory is added to sys.path, allowing imports
186 When False, the current working directory is added to sys.path, allowing imports
188 of modules defined in the current directory."""
187 of modules defined in the current directory."""
189 ).tag(config=True)
188 ).tag(config=True)
190 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC',
189 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC',
191 allow_none=True)
190 allow_none=True)
192 # whether interact-loop should start
191 # whether interact-loop should start
193 interact = Bool(True)
192 interact = Bool(True)
194
193
195 user_ns = Instance(dict, args=None, allow_none=True)
194 user_ns = Instance(dict, args=None, allow_none=True)
196 @observe('user_ns')
195 @observe('user_ns')
197 def _user_ns_changed(self, change):
196 def _user_ns_changed(self, change):
198 if self.shell is not None:
197 if self.shell is not None:
199 self.shell.user_ns = change['new']
198 self.shell.user_ns = change['new']
200 self.shell.init_user_ns()
199 self.shell.init_user_ns()
201
200
202 def init_path(self):
201 def init_path(self):
203 """Add current working directory, '', to sys.path
202 """Add current working directory, '', to sys.path
204
203
205 Unlike Python's default, we insert before the first `site-packages`
204 Unlike Python's default, we insert before the first `site-packages`
206 or `dist-packages` directory,
205 or `dist-packages` directory,
207 so that it is after the standard library.
206 so that it is after the standard library.
208
207
209 .. versionchanged:: 7.2
208 .. versionchanged:: 7.2
210 Try to insert after the standard library, instead of first.
209 Try to insert after the standard library, instead of first.
211 .. versionchanged:: 8.0
210 .. versionchanged:: 8.0
212 Allow optionally not including the current directory in sys.path
211 Allow optionally not including the current directory in sys.path
213 """
212 """
214 if '' in sys.path or self.ignore_cwd:
213 if '' in sys.path or self.ignore_cwd:
215 return
214 return
216 for idx, path in enumerate(sys.path):
215 for idx, path in enumerate(sys.path):
217 parent, last_part = os.path.split(path)
216 parent, last_part = os.path.split(path)
218 if last_part in {'site-packages', 'dist-packages'}:
217 if last_part in {'site-packages', 'dist-packages'}:
219 break
218 break
220 else:
219 else:
221 # no site-packages or dist-packages found (?!)
220 # no site-packages or dist-packages found (?!)
222 # back to original behavior of inserting at the front
221 # back to original behavior of inserting at the front
223 idx = 0
222 idx = 0
224 sys.path.insert(idx, '')
223 sys.path.insert(idx, '')
225
224
226 def init_shell(self):
225 def init_shell(self):
227 raise NotImplementedError("Override in subclasses")
226 raise NotImplementedError("Override in subclasses")
228
227
229 def init_gui_pylab(self):
228 def init_gui_pylab(self):
230 """Enable GUI event loop integration, taking pylab into account."""
229 """Enable GUI event loop integration, taking pylab into account."""
231 enable = False
230 enable = False
232 shell = self.shell
231 shell = self.shell
233 if self.pylab:
232 if self.pylab:
234 enable = lambda key: shell.enable_pylab(key, import_all=self.pylab_import_all)
233 enable = lambda key: shell.enable_pylab(key, import_all=self.pylab_import_all)
235 key = self.pylab
234 key = self.pylab
236 elif self.matplotlib:
235 elif self.matplotlib:
237 enable = shell.enable_matplotlib
236 enable = shell.enable_matplotlib
238 key = self.matplotlib
237 key = self.matplotlib
239 elif self.gui:
238 elif self.gui:
240 enable = shell.enable_gui
239 enable = shell.enable_gui
241 key = self.gui
240 key = self.gui
242
241
243 if not enable:
242 if not enable:
244 return
243 return
245
244
246 try:
245 try:
247 r = enable(key)
246 r = enable(key)
248 except ImportError:
247 except ImportError:
249 self.log.warning("Eventloop or matplotlib integration failed. Is matplotlib installed?")
248 self.log.warning("Eventloop or matplotlib integration failed. Is matplotlib installed?")
250 self.shell.showtraceback()
249 self.shell.showtraceback()
251 return
250 return
252 except Exception:
251 except Exception:
253 self.log.warning("GUI event loop or pylab initialization failed")
252 self.log.warning("GUI event loop or pylab initialization failed")
254 self.shell.showtraceback()
253 self.shell.showtraceback()
255 return
254 return
256
255
257 if isinstance(r, tuple):
256 if isinstance(r, tuple):
258 gui, backend = r[:2]
257 gui, backend = r[:2]
259 self.log.info("Enabling GUI event loop integration, "
258 self.log.info("Enabling GUI event loop integration, "
260 "eventloop=%s, matplotlib=%s", gui, backend)
259 "eventloop=%s, matplotlib=%s", gui, backend)
261 if key == "auto":
260 if key == "auto":
262 print("Using matplotlib backend: %s" % backend)
261 print("Using matplotlib backend: %s" % backend)
263 else:
262 else:
264 gui = r
263 gui = r
265 self.log.info("Enabling GUI event loop integration, "
264 self.log.info("Enabling GUI event loop integration, "
266 "eventloop=%s", gui)
265 "eventloop=%s", gui)
267
266
268 def init_extensions(self):
267 def init_extensions(self):
269 """Load all IPython extensions in IPythonApp.extensions.
268 """Load all IPython extensions in IPythonApp.extensions.
270
269
271 This uses the :meth:`ExtensionManager.load_extensions` to load all
270 This uses the :meth:`ExtensionManager.load_extensions` to load all
272 the extensions listed in ``self.extensions``.
271 the extensions listed in ``self.extensions``.
273 """
272 """
274 try:
273 try:
275 self.log.debug("Loading IPython extensions...")
274 self.log.debug("Loading IPython extensions...")
276 extensions = (
275 extensions = (
277 self.default_extensions + self.extensions + self.extra_extensions
276 self.default_extensions + self.extensions + self.extra_extensions
278 )
277 )
279 for ext in extensions:
278 for ext in extensions:
280 try:
279 try:
281 self.log.info("Loading IPython extension: %s", ext)
280 self.log.info("Loading IPython extension: %s", ext)
282 self.shell.extension_manager.load_extension(ext)
281 self.shell.extension_manager.load_extension(ext)
283 except:
282 except:
284 if self.reraise_ipython_extension_failures:
283 if self.reraise_ipython_extension_failures:
285 raise
284 raise
286 msg = ("Error in loading extension: {ext}\n"
285 msg = ("Error in loading extension: {ext}\n"
287 "Check your config files in {location}".format(
286 "Check your config files in {location}".format(
288 ext=ext,
287 ext=ext,
289 location=self.profile_dir.location
288 location=self.profile_dir.location
290 ))
289 ))
291 self.log.warning(msg, exc_info=True)
290 self.log.warning(msg, exc_info=True)
292 except:
291 except:
293 if self.reraise_ipython_extension_failures:
292 if self.reraise_ipython_extension_failures:
294 raise
293 raise
295 self.log.warning("Unknown error in loading extensions:", exc_info=True)
294 self.log.warning("Unknown error in loading extensions:", exc_info=True)
296
295
297 def init_code(self):
296 def init_code(self):
298 """run the pre-flight code, specified via exec_lines"""
297 """run the pre-flight code, specified via exec_lines"""
299 self._run_startup_files()
298 self._run_startup_files()
300 self._run_exec_lines()
299 self._run_exec_lines()
301 self._run_exec_files()
300 self._run_exec_files()
302
301
303 # Hide variables defined here from %who etc.
302 # Hide variables defined here from %who etc.
304 if self.hide_initial_ns:
303 if self.hide_initial_ns:
305 self.shell.user_ns_hidden.update(self.shell.user_ns)
304 self.shell.user_ns_hidden.update(self.shell.user_ns)
306
305
307 # command-line execution (ipython -i script.py, ipython -m module)
306 # command-line execution (ipython -i script.py, ipython -m module)
308 # should *not* be excluded from %whos
307 # should *not* be excluded from %whos
309 self._run_cmd_line_code()
308 self._run_cmd_line_code()
310 self._run_module()
309 self._run_module()
311
310
312 # flush output, so itwon't be attached to the first cell
311 # flush output, so itwon't be attached to the first cell
313 sys.stdout.flush()
312 sys.stdout.flush()
314 sys.stderr.flush()
313 sys.stderr.flush()
315 self.shell._sys_modules_keys = set(sys.modules.keys())
314 self.shell._sys_modules_keys = set(sys.modules.keys())
316
315
317 def _run_exec_lines(self):
316 def _run_exec_lines(self):
318 """Run lines of code in IPythonApp.exec_lines in the user's namespace."""
317 """Run lines of code in IPythonApp.exec_lines in the user's namespace."""
319 if not self.exec_lines:
318 if not self.exec_lines:
320 return
319 return
321 try:
320 try:
322 self.log.debug("Running code from IPythonApp.exec_lines...")
321 self.log.debug("Running code from IPythonApp.exec_lines...")
323 for line in self.exec_lines:
322 for line in self.exec_lines:
324 try:
323 try:
325 self.log.info("Running code in user namespace: %s" %
324 self.log.info("Running code in user namespace: %s" %
326 line)
325 line)
327 self.shell.run_cell(line, store_history=False)
326 self.shell.run_cell(line, store_history=False)
328 except:
327 except:
329 self.log.warning("Error in executing line in user "
328 self.log.warning("Error in executing line in user "
330 "namespace: %s" % line)
329 "namespace: %s" % line)
331 self.shell.showtraceback()
330 self.shell.showtraceback()
332 except:
331 except:
333 self.log.warning("Unknown error in handling IPythonApp.exec_lines:")
332 self.log.warning("Unknown error in handling IPythonApp.exec_lines:")
334 self.shell.showtraceback()
333 self.shell.showtraceback()
335
334
336 def _exec_file(self, fname, shell_futures=False):
335 def _exec_file(self, fname, shell_futures=False):
337 try:
336 try:
338 full_filename = filefind(fname, [u'.', self.ipython_dir])
337 full_filename = filefind(fname, [u'.', self.ipython_dir])
339 except IOError:
338 except IOError:
340 self.log.warning("File not found: %r"%fname)
339 self.log.warning("File not found: %r"%fname)
341 return
340 return
342 # Make sure that the running script gets a proper sys.argv as if it
341 # Make sure that the running script gets a proper sys.argv as if it
343 # were run from a system shell.
342 # were run from a system shell.
344 save_argv = sys.argv
343 save_argv = sys.argv
345 sys.argv = [full_filename] + self.extra_args[1:]
344 sys.argv = [full_filename] + self.extra_args[1:]
346 try:
345 try:
347 if os.path.isfile(full_filename):
346 if os.path.isfile(full_filename):
348 self.log.info("Running file in user namespace: %s" %
347 self.log.info("Running file in user namespace: %s" %
349 full_filename)
348 full_filename)
350 # Ensure that __file__ is always defined to match Python
349 # Ensure that __file__ is always defined to match Python
351 # behavior.
350 # behavior.
352 with preserve_keys(self.shell.user_ns, '__file__'):
351 with preserve_keys(self.shell.user_ns, '__file__'):
353 self.shell.user_ns['__file__'] = fname
352 self.shell.user_ns['__file__'] = fname
354 if full_filename.endswith('.ipy') or full_filename.endswith('.ipynb'):
353 if full_filename.endswith('.ipy') or full_filename.endswith('.ipynb'):
355 self.shell.safe_execfile_ipy(full_filename,
354 self.shell.safe_execfile_ipy(full_filename,
356 shell_futures=shell_futures)
355 shell_futures=shell_futures)
357 else:
356 else:
358 # default to python, even without extension
357 # default to python, even without extension
359 self.shell.safe_execfile(full_filename,
358 self.shell.safe_execfile(full_filename,
360 self.shell.user_ns,
359 self.shell.user_ns,
361 shell_futures=shell_futures,
360 shell_futures=shell_futures,
362 raise_exceptions=True)
361 raise_exceptions=True)
363 finally:
362 finally:
364 sys.argv = save_argv
363 sys.argv = save_argv
365
364
366 def _run_startup_files(self):
365 def _run_startup_files(self):
367 """Run files from profile startup directory"""
366 """Run files from profile startup directory"""
368 startup_dirs = [self.profile_dir.startup_dir] + [
367 startup_dirs = [self.profile_dir.startup_dir] + [
369 os.path.join(p, 'startup') for p in chain(ENV_CONFIG_DIRS, SYSTEM_CONFIG_DIRS)
368 os.path.join(p, 'startup') for p in chain(ENV_CONFIG_DIRS, SYSTEM_CONFIG_DIRS)
370 ]
369 ]
371 startup_files = []
370 startup_files = []
372
371
373 if self.exec_PYTHONSTARTUP and os.environ.get('PYTHONSTARTUP', False) and \
372 if self.exec_PYTHONSTARTUP and os.environ.get('PYTHONSTARTUP', False) and \
374 not (self.file_to_run or self.code_to_run or self.module_to_run):
373 not (self.file_to_run or self.code_to_run or self.module_to_run):
375 python_startup = os.environ['PYTHONSTARTUP']
374 python_startup = os.environ['PYTHONSTARTUP']
376 self.log.debug("Running PYTHONSTARTUP file %s...", python_startup)
375 self.log.debug("Running PYTHONSTARTUP file %s...", python_startup)
377 try:
376 try:
378 self._exec_file(python_startup)
377 self._exec_file(python_startup)
379 except:
378 except:
380 self.log.warning("Unknown error in handling PYTHONSTARTUP file %s:", python_startup)
379 self.log.warning("Unknown error in handling PYTHONSTARTUP file %s:", python_startup)
381 self.shell.showtraceback()
380 self.shell.showtraceback()
382 for startup_dir in startup_dirs[::-1]:
381 for startup_dir in startup_dirs[::-1]:
383 startup_files += glob.glob(os.path.join(startup_dir, '*.py'))
382 startup_files += glob.glob(os.path.join(startup_dir, '*.py'))
384 startup_files += glob.glob(os.path.join(startup_dir, '*.ipy'))
383 startup_files += glob.glob(os.path.join(startup_dir, '*.ipy'))
385 if not startup_files:
384 if not startup_files:
386 return
385 return
387
386
388 self.log.debug("Running startup files from %s...", startup_dir)
387 self.log.debug("Running startup files from %s...", startup_dir)
389 try:
388 try:
390 for fname in sorted(startup_files):
389 for fname in sorted(startup_files):
391 self._exec_file(fname)
390 self._exec_file(fname)
392 except:
391 except:
393 self.log.warning("Unknown error in handling startup files:")
392 self.log.warning("Unknown error in handling startup files:")
394 self.shell.showtraceback()
393 self.shell.showtraceback()
395
394
396 def _run_exec_files(self):
395 def _run_exec_files(self):
397 """Run files from IPythonApp.exec_files"""
396 """Run files from IPythonApp.exec_files"""
398 if not self.exec_files:
397 if not self.exec_files:
399 return
398 return
400
399
401 self.log.debug("Running files in IPythonApp.exec_files...")
400 self.log.debug("Running files in IPythonApp.exec_files...")
402 try:
401 try:
403 for fname in self.exec_files:
402 for fname in self.exec_files:
404 self._exec_file(fname)
403 self._exec_file(fname)
405 except:
404 except:
406 self.log.warning("Unknown error in handling IPythonApp.exec_files:")
405 self.log.warning("Unknown error in handling IPythonApp.exec_files:")
407 self.shell.showtraceback()
406 self.shell.showtraceback()
408
407
409 def _run_cmd_line_code(self):
408 def _run_cmd_line_code(self):
410 """Run code or file specified at the command-line"""
409 """Run code or file specified at the command-line"""
411 if self.code_to_run:
410 if self.code_to_run:
412 line = self.code_to_run
411 line = self.code_to_run
413 try:
412 try:
414 self.log.info("Running code given at command line (c=): %s" %
413 self.log.info("Running code given at command line (c=): %s" %
415 line)
414 line)
416 self.shell.run_cell(line, store_history=False)
415 self.shell.run_cell(line, store_history=False)
417 except:
416 except:
418 self.log.warning("Error in executing line in user namespace: %s" %
417 self.log.warning("Error in executing line in user namespace: %s" %
419 line)
418 line)
420 self.shell.showtraceback()
419 self.shell.showtraceback()
421 if not self.interact:
420 if not self.interact:
422 self.exit(1)
421 self.exit(1)
423
422
424 # Like Python itself, ignore the second if the first of these is present
423 # Like Python itself, ignore the second if the first of these is present
425 elif self.file_to_run:
424 elif self.file_to_run:
426 fname = self.file_to_run
425 fname = self.file_to_run
427 if os.path.isdir(fname):
426 if os.path.isdir(fname):
428 fname = os.path.join(fname, "__main__.py")
427 fname = os.path.join(fname, "__main__.py")
429 if not os.path.exists(fname):
428 if not os.path.exists(fname):
430 self.log.warning("File '%s' doesn't exist", fname)
429 self.log.warning("File '%s' doesn't exist", fname)
431 if not self.interact:
430 if not self.interact:
432 self.exit(2)
431 self.exit(2)
433 try:
432 try:
434 self._exec_file(fname, shell_futures=True)
433 self._exec_file(fname, shell_futures=True)
435 except:
434 except:
436 self.shell.showtraceback(tb_offset=4)
435 self.shell.showtraceback(tb_offset=4)
437 if not self.interact:
436 if not self.interact:
438 self.exit(1)
437 self.exit(1)
439
438
440 def _run_module(self):
439 def _run_module(self):
441 """Run module specified at the command-line."""
440 """Run module specified at the command-line."""
442 if self.module_to_run:
441 if self.module_to_run:
443 # Make sure that the module gets a proper sys.argv as if it were
442 # Make sure that the module gets a proper sys.argv as if it were
444 # run using `python -m`.
443 # run using `python -m`.
445 save_argv = sys.argv
444 save_argv = sys.argv
446 sys.argv = [sys.executable] + self.extra_args
445 sys.argv = [sys.executable] + self.extra_args
447 try:
446 try:
448 self.shell.safe_run_module(self.module_to_run,
447 self.shell.safe_run_module(self.module_to_run,
449 self.shell.user_ns)
448 self.shell.user_ns)
450 finally:
449 finally:
451 sys.argv = save_argv
450 sys.argv = save_argv
@@ -1,270 +1,270
1 """Tests for pylab tools module.
1 """Tests for pylab tools module.
2 """
2 """
3
3
4 # Copyright (c) IPython Development Team.
4 # Copyright (c) IPython Development Team.
5 # Distributed under the terms of the Modified BSD License.
5 # Distributed under the terms of the Modified BSD License.
6
6
7
7
8 from binascii import a2b_base64
8 from binascii import a2b_base64
9 from io import BytesIO
9 from io import BytesIO
10
10
11 import pytest
11 import pytest
12
12
13 matplotlib = pytest.importorskip("matplotlib")
13 matplotlib = pytest.importorskip("matplotlib")
14 matplotlib.use('Agg')
14 matplotlib.use('Agg')
15 from matplotlib.figure import Figure
15 from matplotlib.figure import Figure
16
16
17 from matplotlib import pyplot as plt
17 from matplotlib import pyplot as plt
18 from matplotlib_inline import backend_inline
18 from matplotlib_inline import backend_inline
19 import numpy as np
19 import numpy as np
20
20
21 from IPython.core.getipython import get_ipython
21 from IPython.core.getipython import get_ipython
22 from IPython.core.interactiveshell import InteractiveShell
22 from IPython.core.interactiveshell import InteractiveShell
23 from IPython.core.display import _PNG, _JPEG
23 from IPython.core.display import _PNG, _JPEG
24 from .. import pylabtools as pt
24 from .. import pylabtools as pt
25
25
26 from IPython.testing import decorators as dec
26 from IPython.testing import decorators as dec
27
27
28
28
29 def test_figure_to_svg():
29 def test_figure_to_svg():
30 # simple empty-figure test
30 # simple empty-figure test
31 fig = plt.figure()
31 fig = plt.figure()
32 assert pt.print_figure(fig, "svg") is None
32 assert pt.print_figure(fig, "svg") is None
33
33
34 plt.close('all')
34 plt.close('all')
35
35
36 # simple check for at least svg-looking output
36 # simple check for at least svg-looking output
37 fig = plt.figure()
37 fig = plt.figure()
38 ax = fig.add_subplot(1,1,1)
38 ax = fig.add_subplot(1,1,1)
39 ax.plot([1,2,3])
39 ax.plot([1,2,3])
40 plt.draw()
40 plt.draw()
41 svg = pt.print_figure(fig, "svg")[:100].lower()
41 svg = pt.print_figure(fig, "svg")[:100].lower()
42 assert "doctype svg" in svg
42 assert "doctype svg" in svg
43
43
44
44
45 def _check_pil_jpeg_bytes():
45 def _check_pil_jpeg_bytes():
46 """Skip if PIL can't write JPEGs to BytesIO objects"""
46 """Skip if PIL can't write JPEGs to BytesIO objects"""
47 # PIL's JPEG plugin can't write to BytesIO objects
47 # PIL's JPEG plugin can't write to BytesIO objects
48 # Pillow fixes this
48 # Pillow fixes this
49 from PIL import Image
49 from PIL import Image
50 buf = BytesIO()
50 buf = BytesIO()
51 img = Image.new("RGB", (4,4))
51 img = Image.new("RGB", (4,4))
52 try:
52 try:
53 img.save(buf, 'jpeg')
53 img.save(buf, 'jpeg')
54 except Exception as e:
54 except Exception as e:
55 ename = e.__class__.__name__
55 ename = e.__class__.__name__
56 raise pytest.skip("PIL can't write JPEG to BytesIO: %s: %s" % (ename, e)) from e
56 raise pytest.skip("PIL can't write JPEG to BytesIO: %s: %s" % (ename, e)) from e
57
57
58 @dec.skip_without("PIL.Image")
58 @dec.skip_without("PIL.Image")
59 def test_figure_to_jpeg():
59 def test_figure_to_jpeg():
60 _check_pil_jpeg_bytes()
60 _check_pil_jpeg_bytes()
61 # simple check for at least jpeg-looking output
61 # simple check for at least jpeg-looking output
62 fig = plt.figure()
62 fig = plt.figure()
63 ax = fig.add_subplot(1,1,1)
63 ax = fig.add_subplot(1,1,1)
64 ax.plot([1,2,3])
64 ax.plot([1,2,3])
65 plt.draw()
65 plt.draw()
66 jpeg = pt.print_figure(fig, 'jpeg', pil_kwargs={'optimize': 50})[:100].lower()
66 jpeg = pt.print_figure(fig, 'jpeg', pil_kwargs={'optimize': 50})[:100].lower()
67 assert jpeg.startswith(_JPEG)
67 assert jpeg.startswith(_JPEG)
68
68
69 def test_retina_figure():
69 def test_retina_figure():
70 # simple empty-figure test
70 # simple empty-figure test
71 fig = plt.figure()
71 fig = plt.figure()
72 assert pt.retina_figure(fig) == None
72 assert pt.retina_figure(fig) == None
73 plt.close('all')
73 plt.close('all')
74
74
75 fig = plt.figure()
75 fig = plt.figure()
76 ax = fig.add_subplot(1,1,1)
76 ax = fig.add_subplot(1,1,1)
77 ax.plot([1,2,3])
77 ax.plot([1,2,3])
78 plt.draw()
78 plt.draw()
79 png, md = pt.retina_figure(fig)
79 png, md = pt.retina_figure(fig)
80 assert png.startswith(_PNG)
80 assert png.startswith(_PNG)
81 assert "width" in md
81 assert "width" in md
82 assert "height" in md
82 assert "height" in md
83
83
84
84
85 _fmt_mime_map = {
85 _fmt_mime_map = {
86 'png': 'image/png',
86 'png': 'image/png',
87 'jpeg': 'image/jpeg',
87 'jpeg': 'image/jpeg',
88 'pdf': 'application/pdf',
88 'pdf': 'application/pdf',
89 'retina': 'image/png',
89 'retina': 'image/png',
90 'svg': 'image/svg+xml',
90 'svg': 'image/svg+xml',
91 }
91 }
92
92
93 def test_select_figure_formats_str():
93 def test_select_figure_formats_str():
94 ip = get_ipython()
94 ip = get_ipython()
95 for fmt, active_mime in _fmt_mime_map.items():
95 for fmt, active_mime in _fmt_mime_map.items():
96 pt.select_figure_formats(ip, fmt)
96 pt.select_figure_formats(ip, fmt)
97 for mime, f in ip.display_formatter.formatters.items():
97 for mime, f in ip.display_formatter.formatters.items():
98 if mime == active_mime:
98 if mime == active_mime:
99 assert Figure in f
99 assert Figure in f
100 else:
100 else:
101 assert Figure not in f
101 assert Figure not in f
102
102
103 def test_select_figure_formats_kwargs():
103 def test_select_figure_formats_kwargs():
104 ip = get_ipython()
104 ip = get_ipython()
105 kwargs = dict(bbox_inches="tight")
105 kwargs = dict(bbox_inches="tight")
106 pt.select_figure_formats(ip, "png", **kwargs)
106 pt.select_figure_formats(ip, "png", **kwargs)
107 formatter = ip.display_formatter.formatters["image/png"]
107 formatter = ip.display_formatter.formatters["image/png"]
108 f = formatter.lookup_by_type(Figure)
108 f = formatter.lookup_by_type(Figure)
109 cell = f.keywords
109 cell = f.keywords
110 expected = kwargs
110 expected = kwargs
111 expected["base64"] = True
111 expected["base64"] = True
112 expected["fmt"] = "png"
112 expected["fmt"] = "png"
113 assert cell == expected
113 assert cell == expected
114
114
115 # check that the formatter doesn't raise
115 # check that the formatter doesn't raise
116 fig = plt.figure()
116 fig = plt.figure()
117 ax = fig.add_subplot(1,1,1)
117 ax = fig.add_subplot(1,1,1)
118 ax.plot([1,2,3])
118 ax.plot([1,2,3])
119 plt.draw()
119 plt.draw()
120 formatter.enabled = True
120 formatter.enabled = True
121 png = formatter(fig)
121 png = formatter(fig)
122 assert isinstance(png, str)
122 assert isinstance(png, str)
123 png_bytes = a2b_base64(png)
123 png_bytes = a2b_base64(png)
124 assert png_bytes.startswith(_PNG)
124 assert png_bytes.startswith(_PNG)
125
125
126 def test_select_figure_formats_set():
126 def test_select_figure_formats_set():
127 ip = get_ipython()
127 ip = get_ipython()
128 for fmts in [
128 for fmts in [
129 {'png', 'svg'},
129 {'png', 'svg'},
130 ['png'],
130 ['png'],
131 ('jpeg', 'pdf', 'retina'),
131 ('jpeg', 'pdf', 'retina'),
132 {'svg'},
132 {'svg'},
133 ]:
133 ]:
134 active_mimes = {_fmt_mime_map[fmt] for fmt in fmts}
134 active_mimes = {_fmt_mime_map[fmt] for fmt in fmts}
135 pt.select_figure_formats(ip, fmts)
135 pt.select_figure_formats(ip, fmts)
136 for mime, f in ip.display_formatter.formatters.items():
136 for mime, f in ip.display_formatter.formatters.items():
137 if mime in active_mimes:
137 if mime in active_mimes:
138 assert Figure in f
138 assert Figure in f
139 else:
139 else:
140 assert Figure not in f
140 assert Figure not in f
141
141
142 def test_select_figure_formats_bad():
142 def test_select_figure_formats_bad():
143 ip = get_ipython()
143 ip = get_ipython()
144 with pytest.raises(ValueError):
144 with pytest.raises(ValueError):
145 pt.select_figure_formats(ip, 'foo')
145 pt.select_figure_formats(ip, 'foo')
146 with pytest.raises(ValueError):
146 with pytest.raises(ValueError):
147 pt.select_figure_formats(ip, {'png', 'foo'})
147 pt.select_figure_formats(ip, {'png', 'foo'})
148 with pytest.raises(ValueError):
148 with pytest.raises(ValueError):
149 pt.select_figure_formats(ip, ['retina', 'pdf', 'bar', 'bad'])
149 pt.select_figure_formats(ip, ['retina', 'pdf', 'bar', 'bad'])
150
150
151 def test_import_pylab():
151 def test_import_pylab():
152 ns = {}
152 ns = {}
153 pt.import_pylab(ns, import_all=False)
153 pt.import_pylab(ns, import_all=False)
154 assert "plt" in ns
154 assert "plt" in ns
155 assert ns["np"] == np
155 assert ns["np"] == np
156
156
157
157
158 class TestPylabSwitch(object):
158 class TestPylabSwitch(object):
159 class Shell(InteractiveShell):
159 class Shell(InteractiveShell):
160 def init_history(self):
160 def init_history(self):
161 """Sets up the command history, and starts regular autosaves."""
161 """Sets up the command history, and starts regular autosaves."""
162 self.config.HistoryManager.hist_file = ":memory:"
162 self.config.HistoryManager.hist_file = ":memory:"
163 super().init_history()
163 super().init_history()
164
164
165 def enable_gui(self, gui):
165 def enable_gui(self, gui):
166 pass
166 pass
167
167
168 def setup(self):
168 def setup(self):
169 import matplotlib
169 import matplotlib
170 def act_mpl(backend):
170 def act_mpl(backend):
171 matplotlib.rcParams['backend'] = backend
171 matplotlib.rcParams['backend'] = backend
172
172
173 # Save rcParams since they get modified
173 # Save rcParams since they get modified
174 self._saved_rcParams = matplotlib.rcParams
174 self._saved_rcParams = matplotlib.rcParams
175 self._saved_rcParamsOrig = matplotlib.rcParamsOrig
175 self._saved_rcParamsOrig = matplotlib.rcParamsOrig
176 matplotlib.rcParams = dict(backend="QtAgg")
176 matplotlib.rcParams = dict(backend="QtAgg")
177 matplotlib.rcParamsOrig = dict(backend="QtAgg")
177 matplotlib.rcParamsOrig = dict(backend="QtAgg")
178
178
179 # Mock out functions
179 # Mock out functions
180 self._save_am = pt.activate_matplotlib
180 self._save_am = pt.activate_matplotlib
181 pt.activate_matplotlib = act_mpl
181 pt.activate_matplotlib = act_mpl
182 self._save_ip = pt.import_pylab
182 self._save_ip = pt.import_pylab
183 pt.import_pylab = lambda *a,**kw:None
183 pt.import_pylab = lambda *a,**kw:None
184 self._save_cis = backend_inline.configure_inline_support
184 self._save_cis = backend_inline.configure_inline_support
185 backend_inline.configure_inline_support = lambda *a, **kw: None
185 backend_inline.configure_inline_support = lambda *a, **kw: None
186
186
187 def teardown(self):
187 def teardown(self):
188 pt.activate_matplotlib = self._save_am
188 pt.activate_matplotlib = self._save_am
189 pt.import_pylab = self._save_ip
189 pt.import_pylab = self._save_ip
190 backend_inline.configure_inline_support = self._save_cis
190 backend_inline.configure_inline_support = self._save_cis
191 import matplotlib
191 import matplotlib
192 matplotlib.rcParams = self._saved_rcParams
192 matplotlib.rcParams = self._saved_rcParams
193 matplotlib.rcParamsOrig = self._saved_rcParamsOrig
193 matplotlib.rcParamsOrig = self._saved_rcParamsOrig
194
194
195 def test_qt(self):
195 def test_qt(self):
196 s = self.Shell()
196 s = self.Shell()
197 gui, backend = s.enable_matplotlib(None)
197 gui, backend = s.enable_matplotlib(None)
198 assert gui == "qt"
198 assert gui == "qt"
199 assert s.pylab_gui_select == "qt"
199 assert s.pylab_gui_select == "qt"
200
200
201 gui, backend = s.enable_matplotlib("inline")
201 gui, backend = s.enable_matplotlib("inline")
202 assert gui == "inline"
202 assert gui is None
203 assert s.pylab_gui_select == "qt"
203 assert s.pylab_gui_select == "qt"
204
204
205 gui, backend = s.enable_matplotlib("qt")
205 gui, backend = s.enable_matplotlib("qt")
206 assert gui == "qt"
206 assert gui == "qt"
207 assert s.pylab_gui_select == "qt"
207 assert s.pylab_gui_select == "qt"
208
208
209 gui, backend = s.enable_matplotlib("inline")
209 gui, backend = s.enable_matplotlib("inline")
210 assert gui == "inline"
210 assert gui is None
211 assert s.pylab_gui_select == "qt"
211 assert s.pylab_gui_select == "qt"
212
212
213 gui, backend = s.enable_matplotlib()
213 gui, backend = s.enable_matplotlib()
214 assert gui == "qt"
214 assert gui == "qt"
215 assert s.pylab_gui_select == "qt"
215 assert s.pylab_gui_select == "qt"
216
216
217 def test_inline(self):
217 def test_inline(self):
218 s = self.Shell()
218 s = self.Shell()
219 gui, backend = s.enable_matplotlib("inline")
219 gui, backend = s.enable_matplotlib("inline")
220 assert gui == "inline"
220 assert gui is None
221 assert s.pylab_gui_select == None
221 assert s.pylab_gui_select == None
222
222
223 gui, backend = s.enable_matplotlib("inline")
223 gui, backend = s.enable_matplotlib("inline")
224 assert gui == "inline"
224 assert gui is None
225 assert s.pylab_gui_select == None
225 assert s.pylab_gui_select == None
226
226
227 gui, backend = s.enable_matplotlib("qt")
227 gui, backend = s.enable_matplotlib("qt")
228 assert gui == "qt"
228 assert gui == "qt"
229 assert s.pylab_gui_select == "qt"
229 assert s.pylab_gui_select == "qt"
230
230
231 def test_inline_twice(self):
231 def test_inline_twice(self):
232 "Using '%matplotlib inline' twice should not reset formatters"
232 "Using '%matplotlib inline' twice should not reset formatters"
233
233
234 ip = self.Shell()
234 ip = self.Shell()
235 gui, backend = ip.enable_matplotlib("inline")
235 gui, backend = ip.enable_matplotlib("inline")
236 assert gui == "inline"
236 assert gui is None
237
237
238 fmts = {'png'}
238 fmts = {'png'}
239 active_mimes = {_fmt_mime_map[fmt] for fmt in fmts}
239 active_mimes = {_fmt_mime_map[fmt] for fmt in fmts}
240 pt.select_figure_formats(ip, fmts)
240 pt.select_figure_formats(ip, fmts)
241
241
242 gui, backend = ip.enable_matplotlib("inline")
242 gui, backend = ip.enable_matplotlib("inline")
243 assert gui == "inline"
243 assert gui is None
244
244
245 for mime, f in ip.display_formatter.formatters.items():
245 for mime, f in ip.display_formatter.formatters.items():
246 if mime in active_mimes:
246 if mime in active_mimes:
247 assert Figure in f
247 assert Figure in f
248 else:
248 else:
249 assert Figure not in f
249 assert Figure not in f
250
250
251 def test_qt_gtk(self):
251 def test_qt_gtk(self):
252 s = self.Shell()
252 s = self.Shell()
253 gui, backend = s.enable_matplotlib("qt")
253 gui, backend = s.enable_matplotlib("qt")
254 assert gui == "qt"
254 assert gui == "qt"
255 assert s.pylab_gui_select == "qt"
255 assert s.pylab_gui_select == "qt"
256
256
257 gui, backend = s.enable_matplotlib("gtk")
257 gui, backend = s.enable_matplotlib("gtk3")
258 assert gui == "qt"
258 assert gui == "qt"
259 assert s.pylab_gui_select == "qt"
259 assert s.pylab_gui_select == "qt"
260
260
261
261
262 def test_no_gui_backends():
262 def test_no_gui_backends():
263 for k in ['agg', 'svg', 'pdf', 'ps']:
263 for k in ['agg', 'svg', 'pdf', 'ps']:
264 assert k not in pt.backend2gui
264 assert k not in pt.backend2gui
265
265
266
266
267 def test_figure_no_canvas():
267 def test_figure_no_canvas():
268 fig = Figure()
268 fig = Figure()
269 fig.canvas = None
269 fig.canvas = None
270 pt.print_figure(fig)
270 pt.print_figure(fig)
@@ -1,1010 +1,1010
1 """IPython terminal interface using prompt_toolkit"""
1 """IPython terminal interface using prompt_toolkit"""
2
2
3 import os
3 import os
4 import sys
4 import sys
5 import inspect
5 import inspect
6 from warnings import warn
6 from warnings import warn
7 from typing import Union as UnionType, Optional
7 from typing import Union as UnionType, Optional
8
8
9 from IPython.core.async_helpers import get_asyncio_loop
9 from IPython.core.async_helpers import get_asyncio_loop
10 from IPython.core.interactiveshell import InteractiveShell, InteractiveShellABC
10 from IPython.core.interactiveshell import InteractiveShell, InteractiveShellABC
11 from IPython.utils.py3compat import input
11 from IPython.utils.py3compat import input
12 from IPython.utils.terminal import toggle_set_term_title, set_term_title, restore_term_title
12 from IPython.utils.terminal import toggle_set_term_title, set_term_title, restore_term_title
13 from IPython.utils.process import abbrev_cwd
13 from IPython.utils.process import abbrev_cwd
14 from traitlets import (
14 from traitlets import (
15 Bool,
15 Bool,
16 Unicode,
16 Unicode,
17 Dict,
17 Dict,
18 Integer,
18 Integer,
19 List,
19 List,
20 observe,
20 observe,
21 Instance,
21 Instance,
22 Type,
22 Type,
23 default,
23 default,
24 Enum,
24 Enum,
25 Union,
25 Union,
26 Any,
26 Any,
27 validate,
27 validate,
28 Float,
28 Float,
29 )
29 )
30
30
31 from prompt_toolkit.auto_suggest import AutoSuggestFromHistory
31 from prompt_toolkit.auto_suggest import AutoSuggestFromHistory
32 from prompt_toolkit.enums import DEFAULT_BUFFER, EditingMode
32 from prompt_toolkit.enums import DEFAULT_BUFFER, EditingMode
33 from prompt_toolkit.filters import HasFocus, Condition, IsDone
33 from prompt_toolkit.filters import HasFocus, Condition, IsDone
34 from prompt_toolkit.formatted_text import PygmentsTokens
34 from prompt_toolkit.formatted_text import PygmentsTokens
35 from prompt_toolkit.history import History
35 from prompt_toolkit.history import History
36 from prompt_toolkit.layout.processors import ConditionalProcessor, HighlightMatchingBracketProcessor
36 from prompt_toolkit.layout.processors import ConditionalProcessor, HighlightMatchingBracketProcessor
37 from prompt_toolkit.output import ColorDepth
37 from prompt_toolkit.output import ColorDepth
38 from prompt_toolkit.patch_stdout import patch_stdout
38 from prompt_toolkit.patch_stdout import patch_stdout
39 from prompt_toolkit.shortcuts import PromptSession, CompleteStyle, print_formatted_text
39 from prompt_toolkit.shortcuts import PromptSession, CompleteStyle, print_formatted_text
40 from prompt_toolkit.styles import DynamicStyle, merge_styles
40 from prompt_toolkit.styles import DynamicStyle, merge_styles
41 from prompt_toolkit.styles.pygments import style_from_pygments_cls, style_from_pygments_dict
41 from prompt_toolkit.styles.pygments import style_from_pygments_cls, style_from_pygments_dict
42 from prompt_toolkit import __version__ as ptk_version
42 from prompt_toolkit import __version__ as ptk_version
43
43
44 from pygments.styles import get_style_by_name
44 from pygments.styles import get_style_by_name
45 from pygments.style import Style
45 from pygments.style import Style
46 from pygments.token import Token
46 from pygments.token import Token
47
47
48 from .debugger import TerminalPdb, Pdb
48 from .debugger import TerminalPdb, Pdb
49 from .magics import TerminalMagics
49 from .magics import TerminalMagics
50 from .pt_inputhooks import get_inputhook_name_and_func
50 from .pt_inputhooks import get_inputhook_name_and_func
51 from .prompts import Prompts, ClassicPrompts, RichPromptDisplayHook
51 from .prompts import Prompts, ClassicPrompts, RichPromptDisplayHook
52 from .ptutils import IPythonPTCompleter, IPythonPTLexer
52 from .ptutils import IPythonPTCompleter, IPythonPTLexer
53 from .shortcuts import (
53 from .shortcuts import (
54 KEY_BINDINGS,
54 KEY_BINDINGS,
55 create_ipython_shortcuts,
55 create_ipython_shortcuts,
56 create_identifier,
56 create_identifier,
57 RuntimeBinding,
57 RuntimeBinding,
58 add_binding,
58 add_binding,
59 )
59 )
60 from .shortcuts.filters import KEYBINDING_FILTERS, filter_from_string
60 from .shortcuts.filters import KEYBINDING_FILTERS, filter_from_string
61 from .shortcuts.auto_suggest import (
61 from .shortcuts.auto_suggest import (
62 NavigableAutoSuggestFromHistory,
62 NavigableAutoSuggestFromHistory,
63 AppendAutoSuggestionInAnyLine,
63 AppendAutoSuggestionInAnyLine,
64 )
64 )
65
65
66 PTK3 = ptk_version.startswith('3.')
66 PTK3 = ptk_version.startswith('3.')
67
67
68
68
69 class _NoStyle(Style):
69 class _NoStyle(Style):
70 pass
70 pass
71
71
72
72
73 _style_overrides_light_bg = {
73 _style_overrides_light_bg = {
74 Token.Prompt: '#ansibrightblue',
74 Token.Prompt: '#ansibrightblue',
75 Token.PromptNum: '#ansiblue bold',
75 Token.PromptNum: '#ansiblue bold',
76 Token.OutPrompt: '#ansibrightred',
76 Token.OutPrompt: '#ansibrightred',
77 Token.OutPromptNum: '#ansired bold',
77 Token.OutPromptNum: '#ansired bold',
78 }
78 }
79
79
80 _style_overrides_linux = {
80 _style_overrides_linux = {
81 Token.Prompt: '#ansibrightgreen',
81 Token.Prompt: '#ansibrightgreen',
82 Token.PromptNum: '#ansigreen bold',
82 Token.PromptNum: '#ansigreen bold',
83 Token.OutPrompt: '#ansibrightred',
83 Token.OutPrompt: '#ansibrightred',
84 Token.OutPromptNum: '#ansired bold',
84 Token.OutPromptNum: '#ansired bold',
85 }
85 }
86
86
87
87
88 def _backward_compat_continuation_prompt_tokens(method, width: int, *, lineno: int):
88 def _backward_compat_continuation_prompt_tokens(method, width: int, *, lineno: int):
89 """
89 """
90 Sagemath use custom prompt and we broke them in 8.19.
90 Sagemath use custom prompt and we broke them in 8.19.
91 """
91 """
92 sig = inspect.signature(method)
92 sig = inspect.signature(method)
93 if "lineno" in inspect.signature(method).parameters or any(
93 if "lineno" in inspect.signature(method).parameters or any(
94 [p.kind == p.VAR_KEYWORD for p in sig.parameters.values()]
94 [p.kind == p.VAR_KEYWORD for p in sig.parameters.values()]
95 ):
95 ):
96 return method(width, lineno=lineno)
96 return method(width, lineno=lineno)
97 else:
97 else:
98 return method(width)
98 return method(width)
99
99
100
100
101 def get_default_editor():
101 def get_default_editor():
102 try:
102 try:
103 return os.environ['EDITOR']
103 return os.environ['EDITOR']
104 except KeyError:
104 except KeyError:
105 pass
105 pass
106 except UnicodeError:
106 except UnicodeError:
107 warn("$EDITOR environment variable is not pure ASCII. Using platform "
107 warn("$EDITOR environment variable is not pure ASCII. Using platform "
108 "default editor.")
108 "default editor.")
109
109
110 if os.name == 'posix':
110 if os.name == 'posix':
111 return 'vi' # the only one guaranteed to be there!
111 return 'vi' # the only one guaranteed to be there!
112 else:
112 else:
113 return "notepad" # same in Windows!
113 return "notepad" # same in Windows!
114
114
115
115
116 # conservatively check for tty
116 # conservatively check for tty
117 # overridden streams can result in things like:
117 # overridden streams can result in things like:
118 # - sys.stdin = None
118 # - sys.stdin = None
119 # - no isatty method
119 # - no isatty method
120 for _name in ('stdin', 'stdout', 'stderr'):
120 for _name in ('stdin', 'stdout', 'stderr'):
121 _stream = getattr(sys, _name)
121 _stream = getattr(sys, _name)
122 try:
122 try:
123 if not _stream or not hasattr(_stream, "isatty") or not _stream.isatty():
123 if not _stream or not hasattr(_stream, "isatty") or not _stream.isatty():
124 _is_tty = False
124 _is_tty = False
125 break
125 break
126 except ValueError:
126 except ValueError:
127 # stream is closed
127 # stream is closed
128 _is_tty = False
128 _is_tty = False
129 break
129 break
130 else:
130 else:
131 _is_tty = True
131 _is_tty = True
132
132
133
133
134 _use_simple_prompt = ('IPY_TEST_SIMPLE_PROMPT' in os.environ) or (not _is_tty)
134 _use_simple_prompt = ('IPY_TEST_SIMPLE_PROMPT' in os.environ) or (not _is_tty)
135
135
136 def black_reformat_handler(text_before_cursor):
136 def black_reformat_handler(text_before_cursor):
137 """
137 """
138 We do not need to protect against error,
138 We do not need to protect against error,
139 this is taken care at a higher level where any reformat error is ignored.
139 this is taken care at a higher level where any reformat error is ignored.
140 Indeed we may call reformatting on incomplete code.
140 Indeed we may call reformatting on incomplete code.
141 """
141 """
142 import black
142 import black
143
143
144 formatted_text = black.format_str(text_before_cursor, mode=black.FileMode())
144 formatted_text = black.format_str(text_before_cursor, mode=black.FileMode())
145 if not text_before_cursor.endswith("\n") and formatted_text.endswith("\n"):
145 if not text_before_cursor.endswith("\n") and formatted_text.endswith("\n"):
146 formatted_text = formatted_text[:-1]
146 formatted_text = formatted_text[:-1]
147 return formatted_text
147 return formatted_text
148
148
149
149
150 def yapf_reformat_handler(text_before_cursor):
150 def yapf_reformat_handler(text_before_cursor):
151 from yapf.yapflib import file_resources
151 from yapf.yapflib import file_resources
152 from yapf.yapflib import yapf_api
152 from yapf.yapflib import yapf_api
153
153
154 style_config = file_resources.GetDefaultStyleForDir(os.getcwd())
154 style_config = file_resources.GetDefaultStyleForDir(os.getcwd())
155 formatted_text, was_formatted = yapf_api.FormatCode(
155 formatted_text, was_formatted = yapf_api.FormatCode(
156 text_before_cursor, style_config=style_config
156 text_before_cursor, style_config=style_config
157 )
157 )
158 if was_formatted:
158 if was_formatted:
159 if not text_before_cursor.endswith("\n") and formatted_text.endswith("\n"):
159 if not text_before_cursor.endswith("\n") and formatted_text.endswith("\n"):
160 formatted_text = formatted_text[:-1]
160 formatted_text = formatted_text[:-1]
161 return formatted_text
161 return formatted_text
162 else:
162 else:
163 return text_before_cursor
163 return text_before_cursor
164
164
165
165
166 class PtkHistoryAdapter(History):
166 class PtkHistoryAdapter(History):
167 """
167 """
168 Prompt toolkit has it's own way of handling history, Where it assumes it can
168 Prompt toolkit has it's own way of handling history, Where it assumes it can
169 Push/pull from history.
169 Push/pull from history.
170
170
171 """
171 """
172
172
173 def __init__(self, shell):
173 def __init__(self, shell):
174 super().__init__()
174 super().__init__()
175 self.shell = shell
175 self.shell = shell
176 self._refresh()
176 self._refresh()
177
177
178 def append_string(self, string):
178 def append_string(self, string):
179 # we rely on sql for that.
179 # we rely on sql for that.
180 self._loaded = False
180 self._loaded = False
181 self._refresh()
181 self._refresh()
182
182
183 def _refresh(self):
183 def _refresh(self):
184 if not self._loaded:
184 if not self._loaded:
185 self._loaded_strings = list(self.load_history_strings())
185 self._loaded_strings = list(self.load_history_strings())
186
186
187 def load_history_strings(self):
187 def load_history_strings(self):
188 last_cell = ""
188 last_cell = ""
189 res = []
189 res = []
190 for __, ___, cell in self.shell.history_manager.get_tail(
190 for __, ___, cell in self.shell.history_manager.get_tail(
191 self.shell.history_load_length, include_latest=True
191 self.shell.history_load_length, include_latest=True
192 ):
192 ):
193 # Ignore blank lines and consecutive duplicates
193 # Ignore blank lines and consecutive duplicates
194 cell = cell.rstrip()
194 cell = cell.rstrip()
195 if cell and (cell != last_cell):
195 if cell and (cell != last_cell):
196 res.append(cell)
196 res.append(cell)
197 last_cell = cell
197 last_cell = cell
198 yield from res[::-1]
198 yield from res[::-1]
199
199
200 def store_string(self, string: str) -> None:
200 def store_string(self, string: str) -> None:
201 pass
201 pass
202
202
203 class TerminalInteractiveShell(InteractiveShell):
203 class TerminalInteractiveShell(InteractiveShell):
204 mime_renderers = Dict().tag(config=True)
204 mime_renderers = Dict().tag(config=True)
205
205
206 space_for_menu = Integer(6, help='Number of line at the bottom of the screen '
206 space_for_menu = Integer(6, help='Number of line at the bottom of the screen '
207 'to reserve for the tab completion menu, '
207 'to reserve for the tab completion menu, '
208 'search history, ...etc, the height of '
208 'search history, ...etc, the height of '
209 'these menus will at most this value. '
209 'these menus will at most this value. '
210 'Increase it is you prefer long and skinny '
210 'Increase it is you prefer long and skinny '
211 'menus, decrease for short and wide.'
211 'menus, decrease for short and wide.'
212 ).tag(config=True)
212 ).tag(config=True)
213
213
214 pt_app: UnionType[PromptSession, None] = None
214 pt_app: UnionType[PromptSession, None] = None
215 auto_suggest: UnionType[
215 auto_suggest: UnionType[
216 AutoSuggestFromHistory, NavigableAutoSuggestFromHistory, None
216 AutoSuggestFromHistory, NavigableAutoSuggestFromHistory, None
217 ] = None
217 ] = None
218 debugger_history = None
218 debugger_history = None
219
219
220 debugger_history_file = Unicode(
220 debugger_history_file = Unicode(
221 "~/.pdbhistory", help="File in which to store and read history"
221 "~/.pdbhistory", help="File in which to store and read history"
222 ).tag(config=True)
222 ).tag(config=True)
223
223
224 simple_prompt = Bool(_use_simple_prompt,
224 simple_prompt = Bool(_use_simple_prompt,
225 help="""Use `raw_input` for the REPL, without completion and prompt colors.
225 help="""Use `raw_input` for the REPL, without completion and prompt colors.
226
226
227 Useful when controlling IPython as a subprocess, and piping STDIN/OUT/ERR. Known usage are:
227 Useful when controlling IPython as a subprocess, and piping STDIN/OUT/ERR. Known usage are:
228 IPython own testing machinery, and emacs inferior-shell integration through elpy.
228 IPython own testing machinery, and emacs inferior-shell integration through elpy.
229
229
230 This mode default to `True` if the `IPY_TEST_SIMPLE_PROMPT`
230 This mode default to `True` if the `IPY_TEST_SIMPLE_PROMPT`
231 environment variable is set, or the current terminal is not a tty."""
231 environment variable is set, or the current terminal is not a tty."""
232 ).tag(config=True)
232 ).tag(config=True)
233
233
234 @property
234 @property
235 def debugger_cls(self):
235 def debugger_cls(self):
236 return Pdb if self.simple_prompt else TerminalPdb
236 return Pdb if self.simple_prompt else TerminalPdb
237
237
238 confirm_exit = Bool(True,
238 confirm_exit = Bool(True,
239 help="""
239 help="""
240 Set to confirm when you try to exit IPython with an EOF (Control-D
240 Set to confirm when you try to exit IPython with an EOF (Control-D
241 in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit',
241 in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit',
242 you can force a direct exit without any confirmation.""",
242 you can force a direct exit without any confirmation.""",
243 ).tag(config=True)
243 ).tag(config=True)
244
244
245 editing_mode = Unicode('emacs',
245 editing_mode = Unicode('emacs',
246 help="Shortcut style to use at the prompt. 'vi' or 'emacs'.",
246 help="Shortcut style to use at the prompt. 'vi' or 'emacs'.",
247 ).tag(config=True)
247 ).tag(config=True)
248
248
249 emacs_bindings_in_vi_insert_mode = Bool(
249 emacs_bindings_in_vi_insert_mode = Bool(
250 True,
250 True,
251 help="Add shortcuts from 'emacs' insert mode to 'vi' insert mode.",
251 help="Add shortcuts from 'emacs' insert mode to 'vi' insert mode.",
252 ).tag(config=True)
252 ).tag(config=True)
253
253
254 modal_cursor = Bool(
254 modal_cursor = Bool(
255 True,
255 True,
256 help="""
256 help="""
257 Cursor shape changes depending on vi mode: beam in vi insert mode,
257 Cursor shape changes depending on vi mode: beam in vi insert mode,
258 block in nav mode, underscore in replace mode.""",
258 block in nav mode, underscore in replace mode.""",
259 ).tag(config=True)
259 ).tag(config=True)
260
260
261 ttimeoutlen = Float(
261 ttimeoutlen = Float(
262 0.01,
262 0.01,
263 help="""The time in milliseconds that is waited for a key code
263 help="""The time in milliseconds that is waited for a key code
264 to complete.""",
264 to complete.""",
265 ).tag(config=True)
265 ).tag(config=True)
266
266
267 timeoutlen = Float(
267 timeoutlen = Float(
268 0.5,
268 0.5,
269 help="""The time in milliseconds that is waited for a mapped key
269 help="""The time in milliseconds that is waited for a mapped key
270 sequence to complete.""",
270 sequence to complete.""",
271 ).tag(config=True)
271 ).tag(config=True)
272
272
273 autoformatter = Unicode(
273 autoformatter = Unicode(
274 None,
274 None,
275 help="Autoformatter to reformat Terminal code. Can be `'black'`, `'yapf'` or `None`",
275 help="Autoformatter to reformat Terminal code. Can be `'black'`, `'yapf'` or `None`",
276 allow_none=True
276 allow_none=True
277 ).tag(config=True)
277 ).tag(config=True)
278
278
279 auto_match = Bool(
279 auto_match = Bool(
280 False,
280 False,
281 help="""
281 help="""
282 Automatically add/delete closing bracket or quote when opening bracket or quote is entered/deleted.
282 Automatically add/delete closing bracket or quote when opening bracket or quote is entered/deleted.
283 Brackets: (), [], {}
283 Brackets: (), [], {}
284 Quotes: '', \"\"
284 Quotes: '', \"\"
285 """,
285 """,
286 ).tag(config=True)
286 ).tag(config=True)
287
287
288 mouse_support = Bool(False,
288 mouse_support = Bool(False,
289 help="Enable mouse support in the prompt\n(Note: prevents selecting text with the mouse)"
289 help="Enable mouse support in the prompt\n(Note: prevents selecting text with the mouse)"
290 ).tag(config=True)
290 ).tag(config=True)
291
291
292 # We don't load the list of styles for the help string, because loading
292 # We don't load the list of styles for the help string, because loading
293 # Pygments plugins takes time and can cause unexpected errors.
293 # Pygments plugins takes time and can cause unexpected errors.
294 highlighting_style = Union([Unicode('legacy'), Type(klass=Style)],
294 highlighting_style = Union([Unicode('legacy'), Type(klass=Style)],
295 help="""The name or class of a Pygments style to use for syntax
295 help="""The name or class of a Pygments style to use for syntax
296 highlighting. To see available styles, run `pygmentize -L styles`."""
296 highlighting. To see available styles, run `pygmentize -L styles`."""
297 ).tag(config=True)
297 ).tag(config=True)
298
298
299 @validate('editing_mode')
299 @validate('editing_mode')
300 def _validate_editing_mode(self, proposal):
300 def _validate_editing_mode(self, proposal):
301 if proposal['value'].lower() == 'vim':
301 if proposal['value'].lower() == 'vim':
302 proposal['value']= 'vi'
302 proposal['value']= 'vi'
303 elif proposal['value'].lower() == 'default':
303 elif proposal['value'].lower() == 'default':
304 proposal['value']= 'emacs'
304 proposal['value']= 'emacs'
305
305
306 if hasattr(EditingMode, proposal['value'].upper()):
306 if hasattr(EditingMode, proposal['value'].upper()):
307 return proposal['value'].lower()
307 return proposal['value'].lower()
308
308
309 return self.editing_mode
309 return self.editing_mode
310
310
311 @observe('editing_mode')
311 @observe('editing_mode')
312 def _editing_mode(self, change):
312 def _editing_mode(self, change):
313 if self.pt_app:
313 if self.pt_app:
314 self.pt_app.editing_mode = getattr(EditingMode, change.new.upper())
314 self.pt_app.editing_mode = getattr(EditingMode, change.new.upper())
315
315
316 def _set_formatter(self, formatter):
316 def _set_formatter(self, formatter):
317 if formatter is None:
317 if formatter is None:
318 self.reformat_handler = lambda x:x
318 self.reformat_handler = lambda x:x
319 elif formatter == 'black':
319 elif formatter == 'black':
320 self.reformat_handler = black_reformat_handler
320 self.reformat_handler = black_reformat_handler
321 elif formatter == "yapf":
321 elif formatter == "yapf":
322 self.reformat_handler = yapf_reformat_handler
322 self.reformat_handler = yapf_reformat_handler
323 else:
323 else:
324 raise ValueError
324 raise ValueError
325
325
326 @observe("autoformatter")
326 @observe("autoformatter")
327 def _autoformatter_changed(self, change):
327 def _autoformatter_changed(self, change):
328 formatter = change.new
328 formatter = change.new
329 self._set_formatter(formatter)
329 self._set_formatter(formatter)
330
330
331 @observe('highlighting_style')
331 @observe('highlighting_style')
332 @observe('colors')
332 @observe('colors')
333 def _highlighting_style_changed(self, change):
333 def _highlighting_style_changed(self, change):
334 self.refresh_style()
334 self.refresh_style()
335
335
336 def refresh_style(self):
336 def refresh_style(self):
337 self._style = self._make_style_from_name_or_cls(self.highlighting_style)
337 self._style = self._make_style_from_name_or_cls(self.highlighting_style)
338
338
339 highlighting_style_overrides = Dict(
339 highlighting_style_overrides = Dict(
340 help="Override highlighting format for specific tokens"
340 help="Override highlighting format for specific tokens"
341 ).tag(config=True)
341 ).tag(config=True)
342
342
343 true_color = Bool(False,
343 true_color = Bool(False,
344 help="""Use 24bit colors instead of 256 colors in prompt highlighting.
344 help="""Use 24bit colors instead of 256 colors in prompt highlighting.
345 If your terminal supports true color, the following command should
345 If your terminal supports true color, the following command should
346 print ``TRUECOLOR`` in orange::
346 print ``TRUECOLOR`` in orange::
347
347
348 printf \"\\x1b[38;2;255;100;0mTRUECOLOR\\x1b[0m\\n\"
348 printf \"\\x1b[38;2;255;100;0mTRUECOLOR\\x1b[0m\\n\"
349 """,
349 """,
350 ).tag(config=True)
350 ).tag(config=True)
351
351
352 editor = Unicode(get_default_editor(),
352 editor = Unicode(get_default_editor(),
353 help="Set the editor used by IPython (default to $EDITOR/vi/notepad)."
353 help="Set the editor used by IPython (default to $EDITOR/vi/notepad)."
354 ).tag(config=True)
354 ).tag(config=True)
355
355
356 prompts_class = Type(Prompts, help='Class used to generate Prompt token for prompt_toolkit').tag(config=True)
356 prompts_class = Type(Prompts, help='Class used to generate Prompt token for prompt_toolkit').tag(config=True)
357
357
358 prompts = Instance(Prompts)
358 prompts = Instance(Prompts)
359
359
360 @default('prompts')
360 @default('prompts')
361 def _prompts_default(self):
361 def _prompts_default(self):
362 return self.prompts_class(self)
362 return self.prompts_class(self)
363
363
364 # @observe('prompts')
364 # @observe('prompts')
365 # def _(self, change):
365 # def _(self, change):
366 # self._update_layout()
366 # self._update_layout()
367
367
368 @default('displayhook_class')
368 @default('displayhook_class')
369 def _displayhook_class_default(self):
369 def _displayhook_class_default(self):
370 return RichPromptDisplayHook
370 return RichPromptDisplayHook
371
371
372 term_title = Bool(True,
372 term_title = Bool(True,
373 help="Automatically set the terminal title"
373 help="Automatically set the terminal title"
374 ).tag(config=True)
374 ).tag(config=True)
375
375
376 term_title_format = Unicode("IPython: {cwd}",
376 term_title_format = Unicode("IPython: {cwd}",
377 help="Customize the terminal title format. This is a python format string. " +
377 help="Customize the terminal title format. This is a python format string. " +
378 "Available substitutions are: {cwd}."
378 "Available substitutions are: {cwd}."
379 ).tag(config=True)
379 ).tag(config=True)
380
380
381 display_completions = Enum(('column', 'multicolumn','readlinelike'),
381 display_completions = Enum(('column', 'multicolumn','readlinelike'),
382 help= ( "Options for displaying tab completions, 'column', 'multicolumn', and "
382 help= ( "Options for displaying tab completions, 'column', 'multicolumn', and "
383 "'readlinelike'. These options are for `prompt_toolkit`, see "
383 "'readlinelike'. These options are for `prompt_toolkit`, see "
384 "`prompt_toolkit` documentation for more information."
384 "`prompt_toolkit` documentation for more information."
385 ),
385 ),
386 default_value='multicolumn').tag(config=True)
386 default_value='multicolumn').tag(config=True)
387
387
388 highlight_matching_brackets = Bool(True,
388 highlight_matching_brackets = Bool(True,
389 help="Highlight matching brackets.",
389 help="Highlight matching brackets.",
390 ).tag(config=True)
390 ).tag(config=True)
391
391
392 extra_open_editor_shortcuts = Bool(False,
392 extra_open_editor_shortcuts = Bool(False,
393 help="Enable vi (v) or Emacs (C-X C-E) shortcuts to open an external editor. "
393 help="Enable vi (v) or Emacs (C-X C-E) shortcuts to open an external editor. "
394 "This is in addition to the F2 binding, which is always enabled."
394 "This is in addition to the F2 binding, which is always enabled."
395 ).tag(config=True)
395 ).tag(config=True)
396
396
397 handle_return = Any(None,
397 handle_return = Any(None,
398 help="Provide an alternative handler to be called when the user presses "
398 help="Provide an alternative handler to be called when the user presses "
399 "Return. This is an advanced option intended for debugging, which "
399 "Return. This is an advanced option intended for debugging, which "
400 "may be changed or removed in later releases."
400 "may be changed or removed in later releases."
401 ).tag(config=True)
401 ).tag(config=True)
402
402
403 enable_history_search = Bool(True,
403 enable_history_search = Bool(True,
404 help="Allows to enable/disable the prompt toolkit history search"
404 help="Allows to enable/disable the prompt toolkit history search"
405 ).tag(config=True)
405 ).tag(config=True)
406
406
407 autosuggestions_provider = Unicode(
407 autosuggestions_provider = Unicode(
408 "NavigableAutoSuggestFromHistory",
408 "NavigableAutoSuggestFromHistory",
409 help="Specifies from which source automatic suggestions are provided. "
409 help="Specifies from which source automatic suggestions are provided. "
410 "Can be set to ``'NavigableAutoSuggestFromHistory'`` (:kbd:`up` and "
410 "Can be set to ``'NavigableAutoSuggestFromHistory'`` (:kbd:`up` and "
411 ":kbd:`down` swap suggestions), ``'AutoSuggestFromHistory'``, "
411 ":kbd:`down` swap suggestions), ``'AutoSuggestFromHistory'``, "
412 " or ``None`` to disable automatic suggestions. "
412 " or ``None`` to disable automatic suggestions. "
413 "Default is `'NavigableAutoSuggestFromHistory`'.",
413 "Default is `'NavigableAutoSuggestFromHistory`'.",
414 allow_none=True,
414 allow_none=True,
415 ).tag(config=True)
415 ).tag(config=True)
416
416
417 def _set_autosuggestions(self, provider):
417 def _set_autosuggestions(self, provider):
418 # disconnect old handler
418 # disconnect old handler
419 if self.auto_suggest and isinstance(
419 if self.auto_suggest and isinstance(
420 self.auto_suggest, NavigableAutoSuggestFromHistory
420 self.auto_suggest, NavigableAutoSuggestFromHistory
421 ):
421 ):
422 self.auto_suggest.disconnect()
422 self.auto_suggest.disconnect()
423 if provider is None:
423 if provider is None:
424 self.auto_suggest = None
424 self.auto_suggest = None
425 elif provider == "AutoSuggestFromHistory":
425 elif provider == "AutoSuggestFromHistory":
426 self.auto_suggest = AutoSuggestFromHistory()
426 self.auto_suggest = AutoSuggestFromHistory()
427 elif provider == "NavigableAutoSuggestFromHistory":
427 elif provider == "NavigableAutoSuggestFromHistory":
428 self.auto_suggest = NavigableAutoSuggestFromHistory()
428 self.auto_suggest = NavigableAutoSuggestFromHistory()
429 else:
429 else:
430 raise ValueError("No valid provider.")
430 raise ValueError("No valid provider.")
431 if self.pt_app:
431 if self.pt_app:
432 self.pt_app.auto_suggest = self.auto_suggest
432 self.pt_app.auto_suggest = self.auto_suggest
433
433
434 @observe("autosuggestions_provider")
434 @observe("autosuggestions_provider")
435 def _autosuggestions_provider_changed(self, change):
435 def _autosuggestions_provider_changed(self, change):
436 provider = change.new
436 provider = change.new
437 self._set_autosuggestions(provider)
437 self._set_autosuggestions(provider)
438
438
439 shortcuts = List(
439 shortcuts = List(
440 trait=Dict(
440 trait=Dict(
441 key_trait=Enum(
441 key_trait=Enum(
442 [
442 [
443 "command",
443 "command",
444 "match_keys",
444 "match_keys",
445 "match_filter",
445 "match_filter",
446 "new_keys",
446 "new_keys",
447 "new_filter",
447 "new_filter",
448 "create",
448 "create",
449 ]
449 ]
450 ),
450 ),
451 per_key_traits={
451 per_key_traits={
452 "command": Unicode(),
452 "command": Unicode(),
453 "match_keys": List(Unicode()),
453 "match_keys": List(Unicode()),
454 "match_filter": Unicode(),
454 "match_filter": Unicode(),
455 "new_keys": List(Unicode()),
455 "new_keys": List(Unicode()),
456 "new_filter": Unicode(),
456 "new_filter": Unicode(),
457 "create": Bool(False),
457 "create": Bool(False),
458 },
458 },
459 ),
459 ),
460 help="""Add, disable or modifying shortcuts.
460 help="""Add, disable or modifying shortcuts.
461
461
462 Each entry on the list should be a dictionary with ``command`` key
462 Each entry on the list should be a dictionary with ``command`` key
463 identifying the target function executed by the shortcut and at least
463 identifying the target function executed by the shortcut and at least
464 one of the following:
464 one of the following:
465
465
466 - ``match_keys``: list of keys used to match an existing shortcut,
466 - ``match_keys``: list of keys used to match an existing shortcut,
467 - ``match_filter``: shortcut filter used to match an existing shortcut,
467 - ``match_filter``: shortcut filter used to match an existing shortcut,
468 - ``new_keys``: list of keys to set,
468 - ``new_keys``: list of keys to set,
469 - ``new_filter``: a new shortcut filter to set
469 - ``new_filter``: a new shortcut filter to set
470
470
471 The filters have to be composed of pre-defined verbs and joined by one
471 The filters have to be composed of pre-defined verbs and joined by one
472 of the following conjunctions: ``&`` (and), ``|`` (or), ``~`` (not).
472 of the following conjunctions: ``&`` (and), ``|`` (or), ``~`` (not).
473 The pre-defined verbs are:
473 The pre-defined verbs are:
474
474
475 {}
475 {}
476
476
477
477
478 To disable a shortcut set ``new_keys`` to an empty list.
478 To disable a shortcut set ``new_keys`` to an empty list.
479 To add a shortcut add key ``create`` with value ``True``.
479 To add a shortcut add key ``create`` with value ``True``.
480
480
481 When modifying/disabling shortcuts, ``match_keys``/``match_filter`` can
481 When modifying/disabling shortcuts, ``match_keys``/``match_filter`` can
482 be omitted if the provided specification uniquely identifies a shortcut
482 be omitted if the provided specification uniquely identifies a shortcut
483 to be modified/disabled. When modifying a shortcut ``new_filter`` or
483 to be modified/disabled. When modifying a shortcut ``new_filter`` or
484 ``new_keys`` can be omitted which will result in reuse of the existing
484 ``new_keys`` can be omitted which will result in reuse of the existing
485 filter/keys.
485 filter/keys.
486
486
487 Only shortcuts defined in IPython (and not default prompt-toolkit
487 Only shortcuts defined in IPython (and not default prompt-toolkit
488 shortcuts) can be modified or disabled. The full list of shortcuts,
488 shortcuts) can be modified or disabled. The full list of shortcuts,
489 command identifiers and filters is available under
489 command identifiers and filters is available under
490 :ref:`terminal-shortcuts-list`.
490 :ref:`terminal-shortcuts-list`.
491 """.format(
491 """.format(
492 "\n ".join([f"- `{k}`" for k in KEYBINDING_FILTERS])
492 "\n ".join([f"- `{k}`" for k in KEYBINDING_FILTERS])
493 ),
493 ),
494 ).tag(config=True)
494 ).tag(config=True)
495
495
496 @observe("shortcuts")
496 @observe("shortcuts")
497 def _shortcuts_changed(self, change):
497 def _shortcuts_changed(self, change):
498 if self.pt_app:
498 if self.pt_app:
499 self.pt_app.key_bindings = self._merge_shortcuts(user_shortcuts=change.new)
499 self.pt_app.key_bindings = self._merge_shortcuts(user_shortcuts=change.new)
500
500
501 def _merge_shortcuts(self, user_shortcuts):
501 def _merge_shortcuts(self, user_shortcuts):
502 # rebuild the bindings list from scratch
502 # rebuild the bindings list from scratch
503 key_bindings = create_ipython_shortcuts(self)
503 key_bindings = create_ipython_shortcuts(self)
504
504
505 # for now we only allow adding shortcuts for commands which are already
505 # for now we only allow adding shortcuts for commands which are already
506 # registered; this is a security precaution.
506 # registered; this is a security precaution.
507 known_commands = {
507 known_commands = {
508 create_identifier(binding.command): binding.command
508 create_identifier(binding.command): binding.command
509 for binding in KEY_BINDINGS
509 for binding in KEY_BINDINGS
510 }
510 }
511 shortcuts_to_skip = []
511 shortcuts_to_skip = []
512 shortcuts_to_add = []
512 shortcuts_to_add = []
513
513
514 for shortcut in user_shortcuts:
514 for shortcut in user_shortcuts:
515 command_id = shortcut["command"]
515 command_id = shortcut["command"]
516 if command_id not in known_commands:
516 if command_id not in known_commands:
517 allowed_commands = "\n - ".join(known_commands)
517 allowed_commands = "\n - ".join(known_commands)
518 raise ValueError(
518 raise ValueError(
519 f"{command_id} is not a known shortcut command."
519 f"{command_id} is not a known shortcut command."
520 f" Allowed commands are: \n - {allowed_commands}"
520 f" Allowed commands are: \n - {allowed_commands}"
521 )
521 )
522 old_keys = shortcut.get("match_keys", None)
522 old_keys = shortcut.get("match_keys", None)
523 old_filter = (
523 old_filter = (
524 filter_from_string(shortcut["match_filter"])
524 filter_from_string(shortcut["match_filter"])
525 if "match_filter" in shortcut
525 if "match_filter" in shortcut
526 else None
526 else None
527 )
527 )
528 matching = [
528 matching = [
529 binding
529 binding
530 for binding in KEY_BINDINGS
530 for binding in KEY_BINDINGS
531 if (
531 if (
532 (old_filter is None or binding.filter == old_filter)
532 (old_filter is None or binding.filter == old_filter)
533 and (old_keys is None or [k for k in binding.keys] == old_keys)
533 and (old_keys is None or [k for k in binding.keys] == old_keys)
534 and create_identifier(binding.command) == command_id
534 and create_identifier(binding.command) == command_id
535 )
535 )
536 ]
536 ]
537
537
538 new_keys = shortcut.get("new_keys", None)
538 new_keys = shortcut.get("new_keys", None)
539 new_filter = shortcut.get("new_filter", None)
539 new_filter = shortcut.get("new_filter", None)
540
540
541 command = known_commands[command_id]
541 command = known_commands[command_id]
542
542
543 creating_new = shortcut.get("create", False)
543 creating_new = shortcut.get("create", False)
544 modifying_existing = not creating_new and (
544 modifying_existing = not creating_new and (
545 new_keys is not None or new_filter
545 new_keys is not None or new_filter
546 )
546 )
547
547
548 if creating_new and new_keys == []:
548 if creating_new and new_keys == []:
549 raise ValueError("Cannot add a shortcut without keys")
549 raise ValueError("Cannot add a shortcut without keys")
550
550
551 if modifying_existing:
551 if modifying_existing:
552 specification = {
552 specification = {
553 key: shortcut[key]
553 key: shortcut[key]
554 for key in ["command", "filter"]
554 for key in ["command", "filter"]
555 if key in shortcut
555 if key in shortcut
556 }
556 }
557 if len(matching) == 0:
557 if len(matching) == 0:
558 raise ValueError(
558 raise ValueError(
559 f"No shortcuts matching {specification} found in {KEY_BINDINGS}"
559 f"No shortcuts matching {specification} found in {KEY_BINDINGS}"
560 )
560 )
561 elif len(matching) > 1:
561 elif len(matching) > 1:
562 raise ValueError(
562 raise ValueError(
563 f"Multiple shortcuts matching {specification} found,"
563 f"Multiple shortcuts matching {specification} found,"
564 f" please add keys/filter to select one of: {matching}"
564 f" please add keys/filter to select one of: {matching}"
565 )
565 )
566
566
567 matched = matching[0]
567 matched = matching[0]
568 old_filter = matched.filter
568 old_filter = matched.filter
569 old_keys = list(matched.keys)
569 old_keys = list(matched.keys)
570 shortcuts_to_skip.append(
570 shortcuts_to_skip.append(
571 RuntimeBinding(
571 RuntimeBinding(
572 command,
572 command,
573 keys=old_keys,
573 keys=old_keys,
574 filter=old_filter,
574 filter=old_filter,
575 )
575 )
576 )
576 )
577
577
578 if new_keys != []:
578 if new_keys != []:
579 shortcuts_to_add.append(
579 shortcuts_to_add.append(
580 RuntimeBinding(
580 RuntimeBinding(
581 command,
581 command,
582 keys=new_keys or old_keys,
582 keys=new_keys or old_keys,
583 filter=filter_from_string(new_filter)
583 filter=filter_from_string(new_filter)
584 if new_filter is not None
584 if new_filter is not None
585 else (
585 else (
586 old_filter
586 old_filter
587 if old_filter is not None
587 if old_filter is not None
588 else filter_from_string("always")
588 else filter_from_string("always")
589 ),
589 ),
590 )
590 )
591 )
591 )
592
592
593 # rebuild the bindings list from scratch
593 # rebuild the bindings list from scratch
594 key_bindings = create_ipython_shortcuts(self, skip=shortcuts_to_skip)
594 key_bindings = create_ipython_shortcuts(self, skip=shortcuts_to_skip)
595 for binding in shortcuts_to_add:
595 for binding in shortcuts_to_add:
596 add_binding(key_bindings, binding)
596 add_binding(key_bindings, binding)
597
597
598 return key_bindings
598 return key_bindings
599
599
600 prompt_includes_vi_mode = Bool(True,
600 prompt_includes_vi_mode = Bool(True,
601 help="Display the current vi mode (when using vi editing mode)."
601 help="Display the current vi mode (when using vi editing mode)."
602 ).tag(config=True)
602 ).tag(config=True)
603
603
604 prompt_line_number_format = Unicode(
604 prompt_line_number_format = Unicode(
605 "",
605 "",
606 help="The format for line numbering, will be passed `line` (int, 1 based)"
606 help="The format for line numbering, will be passed `line` (int, 1 based)"
607 " the current line number and `rel_line` the relative line number."
607 " the current line number and `rel_line` the relative line number."
608 " for example to display both you can use the following template string :"
608 " for example to display both you can use the following template string :"
609 " c.TerminalInteractiveShell.prompt_line_number_format='{line: 4d}/{rel_line:+03d} | '"
609 " c.TerminalInteractiveShell.prompt_line_number_format='{line: 4d}/{rel_line:+03d} | '"
610 " This will display the current line number, with leading space and a width of at least 4"
610 " This will display the current line number, with leading space and a width of at least 4"
611 " character, as well as the relative line number 0 padded and always with a + or - sign."
611 " character, as well as the relative line number 0 padded and always with a + or - sign."
612 " Note that when using Emacs mode the prompt of the first line may not update.",
612 " Note that when using Emacs mode the prompt of the first line may not update.",
613 ).tag(config=True)
613 ).tag(config=True)
614
614
615 @observe('term_title')
615 @observe('term_title')
616 def init_term_title(self, change=None):
616 def init_term_title(self, change=None):
617 # Enable or disable the terminal title.
617 # Enable or disable the terminal title.
618 if self.term_title and _is_tty:
618 if self.term_title and _is_tty:
619 toggle_set_term_title(True)
619 toggle_set_term_title(True)
620 set_term_title(self.term_title_format.format(cwd=abbrev_cwd()))
620 set_term_title(self.term_title_format.format(cwd=abbrev_cwd()))
621 else:
621 else:
622 toggle_set_term_title(False)
622 toggle_set_term_title(False)
623
623
624 def restore_term_title(self):
624 def restore_term_title(self):
625 if self.term_title and _is_tty:
625 if self.term_title and _is_tty:
626 restore_term_title()
626 restore_term_title()
627
627
628 def init_display_formatter(self):
628 def init_display_formatter(self):
629 super(TerminalInteractiveShell, self).init_display_formatter()
629 super(TerminalInteractiveShell, self).init_display_formatter()
630 # terminal only supports plain text
630 # terminal only supports plain text
631 self.display_formatter.active_types = ["text/plain"]
631 self.display_formatter.active_types = ["text/plain"]
632
632
633 def init_prompt_toolkit_cli(self):
633 def init_prompt_toolkit_cli(self):
634 if self.simple_prompt:
634 if self.simple_prompt:
635 # Fall back to plain non-interactive output for tests.
635 # Fall back to plain non-interactive output for tests.
636 # This is very limited.
636 # This is very limited.
637 def prompt():
637 def prompt():
638 prompt_text = "".join(x[1] for x in self.prompts.in_prompt_tokens())
638 prompt_text = "".join(x[1] for x in self.prompts.in_prompt_tokens())
639 lines = [input(prompt_text)]
639 lines = [input(prompt_text)]
640 prompt_continuation = "".join(x[1] for x in self.prompts.continuation_prompt_tokens())
640 prompt_continuation = "".join(x[1] for x in self.prompts.continuation_prompt_tokens())
641 while self.check_complete('\n'.join(lines))[0] == 'incomplete':
641 while self.check_complete('\n'.join(lines))[0] == 'incomplete':
642 lines.append( input(prompt_continuation) )
642 lines.append( input(prompt_continuation) )
643 return '\n'.join(lines)
643 return '\n'.join(lines)
644 self.prompt_for_code = prompt
644 self.prompt_for_code = prompt
645 return
645 return
646
646
647 # Set up keyboard shortcuts
647 # Set up keyboard shortcuts
648 key_bindings = self._merge_shortcuts(user_shortcuts=self.shortcuts)
648 key_bindings = self._merge_shortcuts(user_shortcuts=self.shortcuts)
649
649
650 # Pre-populate history from IPython's history database
650 # Pre-populate history from IPython's history database
651 history = PtkHistoryAdapter(self)
651 history = PtkHistoryAdapter(self)
652
652
653 self._style = self._make_style_from_name_or_cls(self.highlighting_style)
653 self._style = self._make_style_from_name_or_cls(self.highlighting_style)
654 self.style = DynamicStyle(lambda: self._style)
654 self.style = DynamicStyle(lambda: self._style)
655
655
656 editing_mode = getattr(EditingMode, self.editing_mode.upper())
656 editing_mode = getattr(EditingMode, self.editing_mode.upper())
657
657
658 self._use_asyncio_inputhook = False
658 self._use_asyncio_inputhook = False
659 self.pt_app = PromptSession(
659 self.pt_app = PromptSession(
660 auto_suggest=self.auto_suggest,
660 auto_suggest=self.auto_suggest,
661 editing_mode=editing_mode,
661 editing_mode=editing_mode,
662 key_bindings=key_bindings,
662 key_bindings=key_bindings,
663 history=history,
663 history=history,
664 completer=IPythonPTCompleter(shell=self),
664 completer=IPythonPTCompleter(shell=self),
665 enable_history_search=self.enable_history_search,
665 enable_history_search=self.enable_history_search,
666 style=self.style,
666 style=self.style,
667 include_default_pygments_style=False,
667 include_default_pygments_style=False,
668 mouse_support=self.mouse_support,
668 mouse_support=self.mouse_support,
669 enable_open_in_editor=self.extra_open_editor_shortcuts,
669 enable_open_in_editor=self.extra_open_editor_shortcuts,
670 color_depth=self.color_depth,
670 color_depth=self.color_depth,
671 tempfile_suffix=".py",
671 tempfile_suffix=".py",
672 **self._extra_prompt_options(),
672 **self._extra_prompt_options(),
673 )
673 )
674 if isinstance(self.auto_suggest, NavigableAutoSuggestFromHistory):
674 if isinstance(self.auto_suggest, NavigableAutoSuggestFromHistory):
675 self.auto_suggest.connect(self.pt_app)
675 self.auto_suggest.connect(self.pt_app)
676
676
677 def _make_style_from_name_or_cls(self, name_or_cls):
677 def _make_style_from_name_or_cls(self, name_or_cls):
678 """
678 """
679 Small wrapper that make an IPython compatible style from a style name
679 Small wrapper that make an IPython compatible style from a style name
680
680
681 We need that to add style for prompt ... etc.
681 We need that to add style for prompt ... etc.
682 """
682 """
683 style_overrides = {}
683 style_overrides = {}
684 if name_or_cls == 'legacy':
684 if name_or_cls == 'legacy':
685 legacy = self.colors.lower()
685 legacy = self.colors.lower()
686 if legacy == 'linux':
686 if legacy == 'linux':
687 style_cls = get_style_by_name('monokai')
687 style_cls = get_style_by_name('monokai')
688 style_overrides = _style_overrides_linux
688 style_overrides = _style_overrides_linux
689 elif legacy == 'lightbg':
689 elif legacy == 'lightbg':
690 style_overrides = _style_overrides_light_bg
690 style_overrides = _style_overrides_light_bg
691 style_cls = get_style_by_name('pastie')
691 style_cls = get_style_by_name('pastie')
692 elif legacy == 'neutral':
692 elif legacy == 'neutral':
693 # The default theme needs to be visible on both a dark background
693 # The default theme needs to be visible on both a dark background
694 # and a light background, because we can't tell what the terminal
694 # and a light background, because we can't tell what the terminal
695 # looks like. These tweaks to the default theme help with that.
695 # looks like. These tweaks to the default theme help with that.
696 style_cls = get_style_by_name('default')
696 style_cls = get_style_by_name('default')
697 style_overrides.update({
697 style_overrides.update({
698 Token.Number: '#ansigreen',
698 Token.Number: '#ansigreen',
699 Token.Operator: 'noinherit',
699 Token.Operator: 'noinherit',
700 Token.String: '#ansiyellow',
700 Token.String: '#ansiyellow',
701 Token.Name.Function: '#ansiblue',
701 Token.Name.Function: '#ansiblue',
702 Token.Name.Class: 'bold #ansiblue',
702 Token.Name.Class: 'bold #ansiblue',
703 Token.Name.Namespace: 'bold #ansiblue',
703 Token.Name.Namespace: 'bold #ansiblue',
704 Token.Name.Variable.Magic: '#ansiblue',
704 Token.Name.Variable.Magic: '#ansiblue',
705 Token.Prompt: '#ansigreen',
705 Token.Prompt: '#ansigreen',
706 Token.PromptNum: '#ansibrightgreen bold',
706 Token.PromptNum: '#ansibrightgreen bold',
707 Token.OutPrompt: '#ansired',
707 Token.OutPrompt: '#ansired',
708 Token.OutPromptNum: '#ansibrightred bold',
708 Token.OutPromptNum: '#ansibrightred bold',
709 })
709 })
710
710
711 # Hack: Due to limited color support on the Windows console
711 # Hack: Due to limited color support on the Windows console
712 # the prompt colors will be wrong without this
712 # the prompt colors will be wrong without this
713 if os.name == 'nt':
713 if os.name == 'nt':
714 style_overrides.update({
714 style_overrides.update({
715 Token.Prompt: '#ansidarkgreen',
715 Token.Prompt: '#ansidarkgreen',
716 Token.PromptNum: '#ansigreen bold',
716 Token.PromptNum: '#ansigreen bold',
717 Token.OutPrompt: '#ansidarkred',
717 Token.OutPrompt: '#ansidarkred',
718 Token.OutPromptNum: '#ansired bold',
718 Token.OutPromptNum: '#ansired bold',
719 })
719 })
720 elif legacy =='nocolor':
720 elif legacy =='nocolor':
721 style_cls=_NoStyle
721 style_cls=_NoStyle
722 style_overrides = {}
722 style_overrides = {}
723 else :
723 else :
724 raise ValueError('Got unknown colors: ', legacy)
724 raise ValueError('Got unknown colors: ', legacy)
725 else :
725 else :
726 if isinstance(name_or_cls, str):
726 if isinstance(name_or_cls, str):
727 style_cls = get_style_by_name(name_or_cls)
727 style_cls = get_style_by_name(name_or_cls)
728 else:
728 else:
729 style_cls = name_or_cls
729 style_cls = name_or_cls
730 style_overrides = {
730 style_overrides = {
731 Token.Prompt: '#ansigreen',
731 Token.Prompt: '#ansigreen',
732 Token.PromptNum: '#ansibrightgreen bold',
732 Token.PromptNum: '#ansibrightgreen bold',
733 Token.OutPrompt: '#ansired',
733 Token.OutPrompt: '#ansired',
734 Token.OutPromptNum: '#ansibrightred bold',
734 Token.OutPromptNum: '#ansibrightred bold',
735 }
735 }
736 style_overrides.update(self.highlighting_style_overrides)
736 style_overrides.update(self.highlighting_style_overrides)
737 style = merge_styles([
737 style = merge_styles([
738 style_from_pygments_cls(style_cls),
738 style_from_pygments_cls(style_cls),
739 style_from_pygments_dict(style_overrides),
739 style_from_pygments_dict(style_overrides),
740 ])
740 ])
741
741
742 return style
742 return style
743
743
744 @property
744 @property
745 def pt_complete_style(self):
745 def pt_complete_style(self):
746 return {
746 return {
747 'multicolumn': CompleteStyle.MULTI_COLUMN,
747 'multicolumn': CompleteStyle.MULTI_COLUMN,
748 'column': CompleteStyle.COLUMN,
748 'column': CompleteStyle.COLUMN,
749 'readlinelike': CompleteStyle.READLINE_LIKE,
749 'readlinelike': CompleteStyle.READLINE_LIKE,
750 }[self.display_completions]
750 }[self.display_completions]
751
751
752 @property
752 @property
753 def color_depth(self):
753 def color_depth(self):
754 return (ColorDepth.TRUE_COLOR if self.true_color else None)
754 return (ColorDepth.TRUE_COLOR if self.true_color else None)
755
755
756 def _extra_prompt_options(self):
756 def _extra_prompt_options(self):
757 """
757 """
758 Return the current layout option for the current Terminal InteractiveShell
758 Return the current layout option for the current Terminal InteractiveShell
759 """
759 """
760 def get_message():
760 def get_message():
761 return PygmentsTokens(self.prompts.in_prompt_tokens())
761 return PygmentsTokens(self.prompts.in_prompt_tokens())
762
762
763 if self.editing_mode == "emacs" and self.prompt_line_number_format == "":
763 if self.editing_mode == "emacs" and self.prompt_line_number_format == "":
764 # with emacs mode the prompt is (usually) static, so we call only
764 # with emacs mode the prompt is (usually) static, so we call only
765 # the function once. With VI mode it can toggle between [ins] and
765 # the function once. With VI mode it can toggle between [ins] and
766 # [nor] so we can't precompute.
766 # [nor] so we can't precompute.
767 # here I'm going to favor the default keybinding which almost
767 # here I'm going to favor the default keybinding which almost
768 # everybody uses to decrease CPU usage.
768 # everybody uses to decrease CPU usage.
769 # if we have issues with users with custom Prompts we can see how to
769 # if we have issues with users with custom Prompts we can see how to
770 # work around this.
770 # work around this.
771 get_message = get_message()
771 get_message = get_message()
772
772
773 options = {
773 options = {
774 "complete_in_thread": False,
774 "complete_in_thread": False,
775 "lexer": IPythonPTLexer(),
775 "lexer": IPythonPTLexer(),
776 "reserve_space_for_menu": self.space_for_menu,
776 "reserve_space_for_menu": self.space_for_menu,
777 "message": get_message,
777 "message": get_message,
778 "prompt_continuation": (
778 "prompt_continuation": (
779 lambda width, lineno, is_soft_wrap: PygmentsTokens(
779 lambda width, lineno, is_soft_wrap: PygmentsTokens(
780 _backward_compat_continuation_prompt_tokens(
780 _backward_compat_continuation_prompt_tokens(
781 self.prompts.continuation_prompt_tokens, width, lineno=lineno
781 self.prompts.continuation_prompt_tokens, width, lineno=lineno
782 )
782 )
783 )
783 )
784 ),
784 ),
785 "multiline": True,
785 "multiline": True,
786 "complete_style": self.pt_complete_style,
786 "complete_style": self.pt_complete_style,
787 "input_processors": [
787 "input_processors": [
788 # Highlight matching brackets, but only when this setting is
788 # Highlight matching brackets, but only when this setting is
789 # enabled, and only when the DEFAULT_BUFFER has the focus.
789 # enabled, and only when the DEFAULT_BUFFER has the focus.
790 ConditionalProcessor(
790 ConditionalProcessor(
791 processor=HighlightMatchingBracketProcessor(chars="[](){}"),
791 processor=HighlightMatchingBracketProcessor(chars="[](){}"),
792 filter=HasFocus(DEFAULT_BUFFER)
792 filter=HasFocus(DEFAULT_BUFFER)
793 & ~IsDone()
793 & ~IsDone()
794 & Condition(lambda: self.highlight_matching_brackets),
794 & Condition(lambda: self.highlight_matching_brackets),
795 ),
795 ),
796 # Show auto-suggestion in lines other than the last line.
796 # Show auto-suggestion in lines other than the last line.
797 ConditionalProcessor(
797 ConditionalProcessor(
798 processor=AppendAutoSuggestionInAnyLine(),
798 processor=AppendAutoSuggestionInAnyLine(),
799 filter=HasFocus(DEFAULT_BUFFER)
799 filter=HasFocus(DEFAULT_BUFFER)
800 & ~IsDone()
800 & ~IsDone()
801 & Condition(
801 & Condition(
802 lambda: isinstance(
802 lambda: isinstance(
803 self.auto_suggest, NavigableAutoSuggestFromHistory
803 self.auto_suggest, NavigableAutoSuggestFromHistory
804 )
804 )
805 ),
805 ),
806 ),
806 ),
807 ],
807 ],
808 }
808 }
809 if not PTK3:
809 if not PTK3:
810 options['inputhook'] = self.inputhook
810 options['inputhook'] = self.inputhook
811
811
812 return options
812 return options
813
813
814 def prompt_for_code(self):
814 def prompt_for_code(self):
815 if self.rl_next_input:
815 if self.rl_next_input:
816 default = self.rl_next_input
816 default = self.rl_next_input
817 self.rl_next_input = None
817 self.rl_next_input = None
818 else:
818 else:
819 default = ''
819 default = ''
820
820
821 # In order to make sure that asyncio code written in the
821 # In order to make sure that asyncio code written in the
822 # interactive shell doesn't interfere with the prompt, we run the
822 # interactive shell doesn't interfere with the prompt, we run the
823 # prompt in a different event loop.
823 # prompt in a different event loop.
824 # If we don't do this, people could spawn coroutine with a
824 # If we don't do this, people could spawn coroutine with a
825 # while/true inside which will freeze the prompt.
825 # while/true inside which will freeze the prompt.
826
826
827 with patch_stdout(raw=True):
827 with patch_stdout(raw=True):
828 if self._use_asyncio_inputhook:
828 if self._use_asyncio_inputhook:
829 # When we integrate the asyncio event loop, run the UI in the
829 # When we integrate the asyncio event loop, run the UI in the
830 # same event loop as the rest of the code. don't use an actual
830 # same event loop as the rest of the code. don't use an actual
831 # input hook. (Asyncio is not made for nesting event loops.)
831 # input hook. (Asyncio is not made for nesting event loops.)
832 asyncio_loop = get_asyncio_loop()
832 asyncio_loop = get_asyncio_loop()
833 text = asyncio_loop.run_until_complete(
833 text = asyncio_loop.run_until_complete(
834 self.pt_app.prompt_async(
834 self.pt_app.prompt_async(
835 default=default, **self._extra_prompt_options()
835 default=default, **self._extra_prompt_options()
836 )
836 )
837 )
837 )
838 else:
838 else:
839 text = self.pt_app.prompt(
839 text = self.pt_app.prompt(
840 default=default,
840 default=default,
841 inputhook=self._inputhook,
841 inputhook=self._inputhook,
842 **self._extra_prompt_options(),
842 **self._extra_prompt_options(),
843 )
843 )
844
844
845 return text
845 return text
846
846
847 def enable_win_unicode_console(self):
847 def enable_win_unicode_console(self):
848 # Since IPython 7.10 doesn't support python < 3.6 and PEP 528, Python uses the unicode APIs for the Windows
848 # Since IPython 7.10 doesn't support python < 3.6 and PEP 528, Python uses the unicode APIs for the Windows
849 # console by default, so WUC shouldn't be needed.
849 # console by default, so WUC shouldn't be needed.
850 warn("`enable_win_unicode_console` is deprecated since IPython 7.10, does not do anything and will be removed in the future",
850 warn("`enable_win_unicode_console` is deprecated since IPython 7.10, does not do anything and will be removed in the future",
851 DeprecationWarning,
851 DeprecationWarning,
852 stacklevel=2)
852 stacklevel=2)
853
853
854 def init_io(self):
854 def init_io(self):
855 if sys.platform not in {'win32', 'cli'}:
855 if sys.platform not in {'win32', 'cli'}:
856 return
856 return
857
857
858 import colorama
858 import colorama
859 colorama.init()
859 colorama.init()
860
860
861 def init_magics(self):
861 def init_magics(self):
862 super(TerminalInteractiveShell, self).init_magics()
862 super(TerminalInteractiveShell, self).init_magics()
863 self.register_magics(TerminalMagics)
863 self.register_magics(TerminalMagics)
864
864
865 def init_alias(self):
865 def init_alias(self):
866 # The parent class defines aliases that can be safely used with any
866 # The parent class defines aliases that can be safely used with any
867 # frontend.
867 # frontend.
868 super(TerminalInteractiveShell, self).init_alias()
868 super(TerminalInteractiveShell, self).init_alias()
869
869
870 # Now define aliases that only make sense on the terminal, because they
870 # Now define aliases that only make sense on the terminal, because they
871 # need direct access to the console in a way that we can't emulate in
871 # need direct access to the console in a way that we can't emulate in
872 # GUI or web frontend
872 # GUI or web frontend
873 if os.name == 'posix':
873 if os.name == 'posix':
874 for cmd in ('clear', 'more', 'less', 'man'):
874 for cmd in ('clear', 'more', 'less', 'man'):
875 self.alias_manager.soft_define_alias(cmd, cmd)
875 self.alias_manager.soft_define_alias(cmd, cmd)
876
876
877 def __init__(self, *args, **kwargs) -> None:
877 def __init__(self, *args, **kwargs) -> None:
878 super(TerminalInteractiveShell, self).__init__(*args, **kwargs)
878 super(TerminalInteractiveShell, self).__init__(*args, **kwargs)
879 self._set_autosuggestions(self.autosuggestions_provider)
879 self._set_autosuggestions(self.autosuggestions_provider)
880 self.init_prompt_toolkit_cli()
880 self.init_prompt_toolkit_cli()
881 self.init_term_title()
881 self.init_term_title()
882 self.keep_running = True
882 self.keep_running = True
883 self._set_formatter(self.autoformatter)
883 self._set_formatter(self.autoformatter)
884
884
885 def ask_exit(self):
885 def ask_exit(self):
886 self.keep_running = False
886 self.keep_running = False
887
887
888 rl_next_input = None
888 rl_next_input = None
889
889
890 def interact(self):
890 def interact(self):
891 self.keep_running = True
891 self.keep_running = True
892 while self.keep_running:
892 while self.keep_running:
893 print(self.separate_in, end='')
893 print(self.separate_in, end='')
894
894
895 try:
895 try:
896 code = self.prompt_for_code()
896 code = self.prompt_for_code()
897 except EOFError:
897 except EOFError:
898 if (not self.confirm_exit) \
898 if (not self.confirm_exit) \
899 or self.ask_yes_no('Do you really want to exit ([y]/n)?','y','n'):
899 or self.ask_yes_no('Do you really want to exit ([y]/n)?','y','n'):
900 self.ask_exit()
900 self.ask_exit()
901
901
902 else:
902 else:
903 if code:
903 if code:
904 self.run_cell(code, store_history=True)
904 self.run_cell(code, store_history=True)
905
905
906 def mainloop(self):
906 def mainloop(self):
907 # An extra layer of protection in case someone mashing Ctrl-C breaks
907 # An extra layer of protection in case someone mashing Ctrl-C breaks
908 # out of our internal code.
908 # out of our internal code.
909 while True:
909 while True:
910 try:
910 try:
911 self.interact()
911 self.interact()
912 break
912 break
913 except KeyboardInterrupt as e:
913 except KeyboardInterrupt as e:
914 print("\n%s escaped interact()\n" % type(e).__name__)
914 print("\n%s escaped interact()\n" % type(e).__name__)
915 finally:
915 finally:
916 # An interrupt during the eventloop will mess up the
916 # An interrupt during the eventloop will mess up the
917 # internal state of the prompt_toolkit library.
917 # internal state of the prompt_toolkit library.
918 # Stopping the eventloop fixes this, see
918 # Stopping the eventloop fixes this, see
919 # https://github.com/ipython/ipython/pull/9867
919 # https://github.com/ipython/ipython/pull/9867
920 if hasattr(self, '_eventloop'):
920 if hasattr(self, '_eventloop'):
921 self._eventloop.stop()
921 self._eventloop.stop()
922
922
923 self.restore_term_title()
923 self.restore_term_title()
924
924
925 # try to call some at-exit operation optimistically as some things can't
925 # try to call some at-exit operation optimistically as some things can't
926 # be done during interpreter shutdown. this is technically inaccurate as
926 # be done during interpreter shutdown. this is technically inaccurate as
927 # this make mainlool not re-callable, but that should be a rare if not
927 # this make mainlool not re-callable, but that should be a rare if not
928 # in existent use case.
928 # in existent use case.
929
929
930 self._atexit_once()
930 self._atexit_once()
931
931
932 _inputhook = None
932 _inputhook = None
933 def inputhook(self, context):
933 def inputhook(self, context):
934 if self._inputhook is not None:
934 if self._inputhook is not None:
935 self._inputhook(context)
935 self._inputhook(context)
936
936
937 active_eventloop: Optional[str] = None
937 active_eventloop: Optional[str] = None
938
938
939 def enable_gui(self, gui: Optional[str] = None) -> None:
939 def enable_gui(self, gui: Optional[str] = None) -> None:
940 if self.simple_prompt is True and gui is not None:
940 if self.simple_prompt is True and gui is not None:
941 print(
941 print(
942 f'Cannot install event loop hook for "{gui}" when running with `--simple-prompt`.'
942 f'Cannot install event loop hook for "{gui}" when running with `--simple-prompt`.'
943 )
943 )
944 print(
944 print(
945 "NOTE: Tk is supported natively; use Tk apps and Tk backends with `--simple-prompt`."
945 "NOTE: Tk is supported natively; use Tk apps and Tk backends with `--simple-prompt`."
946 )
946 )
947 return
947 return
948
948
949 if self._inputhook is None and gui is None:
949 if self._inputhook is None and gui is None:
950 print("No event loop hook running.")
950 print("No event loop hook running.")
951 return
951 return
952
952
953 if self._inputhook is not None and gui is not None:
953 if self._inputhook is not None and gui is not None:
954 newev, newinhook = get_inputhook_name_and_func(gui)
954 newev, newinhook = get_inputhook_name_and_func(gui)
955 if self._inputhook == newinhook:
955 if self._inputhook == newinhook:
956 # same inputhook, do nothing
956 # same inputhook, do nothing
957 self.log.info(
957 self.log.info(
958 f"Shell is already running the {self.active_eventloop} eventloop. Doing nothing"
958 f"Shell is already running the {self.active_eventloop} eventloop. Doing nothing"
959 )
959 )
960 return
960 return
961 self.log.warning(
961 self.log.warning(
962 f"Shell is already running a different gui event loop for {self.active_eventloop}. "
962 f"Shell is already running a different gui event loop for {self.active_eventloop}. "
963 "Call with no arguments to disable the current loop."
963 "Call with no arguments to disable the current loop."
964 )
964 )
965 return
965 return
966 if self._inputhook is not None and gui is None:
966 if self._inputhook is not None and gui is None:
967 self.active_eventloop = self._inputhook = None
967 self.active_eventloop = self._inputhook = None
968
968
969 if gui and (gui not in {"inline", "webagg"}):
969 if gui and (gui not in {None, "webagg"}):
970 # This hook runs with each cycle of the `prompt_toolkit`'s event loop.
970 # This hook runs with each cycle of the `prompt_toolkit`'s event loop.
971 self.active_eventloop, self._inputhook = get_inputhook_name_and_func(gui)
971 self.active_eventloop, self._inputhook = get_inputhook_name_and_func(gui)
972 else:
972 else:
973 self.active_eventloop = self._inputhook = None
973 self.active_eventloop = self._inputhook = None
974
974
975 self._use_asyncio_inputhook = gui == "asyncio"
975 self._use_asyncio_inputhook = gui == "asyncio"
976
976
977 # Run !system commands directly, not through pipes, so terminal programs
977 # Run !system commands directly, not through pipes, so terminal programs
978 # work correctly.
978 # work correctly.
979 system = InteractiveShell.system_raw
979 system = InteractiveShell.system_raw
980
980
981 def auto_rewrite_input(self, cmd):
981 def auto_rewrite_input(self, cmd):
982 """Overridden from the parent class to use fancy rewriting prompt"""
982 """Overridden from the parent class to use fancy rewriting prompt"""
983 if not self.show_rewritten_input:
983 if not self.show_rewritten_input:
984 return
984 return
985
985
986 tokens = self.prompts.rewrite_prompt_tokens()
986 tokens = self.prompts.rewrite_prompt_tokens()
987 if self.pt_app:
987 if self.pt_app:
988 print_formatted_text(PygmentsTokens(tokens), end='',
988 print_formatted_text(PygmentsTokens(tokens), end='',
989 style=self.pt_app.app.style)
989 style=self.pt_app.app.style)
990 print(cmd)
990 print(cmd)
991 else:
991 else:
992 prompt = ''.join(s for t, s in tokens)
992 prompt = ''.join(s for t, s in tokens)
993 print(prompt, cmd, sep='')
993 print(prompt, cmd, sep='')
994
994
995 _prompts_before = None
995 _prompts_before = None
996 def switch_doctest_mode(self, mode):
996 def switch_doctest_mode(self, mode):
997 """Switch prompts to classic for %doctest_mode"""
997 """Switch prompts to classic for %doctest_mode"""
998 if mode:
998 if mode:
999 self._prompts_before = self.prompts
999 self._prompts_before = self.prompts
1000 self.prompts = ClassicPrompts(self)
1000 self.prompts = ClassicPrompts(self)
1001 elif self._prompts_before:
1001 elif self._prompts_before:
1002 self.prompts = self._prompts_before
1002 self.prompts = self._prompts_before
1003 self._prompts_before = None
1003 self._prompts_before = None
1004 # self._update_layout()
1004 # self._update_layout()
1005
1005
1006
1006
1007 InteractiveShellABC.register(TerminalInteractiveShell)
1007 InteractiveShellABC.register(TerminalInteractiveShell)
1008
1008
1009 if __name__ == '__main__':
1009 if __name__ == '__main__':
1010 TerminalInteractiveShell.instance().interact()
1010 TerminalInteractiveShell.instance().interact()
General Comments 0
You need to be logged in to leave comments. Login now