diff options
author | robot-piglet <robot-piglet@yandex-team.com> | 2024-04-15 10:18:44 +0300 |
---|---|---|
committer | robot-piglet <robot-piglet@yandex-team.com> | 2024-04-15 10:26:35 +0300 |
commit | 7930380b354abe9969174901a4e8a730ab1d0906 (patch) | |
tree | 43c5e5107bc0cf0ac7c74f82874451a7a83aa173 /contrib/python/ipython/py3 | |
parent | 969a7065950f3f4c76d45c7bb813a3e27df8a466 (diff) | |
download | ydb-7930380b354abe9969174901a4e8a730ab1d0906.tar.gz |
Intermediate changes
Diffstat (limited to 'contrib/python/ipython/py3')
7 files changed, 196 insertions, 53 deletions
diff --git a/contrib/python/ipython/py3/.dist-info/METADATA b/contrib/python/ipython/py3/.dist-info/METADATA index 11836decd6..44c7fe3fa0 100644 --- a/contrib/python/ipython/py3/.dist-info/METADATA +++ b/contrib/python/ipython/py3/.dist-info/METADATA @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: ipython -Version: 8.22.2 +Version: 8.23.0 Summary: IPython: Productive Interactive Computing Author: The IPython Development Team Author-email: ipython-dev@python.org @@ -33,12 +33,12 @@ Requires-Dist: prompt-toolkit <3.1.0,>=3.0.41 Requires-Dist: pygments >=2.4.0 Requires-Dist: stack-data Requires-Dist: traitlets >=5.13.0 -Requires-Dist: typing-extensions ; python_version < "3.10" Requires-Dist: exceptiongroup ; python_version < "3.11" +Requires-Dist: typing-extensions ; python_version < "3.12" Requires-Dist: pexpect >4.3 ; sys_platform != "win32" and sys_platform != "emscripten" Requires-Dist: colorama ; sys_platform == "win32" Provides-Extra: all -Requires-Dist: ipython[black,doc,kernel,nbconvert,nbformat,notebook,parallel,qtconsole,terminal] ; extra == 'all' +Requires-Dist: ipython[black,doc,kernel,matplotlib,nbconvert,nbformat,notebook,parallel,qtconsole] ; extra == 'all' Requires-Dist: ipython[test,test_extra] ; extra == 'all' Provides-Extra: black Requires-Dist: black ; extra == 'black' @@ -56,6 +56,8 @@ Requires-Dist: exceptiongroup ; extra == 'doc' Requires-Dist: ipython[test] ; extra == 'doc' Provides-Extra: kernel Requires-Dist: ipykernel ; extra == 'kernel' +Provides-Extra: matplotlib +Requires-Dist: matplotlib ; extra == 'matplotlib' Provides-Extra: nbconvert Requires-Dist: nbconvert ; extra == 'nbconvert' Provides-Extra: nbformat diff --git a/contrib/python/ipython/py3/IPython/core/guarded_eval.py b/contrib/python/ipython/py3/IPython/core/guarded_eval.py index a304affc35..d8ac9928af 100644 --- a/contrib/python/ipython/py3/IPython/core/guarded_eval.py +++ b/contrib/python/ipython/py3/IPython/core/guarded_eval.py @@ -1,16 +1,23 @@ -from inspect import signature, Signature +from inspect import isclass, signature, Signature from typing import ( - Any, + Annotated, + AnyStr, Callable, Dict, + Literal, + NamedTuple, + NewType, + Optional, + Protocol, Set, Sequence, Tuple, - NamedTuple, Type, - Literal, + TypeGuard, Union, - TYPE_CHECKING, + get_args, + get_origin, + is_typeddict, ) import ast import builtins @@ -21,15 +28,18 @@ from functools import cached_property from dataclasses import dataclass, field from types import MethodDescriptorType, ModuleType -from IPython.utils.docs import GENERATING_DOCUMENTATION from IPython.utils.decorators import undoc -if TYPE_CHECKING or GENERATING_DOCUMENTATION: - from typing_extensions import Protocol +if sys.version_info < (3, 11): + from typing_extensions import Self, LiteralString +else: + from typing import Self, LiteralString + +if sys.version_info < (3, 12): + from typing_extensions import TypeAliasType else: - # do not require on runtime - Protocol = object # requires Python >=3.8 + from typing import TypeAliasType @undoc @@ -337,6 +347,7 @@ class _IdentitySubscript: IDENTITY_SUBSCRIPT = _IdentitySubscript() SUBSCRIPT_MARKER = "__SUBSCRIPT_SENTINEL__" UNKNOWN_SIGNATURE = Signature() +NOT_EVALUATED = object() class GuardRejection(Exception): @@ -417,9 +428,37 @@ UNARY_OP_DUNDERS: Dict[Type[ast.unaryop], Tuple[str, ...]] = { } -class Duck: +class ImpersonatingDuck: """A dummy class used to create objects of other classes without calling their ``__init__``""" + # no-op: override __class__ to impersonate + + +class _Duck: + """A dummy class used to create objects pretending to have given attributes""" + + def __init__(self, attributes: Optional[dict] = None, items: Optional[dict] = None): + self.attributes = attributes or {} + self.items = items or {} + + def __getattr__(self, attr: str): + return self.attributes[attr] + + def __hasattr__(self, attr: str): + return attr in self.attributes + + def __dir__(self): + return [*dir(super), *self.attributes] + + def __getitem__(self, key: str): + return self.items[key] + + def __hasitem__(self, key: str): + return self.items[key] + + def _ipython_key_completions_(self): + return self.items.keys() + def _find_dunder(node_op, dunders) -> Union[Tuple[str, ...], None]: dunder = None @@ -557,19 +596,7 @@ def eval_node(node: Union[ast.AST, None], context: EvaluationContext): f" not allowed in {context.evaluation} mode", ) if isinstance(node, ast.Name): - if policy.allow_locals_access and node.id in context.locals: - return context.locals[node.id] - if policy.allow_globals_access and node.id in context.globals: - return context.globals[node.id] - if policy.allow_builtins_access and hasattr(builtins, node.id): - # note: do not use __builtins__, it is implementation detail of cPython - return getattr(builtins, node.id) - if not policy.allow_globals_access and not policy.allow_locals_access: - raise GuardRejection( - f"Namespace access not allowed in {context.evaluation} mode" - ) - else: - raise NameError(f"{node.id} not found in locals, globals, nor builtins") + return _eval_node_name(node.id, context) if isinstance(node, ast.Attribute): value = eval_node(node.value, context) if policy.can_get_attr(value, node.attr): @@ -590,27 +617,19 @@ 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 + if isclass(func): + # this code path gets entered when calling class e.g. `MyClass()` + # or `my_instance.__class__()` - in both cases `func` is `MyClass`. + # Should return `MyClass` if `__new__` is not overridden, + # otherwise whatever `__new__` return type is. + overridden_return_type = _eval_return_type(func.__new__, node, context) + if overridden_return_type is not NOT_EVALUATED: + return overridden_return_type + return _create_duck_for_heap_type(func) + else: + return_type = _eval_return_type(func, node, context) + if return_type is not NOT_EVALUATED: + return return_type raise GuardRejection( "Call for", func, # not joined to avoid calling `repr` @@ -619,6 +638,125 @@ def eval_node(node: Union[ast.AST, None], context: EvaluationContext): raise ValueError("Unhandled node", ast.dump(node)) +def _eval_return_type(func: Callable, node: ast.Call, context: EvaluationContext): + """Evaluate return type of a given callable function. + + Returns the built-in type, a duck or NOT_EVALUATED sentinel. + """ + 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 + if not_empty: + return _resolve_annotation(sig.return_annotation, sig, func, node, context) + return NOT_EVALUATED + + +def _resolve_annotation( + annotation, + sig: Signature, + func: Callable, + node: ast.Call, + context: EvaluationContext, +): + """Resolve annotation created by user with `typing` module and custom objects.""" + annotation = ( + _eval_node_name(annotation, context) + if isinstance(annotation, str) + else annotation + ) + origin = get_origin(annotation) + if annotation is Self and hasattr(func, "__self__"): + return func.__self__ + elif origin is Literal: + type_args = get_args(annotation) + if len(type_args) == 1: + return type_args[0] + elif annotation is LiteralString: + return "" + elif annotation is AnyStr: + index = None + for i, (key, value) in enumerate(sig.parameters.items()): + if value.annotation is AnyStr: + index = i + break + if index is not None and index < len(node.args): + return eval_node(node.args[index], context) + elif origin is TypeGuard: + return bool() + elif origin is Union: + attributes = [ + attr + for type_arg in get_args(annotation) + for attr in dir(_resolve_annotation(type_arg, sig, func, node, context)) + ] + return _Duck(attributes=dict.fromkeys(attributes)) + elif is_typeddict(annotation): + return _Duck( + attributes=dict.fromkeys(dir(dict())), + items={ + k: _resolve_annotation(v, sig, func, node, context) + for k, v in annotation.__annotations__.items() + }, + ) + elif hasattr(annotation, "_is_protocol"): + return _Duck(attributes=dict.fromkeys(dir(annotation))) + elif origin is Annotated: + type_arg = get_args(annotation)[0] + return _resolve_annotation(type_arg, sig, func, node, context) + elif isinstance(annotation, NewType): + return _eval_or_create_duck(annotation.__supertype__, node, context) + elif isinstance(annotation, TypeAliasType): + return _eval_or_create_duck(annotation.__value__, node, context) + else: + return _eval_or_create_duck(annotation, node, context) + + +def _eval_node_name(node_id: str, context: EvaluationContext): + policy = EVALUATION_POLICIES[context.evaluation] + if policy.allow_locals_access and node_id in context.locals: + return context.locals[node_id] + if policy.allow_globals_access and node_id in context.globals: + return context.globals[node_id] + if policy.allow_builtins_access and hasattr(builtins, node_id): + # note: do not use __builtins__, it is implementation detail of cPython + return getattr(builtins, node_id) + if not policy.allow_globals_access and not policy.allow_locals_access: + raise GuardRejection( + f"Namespace access not allowed in {context.evaluation} mode" + ) + else: + raise NameError(f"{node_id} not found in locals, globals, nor builtins") + + +def _eval_or_create_duck(duck_type, node: ast.Call, context: EvaluationContext): + policy = EVALUATION_POLICIES[context.evaluation] + # if allow-listed builtin is on type annotation, instantiate it + if policy.can_call(duck_type) and not node.keywords: + args = [eval_node(arg, context) for arg in node.args] + return duck_type(*args) + # if custom class is in type annotation, mock it + return _create_duck_for_heap_type(duck_type) + + +def _create_duck_for_heap_type(duck_type): + """Create an imitation of an object of a given type (a duck). + + Returns the duck or NOT_EVALUATED sentinel if duck could not be created. + """ + duck = ImpersonatingDuck() + try: + # this only works for heap types, not builtins + duck.__class__ = duck_type + return duck + except TypeError: + pass + return NOT_EVALUATED + + SUPPORTED_EXTERNAL_GETITEM = { ("pandas", "core", "indexing", "_iLocIndexer"), ("pandas", "core", "indexing", "_LocIndexer"), diff --git a/contrib/python/ipython/py3/IPython/core/magics/basic.py b/contrib/python/ipython/py3/IPython/core/magics/basic.py index 3ac4049614..3e3eb2d3f8 100644 --- a/contrib/python/ipython/py3/IPython/core/magics/basic.py +++ b/contrib/python/ipython/py3/IPython/core/magics/basic.py @@ -40,6 +40,9 @@ class MagicsDisplay(object): def _repr_pretty_(self, p, cycle): p.text(self._lsmagic()) + def __repr__(self): + return self.__str__() + def __str__(self): return self._lsmagic() diff --git a/contrib/python/ipython/py3/IPython/core/magics/execution.py b/contrib/python/ipython/py3/IPython/core/magics/execution.py index 4147dac963..f3688f4eb0 100644 --- a/contrib/python/ipython/py3/IPython/core/magics/execution.py +++ b/contrib/python/ipython/py3/IPython/core/magics/execution.py @@ -1506,7 +1506,7 @@ class ExecutionMagics(Magics): @line_cell_magic def code_wrap(self, line, cell=None): """ - Simple magic to quickly define a code transformer for all IPython's future imput. + Simple magic to quickly define a code transformer for all IPython's future input. ``__code__`` and ``__ret__`` are special variable that represent the code to run and the value of the last expression of ``__code__`` respectively. diff --git a/contrib/python/ipython/py3/IPython/core/release.py b/contrib/python/ipython/py3/IPython/core/release.py index f668902edf..6a22386858 100644 --- a/contrib/python/ipython/py3/IPython/core/release.py +++ b/contrib/python/ipython/py3/IPython/core/release.py @@ -16,8 +16,8 @@ # release. 'dev' as a _version_extra string means this is a development # version _version_major = 8 -_version_minor = 22 -_version_patch = 2 +_version_minor = 23 +_version_patch = 0 _version_extra = ".dev" # _version_extra = "rc1" _version_extra = "" # Uncomment this for full releases diff --git a/contrib/python/ipython/py3/IPython/utils/_sysinfo.py b/contrib/python/ipython/py3/IPython/utils/_sysinfo.py index 22be56b84b..9cf8685be1 100644 --- a/contrib/python/ipython/py3/IPython/utils/_sysinfo.py +++ b/contrib/python/ipython/py3/IPython/utils/_sysinfo.py @@ -1,2 +1,2 @@ # GENERATED BY setup.py -commit = "d1804576b" +commit = "5e7c4a991" diff --git a/contrib/python/ipython/py3/ya.make b/contrib/python/ipython/py3/ya.make index 76d52094de..3f4c418e00 100644 --- a/contrib/python/ipython/py3/ya.make +++ b/contrib/python/ipython/py3/ya.make @@ -2,7 +2,7 @@ PY3_LIBRARY() -VERSION(8.22.2) +VERSION(8.23.0) LICENSE(BSD-3-Clause) |