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

Skip to content

Commit 1d8dad4

Browse files
Automate signature computation for builtin functions
This improves the compatibility with the inspect module.
1 parent e869222 commit 1d8dad4

File tree

3 files changed

+50
-2
lines changed

3 files changed

+50
-2
lines changed

numpy/core/multiarray.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@
7979
def empty_like(prototype, dtype=None, order=None, subok=None, shape=None):
8080
"""
8181
empty_like(prototype, dtype=None, order='K', subok=True, shape=None)
82+
--
8283
8384
Return a new array with the same shape and type as a given array.
8485
@@ -147,6 +148,7 @@ def empty_like(prototype, dtype=None, order=None, subok=None, shape=None):
147148
def concatenate(arrays, axis=None, out=None, *, dtype=None, casting=None):
148149
"""
149150
concatenate((a1, a2, ...), axis=0, out=None, dtype=None, casting="same_kind")
151+
--
150152
151153
Join a sequence of arrays along an existing axis.
152154
@@ -248,6 +250,7 @@ def concatenate(arrays, axis=None, out=None, *, dtype=None, casting=None):
248250
def inner(a, b):
249251
"""
250252
inner(a, b, /)
253+
--
251254
252255
Inner product of two arrays.
253256
@@ -340,6 +343,7 @@ def inner(a, b):
340343
def where(condition, x=None, y=None):
341344
"""
342345
where(condition, [x, y], /)
346+
--
343347
344348
Return elements chosen from `x` or `y` depending on `condition`.
345349
@@ -415,6 +419,7 @@ def where(condition, x=None, y=None):
415419
def lexsort(keys, axis=None):
416420
"""
417421
lexsort(keys, axis=-1)
422+
--
418423
419424
Perform an indirect stable sort using a sequence of keys.
420425
@@ -497,6 +502,7 @@ def lexsort(keys, axis=None):
497502
def can_cast(from_, to, casting=None):
498503
"""
499504
can_cast(from_, to, casting='safe')
505+
--
500506
501507
Returns True if cast between data types can occur according to the
502508
casting rule. If from is a scalar or array scalar, also returns
@@ -612,6 +618,7 @@ def can_cast(from_, to, casting=None):
612618
def min_scalar_type(a):
613619
"""
614620
min_scalar_type(a, /)
621+
--
615622
616623
For scalar ``a``, returns the data type with the smallest size
617624
and smallest scalar kind which can hold its value. For non-scalar
@@ -663,6 +670,7 @@ def min_scalar_type(a):
663670
def result_type(*arrays_and_dtypes):
664671
"""
665672
result_type(*arrays_and_dtypes)
673+
--
666674
667675
Returns the type that results from applying the NumPy
668676
type promotion rules to the arguments.
@@ -735,6 +743,7 @@ def result_type(*arrays_and_dtypes):
735743
def dot(a, b, out=None):
736744
"""
737745
dot(a, b, out=None)
746+
--
738747
739748
Dot product of two arrays. Specifically,
740749
@@ -824,6 +833,7 @@ def dot(a, b, out=None):
824833
def vdot(a, b):
825834
"""
826835
vdot(a, b, /)
836+
--
827837
828838
Return the dot product of two vectors.
829839
@@ -882,6 +892,7 @@ def vdot(a, b):
882892
def bincount(x, weights=None, minlength=None):
883893
"""
884894
bincount(x, /, weights=None, minlength=0)
895+
--
885896
886897
Count number of occurrences of each value in array of non-negative ints.
887898
@@ -959,6 +970,7 @@ def bincount(x, weights=None, minlength=None):
959970
def ravel_multi_index(multi_index, dims, mode=None, order=None):
960971
"""
961972
ravel_multi_index(multi_index, dims, mode='raise', order='C')
973+
--
962974
963975
Converts a tuple of index arrays into an array of flat
964976
indices, applying boundary modes to the multi-index.
@@ -1020,6 +1032,7 @@ def ravel_multi_index(multi_index, dims, mode=None, order=None):
10201032
def unravel_index(indices, shape=None, order=None):
10211033
"""
10221034
unravel_index(indices, shape, order='C')
1035+
--
10231036
10241037
Converts a flat index or array of flat indices into a tuple
10251038
of coordinate arrays.
@@ -1070,6 +1083,7 @@ def unravel_index(indices, shape=None, order=None):
10701083
def copyto(dst, src, casting=None, where=None):
10711084
"""
10721085
copyto(dst, src, casting='same_kind', where=True)
1086+
--
10731087
10741088
Copies values from one array to another, broadcasting as necessary.
10751089
@@ -1105,6 +1119,7 @@ def copyto(dst, src, casting=None, where=None):
11051119
def putmask(a, mask, values):
11061120
"""
11071121
putmask(a, mask, values)
1122+
--
11081123
11091124
Changes elements of an array based on conditional and input values.
11101125
@@ -1150,6 +1165,7 @@ def putmask(a, mask, values):
11501165
def packbits(a, axis=None, bitorder='big'):
11511166
"""
11521167
packbits(a, /, axis=None, bitorder='big')
1168+
--
11531169
11541170
Packs the elements of a binary-valued array into bits in a uint8 array.
11551171
@@ -1208,6 +1224,7 @@ def packbits(a, axis=None, bitorder='big'):
12081224
def unpackbits(a, axis=None, count=None, bitorder='big'):
12091225
"""
12101226
unpackbits(a, /, axis=None, count=None, bitorder='big')
1227+
--
12111228
12121229
Unpacks elements of a uint8 array into a binary-valued output array.
12131230
@@ -1292,6 +1309,7 @@ def unpackbits(a, axis=None, count=None, bitorder='big'):
12921309
def shares_memory(a, b, max_work=None):
12931310
"""
12941311
shares_memory(a, b, /, max_work=None)
1312+
--
12951313
12961314
Determine if two arrays share memory.
12971315
@@ -1367,6 +1385,7 @@ def shares_memory(a, b, max_work=None):
13671385
def may_share_memory(a, b, max_work=None):
13681386
"""
13691387
may_share_memory(a, b, /, max_work=None)
1388+
--
13701389
13711390
Determine if two arrays might share memory
13721391
@@ -1408,6 +1427,7 @@ def may_share_memory(a, b, max_work=None):
14081427
def is_busday(dates, weekmask=None, holidays=None, busdaycal=None, out=None):
14091428
"""
14101429
is_busday(dates, weekmask='1111100', holidays=None, busdaycal=None, out=None)
1430+
--
14111431
14121432
Calculates which of the given dates are valid days, and which are not.
14131433
@@ -1463,6 +1483,7 @@ def busday_offset(dates, offsets, roll=None, weekmask=None, holidays=None,
14631483
busdaycal=None, out=None):
14641484
"""
14651485
busday_offset(dates, offsets, roll='raise', weekmask='1111100', holidays=None, busdaycal=None, out=None)
1486+
--
14661487
14671488
First adjusts the date to fall on a valid day according to
14681489
the ``roll`` rule, then applies offsets to the given dates
@@ -1557,6 +1578,7 @@ def busday_count(begindates, enddates, weekmask=None, holidays=None,
15571578
busdaycal=None, out=None):
15581579
"""
15591580
busday_count(begindates, enddates, weekmask='1111100', holidays=[], busdaycal=None, out=None)
1581+
--
15601582
15611583
Counts the number of valid days between `begindates` and
15621584
`enddates`, not including the day of `enddates`.
@@ -1625,6 +1647,7 @@ def busday_count(begindates, enddates, weekmask=None, holidays=None,
16251647
def datetime_as_string(arr, unit=None, timezone=None, casting=None):
16261648
"""
16271649
datetime_as_string(arr, unit=None, timezone='naive', casting='same_kind')
1650+
--
16281651
16291652
Convert an array of datetimes into an array of strings.
16301653

numpy/core/overrides.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import collections
33
import functools
44
import os
5+
import textwrap
56

67
from numpy.core._multiarray_umath import (
78
add_docstring, implement_array_function, _get_implementing_args)
@@ -85,6 +86,14 @@ def set_array_function_like_doc(public_api):
8586
ArgSpec = collections.namedtuple('ArgSpec', 'args varargs keywords defaults')
8687

8788

89+
def add_docstring_from_dispatcher(implementation, dispatcher):
90+
"""Use dispatcher to populate doc and text signature of implementation"""
91+
doc = dispatcher.__doc__
92+
if doc is None:
93+
return
94+
add_docstring(implementation, textwrap.dedent(doc).lstrip())
95+
96+
8897
def verify_matching_signatures(implementation, dispatcher):
8998
"""Verify that a dispatcher function has the right signature."""
9099
implementation_spec = ArgSpec(*getargspec(implementation))
@@ -161,7 +170,7 @@ def array_function_dispatch(dispatcher, module=None, verify=True,
161170
if not ARRAY_FUNCTION_ENABLED:
162171
def decorator(implementation):
163172
if docs_from_dispatcher:
164-
add_docstring(implementation, dispatcher.__doc__)
173+
add_docstring_from_dispatcher(implementation, dispatcher)
165174
if module is not None:
166175
implementation.__module__ = module
167176
return implementation
@@ -172,7 +181,7 @@ def decorator(implementation):
172181
verify_matching_signatures(implementation, dispatcher)
173182

174183
if docs_from_dispatcher:
175-
add_docstring(implementation, dispatcher.__doc__)
184+
add_docstring_from_dispatcher(implementation, dispatcher)
176185

177186
@functools.wraps(implementation)
178187
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