aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/tools/python3/Lib/inspect.py
diff options
context:
space:
mode:
authorrobot-contrib <robot-contrib@yandex-team.com>2024-07-02 22:47:57 +0300
committerrobot-contrib <robot-contrib@yandex-team.com>2024-07-02 22:59:47 +0300
commit96b239778766d32d5158aca805e08199b3c0a743 (patch)
treea9c8679261a62138ec4735d878a11f6478cd196a /contrib/tools/python3/Lib/inspect.py
parent292e7317266c2136a1e1bd027e16e6eefb639028 (diff)
downloadydb-96b239778766d32d5158aca805e08199b3c0a743.tar.gz
Update contrib/tools/python3 to 3.12.4
6e8edffbef193b35b45ddccdc3beda6bb2627186
Diffstat (limited to 'contrib/tools/python3/Lib/inspect.py')
-rw-r--r--contrib/tools/python3/Lib/inspect.py59
1 files changed, 42 insertions, 17 deletions
diff --git a/contrib/tools/python3/Lib/inspect.py b/contrib/tools/python3/Lib/inspect.py
index 819ce940ee..497169dacb 100644
--- a/contrib/tools/python3/Lib/inspect.py
+++ b/contrib/tools/python3/Lib/inspect.py
@@ -160,6 +160,7 @@ import builtins
from keyword import iskeyword
from operator import attrgetter
from collections import namedtuple, OrderedDict
+from weakref import ref as make_weakref
# Create constants for the compiler flags in Include/code.h
# We try to get them from dis to avoid duplication
@@ -1798,9 +1799,16 @@ def _check_class(klass, attr):
return entry.__dict__[attr]
return _sentinel
+
@functools.lru_cache()
-def _shadowed_dict_from_mro_tuple(mro):
- for entry in mro:
+def _shadowed_dict_from_weakref_mro_tuple(*weakref_mro):
+ for weakref_entry in weakref_mro:
+ # Normally we'd have to check whether the result of weakref_entry()
+ # is None here, in case the object the weakref is pointing to has died.
+ # In this specific case, however, we know that the only caller of this
+ # function is `_shadowed_dict()`, and that therefore this weakref is
+ # guaranteed to point to an object that is still alive.
+ entry = weakref_entry()
dunder_dict = _get_dunder_dict_of_class(entry)
if '__dict__' in dunder_dict:
class_dict = dunder_dict['__dict__']
@@ -1810,8 +1818,19 @@ def _shadowed_dict_from_mro_tuple(mro):
return class_dict
return _sentinel
+
def _shadowed_dict(klass):
- return _shadowed_dict_from_mro_tuple(_static_getmro(klass))
+ # gh-118013: the inner function here is decorated with lru_cache for
+ # performance reasons, *but* make sure not to pass strong references
+ # to the items in the mro. Doing so can lead to unexpected memory
+ # consumption in cases where classes are dynamically created and
+ # destroyed, and the dynamically created classes happen to be the only
+ # objects that hold strong references to other objects that take up a
+ # significant amount of memory.
+ return _shadowed_dict_from_weakref_mro_tuple(
+ *[make_weakref(entry) for entry in _static_getmro(klass)]
+ )
+
def getattr_static(obj, attr, default=_sentinel):
"""Retrieve attributes without triggering dynamic lookup via the
@@ -2126,8 +2145,10 @@ def _signature_is_builtin(obj):
ismethoddescriptor(obj) or
isinstance(obj, _NonUserDefinedCallables) or
# Can't test 'isinstance(type)' here, as it would
- # also be True for regular python classes
- obj in (type, object))
+ # also be True for regular python classes.
+ # Can't use the `in` operator here, as it would
+ # invoke the custom __eq__ method.
+ obj is type or obj is object)
def _signature_is_functionlike(obj):
@@ -3108,6 +3129,8 @@ class Signature:
parameters_ex = ()
arg_vals = iter(args)
+ pos_only_param_in_kwargs = []
+
while True:
# Let's iterate through the positional arguments and corresponding
# parameters
@@ -3128,10 +3151,10 @@ class Signature:
break
elif param.name in kwargs:
if param.kind == _POSITIONAL_ONLY:
- msg = '{arg!r} parameter is positional only, ' \
- 'but was passed as a keyword'
- msg = msg.format(arg=param.name)
- raise TypeError(msg) from None
+ # Raise a TypeError once we are sure there is no
+ # **kwargs param later.
+ pos_only_param_in_kwargs.append(param)
+ continue
parameters_ex = (param,)
break
elif (param.kind == _VAR_KEYWORD or
@@ -3213,20 +3236,22 @@ class Signature:
format(arg=param_name)) from None
else:
- if param.kind == _POSITIONAL_ONLY:
- # This should never happen in case of a properly built
- # Signature object (but let's have this check here
- # to ensure correct behaviour just in case)
- raise TypeError('{arg!r} parameter is positional only, '
- 'but was passed as a keyword'. \
- format(arg=param.name))
-
arguments[param_name] = arg_val
if kwargs:
if kwargs_param is not None:
# Process our '**kwargs'-like parameter
arguments[kwargs_param.name] = kwargs
+ elif pos_only_param_in_kwargs:
+ raise TypeError(
+ 'got some positional-only arguments passed as '
+ 'keyword arguments: {arg!r}'.format(
+ arg=', '.join(
+ param.name
+ for param in pos_only_param_in_kwargs
+ ),
+ ),
+ )
else:
raise TypeError(
'got an unexpected keyword argument {arg!r}'.format(