inspect.py 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. import functools
  2. import inspect
  3. @functools.lru_cache(maxsize=512)
  4. def _get_func_parameters(func, remove_first):
  5. parameters = tuple(inspect.signature(func).parameters.values())
  6. if remove_first:
  7. parameters = parameters[1:]
  8. return parameters
  9. def _get_callable_parameters(meth_or_func):
  10. is_method = inspect.ismethod(meth_or_func)
  11. func = meth_or_func.__func__ if is_method else meth_or_func
  12. return _get_func_parameters(func, remove_first=is_method)
  13. def get_func_args(func):
  14. params = _get_callable_parameters(func)
  15. return [
  16. param.name for param in params
  17. if param.kind == inspect.Parameter.POSITIONAL_OR_KEYWORD
  18. ]
  19. def get_func_full_args(func):
  20. """
  21. Return a list of (argument name, default value) tuples. If the argument
  22. does not have a default value, omit it in the tuple. Arguments such as
  23. *args and **kwargs are also included.
  24. """
  25. params = _get_callable_parameters(func)
  26. args = []
  27. for param in params:
  28. name = param.name
  29. # Ignore 'self'
  30. if name == 'self':
  31. continue
  32. if param.kind == inspect.Parameter.VAR_POSITIONAL:
  33. name = '*' + name
  34. elif param.kind == inspect.Parameter.VAR_KEYWORD:
  35. name = '**' + name
  36. if param.default != inspect.Parameter.empty:
  37. args.append((name, param.default))
  38. else:
  39. args.append((name,))
  40. return args
  41. def func_accepts_kwargs(func):
  42. """Return True if function 'func' accepts keyword arguments **kwargs."""
  43. return any(
  44. p for p in _get_callable_parameters(func)
  45. if p.kind == p.VAR_KEYWORD
  46. )
  47. def func_accepts_var_args(func):
  48. """
  49. Return True if function 'func' accepts positional arguments *args.
  50. """
  51. return any(
  52. p for p in _get_callable_parameters(func)
  53. if p.kind == p.VAR_POSITIONAL
  54. )
  55. def method_has_no_args(meth):
  56. """Return True if a method only accepts 'self'."""
  57. count = len([
  58. p for p in _get_callable_parameters(meth)
  59. if p.kind == p.POSITIONAL_OR_KEYWORD
  60. ])
  61. return count == 0 if inspect.ismethod(meth) else count == 1
  62. def func_supports_parameter(func, name):
  63. return any(param.name == name for param in _get_callable_parameters(func))