aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/python/ipython/py3/IPython/core/interactiveshell.py
diff options
context:
space:
mode:
authorrobot-contrib <robot-contrib@yandex-team.ru>2022-05-18 00:43:36 +0300
committerrobot-contrib <robot-contrib@yandex-team.ru>2022-05-18 00:43:36 +0300
commit9e5f436a8b2a27bcc7802e443ea3ef3e41a82a75 (patch)
tree78b522cab9f76336e62064d4d8ff7c897659b20e /contrib/python/ipython/py3/IPython/core/interactiveshell.py
parent8113a823ffca6451bb5ff8f0334560885a939a24 (diff)
downloadydb-9e5f436a8b2a27bcc7802e443ea3ef3e41a82a75.tar.gz
Update contrib/python/ipython/py3 to 8.3.0
ref:e84342d4d30476f9148137f37fd0c6405fd36f55
Diffstat (limited to 'contrib/python/ipython/py3/IPython/core/interactiveshell.py')
-rw-r--r--contrib/python/ipython/py3/IPython/core/interactiveshell.py849
1 files changed, 354 insertions, 495 deletions
diff --git a/contrib/python/ipython/py3/IPython/core/interactiveshell.py b/contrib/python/ipython/py3/IPython/core/interactiveshell.py
index 8fd546b847..ea9f6310ba 100644
--- a/contrib/python/ipython/py3/IPython/core/interactiveshell.py
+++ b/contrib/python/ipython/py3/IPython/core/interactiveshell.py
@@ -21,34 +21,53 @@ import inspect
import os
import re
import runpy
+import subprocess
import sys
import tempfile
import traceback
import types
-import subprocess
import warnings
+from ast import stmt
from io import open as io_open
-
+from logging import error
from pathlib import Path
-from pickleshare import PickleShareDB
+from typing import Callable
+from typing import List as ListType
+from typing import Optional, Tuple
+from warnings import warn
+from pickleshare import PickleShareDB
+from tempfile import TemporaryDirectory
+from traitlets import (
+ Any,
+ Bool,
+ CaselessStrEnum,
+ Dict,
+ Enum,
+ Instance,
+ Integer,
+ List,
+ Type,
+ Unicode,
+ default,
+ observe,
+ validate,
+)
from traitlets.config.configurable import SingletonConfigurable
from traitlets.utils.importstring import import_item
-from IPython.core import oinspect
-from IPython.core import magic
-from IPython.core import page
-from IPython.core import prefilter
-from IPython.core import ultratb
+
+import IPython.core.hooks
+from IPython.core import magic, oinspect, page, prefilter, ultratb
from IPython.core.alias import Alias, AliasManager
from IPython.core.autocall import ExitAutocall
from IPython.core.builtin_trap import BuiltinTrap
-from IPython.core.events import EventManager, available_events
from IPython.core.compilerop import CachingCompiler, check_linecache_ipython
from IPython.core.debugger import InterruptiblePdb
from IPython.core.display_trap import DisplayTrap
from IPython.core.displayhook import DisplayHook
from IPython.core.displaypub import DisplayPublisher
from IPython.core.error import InputRejected, UsageError
+from IPython.core.events import EventManager, available_events
from IPython.core.extensions import ExtensionManager
from IPython.core.formatters import DisplayFormatter
from IPython.core.history import HistoryManager
@@ -60,36 +79,19 @@ from IPython.core.prefilter import PrefilterManager
from IPython.core.profiledir import ProfileDir
from IPython.core.usage import default_banner
from IPython.display import display
+from IPython.paths import get_ipython_dir
from IPython.testing.skipdoctest import skip_doctest
-from IPython.utils import PyColorize
-from IPython.utils import io
-from IPython.utils import py3compat
-from IPython.utils import openpy
+from IPython.utils import PyColorize, io, openpy, py3compat
from IPython.utils.decorators import undoc
from IPython.utils.io import ask_yes_no
from IPython.utils.ipstruct import Struct
-from IPython.paths import get_ipython_dir
-from IPython.utils.path import get_home_dir, get_py_filename, ensure_dir_exists
-from IPython.utils.process import system, getoutput
+from IPython.utils.path import ensure_dir_exists, get_home_dir, get_py_filename
+from IPython.utils.process import getoutput, system
from IPython.utils.strdispatch import StrDispatch
from IPython.utils.syspathcontext import prepended_to_syspath
-from IPython.utils.text import format_screen, LSString, SList, DollarFormatter
-from IPython.utils.tempdir import TemporaryDirectory
-from traitlets import (
- Integer, Bool, CaselessStrEnum, Enum, List, Dict, Unicode, Instance, Type,
- observe, default, validate, Any
-)
-from warnings import warn
-from logging import error
-import IPython.core.hooks
+from IPython.utils.text import DollarFormatter, LSString, SList, format_screen
-from typing import List as ListType, Tuple, Optional
-from ast import AST
-
-# NoOpContext is deprecated, but ipykernel imports it from here.
-# See https://github.com/ipython/ipykernel/issues/157
-# (2016, let's try to remove than in IPython 8.0)
-from IPython.utils.contexts import NoOpContext
+sphinxify: Optional[Callable]
try:
import docrepr.sphinxify as sphx
@@ -115,118 +117,25 @@ class ProvisionalWarning(DeprecationWarning):
"""
pass
-if sys.version_info > (3,8):
- from ast import Module
-else :
- # mock the new API, ignore second argument
- # see https://github.com/ipython/ipython/issues/11590
- from ast import Module as OriginalModule
- Module = lambda nodelist, type_ignores: OriginalModule(nodelist)
-
-if sys.version_info > (3,6):
- _assign_nodes = (ast.AugAssign, ast.AnnAssign, ast.Assign)
- _single_targets_nodes = (ast.AugAssign, ast.AnnAssign)
-else:
- _assign_nodes = (ast.AugAssign, ast.Assign )
- _single_targets_nodes = (ast.AugAssign, )
+from ast import Module
+
+_assign_nodes = (ast.AugAssign, ast.AnnAssign, ast.Assign)
+_single_targets_nodes = (ast.AugAssign, ast.AnnAssign)
#-----------------------------------------------------------------------------
# Await Helpers
#-----------------------------------------------------------------------------
-def removed_co_newlocals(function:types.FunctionType) -> types.FunctionType:
- """Return a function that do not create a new local scope.
-
- Given a function, create a clone of this function where the co_newlocal flag
- has been removed, making this function code actually run in the sourounding
- scope.
-
- We need this in order to run asynchronous code in user level namespace.
- """
- from types import CodeType, FunctionType
- CO_NEWLOCALS = 0x0002
- code = function.__code__
- new_co_flags = code.co_flags & ~CO_NEWLOCALS
- if sys.version_info > (3, 8, 0, 'alpha', 3):
- new_code = code.replace(co_flags=new_co_flags)
- else:
- new_code = CodeType(
- code.co_argcount,
- code.co_kwonlyargcount,
- code.co_nlocals,
- code.co_stacksize,
- new_co_flags,
- code.co_code,
- code.co_consts,
- code.co_names,
- code.co_varnames,
- code.co_filename,
- code.co_name,
- code.co_firstlineno,
- code.co_lnotab,
- code.co_freevars,
- code.co_cellvars
- )
- return FunctionType(new_code, globals(), function.__name__, function.__defaults__)
-
-
# we still need to run things using the asyncio eventloop, but there is no
# async integration
-from .async_helpers import (_asyncio_runner, _asyncify, _pseudo_sync_runner)
-from .async_helpers import _curio_runner, _trio_runner, _should_be_async
-
-
-def _ast_asyncify(cell:str, wrapper_name:str) -> ast.Module:
- """
- Parse a cell with top-level await and modify the AST to be able to run it later.
-
- Parameter
- ---------
-
- cell: str
- The code cell to asyncronify
- wrapper_name: str
- The name of the function to be used to wrap the passed `cell`. It is
- advised to **not** use a python identifier in order to not pollute the
- global namespace in which the function will be ran.
-
- Return
- ------
-
- A module object AST containing **one** function named `wrapper_name`.
-
- The given code is wrapped in a async-def function, parsed into an AST, and
- the resulting function definition AST is modified to return the last
- expression.
-
- The last expression or await node is moved into a return statement at the
- end of the function, and removed from its original location. If the last
- node is not Expr or Await nothing is done.
-
- The function `__code__` will need to be later modified (by
- ``removed_co_newlocals``) in a subsequent step to not create new `locals()`
- meaning that the local and global scope are the same, ie as if the body of
- the function was at module level.
-
- Lastly a call to `locals()` is made just before the last expression of the
- function, or just after the last assignment or statement to make sure the
- global dict is updated as python function work with a local fast cache which
- is updated only on `local()` calls.
- """
+from .async_helpers import (
+ _asyncio_runner,
+ _curio_runner,
+ _pseudo_sync_runner,
+ _should_be_async,
+ _trio_runner,
+)
- from ast import Expr, Await, Return
- if sys.version_info >= (3,8):
- return ast.parse(cell)
- tree = ast.parse(_asyncify(cell))
-
- function_def = tree.body[0]
- function_def.name = wrapper_name
- try_block = function_def.body[0]
- lastexpr = try_block.body[-1]
- if isinstance(lastexpr, (Expr, Await)):
- try_block.body[-1] = Return(lastexpr.value)
- ast.fix_missing_locations(tree)
- return tree
#-----------------------------------------------------------------------------
# Globals
#-----------------------------------------------------------------------------
@@ -262,13 +171,6 @@ def no_op(*a, **kw):
class SpaceInInput(Exception): pass
-def get_default_colors():
- "DEPRECATED"
- warn('get_default_color is deprecated since IPython 5.0, and returns `Neutral` on all platforms.',
- DeprecationWarning, stacklevel=2)
- return 'Neutral'
-
-
class SeparateUnicode(Unicode):
r"""A Unicode subclass to validate separate_in, separate_out, etc.
@@ -329,7 +231,7 @@ class ExecutionResult(object):
"""
execution_count = None
error_before_exec = None
- error_in_exec = None
+ error_in_exec: Optional[BaseException] = None
info = None
result = None
@@ -551,29 +453,6 @@ class InteractiveShell(SingletonConfigurable):
will be displayed as regular output instead."""
).tag(config=True)
- # deprecated prompt traits:
-
- prompt_in1 = Unicode('In [\\#]: ',
- help="Deprecated since IPython 4.0 and ignored since 5.0, set TerminalInteractiveShell.prompts object directly."
- ).tag(config=True)
- prompt_in2 = Unicode(' .\\D.: ',
- help="Deprecated since IPython 4.0 and ignored since 5.0, set TerminalInteractiveShell.prompts object directly."
- ).tag(config=True)
- prompt_out = Unicode('Out[\\#]: ',
- help="Deprecated since IPython 4.0 and ignored since 5.0, set TerminalInteractiveShell.prompts object directly."
- ).tag(config=True)
- prompts_pad_left = Bool(True,
- help="Deprecated since IPython 4.0 and ignored since 5.0, set TerminalInteractiveShell.prompts object directly."
- ).tag(config=True)
-
- @observe('prompt_in1', 'prompt_in2', 'prompt_out', 'prompt_pad_left')
- def _prompt_trait_changed(self, change):
- name = change['name']
- warn("InteractiveShell.{name} is deprecated since IPython 4.0"
- " and ignored since 5.0, set TerminalInteractiveShell.prompts"
- " object directly.".format(name=name))
-
- # protect against weird cases where self.config may not exist:
show_rewritten_input = Bool(True,
help="Show rewritten input, e.g. for autocall."
@@ -707,8 +586,6 @@ class InteractiveShell(SingletonConfigurable):
self.init_pdb()
self.init_extension_manager()
self.init_payload()
- self.init_deprecation_warnings()
- self.hooks.late_startup_hook()
self.events.trigger('shell_initialized', self)
atexit.register(self.atexit_operations)
@@ -775,6 +652,7 @@ class InteractiveShell(SingletonConfigurable):
self.meta = Struct()
# Temporary files used for various purposes. Deleted at exit.
+ # The files here are stored with Path from Pathlib
self.tempfiles = []
self.tempdirs = []
@@ -832,16 +710,6 @@ class InteractiveShell(SingletonConfigurable):
elif self.logstart:
self.magic('logstart')
- def init_deprecation_warnings(self):
- """
- register default filter for deprecation warning.
-
- This will allow deprecation warning of function used interactively to show
- warning to users, and still hide deprecation warning from libraries import.
- """
- if sys.version_info < (3,7):
- warnings.filterwarnings("default", category=DeprecationWarning, module=self.user_ns.get("__name__"))
-
def init_builtins(self):
# A single, static flag that we set to True. Its presence indicates
@@ -862,16 +730,9 @@ class InteractiveShell(SingletonConfigurable):
self.object_info_string_level)
def init_io(self):
- # This will just use sys.stdout and sys.stderr. If you want to
- # override sys.stdout and sys.stderr themselves, you need to do that
- # *before* instantiating this class, because io holds onto
- # references to the underlying streams.
- # io.std* are deprecated, but don't show our own deprecation warnings
- # during initialization of the deprecated API.
- with warnings.catch_warnings():
- warnings.simplefilter('ignore', DeprecationWarning)
- io.stdout = io.IOStream(sys.stdout)
- io.stderr = io.IOStream(sys.stderr)
+ # implemented in subclasses, TerminalInteractiveShell does call
+ # colorama.init().
+ pass
def init_prompts(self):
# Set system prompts, so that scripts can decide if they are running
@@ -907,13 +768,42 @@ class InteractiveShell(SingletonConfigurable):
# the appropriate time.
self.display_trap = DisplayTrap(hook=self.displayhook)
+ @staticmethod
+ def get_path_links(p: Path):
+ """Gets path links including all symlinks
+
+ Examples
+ --------
+ In [1]: from IPython.core.interactiveshell import InteractiveShell
+
+ In [2]: import sys, pathlib
+
+ In [3]: paths = InteractiveShell.get_path_links(pathlib.Path(sys.executable))
+
+ In [4]: len(paths) == len(set(paths))
+ Out[4]: True
+
+ In [5]: bool(paths)
+ Out[5]: True
+ """
+ paths = [p]
+ while p.is_symlink():
+ new_path = Path(os.readlink(p))
+ if not new_path.is_absolute():
+ new_path = p.parent / new_path
+ p = new_path
+ paths.append(p)
+ return paths
+
def init_virtualenv(self):
"""Add the current virtualenv to sys.path so the user can import modules from it.
This isn't perfect: it doesn't use the Python interpreter with which the
virtualenv was built, and it ignores the --no-site-packages option. A
warning will appear suggesting the user installs IPython in the
virtualenv, but for many cases, it probably works well enough.
+
Adapted from code snippets online.
+
http://blog.ufsoft.org/2009/1/29/ipython-and-virtualenv
"""
if 'VIRTUAL_ENV' not in os.environ:
@@ -930,10 +820,7 @@ class InteractiveShell(SingletonConfigurable):
# stdlib venv may symlink sys.executable, so we can't use realpath.
# but others can symlink *to* the venv Python, so we can't just use sys.executable.
# So we just check every item in the symlink tree (generally <= 3)
- paths = [p]
- while p.is_symlink():
- p = Path(os.readlink(p))
- paths.append(p.resolve())
+ paths = self.get_path_links(p)
# In Cygwin paths like "c:\..." and '\cygdrive\c\...' are possible
if p_venv.parts[1] == "cygdrive":
@@ -1029,13 +916,12 @@ class InteractiveShell(SingletonConfigurable):
for hook_name in hooks.__all__:
# default hooks have priority 100, i.e. low; user hooks should have
# 0-100 priority
- self.set_hook(hook_name,getattr(hooks,hook_name), 100, _warn_deprecated=False)
+ self.set_hook(hook_name, getattr(hooks, hook_name), 100)
if self.display_page:
self.set_hook('show_in_pager', page.as_hook(page.display_page), 90)
- def set_hook(self,name,hook, priority=50, str_key=None, re_key=None,
- _warn_deprecated=True):
+ def set_hook(self, name, hook, priority=50, str_key=None, re_key=None):
"""set_hook(name,hook) -> sets an internal IPython hook.
IPython exposes some of its internal API as user-modifiable hooks. By
@@ -1065,9 +951,13 @@ class InteractiveShell(SingletonConfigurable):
print("Warning! Hook '%s' is not one of %s" % \
(name, IPython.core.hooks.__all__ ))
- if _warn_deprecated and (name in IPython.core.hooks.deprecated):
+ if name in IPython.core.hooks.deprecated:
alternative = IPython.core.hooks.deprecated[name]
- warn("Hook {} is deprecated. Use {} instead.".format(name, alternative), stacklevel=2)
+ raise ValueError(
+ "Hook {} has been deprecated since IPython 5.0. Use {} instead.".format(
+ name, alternative
+ )
+ )
if not dp:
dp = IPython.core.hooks.CommandChainDispatcher()
@@ -1091,12 +981,13 @@ class InteractiveShell(SingletonConfigurable):
def register_post_execute(self, func):
"""DEPRECATED: Use ip.events.register('post_run_cell', func)
-
+
Register a function for calling after code execution.
"""
- warn("ip.register_post_execute is deprecated, use "
- "ip.events.register('post_run_cell', func) instead.", stacklevel=2)
- self.events.register('post_run_cell', func)
+ raise ValueError(
+ "ip.register_post_execute is deprecated since IPython 1.0, use "
+ "ip.events.register('post_run_cell', func) instead."
+ )
def _clear_warning_registry(self):
# clear the warning registry, so that different code blocks with
@@ -1111,14 +1002,14 @@ class InteractiveShell(SingletonConfigurable):
def new_main_mod(self, filename, modname):
"""Return a new 'main' module object for user code execution.
-
+
``filename`` should be the path of the script which will be run in the
module. Requests with the same filename will get the same module, with
its namespace cleared.
-
+
``modname`` should be the module name - normally either '__main__' or
the basename of the file without the extension.
-
+
When scripts are executed via %run, we must keep a reference to their
__main__ module around so that Python doesn't
clear it, rendering references to module globals useless.
@@ -1154,7 +1045,6 @@ class InteractiveShell(SingletonConfigurable):
Examples
--------
-
In [15]: import IPython
In [16]: m = _ip.new_main_mod(IPython.__file__, 'IPython')
@@ -1304,10 +1194,10 @@ class InteractiveShell(SingletonConfigurable):
def prepare_user_module(self, user_module=None, user_ns=None):
"""Prepare the module and namespace in which user code will be run.
-
+
When IPython is started normally, both parameters are None: a new module
is created automatically, and its __dict__ used as the namespace.
-
+
If only user_module is provided, its __dict__ is used as the namespace.
If only user_ns is provided, a dummy module is created, and user_ns
becomes the global namespace. If both are provided (as they may be
@@ -1428,7 +1318,7 @@ class InteractiveShell(SingletonConfigurable):
def all_ns_refs(self):
"""Get a list of references to all the namespace dictionaries in which
IPython might store a user-created object.
-
+
Note that this does not include the displayhook, which also caches
objects from the output."""
return [self.user_ns, self.user_global_ns, self.user_ns_hidden] + \
@@ -1524,8 +1414,8 @@ class InteractiveShell(SingletonConfigurable):
else: # Delete by object
try:
obj = self.user_ns[varname]
- except KeyError:
- raise NameError("name '%s' is not defined" % varname)
+ except KeyError as e:
+ raise NameError("name '%s' is not defined" % varname) from e
# Also check in output history
ns_refs.append(self.history_manager.output_hist)
for ns in ns_refs:
@@ -1555,8 +1445,8 @@ class InteractiveShell(SingletonConfigurable):
if regex is not None:
try:
m = re.compile(regex)
- except TypeError:
- raise TypeError('regex must be a string or compiled pattern')
+ except TypeError as e:
+ raise TypeError('regex must be a string or compiled pattern') from e
# Search for keys in each namespace that match the given regex
# If a match is found, delete the key/value pair.
for ns in self.all_ns_refs:
@@ -1615,15 +1505,15 @@ class InteractiveShell(SingletonConfigurable):
def drop_by_id(self, variables):
"""Remove a dict of variables from the user namespace, if they are the
same as the values in the dictionary.
-
+
This is intended for use by extensions: variables that they've added can
be taken back out if they are unloaded, without removing any that the
user has overwritten.
-
+
Parameters
----------
variables : dict
- A dictionary mapping object names (as strings) to the objects.
+ A dictionary mapping object names (as strings) to the objects.
"""
for name, obj in variables.items():
if name in self.user_ns and self.user_ns[name] is obj:
@@ -1820,7 +1710,7 @@ class InteractiveShell(SingletonConfigurable):
"""Get object info as formatted text"""
return self.object_inspect_mime(oname, detail_level)['text/plain']
- def object_inspect_mime(self, oname, detail_level=0):
+ def object_inspect_mime(self, oname, detail_level=0, omit_sections=()):
"""Get object info as a mimebundle of formatted representations.
A mimebundle is a dictionary, keyed by mime-type.
@@ -1840,6 +1730,7 @@ class InteractiveShell(SingletonConfigurable):
info=info,
detail_level=detail_level,
formatter=docformat,
+ omit_sections=omit_sections,
)
else:
raise KeyError(oname)
@@ -1892,7 +1783,6 @@ class InteractiveShell(SingletonConfigurable):
Parameters
----------
-
exc_tuple : tuple of exception classes
A *tuple* of exception classes, for which to call the defined
handler. It is very important that you use a tuple, and NOT A
@@ -1922,10 +1812,11 @@ class InteractiveShell(SingletonConfigurable):
Notes
-----
-
WARNING: by putting in your own exception handler into IPython's main
execution loop, you run a very good chance of nasty crashes. This
- facility should only be used if you really know what you are doing."""
+ facility should only be used if you really know what you are doing.
+ """
+
if not isinstance(exc_tuple, tuple):
raise TypeError("The custom exceptions must be given as a tuple.")
@@ -1937,10 +1828,10 @@ class InteractiveShell(SingletonConfigurable):
def validate_stb(stb):
"""validate structured traceback return type
-
+
return type of CustomTB *should* be a list of strings, but allow
single strings or None, which are harmless.
-
+
This function will *always* return a list of strings,
and will raise a TypeError if stb is inappropriate.
"""
@@ -2095,10 +1986,19 @@ class InteractiveShell(SingletonConfigurable):
# Exception classes can customise their traceback - we
# use this in IPython.parallel for exceptions occurring
# in the engines. This should return a list of strings.
- stb = value._render_traceback_()
+ if hasattr(value, "_render_traceback_"):
+ stb = value._render_traceback_()
+ else:
+ stb = self.InteractiveTB.structured_traceback(
+ etype, value, tb, tb_offset=tb_offset
+ )
+
except Exception:
- stb = self.InteractiveTB.structured_traceback(etype,
- value, tb, tb_offset=tb_offset)
+ print(
+ "Unexpected exception formatting exception. Falling back to standard exception"
+ )
+ traceback.print_exc()
+ return None
self._showtraceback(etype, value, stb)
if self.call_pdb:
@@ -2135,7 +2035,7 @@ class InteractiveShell(SingletonConfigurable):
If the syntax error occurred when running a compiled code (i.e. running_compile_code=True),
longer stack trace will be displayed.
- """
+ """
etype, value, last_traceback = self._get_exc_info()
if filename and issubclass(etype, SyntaxError):
@@ -2160,19 +2060,6 @@ class InteractiveShell(SingletonConfigurable):
the %paste magic."""
self.showsyntaxerror()
- #-------------------------------------------------------------------------
- # Things related to readline
- #-------------------------------------------------------------------------
-
- def init_readline(self):
- """DEPRECATED
-
- Moved to terminal subclass, here only to simplify the init logic."""
- # Set a number of methods that depend on readline to be no-op
- warnings.warn('`init_readline` is no-op since IPython 5.0 and is Deprecated',
- DeprecationWarning, stacklevel=2)
- self.set_custom_completer = no_op
-
@skip_doctest
def set_next_input(self, s, replace=False):
""" Sets the 'default' input string for the next command line.
@@ -2201,8 +2088,12 @@ class InteractiveShell(SingletonConfigurable):
(typically over the network by remote frontends).
"""
from IPython.core.completer import IPCompleter
- from IPython.core.completerlib import (module_completer,
- magic_run_completer, cd_completer, reset_completer)
+ from IPython.core.completerlib import (
+ cd_completer,
+ magic_run_completer,
+ module_completer,
+ reset_completer,
+ )
self.Completer = IPCompleter(shell=self,
namespace=self.user_ns,
@@ -2229,26 +2120,24 @@ class InteractiveShell(SingletonConfigurable):
Parameters
----------
-
- text : string
- A string of text to be completed on. It can be given as empty and
- instead a line/position pair are given. In this case, the
- completer itself will split the line like readline does.
-
- line : string, optional
- The complete line that text is part of.
-
- cursor_pos : int, optional
- The position of the cursor on the input line.
+ text : string
+ A string of text to be completed on. It can be given as empty and
+ instead a line/position pair are given. In this case, the
+ completer itself will split the line like readline does.
+ line : string, optional
+ The complete line that text is part of.
+ cursor_pos : int, optional
+ The position of the cursor on the input line.
Returns
-------
- text : string
+ text : string
The actual text that was completed.
-
- matches : list
+ matches : list
A sorted list with all possible completions.
+ Notes
+ -----
The optional arguments allow the completion to take more context into
account, and are part of the low-level completion API.
@@ -2257,8 +2146,8 @@ class InteractiveShell(SingletonConfigurable):
exposing it as a method, it can be used by other non-readline
environments (such as GUIs) for text completion.
- Simple usage example:
-
+ Examples
+ --------
In [1]: x = 'hello'
In [2]: _ip.complete('x.l')
@@ -2341,7 +2230,7 @@ class InteractiveShell(SingletonConfigurable):
func, magic_kind=magic_kind, magic_name=magic_name
)
- def _find_with_lazy_load(self, type_, magic_name: str):
+ def _find_with_lazy_load(self, /, type_, magic_name: str):
"""
Try to find a magic potentially lazy-loading it.
@@ -2374,14 +2263,12 @@ class InteractiveShell(SingletonConfigurable):
Parameters
----------
magic_name : str
- Name of the desired magic function, without '%' prefix.
-
+ Name of the desired magic function, without '%' prefix.
line : str
- The rest of the input line as a single string.
-
+ The rest of the input line as a single string.
_stack_depth : int
- If run_line_magic() is called from magic() then _stack_depth=2.
- This is added to ensure backward compatibility for use of 'get_ipython().magic()'
+ If run_line_magic() is called from magic() then _stack_depth=2.
+ This is added to ensure backward compatibility for use of 'get_ipython().magic()'
"""
fn = self._find_with_lazy_load("line", magic_name)
if fn is None:
@@ -2423,7 +2310,7 @@ class InteractiveShell(SingletonConfigurable):
Parameters
----------
stack_depth : int
- Depth relative to calling frame
+ Depth relative to calling frame
"""
return sys._getframe(stack_depth + 1).f_locals
@@ -2433,13 +2320,11 @@ class InteractiveShell(SingletonConfigurable):
Parameters
----------
magic_name : str
- Name of the desired magic function, without '%' prefix.
-
+ Name of the desired magic function, without '%' prefix.
line : str
- The rest of the first input line as a single string.
-
+ The rest of the first input line as a single string.
cell : str
- The body of the cell as a (possibly multiline) string.
+ The body of the cell as a (possibly multiline) string.
"""
fn = self._find_with_lazy_load("cell", magic_name)
if fn is None:
@@ -2491,7 +2376,11 @@ class InteractiveShell(SingletonConfigurable):
return self.magics_manager.magics[magic_kind].get(magic_name)
def magic(self, arg_s):
- """DEPRECATED. Use run_line_magic() instead.
+ """
+ DEPRECATED
+
+ Deprecated since IPython 0.13 (warning added in
+ 8.1), use run_line_magic(magic_name, parameter_s).
Call a magic function by name.
@@ -2509,6 +2398,12 @@ class InteractiveShell(SingletonConfigurable):
valid Python code you can type at the interpreter, including loops and
compound statements.
"""
+ warnings.warn(
+ "`magic(...)` is deprecated since IPython 0.13 (warning added in "
+ "8.1), use run_line_magic(magic_name, parameter_s).",
+ DeprecationWarning,
+ stacklevel=2,
+ )
# TODO: should we issue a loud deprecation warning here?
magic_name, _, magic_arg_s = arg_s.partition(' ')
magic_name = magic_name.lstrip(prefilter.ESC_MAGIC)
@@ -2548,9 +2443,9 @@ class InteractiveShell(SingletonConfigurable):
Parameters
----------
cmd : str
- Command to execute (can not end in '&', as background processes are
- not supported. Should not be a command that expects input
- other than simple text.
+ Command to execute (can not end in '&', as background processes are
+ not supported. Should not be a command that expects input
+ other than simple text.
"""
if cmd.rstrip().endswith('&'):
# this is *far* from a rigorous test
@@ -2572,9 +2467,21 @@ class InteractiveShell(SingletonConfigurable):
Parameters
----------
cmd : str
- Command to execute.
+ Command to execute.
"""
cmd = self.var_expand(cmd, depth=1)
+ # warn if there is an IPython magic alternative.
+ main_cmd = cmd.split()[0]
+ has_magic_alternatives = ("pip", "conda", "cd")
+
+ if main_cmd in has_magic_alternatives:
+ warnings.warn(
+ (
+ "You executed the system command !{0} which may not work "
+ "as expected. Try the IPython magic %{0} instead."
+ ).format(main_cmd)
+ )
+
# protect os.system from UNC paths on Windows, which it can't handle:
if sys.platform == 'win32':
from IPython.utils._process_win32 import AvoidUNCPath
@@ -2623,18 +2530,18 @@ class InteractiveShell(SingletonConfigurable):
Parameters
----------
cmd : str
- Command to execute (can not end in '&', as background processes are
- not supported.
+ Command to execute (can not end in '&', as background processes are
+ not supported.
split : bool, optional
- If True, split the output into an IPython SList. Otherwise, an
- IPython LSString is returned. These are objects similar to normal
- lists and strings, with a few convenience attributes for easier
- manipulation of line-based output. You can use '?' on them for
- details.
+ If True, split the output into an IPython SList. Otherwise, an
+ IPython LSString is returned. These are objects similar to normal
+ lists and strings, with a few convenience attributes for easier
+ manipulation of line-based output. You can use '?' on them for
+ details.
depth : int, optional
- How many frames above the caller are the local variables which should
- be expanded in the command string? The default (0) assumes that the
- expansion variables are in the stack frame calling this function.
+ How many frames above the caller are the local variables which should
+ be expanded in the command string? The default (0) assumes that the
+ expansion variables are in the stack frame calling this function.
"""
if cmd.rstrip().endswith('&'):
# this is *far* from a rigorous test
@@ -2717,10 +2624,10 @@ class InteractiveShell(SingletonConfigurable):
stb = self.InteractiveTB.get_exception_only(etype, evalue)
exc_info = {
- u'status' : 'error',
- u'traceback' : stb,
- u'ename' : etype.__name__,
- u'evalue' : py3compat.safe_unicode(evalue),
+ "status": "error",
+ "traceback": stb,
+ "ename": etype.__name__,
+ "evalue": py3compat.safe_unicode(evalue),
}
return exc_info
@@ -2745,9 +2652,9 @@ class InteractiveShell(SingletonConfigurable):
Parameters
----------
expressions : dict
- A dict with string keys and string values. The expression values
- should be valid Python expressions, each of which will be evaluated
- in the user namespace.
+ A dict with string keys and string values. The expression values
+ should be valid Python expressions, each of which will be evaluated
+ in the user namespace.
Returns
-------
@@ -2794,7 +2701,7 @@ class InteractiveShell(SingletonConfigurable):
----------
fname : string
The name of the file to be executed.
- where : tuple
+ *where : tuple
One or two namespaces, passed to execfile() as (globals,locals).
If only one is given, it is passed as both.
exit_ignore : bool (False)
@@ -2809,11 +2716,11 @@ class InteractiveShell(SingletonConfigurable):
__future__ imports are not shared in either direction.
"""
- fname = os.path.abspath(os.path.expanduser(fname))
+ fname = Path(fname).expanduser().resolve()
# Make sure we can open the file
try:
- with open(fname):
+ with fname.open("rb"):
pass
except:
warn('Could not open file <%s> for safe execution.' % fname)
@@ -2822,7 +2729,7 @@ class InteractiveShell(SingletonConfigurable):
# Find things also in current directory. This is needed to mimic the
# behavior of running a script from the system command line, where
# Python inserts the script's directory into sys.path
- dname = os.path.dirname(fname)
+ dname = str(fname.parent)
with prepended_to_syspath(dname), self.builtin_trap:
try:
@@ -2867,11 +2774,11 @@ class InteractiveShell(SingletonConfigurable):
raise_exceptions : bool (False)
If True raise exceptions everywhere. Meant for testing.
"""
- fname = os.path.abspath(os.path.expanduser(fname))
+ fname = Path(fname).expanduser().resolve()
# Make sure we can open the file
try:
- with open(fname):
+ with fname.open("rb"):
pass
except:
warn('Could not open file <%s> for safe execution.' % fname)
@@ -2880,11 +2787,11 @@ class InteractiveShell(SingletonConfigurable):
# Find things also in current directory. This is needed to mimic the
# behavior of running a script from the system command line, where
# Python inserts the script's directory into sys.path
- dname = os.path.dirname(fname)
-
+ dname = str(fname.parent)
+
def get_cells():
"""generator for sequence of code blocks to run"""
- if fname.endswith('.ipynb'):
+ if fname.suffix == ".ipynb":
from nbformat import read
nb = read(fname, as_version=4)
if not nb.cells:
@@ -2893,8 +2800,7 @@ class InteractiveShell(SingletonConfigurable):
if cell.cell_type == 'code':
yield cell.source
else:
- with open(fname) as f:
- yield f.read()
+ yield fname.read_text(encoding="utf-8")
with prepended_to_syspath(dname):
try:
@@ -2951,19 +2857,19 @@ class InteractiveShell(SingletonConfigurable):
Parameters
----------
raw_cell : str
- The code (including IPython code such as %magic functions) to run.
+ The code (including IPython code such as %magic functions) to run.
store_history : bool
- If True, the raw and translated cell will be stored in IPython's
- history. For user code calling back into IPython's machinery, this
- should be set to False.
+ If True, the raw and translated cell will be stored in IPython's
+ history. For user code calling back into IPython's machinery, this
+ should be set to False.
silent : bool
- If True, avoid side-effects, such as implicit displayhooks and
- and logging. silent=True forces store_history=False.
+ If True, avoid side-effects, such as implicit displayhooks and
+ and logging. silent=True forces store_history=False.
shell_futures : bool
- If True, the code will share future statements with the interactive
- shell. It will both be affected by previous __future__ imports, and
- any __future__ imports in the code will affect the shell. If False,
- __future__ imports are not shared in either direction.
+ If True, the code will share future statements with the interactive
+ shell. It will both be affected by previous __future__ imports, and
+ any __future__ imports in the code will affect the shell. If False,
+ __future__ imports are not shared in either direction.
Returns
-------
@@ -3035,7 +2941,6 @@ class InteractiveShell(SingletonConfigurable):
result.error_in_exec = e
self.showtraceback(running_compiled_code=True)
return result
- return
def should_run_async(
self, raw_cell: str, *, transformed_cell=None, preprocessing_exc_tuple=None
@@ -3044,14 +2949,13 @@ class InteractiveShell(SingletonConfigurable):
Parameters
----------
- raw_cell: str
+ raw_cell : str
The code to be executed
Returns
-------
result: bool
Whether the code needs to be run with a coroutine runner or not
-
.. versionadded:: 7.0
"""
if not self.autoawait:
@@ -3175,9 +3079,8 @@ class InteractiveShell(SingletonConfigurable):
cell = raw_cell
# Store raw and processed history
- if store_history:
- self.history_manager.store_inputs(self.execution_count,
- cell, raw_cell)
+ if store_history and raw_cell.strip(" %") != "paste":
+ self.history_manager.store_inputs(self.execution_count, cell, raw_cell)
if not silent:
self.logger.log(cell, raw_cell)
@@ -3196,35 +3099,12 @@ class InteractiveShell(SingletonConfigurable):
_run_async = False
with self.builtin_trap:
- cell_name = self.compile.cache(
- cell, self.execution_count, raw_code=raw_cell
- )
+ cell_name = compiler.cache(cell, self.execution_count, raw_code=raw_cell)
with self.display_trap:
# Compile to bytecode
try:
- if sys.version_info < (3,8) and self.autoawait:
- if _should_be_async(cell):
- # the code AST below will not be user code: we wrap it
- # in an `async def`. This will likely make some AST
- # transformer below miss some transform opportunity and
- # introduce a small coupling to run_code (in which we
- # bake some assumptions of what _ast_asyncify returns.
- # they are ways around (like grafting part of the ast
- # later:
- # - Here, return code_ast.body[0].body[1:-1], as well
- # as last expression in return statement which is
- # the user code part.
- # - Let it go through the AST transformers, and graft
- # - it back after the AST transform
- # But that seem unreasonable, at least while we
- # do not need it.
- code_ast = _ast_asyncify(cell, 'async-def-wrapper')
- _run_async = True
- else:
- code_ast = compiler.ast_parse(cell, filename=cell_name)
- else:
- code_ast = compiler.ast_parse(cell, filename=cell_name)
+ code_ast = compiler.ast_parse(cell, filename=cell_name)
except self.custom_exceptions as e:
etype, value, tb = sys.exc_info()
self.CustomTB(etype, value, tb)
@@ -3250,8 +3130,6 @@ class InteractiveShell(SingletonConfigurable):
# Execute the user code
interactivity = "none" if silent else self.ast_node_interactivity
- if _run_async:
- interactivity = 'async'
has_raised = await self.run_ast_nodes(code_ast.body, cell_name,
interactivity=interactivity, compiler=compiler, result=result)
@@ -3308,8 +3186,8 @@ class InteractiveShell(SingletonConfigurable):
Parameters
----------
node : ast.Node
- The root node to be transformed. Typically called with the ast.Module
- produced by parsing user input.
+ The root node to be transformed. Typically called with the ast.Module
+ produced by parsing user input.
Returns
-------
@@ -3356,8 +3234,14 @@ class InteractiveShell(SingletonConfigurable):
return code
return code.replace(co_name="<cell line: %s>" % (first_real_line,))
- async def run_ast_nodes(self, nodelist:ListType[AST], cell_name:str, interactivity='last_expr',
- compiler=compile, result=None):
+ async def run_ast_nodes(
+ self,
+ nodelist: ListType[stmt],
+ cell_name: str,
+ interactivity="last_expr",
+ compiler=compile,
+ result=None,
+ ):
"""Run a sequence of AST nodes. The execution mode depends on the
interactivity parameter.
@@ -3377,11 +3261,6 @@ class InteractiveShell(SingletonConfigurable):
or the last assignment. Other values for this parameter will raise a
ValueError.
- Experimental value: 'async' Will try to run top level interactive
- async/await code in default runner, this will not respect the
- interactivity setting and will only run the last node if it is an
- expression.
-
compiler : callable
A function with the same interface as the built-in compile(), to turn
the AST nodes into code objects. Default is the built-in compile().
@@ -3396,6 +3275,7 @@ class InteractiveShell(SingletonConfigurable):
if not nodelist:
return
+
if interactivity == 'last_expr_or_assign':
if isinstance(nodelist[-1], _assign_nodes):
asg = nodelist[-1]
@@ -3424,53 +3304,38 @@ class InteractiveShell(SingletonConfigurable):
to_run_exec, to_run_interactive = nodelist[:-1], nodelist[-1:]
elif interactivity == 'all':
to_run_exec, to_run_interactive = [], nodelist
- elif interactivity == 'async':
- to_run_exec, to_run_interactive = [], nodelist
- _async = True
else:
raise ValueError("Interactivity was %r" % interactivity)
try:
- if _async and sys.version_info > (3,8):
- raise ValueError("This branch should never happen on Python 3.8 and above, "
- "please try to upgrade IPython and open a bug report with your case.")
- if _async:
- # If interactivity is async the semantics of run_code are
- # completely different Skip usual machinery.
- mod = Module(nodelist, [])
- async_wrapper_code = compiler(mod, cell_name, 'exec')
- exec(async_wrapper_code, self.user_global_ns, self.user_ns)
- async_code = removed_co_newlocals(self.user_ns.pop('async-def-wrapper')).__code__
- if (await self.run_code(async_code, result, async_=True)):
+
+ def compare(code):
+ is_async = inspect.CO_COROUTINE & code.co_flags == inspect.CO_COROUTINE
+ return is_async
+
+ # refactor that to just change the mod constructor.
+ to_run = []
+ for node in to_run_exec:
+ to_run.append((node, "exec"))
+
+ for node in to_run_interactive:
+ to_run.append((node, "single"))
+
+ for node, mode in to_run:
+ if mode == "exec":
+ mod = Module([node], [])
+ elif mode == "single":
+ mod = ast.Interactive([node])
+ with compiler.extra_flags(
+ getattr(ast, "PyCF_ALLOW_TOP_LEVEL_AWAIT", 0x0)
+ if self.autoawait
+ else 0x0
+ ):
+ code = compiler(mod, cell_name, mode)
+ code = self._update_code_co_name(code)
+ asy = compare(code)
+ if await self.run_code(code, result, async_=asy):
return True
- else:
- if sys.version_info > (3, 8):
- def compare(code):
- is_async = (inspect.CO_COROUTINE & code.co_flags == inspect.CO_COROUTINE)
- return is_async
- else:
- def compare(code):
- return _async
-
- # refactor that to just change the mod constructor.
- to_run = []
- for node in to_run_exec:
- to_run.append((node, 'exec'))
-
- for node in to_run_interactive:
- to_run.append((node, 'single'))
-
- for node,mode in to_run:
- if mode == 'exec':
- mod = Module([node], [])
- elif mode == 'single':
- mod = ast.Interactive([node])
- with compiler.extra_flags(getattr(ast, 'PyCF_ALLOW_TOP_LEVEL_AWAIT', 0x0) if self.autoawait else 0x0):
- code = compiler(mod, cell_name, mode)
- code = self._update_code_co_name(code)
- asy = compare(code)
- if (await self.run_code(code, result, async_=asy)):
- return True
# Flush softspace
if softspace(sys.stdout, 0):
@@ -3493,21 +3358,6 @@ class InteractiveShell(SingletonConfigurable):
return False
- def _async_exec(self, code_obj: types.CodeType, user_ns: dict):
- """
- Evaluate an asynchronous code object using a code runner
-
- Fake asynchronous execution of code_object in a namespace via a proxy namespace.
-
- Returns coroutine object, which can be executed via async loop runner
-
- WARNING: The semantics of `async_exec` are quite different from `exec`,
- in particular you can only pass a single namespace. It also return a
- handle to the value of the last things returned by code_object.
- """
-
- return eval(code_obj, user_ns)
-
async def run_code(self, code_obj, result=None, *, async_=False):
"""Execute a code object.
@@ -3541,12 +3391,7 @@ class InteractiveShell(SingletonConfigurable):
outflag = True # happens in more places, so it's easier as default
try:
try:
- self.hooks.pre_run_code_hook()
- if async_ and sys.version_info < (3,8):
- last_expr = (await self._async_exec(code_obj, self.user_ns))
- code = compile('last_expr', 'fake', "single")
- exec(code, {'last_expr': last_expr})
- elif async_ :
+ if async_:
await eval(code_obj, self.user_global_ns, self.user_ns)
else:
exec(code_obj, self.user_global_ns, self.user_ns)
@@ -3579,17 +3424,17 @@ class InteractiveShell(SingletonConfigurable):
Parameters
----------
- source : string
- Python input code, which can be multiline.
+ code : string
+ Python input code, which can be multiline.
Returns
-------
status : str
- One of 'complete', 'incomplete', or 'invalid' if source is not a
- prefix of valid code.
+ One of 'complete', 'incomplete', or 'invalid' if source is not a
+ prefix of valid code.
indent : str
- When status is 'incomplete', this is some whitespace to insert on
- the next line of the prompt.
+ When status is 'incomplete', this is some whitespace to insert on
+ the next line of the prompt.
"""
status, nspaces = self.input_transformer_manager.check_complete(code)
return status, ' ' * (nspaces or 0)
@@ -3616,16 +3461,17 @@ class InteractiveShell(SingletonConfigurable):
Parameters
----------
gui : optional, string
- If given, dictates the choice of matplotlib GUI backend to use
- (should be one of IPython's supported backends, 'qt', 'osx', 'tk',
- 'gtk', 'wx' or 'inline'), otherwise we use the default chosen by
- matplotlib (as dictated by the matplotlib build-time options plus the
- user's matplotlibrc configuration file). Note that not all backends
- make sense in all contexts, for example a terminal ipython can't
- display figures inline.
+ If given, dictates the choice of matplotlib GUI backend to use
+ (should be one of IPython's supported backends, 'qt', 'osx', 'tk',
+ 'gtk', 'wx' or 'inline'), otherwise we use the default chosen by
+ matplotlib (as dictated by the matplotlib build-time options plus the
+ user's matplotlibrc configuration file). Note that not all backends
+ make sense in all contexts, for example a terminal ipython can't
+ display figures inline.
"""
- from IPython.core import pylabtools as pt
from matplotlib_inline.backend_inline import configure_inline_support
+
+ from IPython.core import pylabtools as pt
gui, backend = pt.find_gui_and_backend(gui, self.pylab_gui_select)
if gui != 'inline':
@@ -3662,18 +3508,18 @@ class InteractiveShell(SingletonConfigurable):
Parameters
----------
gui : optional, string
- If given, dictates the choice of matplotlib GUI backend to use
- (should be one of IPython's supported backends, 'qt', 'osx', 'tk',
- 'gtk', 'wx' or 'inline'), otherwise we use the default chosen by
- matplotlib (as dictated by the matplotlib build-time options plus the
- user's matplotlibrc configuration file). Note that not all backends
- make sense in all contexts, for example a terminal ipython can't
- display figures inline.
+ If given, dictates the choice of matplotlib GUI backend to use
+ (should be one of IPython's supported backends, 'qt', 'osx', 'tk',
+ 'gtk', 'wx' or 'inline'), otherwise we use the default chosen by
+ matplotlib (as dictated by the matplotlib build-time options plus the
+ user's matplotlibrc configuration file). Note that not all backends
+ make sense in all contexts, for example a terminal ipython can't
+ display figures inline.
import_all : optional, bool, default: True
- Whether to do `from numpy import *` and `from pylab import *`
- in addition to module imports.
+ Whether to do `from numpy import *` and `from pylab import *`
+ in addition to module imports.
welcome_message : deprecated
- This argument is ignored, no welcome message will be displayed.
+ This argument is ignored, no welcome message will be displayed.
"""
from IPython.core.pylabtools import import_pylab
@@ -3738,32 +3584,19 @@ class InteractiveShell(SingletonConfigurable):
- data(None): if data is given, it gets written out to the temp file
immediately, and the file is closed again."""
- dirname = tempfile.mkdtemp(prefix=prefix)
- self.tempdirs.append(dirname)
+ dir_path = Path(tempfile.mkdtemp(prefix=prefix))
+ self.tempdirs.append(dir_path)
- handle, filename = tempfile.mkstemp('.py', prefix, dir=dirname)
+ handle, filename = tempfile.mkstemp(".py", prefix, dir=str(dir_path))
os.close(handle) # On Windows, there can only be one open handle on a file
- self.tempfiles.append(filename)
+
+ file_path = Path(filename)
+ self.tempfiles.append(file_path)
if data:
- with open(filename, 'w') as tmp_file:
- tmp_file.write(data)
+ file_path.write_text(data, encoding="utf-8")
return filename
- @undoc
- def write(self,data):
- """DEPRECATED: Write a string to the default output"""
- warn('InteractiveShell.write() is deprecated, use sys.stdout instead',
- DeprecationWarning, stacklevel=2)
- sys.stdout.write(data)
-
- @undoc
- def write_err(self,data):
- """DEPRECATED: Write a string to the default error output"""
- warn('InteractiveShell.write_err() is deprecated, use sys.stderr instead',
- DeprecationWarning, stacklevel=2)
- sys.stderr.write(data)
-
def ask_yes_no(self, prompt, default=None, interrupt=None):
if self.quiet:
return True
@@ -3778,26 +3611,37 @@ class InteractiveShell(SingletonConfigurable):
Parameters
----------
- range_str : string
+ range_str : str
The set of slices is given as a string, like "~5/6-~4/2 4:8 9",
since this function is for use by magic functions which get their
arguments as strings. The number before the / is the session
number: ~n goes n back from the current session.
+ If empty string is given, returns history of current session
+ without the last input.
+
raw : bool, optional
By default, the processed input is used. If this is true, the raw
input history is used instead.
Notes
-----
-
Slices can be described with two notations:
* ``N:M`` -> standard python form, means including items N...(M-1).
* ``N-M`` -> include items N..M (closed endpoint).
"""
lines = self.history_manager.get_range_by_str(range_str, raw=raw)
- return "\n".join(x for _, _, x in lines)
+ text = "\n".join(x for _, _, x in lines)
+
+ # Skip the last line, as it's probably the magic that called this
+ if not range_str:
+ if "\n" not in text:
+ text = ""
+ else:
+ text = text[: text.rfind("\n")]
+
+ return text
def find_user_code(self, target, raw=True, py_only=False, skip_encoding_cookie=True, search_ns=False):
"""Get a code string from history, file, url, or a string or macro.
@@ -3806,26 +3650,26 @@ class InteractiveShell(SingletonConfigurable):
Parameters
----------
-
target : str
+ A string specifying code to retrieve. This will be tried respectively
+ as: ranges of input history (see %history for syntax), url,
+ corresponding .py file, filename, or an expression evaluating to a
+ string or Macro in the user namespace.
- A string specifying code to retrieve. This will be tried respectively
- as: ranges of input history (see %history for syntax), url,
- corresponding .py file, filename, or an expression evaluating to a
- string or Macro in the user namespace.
+ If empty string is given, returns complete history of current
+ session, without the last line.
raw : bool
- If true (default), retrieve raw history. Has no effect on the other
- retrieval mechanisms.
+ If true (default), retrieve raw history. Has no effect on the other
+ retrieval mechanisms.
py_only : bool (default False)
- Only try to fetch python code, do not try alternative methods to decode file
- if unicode fails.
+ Only try to fetch python code, do not try alternative methods to decode file
+ if unicode fails.
Returns
-------
A string of code.
-
ValueError is raised if nothing is found, and TypeError if it evaluates
to an object of another type. In each case, .args[0] is a printable
message.
@@ -3836,13 +3680,13 @@ class InteractiveShell(SingletonConfigurable):
try:
if target.startswith(('http://', 'https://')):
return openpy.read_py_url(target, skip_encoding_cookie=skip_encoding_cookie)
- except UnicodeDecodeError:
+ except UnicodeDecodeError as e:
if not py_only :
# Deferred import
from urllib.request import urlopen
response = urlopen(target)
return response.read().decode('latin1')
- raise ValueError(("'%s' seem to be unreadable.") % target)
+ raise ValueError(("'%s' seem to be unreadable.") % target) from e
potential_target = [target]
try :
@@ -3854,11 +3698,11 @@ class InteractiveShell(SingletonConfigurable):
if os.path.isfile(tgt): # Read file
try :
return openpy.read_py_file(tgt, skip_encoding_cookie=skip_encoding_cookie)
- except UnicodeDecodeError :
+ except UnicodeDecodeError as e:
if not py_only :
with io_open(tgt,'r', encoding='latin1') as f :
return f.read()
- raise ValueError(("'%s' seem to be unreadable.") % target)
+ raise ValueError(("'%s' seem to be unreadable.") % target) from e
elif os.path.isdir(os.path.expanduser(tgt)):
raise ValueError("'%s' is a directory, not a regular file." % target)
@@ -3870,9 +3714,9 @@ class InteractiveShell(SingletonConfigurable):
try: # User namespace
codeobj = eval(target, self.user_ns)
- except Exception:
+ except Exception as e:
raise ValueError(("'%s' was not found in history, as a file, url, "
- "nor in the user namespace.") % target)
+ "nor in the user namespace.") % target) from e
if isinstance(codeobj, str):
return codeobj
@@ -3882,6 +3726,22 @@ class InteractiveShell(SingletonConfigurable):
raise TypeError("%s is neither a string nor a macro." % target,
codeobj)
+ def _atexit_once(self):
+ """
+ At exist operation that need to be called at most once.
+ Second call to this function per instance will do nothing.
+ """
+
+ if not getattr(self, "_atexit_once_called", False):
+ self._atexit_once_called = True
+ # Clear all user namespaces to release all references cleanly.
+ self.reset(new_session=False)
+ # Close the history session (this stores the end time and line count)
+ # this must be *before* the tempfile cleanup, in case of temporary
+ # history db
+ self.history_manager.end_session()
+ self.history_manager = None
+
#-------------------------------------------------------------------------
# Things related to IPython exiting
#-------------------------------------------------------------------------
@@ -3896,29 +3756,28 @@ class InteractiveShell(SingletonConfigurable):
code that has the appropriate information, rather than trying to
clutter
"""
- # Close the history session (this stores the end time and line count)
- # this must be *before* the tempfile cleanup, in case of temporary
- # history db
- self.history_manager.end_session()
+ self._atexit_once()
# Cleanup all tempfiles and folders left around
for tfile in self.tempfiles:
try:
- os.unlink(tfile)
- except OSError:
+ tfile.unlink()
+ self.tempfiles.remove(tfile)
+ except FileNotFoundError:
pass
-
+ del self.tempfiles
for tdir in self.tempdirs:
try:
- os.rmdir(tdir)
- except OSError:
+ tdir.rmdir()
+ self.tempdirs.remove(tdir)
+ except FileNotFoundError:
pass
+ del self.tempdirs
- # Clear all user namespaces to release all references cleanly.
- self.reset(new_session=False)
-
- # Run user hooks
- self.hooks.shutdown_hook()
+ # Restore user's cursor
+ if hasattr(self, "editing_mode") and self.editing_mode == "vi":
+ sys.stdout.write("\x1b[0 q")
+ sys.stdout.flush()
def cleanup(self):
self.restore_sys_module_state()