aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/python/ipython/py3/IPython/core/oinspect.py
diff options
context:
space:
mode:
authorrobot-piglet <robot-piglet@yandex-team.com>2024-03-12 17:24:47 +0300
committerrobot-piglet <robot-piglet@yandex-team.com>2024-03-12 17:34:45 +0300
commite84602b8f2b95d10d45eb11369ae7d627339c881 (patch)
tree028524c9f076a9c4019a8d78d4a30685b7626c99 /contrib/python/ipython/py3/IPython/core/oinspect.py
parente98c636d759bf6f106a2b90142041bb9d4f1e33f (diff)
downloadydb-e84602b8f2b95d10d45eb11369ae7d627339c881.tar.gz
Intermediate changes
Diffstat (limited to 'contrib/python/ipython/py3/IPython/core/oinspect.py')
-rw-r--r--contrib/python/ipython/py3/IPython/core/oinspect.py186
1 files changed, 143 insertions, 43 deletions
diff --git a/contrib/python/ipython/py3/IPython/core/oinspect.py b/contrib/python/ipython/py3/IPython/core/oinspect.py
index 9eecf290ae..937e5a9d4b 100644
--- a/contrib/python/ipython/py3/IPython/core/oinspect.py
+++ b/contrib/python/ipython/py3/IPython/core/oinspect.py
@@ -24,9 +24,18 @@ import os
import types
import warnings
-from typing import Any, Optional, Dict, Union, List, Tuple
-from typing import TypeAlias
+from typing import (
+ cast,
+ Any,
+ Optional,
+ Dict,
+ Union,
+ List,
+ TypedDict,
+ TypeAlias,
+ Tuple,
+)
import traitlets
@@ -34,15 +43,12 @@ import traitlets
from IPython.core import page
from IPython.lib.pretty import pretty
from IPython.testing.skipdoctest import skip_doctest
-from IPython.utils import PyColorize
-from IPython.utils import openpy
+from IPython.utils import PyColorize, openpy
from IPython.utils.dir2 import safe_hasattr
from IPython.utils.path import compress_user
from IPython.utils.text import indent
-from IPython.utils.wildcard import list_namespace
-from IPython.utils.wildcard import typestr2type
+from IPython.utils.wildcard import list_namespace, typestr2type
from IPython.utils.coloransi import TermColors
-from IPython.utils.py3compat import cast_unicode
from IPython.utils.colorable import Colorable
from IPython.utils.decorators import undoc
@@ -106,23 +112,78 @@ InspectColors = PyColorize.ANSICodeColors
#****************************************************************************
# Auxiliary functions and objects
-# See the messaging spec for the definition of all these fields. This list
-# effectively defines the order of display
-info_fields = ['type_name', 'base_class', 'string_form', 'namespace',
- 'length', 'file', 'definition', 'docstring', 'source',
- 'init_definition', 'class_docstring', 'init_docstring',
- 'call_def', 'call_docstring',
- # These won't be printed but will be used to determine how to
- # format the object
- 'ismagic', 'isalias', 'isclass', 'found', 'name'
- ]
+class InfoDict(TypedDict):
+ type_name: Optional[str]
+ base_class: Optional[str]
+ string_form: Optional[str]
+ namespace: Optional[str]
+ length: Optional[str]
+ file: Optional[str]
+ definition: Optional[str]
+ docstring: Optional[str]
+ source: Optional[str]
+ init_definition: Optional[str]
+ class_docstring: Optional[str]
+ init_docstring: Optional[str]
+ call_def: Optional[str]
+ call_docstring: Optional[str]
+ subclasses: Optional[str]
+ # These won't be printed but will be used to determine how to
+ # format the object
+ ismagic: bool
+ isalias: bool
+ isclass: bool
+ found: bool
+ name: str
+
+
+_info_fields = list(InfoDict.__annotations__.keys())
+
+
+def __getattr__(name):
+ if name == "info_fields":
+ warnings.warn(
+ "IPython.core.oinspect's `info_fields` is considered for deprecation and may be removed in the Future. ",
+ DeprecationWarning,
+ stacklevel=2,
+ )
+ return _info_fields
+
+ raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
+
+
+@dataclass
+class InspectorHookData:
+ """Data passed to the mime hook"""
-def object_info(**kw):
+ obj: Any
+ info: Optional[OInfo]
+ info_dict: InfoDict
+ detail_level: int
+ omit_sections: list[str]
+
+
+@undoc
+def object_info(
+ *,
+ name: str,
+ found: bool,
+ isclass: bool = False,
+ isalias: bool = False,
+ ismagic: bool = False,
+ **kw,
+) -> InfoDict:
"""Make an object info dict with all fields present."""
- infodict = {k:None for k in info_fields}
- infodict.update(kw)
- return infodict
+ infodict = kw
+ infodict = {k: None for k in _info_fields if k not in infodict}
+ infodict["name"] = name # type: ignore
+ infodict["found"] = found # type: ignore
+ infodict["isclass"] = isclass # type: ignore
+ infodict["isalias"] = isalias # type: ignore
+ infodict["ismagic"] = ismagic # type: ignore
+
+ return InfoDict(**infodict) # type:ignore
def get_encoding(obj):
@@ -148,7 +209,8 @@ def get_encoding(obj):
encoding, _lines = openpy.detect_encoding(buffer.readline)
return encoding
-def getdoc(obj) -> Union[str,None]:
+
+def getdoc(obj) -> Union[str, None]:
"""Stable wrapper around inspect.getdoc.
This can't crash because of attribute problems.
@@ -554,8 +616,10 @@ class Inspector(Colorable):
# run contents of file through pager starting at line where the object
# is defined, as long as the file isn't binary and is actually on the
# filesystem.
- if ofile.endswith(('.so', '.dll', '.pyd')):
- print('File %r is binary, not printing.' % ofile)
+ if ofile is None:
+ print("Could not find file for object")
+ elif ofile.endswith((".so", ".dll", ".pyd")):
+ print("File %r is binary, not printing." % ofile)
elif not os.path.isfile(ofile):
print('File %r does not exist, not printing.' % ofile)
else:
@@ -643,7 +707,7 @@ class Inspector(Colorable):
title: str,
key: str,
info,
- omit_sections,
+ omit_sections: List[str],
formatter,
):
"""Append an info value to the unformatted mimebundle being constructed by _make_info_unformatted"""
@@ -740,8 +804,8 @@ class Inspector(Colorable):
oname: str = "",
formatter=None,
info: Optional[OInfo] = None,
- detail_level=0,
- omit_sections=(),
+ detail_level: int = 0,
+ omit_sections: Union[List[str], Tuple[()]] = (),
) -> Bundle:
"""Retrieve an info dict and format it.
@@ -756,11 +820,13 @@ class Inspector(Colorable):
already computed information
detail_level : integer
Granularity of detail level, if set to 1, give more information.
- omit_sections : container[str]
+ omit_sections : list[str]
Titles or keys to omit from output (can be set, tuple, etc., anything supporting `in`)
"""
info_dict = self.info(obj, oname=oname, info=info, detail_level=detail_level)
+ omit_sections = list(omit_sections)
+
bundle = self._make_info_unformatted(
obj,
info_dict,
@@ -768,10 +834,33 @@ class Inspector(Colorable):
detail_level=detail_level,
omit_sections=omit_sections,
)
- for key, hook in self.mime_hooks.items():
- res = hook(obj, info)
- if res is not None:
- bundle[key] = res
+ if self.mime_hooks:
+ hook_data = InspectorHookData(
+ obj=obj,
+ info=info,
+ info_dict=info_dict,
+ detail_level=detail_level,
+ omit_sections=omit_sections,
+ )
+ for key, hook in self.mime_hooks.items(): # type:ignore
+ required_parameters = [
+ parameter
+ for parameter in inspect.signature(hook).parameters.values()
+ if parameter.default != inspect.Parameter.default
+ ]
+ if len(required_parameters) == 1:
+ res = hook(hook_data)
+ else:
+ warnings.warn(
+ "MIME hook format changed in IPython 8.22; hooks should now accept"
+ " a single parameter (InspectorHookData); support for hooks requiring"
+ " two-parameters (obj and info) will be removed in a future version",
+ DeprecationWarning,
+ stacklevel=2,
+ )
+ res = hook(obj, info)
+ if res is not None:
+ bundle[key] = res
return self.format_mime(bundle)
def pinfo(
@@ -830,7 +919,7 @@ class Inspector(Colorable):
)
return self.info(obj, oname=oname, info=info, detail_level=detail_level)
- def info(self, obj, oname="", info=None, detail_level=0) -> Dict[str, Any]:
+ def info(self, obj, oname="", info=None, detail_level=0) -> InfoDict:
"""Compute a dict with detailed information about an object.
Parameters
@@ -847,8 +936,7 @@ class Inspector(Colorable):
Returns
-------
- An object info dict with known fields from `info_fields`. Keys are
- strings, values are string or None.
+ An object info dict with known fields from `info_fields` (see `InfoDict`).
"""
if info is None:
@@ -867,8 +955,18 @@ class Inspector(Colorable):
if info and info.parent is not None and hasattr(info.parent, HOOK_NAME):
parents_docs_dict = getattr(info.parent, HOOK_NAME)
parents_docs = parents_docs_dict.get(att_name, None)
- out = dict(
- name=oname, found=True, isalias=isalias, ismagic=ismagic, subclasses=None
+ out: InfoDict = cast(
+ InfoDict,
+ {
+ **{field: None for field in _info_fields},
+ **{
+ "name": oname,
+ "found": True,
+ "isalias": isalias,
+ "ismagic": ismagic,
+ "subclasses": None,
+ },
+ },
)
if parents_docs:
@@ -914,12 +1012,14 @@ class Inspector(Colorable):
if detail_level >= self.str_detail_level:
try:
ostr = str(obj)
- str_head = 'string_form'
- if not detail_level and len(ostr)>string_max:
+ if not detail_level and len(ostr) > string_max:
ostr = ostr[:shalf] + ' <...> ' + ostr[-shalf:]
- ostr = ("\n" + " " * len(str_head.expandtabs())).\
- join(q.strip() for q in ostr.split("\n"))
- out[str_head] = ostr
+ # TODO: `'string_form'.expandtabs()` seems wrong, but
+ # it was (nearly) like this since the first commit ever.
+ ostr = ("\n" + " " * len("string_form".expandtabs())).join(
+ q.strip() for q in ostr.split("\n")
+ )
+ out["string_form"] = ostr
except:
pass
@@ -1054,7 +1154,7 @@ class Inspector(Colorable):
if call_ds:
out['call_docstring'] = call_ds
- return object_info(**out)
+ return out
@staticmethod
def _source_contains_docstring(src, doc):