You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

inspect.py 4.1 KiB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. from __future__ import absolute_import
  2. import inspect
  3. from django.utils import six
  4. def getargspec(func):
  5. if six.PY2:
  6. return inspect.getargspec(func)
  7. sig = inspect.signature(func)
  8. args = [
  9. p.name for p in sig.parameters.values()
  10. if p.kind == inspect.Parameter.POSITIONAL_OR_KEYWORD
  11. ]
  12. varargs = [
  13. p.name for p in sig.parameters.values()
  14. if p.kind == inspect.Parameter.VAR_POSITIONAL
  15. ]
  16. varargs = varargs[0] if varargs else None
  17. varkw = [
  18. p.name for p in sig.parameters.values()
  19. if p.kind == inspect.Parameter.VAR_KEYWORD
  20. ]
  21. varkw = varkw[0] if varkw else None
  22. defaults = [
  23. p.default for p in sig.parameters.values()
  24. if p.kind == inspect.Parameter.POSITIONAL_OR_KEYWORD and p.default is not p.empty
  25. ] or None
  26. return args, varargs, varkw, defaults
  27. def get_func_args(func):
  28. if six.PY2:
  29. argspec = inspect.getargspec(func)
  30. return argspec.args[1:] # ignore 'self'
  31. sig = inspect.signature(func)
  32. return [
  33. arg_name for arg_name, param in sig.parameters.items()
  34. if param.kind == inspect.Parameter.POSITIONAL_OR_KEYWORD
  35. ]
  36. def get_func_full_args(func):
  37. """
  38. Return a list of (argument name, default value) tuples. If the argument
  39. does not have a default value, omit it in the tuple. Arguments such as
  40. *args and **kwargs are also included.
  41. """
  42. if six.PY2:
  43. argspec = inspect.getargspec(func)
  44. args = argspec.args[1:] # ignore 'self'
  45. defaults = argspec.defaults or []
  46. # Split args into two lists depending on whether they have default value
  47. no_default = args[:len(args) - len(defaults)]
  48. with_default = args[len(args) - len(defaults):]
  49. # Join the two lists and combine it with default values
  50. args = [(arg,) for arg in no_default] + zip(with_default, defaults)
  51. # Add possible *args and **kwargs and prepend them with '*' or '**'
  52. varargs = [('*' + argspec.varargs,)] if argspec.varargs else []
  53. kwargs = [('**' + argspec.keywords,)] if argspec.keywords else []
  54. return args + varargs + kwargs
  55. sig = inspect.signature(func)
  56. args = []
  57. for arg_name, param in sig.parameters.items():
  58. name = arg_name
  59. # Ignore 'self'
  60. if name == 'self':
  61. continue
  62. if param.kind == inspect.Parameter.VAR_POSITIONAL:
  63. name = '*' + name
  64. elif param.kind == inspect.Parameter.VAR_KEYWORD:
  65. name = '**' + name
  66. if param.default != inspect.Parameter.empty:
  67. args.append((name, param.default))
  68. else:
  69. args.append((name,))
  70. return args
  71. def func_accepts_kwargs(func):
  72. if six.PY2:
  73. # Not all callables are inspectable with getargspec, so we'll
  74. # try a couple different ways but in the end fall back on assuming
  75. # it is -- we don't want to prevent registration of valid but weird
  76. # callables.
  77. try:
  78. argspec = inspect.getargspec(func)
  79. except TypeError:
  80. try:
  81. argspec = inspect.getargspec(func.__call__)
  82. except (TypeError, AttributeError):
  83. argspec = None
  84. return not argspec or argspec[2] is not None
  85. return any(
  86. p for p in inspect.signature(func).parameters.values()
  87. if p.kind == p.VAR_KEYWORD
  88. )
  89. def func_accepts_var_args(func):
  90. """
  91. Return True if function 'func' accepts positional arguments *args.
  92. """
  93. if six.PY2:
  94. return inspect.getargspec(func)[1] is not None
  95. return any(
  96. p for p in inspect.signature(func).parameters.values()
  97. if p.kind == p.VAR_POSITIONAL
  98. )
  99. def func_has_no_args(func):
  100. args = inspect.getargspec(func)[0] if six.PY2 else [
  101. p for p in inspect.signature(func).parameters.values()
  102. if p.kind == p.POSITIONAL_OR_KEYWORD
  103. ]
  104. return len(args) == 1
  105. def func_supports_parameter(func, parameter):
  106. if six.PY3:
  107. return parameter in inspect.signature(func).parameters
  108. else:
  109. args, varargs, varkw, defaults = inspect.getargspec(func)
  110. return parameter in args