summaryrefslogtreecommitdiffstats
path: root/Lib/inspect.py
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/inspect.py')
-rw-r--r--Lib/inspect.py62
1 files changed, 62 insertions, 0 deletions
diff --git a/Lib/inspect.py b/Lib/inspect.py
index edbf927..dc94e44 100644
--- a/Lib/inspect.py
+++ b/Lib/inspect.py
@@ -31,6 +31,7 @@ Here are some of the useful functions provided by this module:
__author__ = ('Ka-Ping Yee <ping@lfw.org>',
'Yury Selivanov <yselivanov@sprymix.com>')
+import ast
import importlib.machinery
import itertools
import linecache
@@ -1461,6 +1462,9 @@ def signature(obj):
if isinstance(obj, types.FunctionType):
return Signature.from_function(obj)
+ if isinstance(obj, types.BuiltinFunctionType):
+ return Signature.from_builtin(obj)
+
if isinstance(obj, functools.partial):
sig = signature(obj.func)
@@ -1942,6 +1946,64 @@ class Signature:
return_annotation=annotations.get('return', _empty),
__validate_parameters__=False)
+ @classmethod
+ def from_builtin(cls, func):
+ s = getattr(func, "__text_signature__", None)
+ if not s:
+ return None
+
+ if s.endswith("/)"):
+ kind = Parameter.POSITIONAL_ONLY
+ s = s[:-2] + ')'
+ else:
+ kind = Parameter.POSITIONAL_OR_KEYWORD
+
+ s = "def foo" + s + ": pass"
+
+ try:
+ module = ast.parse(s)
+ except SyntaxError:
+ return None
+ if not isinstance(module, ast.Module):
+ return None
+
+ # ast.FunctionDef
+ f = module.body[0]
+
+ parameters = []
+ empty = Parameter.empty
+
+ def p(name_node, default_node, default=empty):
+ name = name_node.arg
+
+ if isinstance(default_node, ast.Num):
+ default = default.n
+ elif isinstance(default_node, ast.NameConstant):
+ default = default_node.value
+ parameters.append(Parameter(name, kind, default=default, annotation=empty))
+
+ # non-keyword-only parameters
+ for name, default in reversed(list(itertools.zip_longest(reversed(f.args.args), reversed(f.args.defaults), fillvalue=None))):
+ p(name, default)
+
+ # *args
+ if f.args.vararg:
+ kind = Parameter.VAR_POSITIONAL
+ p(f.args.vararg, empty)
+
+ # keyword-only arguments
+ kind = Parameter.KEYWORD_ONLY
+ for name, default in zip(f.args.kwonlyargs, f.args.kw_defaults):
+ p(name, default)
+
+ # **kwargs
+ if f.args.kwarg:
+ kind = Parameter.VAR_KEYWORD
+ p(f.args.kwarg, empty)
+
+ return cls(parameters, return_annotation=cls.empty)
+
+
@property
def parameters(self):
return self._parameters