8000 Automate signature computation for builtin functions · numpy/numpy@2d10ba7 · GitHub
[go: up one dir, main page]

Skip to content

Commit 2d10ba7

Browse files
Automate signature computation for builtin functions
This improves the compatibility with the inspect module.
1 parent 325b72a commit 2d10ba7

File tree

2 files changed

+36
-2
lines changed

2 files changed

+36
-2
lines changed

numpy/core/overrides.py

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"""Implementation of __array_function__ overrides from NEP-18."""
22
import collections
33
import functools
4+
import ast
45
import os
56
import textwrap
67

@@ -86,6 +87,23 @@ def set_array_function_like_doc(public_api):
8687
ArgSpec = collections.namedtuple('ArgSpec', 'args varargs keywords defaults')
8788

8889

90+
def extract_text_signature(obj, docstring):
91+
head = docstring.lstrip().split('\n')[0]
92+
objname = obj.__name__
93+
if not head.startswith(objname):
94+
return None
95+
return head
96+
97+
98+
def add_docstring_with_textsig(implementation, doc):
99+
if doc is None:
100+
return
101+
textsig = extract_text_signature(implementation, doc)
102+
if textsig is not None:
103+
doc = '{}\n--\n\n{}'.format(textsig, doc)
104+
add_docstring(implementation, doc)
105+
106+
89107
def verify_matching_signatures(implementation, dispatcher):
90108
"""Verify that a dispatcher function has the right signature."""
91109
implementation_spec = ArgSpec(*getargspec(implementation))
@@ -162,7 +180,7 @@ def array_function_dispatch(dispatcher, module=None, verify=True,
162180
if not ARRAY_FUNCTION_ENABLED:
163181
def decorator(implementation):
164182
if docs_from_dispatcher:
165-
add_docstring(implementation, dispatcher.__doc__)
183+
add_docstring_with_textsig(implementation, dispatcher.__doc__)
166184
if module is not None:
167185
implementation.__module__ = module
168186
return implementation
@@ -173,7 +191,7 @@ def decorator(implementation):
173191
verify_matching_signatures(implementation, dispatcher)
174192

175193
if docs_from_dispatcher:
176-
add_docstring(implementation, dispatcher.__doc__)
194+
add_docstring_with_textsig(implementation, dispatcher.__doc__)
177195

178196
@functools.wraps(implementation)
179197
def public_api(*args, **kwargs):

numpy/tests/test_public_api.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import subprocess
33
import pkgutil
44
import types
5+
import inspect
56
import importlib
67
import warnings
78

@@ -459,3 +460,18 @@ def check_importable(module_name):
459460
raise AssertionError("Modules that are not really public but looked "
460461
"public and can not be imported: "
461462
"{}".format(module_names))
463+
464+
465+
@pytest.mark.skipif(sys.flags.optimize < 2, reason='docstring stripped')
466+
def test_all_function_have_signature():
467+
allowlist = {'concatenate', 'where'}
468+
469+
for key, value in inspect.getmembers(numpy):
470+
if not inspect.isfunction(value):
471+
continue
472+
if key in allowlist:
473+
continue
474+
try:
475+
inspect.signature(value)
476+
except ValueError:
477+
raise AssertionError("No signature found for {}".format(key))

0 commit comments

Comments
 (0)
0