[1.8.x] Fixed #24979 -- Removed usage of inspect.getargspec().
Backport of 3872a33132
from master
This commit is contained in:
parent
84ec3bfc11
commit
e2ea30c440
|
@ -20,6 +20,7 @@ from django.template.engine import Engine
|
|||
from django.utils import six
|
||||
from django.utils._os import upath
|
||||
from django.utils.decorators import method_decorator
|
||||
from django.utils.inspect import func_has_no_args
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.views.generic import TemplateView
|
||||
|
||||
|
@ -247,7 +248,7 @@ class ModelDetailView(BaseAdminDocsView):
|
|||
|
||||
# Gather model methods.
|
||||
for func_name, func in model.__dict__.items():
|
||||
if (inspect.isfunction(func) and len(inspect.getargspec(func)[0]) == 1):
|
||||
if inspect.isfunction(func) and func_has_no_args(func):
|
||||
try:
|
||||
for exclude in MODEL_METHODS_EXCLUDE:
|
||||
if func_name.startswith(exclude):
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import argparse
|
||||
import inspect
|
||||
|
||||
from django.contrib.gis import gdal
|
||||
from django.core.management.base import BaseCommand, CommandError
|
||||
from django.utils.inspect import get_func_args
|
||||
|
||||
|
||||
class LayerOptionAction(argparse.Action):
|
||||
|
@ -91,7 +91,7 @@ class Command(BaseCommand):
|
|||
from django.contrib.gis.utils.ogrinspect import _ogrinspect, mapping
|
||||
# Filter options to params accepted by `_ogrinspect`
|
||||
ogr_options = {k: v for k, v in options.items()
|
||||
if k in inspect.getargspec(_ogrinspect).args and v is not None}
|
||||
if k in get_func_args(_ogrinspect) and v is not None}
|
||||
output = [s for s in _ogrinspect(ds, model_name, **ogr_options)]
|
||||
|
||||
if options['mapping']:
|
||||
|
|
|
@ -2,7 +2,6 @@ import errno
|
|||
import os
|
||||
import warnings
|
||||
from datetime import datetime
|
||||
from inspect import getargspec
|
||||
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import SuspiciousFileOperation
|
||||
|
@ -14,6 +13,7 @@ from django.utils.deconstruct import deconstructible
|
|||
from django.utils.deprecation import RemovedInDjango110Warning
|
||||
from django.utils.encoding import filepath_to_uri, force_text
|
||||
from django.utils.functional import LazyObject
|
||||
from django.utils.inspect import func_supports_parameter
|
||||
from django.utils.module_loading import import_string
|
||||
from django.utils.six.moves.urllib.parse import urljoin
|
||||
from django.utils.text import get_valid_filename
|
||||
|
@ -49,8 +49,7 @@ class Storage(object):
|
|||
if not hasattr(content, 'chunks'):
|
||||
content = File(content)
|
||||
|
||||
args, varargs, varkw, defaults = getargspec(self.get_available_name)
|
||||
if 'max_length' in args:
|
||||
if func_supports_parameter(self.get_available_name, 'max_length'):
|
||||
name = self.get_available_name(name, max_length=max_length)
|
||||
else:
|
||||
warnings.warn(
|
||||
|
|
|
@ -3,7 +3,6 @@ from __future__ import unicode_literals
|
|||
import collections
|
||||
import datetime
|
||||
import decimal
|
||||
import inspect
|
||||
import math
|
||||
import os
|
||||
import re
|
||||
|
@ -19,6 +18,7 @@ from django.utils import datetime_safe, six
|
|||
from django.utils._os import upath
|
||||
from django.utils.encoding import force_text
|
||||
from django.utils.functional import Promise
|
||||
from django.utils.inspect import get_func_args
|
||||
from django.utils.timezone import utc
|
||||
from django.utils.version import get_docs_version
|
||||
|
||||
|
@ -97,7 +97,7 @@ class OperationWriter(object):
|
|||
|
||||
imports = set()
|
||||
name, args, kwargs = self.operation.deconstruct()
|
||||
argspec = inspect.getargspec(self.operation.__init__)
|
||||
operation_args = get_func_args(self.operation.__init__)
|
||||
|
||||
# See if this operation is in django.db.migrations. If it is,
|
||||
# We can just use the fact we already have that imported,
|
||||
|
@ -110,16 +110,15 @@ class OperationWriter(object):
|
|||
|
||||
self.indent()
|
||||
|
||||
# Start at one because argspec includes "self"
|
||||
for i, arg in enumerate(args, 1):
|
||||
for i, arg in enumerate(args):
|
||||
arg_value = arg
|
||||
arg_name = argspec.args[i]
|
||||
arg_name = operation_args[i]
|
||||
_write(arg_name, arg_value)
|
||||
|
||||
i = len(args)
|
||||
# Only iterate over remaining arguments
|
||||
for arg_name in argspec.args[i + 1:]:
|
||||
if arg_name in kwargs:
|
||||
for arg_name in operation_args[i:]:
|
||||
if arg_name in kwargs: # Don't sort to maintain signature order
|
||||
arg_value = kwargs[arg_name]
|
||||
_write(arg_name, arg_value)
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import datetime
|
||||
import os
|
||||
import warnings
|
||||
from inspect import getargspec
|
||||
|
||||
from django import forms
|
||||
from django.core import checks
|
||||
|
@ -13,6 +12,7 @@ from django.db.models.fields import Field
|
|||
from django.utils import six
|
||||
from django.utils.deprecation import RemovedInDjango110Warning
|
||||
from django.utils.encoding import force_str, force_text
|
||||
from django.utils.inspect import func_supports_parameter
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
|
||||
|
@ -89,8 +89,7 @@ class FieldFile(File):
|
|||
def save(self, name, content, save=True):
|
||||
name = self.field.generate_filename(self.instance, name)
|
||||
|
||||
args, varargs, varkw, defaults = getargspec(self.storage.save)
|
||||
if 'max_length' in args:
|
||||
if func_supports_parameter(self.storage.save, 'max_length'):
|
||||
self.name = self.storage.save(name, content, max_length=self.field.max_length)
|
||||
else:
|
||||
warnings.warn(
|
||||
|
|
|
@ -333,8 +333,16 @@ class ConnectionRouter(object):
|
|||
# If the router doesn't have a method, skip to the next one.
|
||||
continue
|
||||
|
||||
argspec = inspect.getargspec(method)
|
||||
if len(argspec.args) == 3 and not argspec.keywords:
|
||||
if six.PY3:
|
||||
sig = inspect.signature(router.allow_migrate)
|
||||
has_deprecated_signature = not any(
|
||||
p.kind == inspect.Parameter.VAR_KEYWORD for p in sig.parameters.values()
|
||||
)
|
||||
else:
|
||||
argspec = inspect.getargspec(router.allow_migrate)
|
||||
has_deprecated_signature = len(argspec.args) == 3 and not argspec.keywords
|
||||
|
||||
if has_deprecated_signature:
|
||||
warnings.warn(
|
||||
"The signature of allow_migrate has changed from "
|
||||
"allow_migrate(self, db, model) to "
|
||||
|
|
|
@ -2,6 +2,7 @@ import sys
|
|||
import threading
|
||||
import weakref
|
||||
|
||||
from django.utils.inspect import func_accepts_kwargs
|
||||
from django.utils.six.moves import range
|
||||
|
||||
if sys.version_info < (3, 4):
|
||||
|
@ -87,24 +88,11 @@ class Signal(object):
|
|||
|
||||
# If DEBUG is on, check that we got a good receiver
|
||||
if settings.configured and settings.DEBUG:
|
||||
import inspect
|
||||
assert callable(receiver), "Signal receivers must be callable."
|
||||
|
||||
# Check for **kwargs
|
||||
# Not all callables are inspectable with getargspec, so we'll
|
||||
# try a couple different ways but in the end fall back on assuming
|
||||
# it is -- we don't want to prevent registration of valid but weird
|
||||
# callables.
|
||||
try:
|
||||
argspec = inspect.getargspec(receiver)
|
||||
except TypeError:
|
||||
try:
|
||||
argspec = inspect.getargspec(receiver.__call__)
|
||||
except (TypeError, AttributeError):
|
||||
argspec = None
|
||||
if argspec:
|
||||
assert argspec[2] is not None, \
|
||||
"Signal receivers must accept keyword arguments (**kwargs)."
|
||||
if not func_accepts_kwargs(receiver):
|
||||
raise ValueError("Signal receivers must accept keyword arguments (**kwargs).")
|
||||
|
||||
if dispatch_uid:
|
||||
lookup_key = (dispatch_uid, _make_id(sender))
|
||||
|
|
|
@ -51,11 +51,11 @@ u'<html></html>'
|
|||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import inspect
|
||||
import re
|
||||
import warnings
|
||||
from functools import partial
|
||||
from importlib import import_module
|
||||
from inspect import getargspec, getcallargs
|
||||
|
||||
from django.apps import apps
|
||||
from django.template.context import ( # NOQA: imported for backwards compatibility
|
||||
|
@ -68,6 +68,7 @@ from django.utils.encoding import (
|
|||
)
|
||||
from django.utils.formats import localize
|
||||
from django.utils.html import conditional_escape
|
||||
from django.utils.inspect import getargspec
|
||||
from django.utils.itercompat import is_iterable
|
||||
from django.utils.module_loading import module_has_submodule
|
||||
from django.utils.safestring import (
|
||||
|
@ -686,7 +687,8 @@ class FilterExpression(object):
|
|||
plen = len(provided) + 1
|
||||
# Check to see if a decorator is providing the real function.
|
||||
func = getattr(func, '_decorated_function', func)
|
||||
args, varargs, varkw, defaults = getargspec(func)
|
||||
|
||||
args, _, _, defaults = getargspec(func)
|
||||
alen = len(args)
|
||||
dlen = len(defaults or [])
|
||||
# Not enough OR Too many
|
||||
|
@ -847,7 +849,7 @@ class Variable(object):
|
|||
current = current()
|
||||
except TypeError:
|
||||
try:
|
||||
getcallargs(current)
|
||||
inspect.getcallargs(current)
|
||||
except TypeError: # arguments *were* required
|
||||
current = context.template.engine.string_if_invalid # invalid method call
|
||||
else:
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
from __future__ import absolute_import
|
||||
|
||||
import inspect
|
||||
import warnings
|
||||
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
from __future__ import absolute_import
|
||||
|
||||
import inspect
|
||||
|
||||
from django.utils import six
|
||||
|
||||
|
||||
def getargspec(func):
|
||||
if six.PY2:
|
||||
return inspect.getargspec(func)
|
||||
|
||||
sig = inspect.signature(func)
|
||||
args = [
|
||||
p.name for p in sig.parameters.values()
|
||||
if p.kind == inspect.Parameter.POSITIONAL_OR_KEYWORD
|
||||
]
|
||||
varargs = [
|
||||
p.name for p in sig.parameters.values()
|
||||
if p.kind == inspect.Parameter.VAR_POSITIONAL
|
||||
]
|
||||
varargs = varargs[0] if varargs else None
|
||||
varkw = [
|
||||
p.name for p in sig.parameters.values()
|
||||
if p.kind == inspect.Parameter.VAR_KEYWORD
|
||||
]
|
||||
varkw = varkw[0] if varkw else None
|
||||
defaults = [
|
||||
p.default for p in sig.parameters.values()
|
||||
if p.kind == inspect.Parameter.POSITIONAL_OR_KEYWORD and p.default is not p.empty
|
||||
] or None
|
||||
return args, varargs, varkw, defaults
|
||||
|
||||
|
||||
def get_func_args(func):
|
||||
if six.PY2:
|
||||
argspec = inspect.getargspec(func)
|
||||
return argspec.args[1:] # ignore 'self'
|
||||
|
||||
sig = inspect.signature(func)
|
||||
return [
|
||||
arg_name for arg_name, param in sig.parameters.items()
|
||||
if param.kind == inspect.Parameter.POSITIONAL_OR_KEYWORD
|
||||
]
|
||||
|
||||
|
||||
def func_accepts_kwargs(func):
|
||||
if six.PY2:
|
||||
# Not all callables are inspectable with getargspec, so we'll
|
||||
# try a couple different ways but in the end fall back on assuming
|
||||
# it is -- we don't want to prevent registration of valid but weird
|
||||
# callables.
|
||||
try:
|
||||
argspec = inspect.getargspec(func)
|
||||
except TypeError:
|
||||
try:
|
||||
argspec = inspect.getargspec(func.__call__)
|
||||
except (TypeError, AttributeError):
|
||||
argspec = None
|
||||
return not argspec or argspec[2] is not None
|
||||
|
||||
return any(
|
||||
p for p in inspect.signature(func).parameters.values()
|
||||
if p.kind == p.VAR_KEYWORD
|
||||
)
|
||||
|
||||
|
||||
def func_has_no_args(func):
|
||||
args = inspect.getargspec(func)[0] if six.PY2 else [
|
||||
p for p in inspect.signature(func).parameters.values()
|
||||
if p.kind == p.POSITIONAL_OR_KEYWORD and p.default is p.empty
|
||||
]
|
||||
return len(args) == 1
|
||||
|
||||
|
||||
def func_supports_parameter(func, parameter):
|
||||
if six.PY3:
|
||||
return parameter in inspect.signature(func).parameters
|
||||
else:
|
||||
args, varargs, varkw, defaults = inspect.getargspec(func)
|
||||
return parameter in args
|
Loading…
Reference in New Issue