diff options
| author | Adam Johnson <me@adamj.eu> | 2021-03-19 11:23:28 +0000 |
|---|---|---|
| committer | Mariusz Felisiak <felisiak.mariusz@gmail.com> | 2021-03-22 20:49:15 +0100 |
| commit | 15a85183880ebebe1b4a1e16e9b2202897d27d8e (patch) | |
| tree | 8c164a33b02c8a08e7f9c53d8a997dda5d57398f /django | |
| parent | 2420fd2d5c90698454678c81f3f5a7662be2bf72 (diff) | |
[3.2.x] Refs #31732 -- Fixed django.utils.inspect caching for bound methods.
Thanks Alexandr Artemyev for the report, and Simon Charette for the
original patch.
Backport of 562898034f65e17bcdd2d951ac5236a1ec8ea690 from main
Diffstat (limited to 'django')
| -rw-r--r-- | django/utils/inspect.py | 33 |
1 files changed, 21 insertions, 12 deletions
diff --git a/django/utils/inspect.py b/django/utils/inspect.py index 567efcbc17..7e062244e5 100644 --- a/django/utils/inspect.py +++ b/django/utils/inspect.py @@ -3,14 +3,23 @@ import inspect @functools.lru_cache(maxsize=512) -def _get_signature(func): - return inspect.signature(func) +def _get_func_parameters(func, remove_first): + parameters = tuple(inspect.signature(func).parameters.values()) + if remove_first: + parameters = parameters[1:] + return parameters + + +def _get_callable_parameters(meth_or_func): + is_method = inspect.ismethod(meth_or_func) + func = meth_or_func.__func__ if is_method else meth_or_func + return _get_func_parameters(func, remove_first=is_method) def get_func_args(func): - sig = _get_signature(func) + params = _get_callable_parameters(func) return [ - arg_name for arg_name, param in sig.parameters.items() + param.name for param in params if param.kind == inspect.Parameter.POSITIONAL_OR_KEYWORD ] @@ -21,10 +30,10 @@ def get_func_full_args(func): does not have a default value, omit it in the tuple. Arguments such as *args and **kwargs are also included. """ - sig = _get_signature(func) + params = _get_callable_parameters(func) args = [] - for arg_name, param in sig.parameters.items(): - name = arg_name + for param in params: + name = param.name # Ignore 'self' if name == 'self': continue @@ -42,7 +51,7 @@ def get_func_full_args(func): def func_accepts_kwargs(func): """Return True if function 'func' accepts keyword arguments **kwargs.""" return any( - p for p in _get_signature(func).parameters.values() + p for p in _get_callable_parameters(func) if p.kind == p.VAR_KEYWORD ) @@ -52,7 +61,7 @@ def func_accepts_var_args(func): Return True if function 'func' accepts positional arguments *args. """ return any( - p for p in _get_signature(func).parameters.values() + p for p in _get_callable_parameters(func) if p.kind == p.VAR_POSITIONAL ) @@ -60,11 +69,11 @@ def func_accepts_var_args(func): def method_has_no_args(meth): """Return True if a method only accepts 'self'.""" count = len([ - p for p in _get_signature(meth).parameters.values() + p for p in _get_callable_parameters(meth) if p.kind == p.POSITIONAL_OR_KEYWORD ]) return count == 0 if inspect.ismethod(meth) else count == 1 -def func_supports_parameter(func, parameter): - return parameter in _get_signature(func).parameters +def func_supports_parameter(func, name): + return any(param.name == name for param in _get_callable_parameters(func)) |
