aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/tools/python3/Lib/inspect.py
diff options
context:
space:
mode:
authorshadchin <shadchin@yandex-team.com>2024-04-28 21:17:44 +0300
committershadchin <shadchin@yandex-team.com>2024-04-28 21:25:54 +0300
commita55d99a3eb72f90355bc146baeda18aa7eb97352 (patch)
treeb17cfed786effe8b81bba022239d6729f716fbeb /contrib/tools/python3/Lib/inspect.py
parent67bf49d08acf1277eff4c336021ac22d964bb4c4 (diff)
downloadydb-a55d99a3eb72f90355bc146baeda18aa7eb97352.tar.gz
Update Python 3 to 3.12.3
7d09de7d8b99ea2be554ef0fc61276942ca9c2e1
Diffstat (limited to 'contrib/tools/python3/Lib/inspect.py')
-rw-r--r--contrib/tools/python3/Lib/inspect.py171
1 files changed, 77 insertions, 94 deletions
diff --git a/contrib/tools/python3/Lib/inspect.py b/contrib/tools/python3/Lib/inspect.py
index a550202bb0..819ce940ee 100644
--- a/contrib/tools/python3/Lib/inspect.py
+++ b/contrib/tools/python3/Lib/inspect.py
@@ -760,18 +760,14 @@ def unwrap(func, *, stop=None):
:exc:`ValueError` is raised if a cycle is encountered.
"""
- if stop is None:
- def _is_wrapper(f):
- return hasattr(f, '__wrapped__')
- else:
- def _is_wrapper(f):
- return hasattr(f, '__wrapped__') and not stop(f)
f = func # remember the original func for error reporting
# Memoise by id to tolerate non-hashable objects, but store objects to
# ensure they aren't destroyed, which would allow their IDs to be reused.
memo = {id(f): f}
recursion_limit = sys.getrecursionlimit()
- while _is_wrapper(func):
+ while not isinstance(func, type) and hasattr(func, '__wrapped__'):
+ if stop is not None and stop(func):
+ break
func = func.__wrapped__
id_func = id(func)
if (id_func in memo) or (len(memo) >= recursion_limit):
@@ -2007,15 +2003,17 @@ def _signature_get_user_defined_method(cls, method_name):
named ``method_name`` and returns it only if it is a
pure python function.
"""
- try:
- meth = getattr(cls, method_name)
- except AttributeError:
- return
+ if method_name == '__new__':
+ meth = getattr(cls, method_name, None)
else:
- if not isinstance(meth, _NonUserDefinedCallables):
- # Once '__signature__' will be added to 'C'-level
- # callables, this check won't be necessary
- return meth
+ meth = getattr_static(cls, method_name, None)
+ if meth is None or isinstance(meth, _NonUserDefinedCallables):
+ # Once '__signature__' will be added to 'C'-level
+ # callables, this check won't be necessary
+ return None
+ if method_name != '__new__':
+ meth = _descriptor_get(meth, cls)
+ return meth
def _signature_get_partial(wrapped_sig, partial, extra_args=()):
@@ -2460,6 +2458,15 @@ def _signature_from_function(cls, func, skip_bound_arg=True,
__validate_parameters__=is_duck_function)
+def _descriptor_get(descriptor, obj):
+ if isclass(descriptor):
+ return descriptor
+ get = getattr(type(descriptor), '__get__', _sentinel)
+ if get is _sentinel:
+ return descriptor
+ return get(descriptor, obj, type(obj))
+
+
def _signature_from_callable(obj, *,
follow_wrapper_chains=True,
skip_bound_arg=True,
@@ -2568,7 +2575,6 @@ def _signature_from_callable(obj, *,
wrapped_sig = _get_signature_of(obj.func)
return _signature_get_partial(wrapped_sig, obj)
- sig = None
if isinstance(obj, type):
# obj is a class or a metaclass
@@ -2576,88 +2582,65 @@ def _signature_from_callable(obj, *,
# in its metaclass
call = _signature_get_user_defined_method(type(obj), '__call__')
if call is not None:
- sig = _get_signature_of(call)
- else:
- factory_method = None
- new = _signature_get_user_defined_method(obj, '__new__')
- init = _signature_get_user_defined_method(obj, '__init__')
-
- # Go through the MRO and see if any class has user-defined
- # pure Python __new__ or __init__ method
- for base in obj.__mro__:
- # Now we check if the 'obj' class has an own '__new__' method
- if new is not None and '__new__' in base.__dict__:
- factory_method = new
- break
- # or an own '__init__' method
- elif init is not None and '__init__' in base.__dict__:
- factory_method = init
- break
+ return _get_signature_of(call)
- if factory_method is not None:
- sig = _get_signature_of(factory_method)
-
- if sig is None:
- # At this point we know, that `obj` is a class, with no user-
- # defined '__init__', '__new__', or class-level '__call__'
-
- for base in obj.__mro__[:-1]:
- # Since '__text_signature__' is implemented as a
- # descriptor that extracts text signature from the
- # class docstring, if 'obj' is derived from a builtin
- # class, its own '__text_signature__' may be 'None'.
- # Therefore, we go through the MRO (except the last
- # class in there, which is 'object') to find the first
- # class with non-empty text signature.
- try:
- text_sig = base.__text_signature__
- except AttributeError:
- pass
- else:
- if text_sig:
- # If 'base' class has a __text_signature__ attribute:
- # return a signature based on it
- return _signature_fromstr(sigcls, base, text_sig)
-
- # No '__text_signature__' was found for the 'obj' class.
- # Last option is to check if its '__init__' is
- # object.__init__ or type.__init__.
- if type not in obj.__mro__:
- # We have a class (not metaclass), but no user-defined
- # __init__ or __new__ for it
- if (obj.__init__ is object.__init__ and
- obj.__new__ is object.__new__):
- # Return a signature of 'object' builtin.
- return sigcls.from_callable(object)
- else:
- raise ValueError(
- 'no signature found for builtin type {!r}'.format(obj))
+ new = _signature_get_user_defined_method(obj, '__new__')
+ init = _signature_get_user_defined_method(obj, '__init__')
- elif not isinstance(obj, _NonUserDefinedCallables):
- # An object with __call__
- # We also check that the 'obj' is not an instance of
- # types.WrapperDescriptorType or types.MethodWrapperType to avoid
- # infinite recursion (and even potential segfault)
- call = _signature_get_user_defined_method(type(obj), '__call__')
- if call is not None:
+ # Go through the MRO and see if any class has user-defined
+ # pure Python __new__ or __init__ method
+ for base in obj.__mro__:
+ # Now we check if the 'obj' class has an own '__new__' method
+ if new is not None and '__new__' in base.__dict__:
+ sig = _get_signature_of(new)
+ if skip_bound_arg:
+ sig = _signature_bound_method(sig)
+ return sig
+ # or an own '__init__' method
+ elif init is not None and '__init__' in base.__dict__:
+ return _get_signature_of(init)
+
+ # At this point we know, that `obj` is a class, with no user-
+ # defined '__init__', '__new__', or class-level '__call__'
+
+ for base in obj.__mro__[:-1]:
+ # Since '__text_signature__' is implemented as a
+ # descriptor that extracts text signature from the
+ # class docstring, if 'obj' is derived from a builtin
+ # class, its own '__text_signature__' may be 'None'.
+ # Therefore, we go through the MRO (except the last
+ # class in there, which is 'object') to find the first
+ # class with non-empty text signature.
try:
- sig = _get_signature_of(call)
- except ValueError as ex:
- msg = 'no signature found for {!r}'.format(obj)
- raise ValueError(msg) from ex
-
- if sig is not None:
- # For classes and objects we skip the first parameter of their
- # __call__, __new__, or __init__ methods
- if skip_bound_arg:
- return _signature_bound_method(sig)
- else:
- return sig
+ text_sig = base.__text_signature__
+ except AttributeError:
+ pass
+ else:
+ if text_sig:
+ # If 'base' class has a __text_signature__ attribute:
+ # return a signature based on it
+ return _signature_fromstr(sigcls, base, text_sig)
+
+ # No '__text_signature__' was found for the 'obj' class.
+ # Last option is to check if its '__init__' is
+ # object.__init__ or type.__init__.
+ if type not in obj.__mro__:
+ # We have a class (not metaclass), but no user-defined
+ # __init__ or __new__ for it
+ if (obj.__init__ is object.__init__ and
+ obj.__new__ is object.__new__):
+ # Return a signature of 'object' builtin.
+ return sigcls.from_callable(object)
+ else:
+ raise ValueError(
+ 'no signature found for builtin type {!r}'.format(obj))
- if isinstance(obj, types.BuiltinFunctionType):
- # Raise a nicer error message for builtins
- msg = 'no signature found for builtin function {!r}'.format(obj)
- raise ValueError(msg)
+ else:
+ # An object with __call__
+ call = getattr_static(type(obj), '__call__', None)
+ if call is not None:
+ call = _descriptor_get(call, obj)
+ return _get_signature_of(call)
raise ValueError('callable {!r} is not supported by signature'.format(obj))