summaryrefslogtreecommitdiff
path: root/django/utils/inspect.py
diff options
context:
space:
mode:
authorAdam Johnson <me@adamj.eu>2021-03-19 11:23:28 +0000
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2021-03-22 13:17:54 +0100
commit562898034f65e17bcdd2d951ac5236a1ec8ea690 (patch)
tree334787b21eb650ba664628527532a4c4802691a4 /django/utils/inspect.py
parentac72a216a7ef95e8e9cb8651b7e67320597c903b (diff)
Refs #31732 -- Fixed django.utils.inspect caching for bound methods.
Thanks Alexandr Artemyev for the report, and Simon Charette for the original patch.
Diffstat (limited to 'django/utils/inspect.py')
-rw-r--r--django/utils/inspect.py33
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))