aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/python/ipython/py3/IPython/core
diff options
context:
space:
mode:
authorrobot-piglet <robot-piglet@yandex-team.com>2023-11-14 19:18:07 +0300
committerrobot-piglet <robot-piglet@yandex-team.com>2023-11-14 20:20:53 +0300
commit874ef51d3d3edfa25f5a505ec6ab50e172965d1e (patch)
tree620fb5e02063d23509d3aa3df2215c099ccde0b7 /contrib/python/ipython/py3/IPython/core
parente356b34d3b0399e2f170881af15c91e4db9e3d11 (diff)
downloadydb-874ef51d3d3edfa25f5a505ec6ab50e172965d1e.tar.gz
Intermediate changes
Diffstat (limited to 'contrib/python/ipython/py3/IPython/core')
-rw-r--r--contrib/python/ipython/py3/IPython/core/completerlib.py1
-rw-r--r--contrib/python/ipython/py3/IPython/core/display.py2
-rw-r--r--contrib/python/ipython/py3/IPython/core/events.py18
-rw-r--r--contrib/python/ipython/py3/IPython/core/guarded_eval.py27
-rw-r--r--contrib/python/ipython/py3/IPython/core/inputsplitter.py32
-rw-r--r--contrib/python/ipython/py3/IPython/core/inputtransformer.py39
-rw-r--r--contrib/python/ipython/py3/IPython/core/interactiveshell.py26
-rw-r--r--contrib/python/ipython/py3/IPython/core/magics/packaging.py89
-rw-r--r--contrib/python/ipython/py3/IPython/core/oinspect.py2
-rw-r--r--contrib/python/ipython/py3/IPython/core/release.py2
10 files changed, 166 insertions, 72 deletions
diff --git a/contrib/python/ipython/py3/IPython/core/completerlib.py b/contrib/python/ipython/py3/IPython/core/completerlib.py
index 65efa42254..74252dcfad 100644
--- a/contrib/python/ipython/py3/IPython/core/completerlib.py
+++ b/contrib/python/ipython/py3/IPython/core/completerlib.py
@@ -238,6 +238,7 @@ def try_import(mod: str, only_modules=False) -> List[str]:
completions.extend(m_all)
if m_is_init:
+ file_ = m.__file__
completions.extend(arcadia_module_list(mod))
completions_set = {c for c in completions if isinstance(c, str)}
completions_set.discard('__init__')
diff --git a/contrib/python/ipython/py3/IPython/core/display.py b/contrib/python/ipython/py3/IPython/core/display.py
index ffa6e185c4..20e2e34b8f 100644
--- a/contrib/python/ipython/py3/IPython/core/display.py
+++ b/contrib/python/ipython/py3/IPython/core/display.py
@@ -286,7 +286,7 @@ class DisplayObject(object):
in the frontend. The MIME type of the data should match the
subclasses used, so the Png subclass should be used for 'image/png'
data. If the data is a URL, the data will first be downloaded
- and then displayed. If
+ and then displayed.
Parameters
----------
diff --git a/contrib/python/ipython/py3/IPython/core/events.py b/contrib/python/ipython/py3/IPython/core/events.py
index 3a66e75e5a..90ff8f746d 100644
--- a/contrib/python/ipython/py3/IPython/core/events.py
+++ b/contrib/python/ipython/py3/IPython/core/events.py
@@ -13,8 +13,6 @@ events and the arguments which will be passed to them.
This API is experimental in IPython 2.0, and may be revised in future versions.
"""
-from backcall import callback_prototype
-
class EventManager(object):
"""Manage a collection of events and a sequence of callbacks for each.
@@ -63,23 +61,14 @@ class EventManager(object):
"""
if not callable(function):
raise TypeError('Need a callable, got %r' % function)
- callback_proto = available_events.get(event)
if function not in self.callbacks[event]:
- self.callbacks[event].append(callback_proto.adapt(function))
+ self.callbacks[event].append(function)
def unregister(self, event, function):
"""Remove a callback from the given event."""
if function in self.callbacks[event]:
return self.callbacks[event].remove(function)
- # Remove callback in case ``function`` was adapted by `backcall`.
- for callback in self.callbacks[event]:
- try:
- if callback.__wrapped__ is function:
- return self.callbacks[event].remove(callback)
- except AttributeError:
- pass
-
raise ValueError('Function {!r} is not registered as a {} callback'.format(function, event))
def trigger(self, event, *args, **kwargs):
@@ -100,9 +89,8 @@ class EventManager(object):
available_events = {}
def _define_event(callback_function):
- callback_proto = callback_prototype(callback_function)
- available_events[callback_function.__name__] = callback_proto
- return callback_proto
+ available_events[callback_function.__name__] = callback_function
+ return callback_function
# ------------------------------------------------------------------------------
# Callback prototypes
diff --git a/contrib/python/ipython/py3/IPython/core/guarded_eval.py b/contrib/python/ipython/py3/IPython/core/guarded_eval.py
index 5d405b2208..a304affc35 100644
--- a/contrib/python/ipython/py3/IPython/core/guarded_eval.py
+++ b/contrib/python/ipython/py3/IPython/core/guarded_eval.py
@@ -1,3 +1,4 @@
+from inspect import signature, Signature
from typing import (
Any,
Callable,
@@ -335,6 +336,7 @@ class _IdentitySubscript:
IDENTITY_SUBSCRIPT = _IdentitySubscript()
SUBSCRIPT_MARKER = "__SUBSCRIPT_SENTINEL__"
+UNKNOWN_SIGNATURE = Signature()
class GuardRejection(Exception):
@@ -415,6 +417,10 @@ UNARY_OP_DUNDERS: Dict[Type[ast.unaryop], Tuple[str, ...]] = {
}
+class Duck:
+ """A dummy class used to create objects of other classes without calling their ``__init__``"""
+
+
def _find_dunder(node_op, dunders) -> Union[Tuple[str, ...], None]:
dunder = None
for op, candidate_dunder in dunders.items():
@@ -584,6 +590,27 @@ def eval_node(node: Union[ast.AST, None], context: EvaluationContext):
if policy.can_call(func) and not node.keywords:
args = [eval_node(arg, context) for arg in node.args]
return func(*args)
+ try:
+ sig = signature(func)
+ except ValueError:
+ sig = UNKNOWN_SIGNATURE
+ # if annotation was not stringized, or it was stringized
+ # but resolved by signature call we know the return type
+ not_empty = sig.return_annotation is not Signature.empty
+ not_stringized = not isinstance(sig.return_annotation, str)
+ if not_empty and not_stringized:
+ duck = Duck()
+ # if allow-listed builtin is on type annotation, instantiate it
+ if policy.can_call(sig.return_annotation) and not node.keywords:
+ args = [eval_node(arg, context) for arg in node.args]
+ return sig.return_annotation(*args)
+ try:
+ # if custom class is in type annotation, mock it;
+ # this only works for heap types, not builtins
+ duck.__class__ = sig.return_annotation
+ return duck
+ except TypeError:
+ pass
raise GuardRejection(
"Call for",
func, # not joined to avoid calling `repr`
diff --git a/contrib/python/ipython/py3/IPython/core/inputsplitter.py b/contrib/python/ipython/py3/IPython/core/inputsplitter.py
index a4401184bd..33ed563221 100644
--- a/contrib/python/ipython/py3/IPython/core/inputsplitter.py
+++ b/contrib/python/ipython/py3/IPython/core/inputsplitter.py
@@ -31,7 +31,8 @@ import sys
import tokenize
import warnings
-from typing import List
+from typing import List, Tuple, Union, Optional
+from types import CodeType
from IPython.core.inputtransformer import (leading_indent,
classic_prompt,
@@ -91,7 +92,13 @@ def num_ini_spaces(s):
-------
n : int
"""
-
+ warnings.warn(
+ "`num_ini_spaces` is Pending Deprecation since IPython 8.17."
+ "It is considered fro removal in in future version. "
+ "Please open an issue if you believe it should be kept.",
+ stacklevel=2,
+ category=PendingDeprecationWarning,
+ )
ini_spaces = ini_spaces_re.match(s)
if ini_spaces:
return ini_spaces.end()
@@ -144,7 +151,7 @@ def partial_tokens(s):
else:
raise
-def find_next_indent(code):
+def find_next_indent(code) -> int:
"""Find the number of spaces for the next line of indentation"""
tokens = list(partial_tokens(code))
if tokens[-1].type == tokenize.ENDMARKER:
@@ -318,7 +325,7 @@ class InputSplitter(object):
# If self.source matches the first value, the second value is a valid
# current indentation. Otherwise, the cache is invalid and the indentation
# must be recalculated.
- _indent_spaces_cache = None, None
+ _indent_spaces_cache: Union[Tuple[None, None], Tuple[str, int]] = None, None
# String, indicating the default input encoding. It is computed by default
# at initialization time via get_input_encoding(), but it can be reset by a
# client with specific knowledge of the encoding.
@@ -326,11 +333,11 @@ class InputSplitter(object):
# String where the current full source input is stored, properly encoded.
# Reading this attribute is the normal way of querying the currently pushed
# source code, that has been properly encoded.
- source = ''
+ source: str = ""
# Code object corresponding to the current source. It is automatically
# synced to the source, so it can be queried at any time to obtain the code
# object; it will be None if the source doesn't compile to valid Python.
- code = None
+ code: Optional[CodeType] = None
# Private attributes
@@ -339,9 +346,9 @@ class InputSplitter(object):
# Command compiler
_compile: codeop.CommandCompiler
# Boolean indicating whether the current block is complete
- _is_complete = None
+ _is_complete: Optional[bool] = None
# Boolean indicating whether the current block has an unrecoverable syntax error
- _is_invalid = False
+ _is_invalid: bool = False
def __init__(self) -> None:
"""Create a new InputSplitter instance."""
@@ -511,9 +518,10 @@ class InputSplitter(object):
# General fallback - accept more code
return True
- def get_indent_spaces(self):
+ def get_indent_spaces(self) -> int:
sourcefor, n = self._indent_spaces_cache
if sourcefor == self.source:
+ assert n is not None
return n
# self.source always has a trailing newline
@@ -562,7 +570,7 @@ class IPythonInputSplitter(InputSplitter):
# Private attributes
# List with lines of raw input accumulated so far.
- _buffer_raw = None
+ _buffer_raw: List[str]
def __init__(self, line_input_checker=True, physical_line_transforms=None,
logical_line_transforms=None, python_line_transforms=None):
@@ -652,8 +660,8 @@ class IPythonInputSplitter(InputSplitter):
tmp = transform.reset()
if tmp is not None:
yield tmp
-
- out = []
+
+ out: List[str] = []
for t in self.transforms_in_use:
out = _flush(t, out)
diff --git a/contrib/python/ipython/py3/IPython/core/inputtransformer.py b/contrib/python/ipython/py3/IPython/core/inputtransformer.py
index 81cd1fa08c..bb1061e8dc 100644
--- a/contrib/python/ipython/py3/IPython/core/inputtransformer.py
+++ b/contrib/python/ipython/py3/IPython/core/inputtransformer.py
@@ -71,8 +71,8 @@ class InputTransformer(metaclass=abc.ABCMeta):
"""
@functools.wraps(func)
def transformer_factory(**kwargs):
- return cls(func, **kwargs)
-
+ return cls(func, **kwargs) # type: ignore [call-arg]
+
return transformer_factory
class StatelessInputTransformer(InputTransformer):
@@ -194,7 +194,7 @@ def assemble_logical_lines():
line = ''.join(parts)
# Utilities
-def _make_help_call(target, esc, lspace):
+def _make_help_call(target: str, esc: str, lspace: str) -> str:
"""Prepares a pinfo(2)/psearch call from a target name and the escape
(i.e. ? or ??)"""
method = 'pinfo2' if esc == '??' \
@@ -212,17 +212,19 @@ def _make_help_call(target, esc, lspace):
# These define the transformations for the different escape characters.
-def _tr_system(line_info):
+def _tr_system(line_info: LineInfo):
"Translate lines escaped with: !"
cmd = line_info.line.lstrip().lstrip(ESC_SHELL)
return '%sget_ipython().system(%r)' % (line_info.pre, cmd)
-def _tr_system2(line_info):
+
+def _tr_system2(line_info: LineInfo):
"Translate lines escaped with: !!"
cmd = line_info.line.lstrip()[2:]
return '%sget_ipython().getoutput(%r)' % (line_info.pre, cmd)
-def _tr_help(line_info):
+
+def _tr_help(line_info: LineInfo):
"Translate lines escaped with: ?/??"
# A naked help line should just fire the intro help screen
if not line_info.line[1:]:
@@ -230,7 +232,8 @@ def _tr_help(line_info):
return _make_help_call(line_info.ifun, line_info.esc, line_info.pre)
-def _tr_magic(line_info):
+
+def _tr_magic(line_info: LineInfo):
"Translate lines escaped with: %"
tpl = '%sget_ipython().run_line_magic(%r, %r)'
if line_info.line.startswith(ESC_MAGIC2):
@@ -241,17 +244,20 @@ def _tr_magic(line_info):
t_magic_name = t_magic_name.lstrip(ESC_MAGIC)
return tpl % (line_info.pre, t_magic_name, t_magic_arg_s)
-def _tr_quote(line_info):
+
+def _tr_quote(line_info: LineInfo):
"Translate lines escaped with: ,"
return '%s%s("%s")' % (line_info.pre, line_info.ifun,
'", "'.join(line_info.the_rest.split()) )
-def _tr_quote2(line_info):
+
+def _tr_quote2(line_info: LineInfo):
"Translate lines escaped with: ;"
return '%s%s("%s")' % (line_info.pre, line_info.ifun,
line_info.the_rest)
-def _tr_paren(line_info):
+
+def _tr_paren(line_info: LineInfo):
"Translate lines escaped with: /"
return '%s%s(%s)' % (line_info.pre, line_info.ifun,
", ".join(line_info.the_rest.split()))
@@ -266,9 +272,8 @@ tr = { ESC_SHELL : _tr_system,
ESC_PAREN : _tr_paren }
@StatelessInputTransformer.wrap
-def escaped_commands(line):
- """Transform escaped commands - %magic, !system, ?help + various autocalls.
- """
+def escaped_commands(line: str):
+ """Transform escaped commands - %magic, !system, ?help + various autocalls."""
if not line or line.isspace():
return line
lineinf = LineInfo(line)
@@ -342,20 +347,22 @@ def ends_in_comment_or_string(src):
@StatelessInputTransformer.wrap
-def help_end(line):
+def help_end(line: str):
"""Translate lines with ?/?? at the end"""
m = _help_end_re.search(line)
if m is None or ends_in_comment_or_string(line):
return line
target = m.group(1)
esc = m.group(3)
- lspace = _initial_space_re.match(line).group(0)
+ match = _initial_space_re.match(line)
+ assert match is not None
+ lspace = match.group(0)
return _make_help_call(target, esc, lspace)
@CoroutineInputTransformer.wrap
-def cellmagic(end_on_blank_line=False):
+def cellmagic(end_on_blank_line: bool = False):
"""Captures & transforms cell magics.
After a cell magic is started, this stores up any lines it gets until it is
diff --git a/contrib/python/ipython/py3/IPython/core/interactiveshell.py b/contrib/python/ipython/py3/IPython/core/interactiveshell.py
index 894403f98b..0a528c51f2 100644
--- a/contrib/python/ipython/py3/IPython/core/interactiveshell.py
+++ b/contrib/python/ipython/py3/IPython/core/interactiveshell.py
@@ -21,6 +21,7 @@ import inspect
import os
import re
import runpy
+import shutil
import subprocess
import sys
import tempfile
@@ -36,7 +37,28 @@ from typing import List as ListType, Dict as DictType, Any as AnyType
from typing import Optional, Sequence, Tuple
from warnings import warn
-from pickleshare import PickleShareDB
+try:
+ from pickleshare import PickleShareDB
+except ModuleNotFoundError:
+
+ class PickleShareDB: # type: ignore [no-redef]
+ def __init__(self, path):
+ pass
+
+ def get(self, key, default):
+ warn(
+ f"using {key} requires you to install the `pickleshare` library.",
+ stacklevel=2,
+ )
+ return default
+
+ def __setitem__(self, key, value):
+ warn(
+ f"using {key} requires you to install the `pickleshare` library.",
+ stacklevel=2,
+ )
+
+
from tempfile import TemporaryDirectory
from traitlets import (
Any,
@@ -3902,7 +3924,7 @@ class InteractiveShell(SingletonConfigurable):
del self.tempfiles
for tdir in self.tempdirs:
try:
- tdir.rmdir()
+ shutil.rmtree(tdir)
self.tempdirs.remove(tdir)
except FileNotFoundError:
pass
diff --git a/contrib/python/ipython/py3/IPython/core/magics/packaging.py b/contrib/python/ipython/py3/IPython/core/magics/packaging.py
index 2f7652c169..093b0a2ec1 100644
--- a/contrib/python/ipython/py3/IPython/core/magics/packaging.py
+++ b/contrib/python/ipython/py3/IPython/core/magics/packaging.py
@@ -8,6 +8,7 @@
# The full license is in the file COPYING.txt, distributed with this software.
#-----------------------------------------------------------------------------
+import functools
import re
import shlex
import sys
@@ -16,33 +17,49 @@ from pathlib import Path
from IPython.core.magic import Magics, magics_class, line_magic
-def _is_conda_environment():
- """Return True if the current Python executable is in a conda env"""
- # TODO: does this need to change on windows?
- return Path(sys.prefix, "conda-meta", "history").exists()
+def is_conda_environment(func):
+ @functools.wraps(func)
+ def wrapper(*args, **kwargs):
+ """Return True if the current Python executable is in a conda env"""
+ # TODO: does this need to change on windows?
+ if not Path(sys.prefix, "conda-meta", "history").exists():
+ raise ValueError(
+ "The python kernel does not appear to be a conda environment. "
+ "Please use ``%pip install`` instead."
+ )
+ return func(*args, **kwargs)
+ return wrapper
-def _get_conda_executable():
- """Find the path to the conda executable"""
+
+def _get_conda_like_executable(command):
+ """Find the path to the given executable
+
+ Parameters
+ ----------
+
+ executable: string
+ Value should be: conda, mamba or micromamba
+ """
# Check if there is a conda executable in the same directory as the Python executable.
# This is the case within conda's root environment.
- conda = Path(sys.executable).parent / "conda"
- if conda.is_file():
- return str(conda)
+ executable = Path(sys.executable).parent / command
+ if executable.is_file():
+ return str(executable)
# Otherwise, attempt to extract the executable from conda history.
# This applies in any conda environment.
history = Path(sys.prefix, "conda-meta", "history").read_text(encoding="utf-8")
match = re.search(
- r"^#\s*cmd:\s*(?P<command>.*conda)\s[create|install]",
+ rf"^#\s*cmd:\s*(?P<command>.*{executable})\s[create|install]",
history,
flags=re.MULTILINE,
)
if match:
return match.groupdict()["command"]
- # Fallback: assume conda is available on the system path.
- return "conda"
+ # Fallback: assume the executable is available on the system path.
+ return command
CONDA_COMMANDS_REQUIRING_PREFIX = {
@@ -76,18 +93,7 @@ class PackagingMagics(Magics):
print("Note: you may need to restart the kernel to use updated packages.")
- @line_magic
- def conda(self, line):
- """Run the conda package manager within the current kernel.
-
- Usage:
- %conda install [pkgs]
- """
- if not _is_conda_environment():
- raise ValueError("The python kernel does not appear to be a conda environment. "
- "Please use ``%pip install`` instead.")
-
- conda = _get_conda_executable()
+ def _run_command(self, cmd, line):
args = shlex.split(line)
command = args[0] if len(args) > 0 else ""
args = args[1:] if len(args) > 1 else [""]
@@ -108,5 +114,38 @@ class PackagingMagics(Magics):
if needs_prefix and not has_prefix:
extra_args.extend(["--prefix", sys.prefix])
- self.shell.system(' '.join([conda, command] + extra_args + args))
+ self.shell.system(" ".join([cmd, command] + extra_args + args))
print("\nNote: you may need to restart the kernel to use updated packages.")
+
+ @line_magic
+ @is_conda_environment
+ def conda(self, line):
+ """Run the conda package manager within the current kernel.
+
+ Usage:
+ %conda install [pkgs]
+ """
+ conda = _get_conda_like_executable("conda")
+ self._run_command(conda, line)
+
+ @line_magic
+ @is_conda_environment
+ def mamba(self, line):
+ """Run the mamba package manager within the current kernel.
+
+ Usage:
+ %mamba install [pkgs]
+ """
+ mamba = _get_conda_like_executable("mamba")
+ self._run_command(mamba, line)
+
+ @line_magic
+ @is_conda_environment
+ def micromamba(self, line):
+ """Run the conda package manager within the current kernel.
+
+ Usage:
+ %micromamba install [pkgs]
+ """
+ micromamba = _get_conda_like_executable("micromamba")
+ self._run_command(micromamba, line)
diff --git a/contrib/python/ipython/py3/IPython/core/oinspect.py b/contrib/python/ipython/py3/IPython/core/oinspect.py
index ef6a0d02d7..d77a732267 100644
--- a/contrib/python/ipython/py3/IPython/core/oinspect.py
+++ b/contrib/python/ipython/py3/IPython/core/oinspect.py
@@ -416,6 +416,8 @@ class Inspector(Colorable):
If any exception is generated, None is returned instead and the
exception is suppressed."""
+ if not callable(obj):
+ return None
try:
return _render_signature(signature(obj), oname)
except:
diff --git a/contrib/python/ipython/py3/IPython/core/release.py b/contrib/python/ipython/py3/IPython/core/release.py
index 152ebcb87b..ee0042d081 100644
--- a/contrib/python/ipython/py3/IPython/core/release.py
+++ b/contrib/python/ipython/py3/IPython/core/release.py
@@ -16,7 +16,7 @@
# release. 'dev' as a _version_extra string means this is a development
# version
_version_major = 8
-_version_minor = 16
+_version_minor = 17
_version_patch = 1
_version_extra = ".dev"
# _version_extra = "rc1"