From b3bc0fbb555f423e2b335415c40cb3d6d82a6222 Mon Sep 17 00:00:00 2001 From: Ross Barnowski Date: Wed, 8 Jul 2020 18:44:37 -0700 Subject: [PATCH 1/6] MAINT: rm _inspect from numpy/core/overrides. Replace usage of numpy.compat._inspect with implementation based on the standard inspect module. --- numpy/core/overrides.py | 41 +++++++++++++++++++---------------------- 1 file changed, 19 insertions(+), 22 deletions(-) diff --git a/numpy/core/overrides.py b/numpy/core/overrides.py index 816b11293cfd..d254a20368cd 100644 --- a/numpy/core/overrides.py +++ b/numpy/core/overrides.py @@ -3,10 +3,10 @@ import functools import os import textwrap +import inspect from numpy.core._multiarray_umath import ( add_docstring, implement_array_function, _get_implementing_args) -from numpy.compat._inspect import getargspec ARRAY_FUNCTION_ENABLED = bool( @@ -66,29 +66,26 @@ """) -ArgSpec = collections.namedtuple('ArgSpec', 'args varargs keywords defaults') - - def verify_matching_signatures(implementation, dispatcher): """Verify that a dispatcher function has the right signature.""" - implementation_spec = ArgSpec(*getargspec(implementation)) - dispatcher_spec = ArgSpec(*getargspec(dispatcher)) - - if (implementation_spec.args != dispatcher_spec.args or - implementation_spec.varargs != dispatcher_spec.varargs or - implementation_spec.keywords != dispatcher_spec.keywords or - (bool(implementation_spec.defaults) != - bool(dispatcher_spec.defaults)) or - (implementation_spec.defaults is not None and - len(implementation_spec.defaults) != - len(dispatcher_spec.defaults))): - raise RuntimeError('implementation and dispatcher for %s have ' - 'different function signatures' % implementation) - - if implementation_spec.defaults is not None: - if dispatcher_spec.defaults != (None,) * len(dispatcher_spec.defaults): - raise RuntimeError('dispatcher functions can only use None for ' - 'default argument values') + # Get an ordered dict of Parameter objects from each signature + implementation_sig = inspect.signature(implementation).parameters + dispatcher_sig = inspect.signature(dispatcher).parameters + + for p1, p2 in zip(implementation_sig.values(), dispatcher_sig.values()): + if ( + (p1.name != p2.name) or (p1.kind != p2.kind) or + ((p1.default is p1.empty) and (p2.default is not p2.empty)) + ): + raise RuntimeError( + f'implementation and dispatcher for {implementation} have ' + 'different function signatures' + ) + if (p1.default is not p1.empty) and (p2.default is not None): + raise RuntimeError( + f'dispatcher functions can only use None for default ' + 'argument values' + ) def set_module(module): From 82f94cd01007c4f30355f386befae397f77f58cb Mon Sep 17 00:00:00 2001 From: Ross Barnowski Date: Wed, 8 Jul 2020 18:45:18 -0700 Subject: [PATCH 2/6] MAINT: rm _inspect from numpy/ma/core. Replace usage of numpy.compat._inspect with implementation based on the standard inspect module. --- numpy/ma/core.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/numpy/ma/core.py b/numpy/ma/core.py index b5371f51a6bc..aae7b530e822 100644 --- a/numpy/ma/core.py +++ b/numpy/ma/core.py @@ -34,9 +34,7 @@ from numpy import ndarray, amax, amin, iscomplexobj, bool_, _NoValue from numpy import array as narray from numpy.lib.function_base import angle -from numpy.compat import ( - getargspec, formatargspec, long, unicode, bytes - ) +from numpy.compat import long, unicode, bytes from numpy import expand_dims from numpy.core.numeric import normalize_axis_tuple from numpy.core._internal import recursive @@ -135,8 +133,8 @@ def get_object_signature(obj): """ try: - sig = formatargspec(*getargspec(obj)) - except TypeError: + sig = str(inspect.signature(obj)) + except ValueError: sig = '' return sig From 0f84e10633d6bc62bab0957f7d7b3e3c9deafaf2 Mon Sep 17 00:00:00 2001 From: Ross Barnowski Date: Thu, 9 Jul 2020 14:15:17 -0700 Subject: [PATCH 3/6] MAINT: modify impl of verify_matching_signatures. Use the parameter replacement mechansism for inspect.signature to verify consistent signatures between the dispatcher and primary function implementation. Co-authored-by: Eric Wieser --- numpy/core/overrides.py | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/numpy/core/overrides.py b/numpy/core/overrides.py index d254a20368cd..524227062bec 100644 --- a/numpy/core/overrides.py +++ b/numpy/core/overrides.py @@ -68,24 +68,26 @@ def verify_matching_signatures(implementation, dispatcher): """Verify that a dispatcher function has the right signature.""" - # Get an ordered dict of Parameter objects from each signature - implementation_sig = inspect.signature(implementation).parameters - dispatcher_sig = inspect.signature(dispatcher).parameters - - for p1, p2 in zip(implementation_sig.values(), dispatcher_sig.values()): - if ( - (p1.name != p2.name) or (p1.kind != p2.kind) or - ((p1.default is p1.empty) and (p2.default is not p2.empty)) - ): - raise RuntimeError( - f'implementation and dispatcher for {implementation} have ' - 'different function signatures' - ) - if (p1.default is not p1.empty) and (p2.default is not None): - raise RuntimeError( - f'dispatcher functions can only use None for default ' - 'argument values' + implementation_sig = inspect.signature(implementation) + dispatcher_sig = inspect.signature(dispatcher) + + implementation_sig_with_none_defaults = implementation_sig.replace( + parameters=[ + p.replace( + annotation=p.empty, + default=p.empty if p.default is p.empty else None ) + for p in implementation_sig.parameters.values() + ] + ) + + if dispatcher_sig != implementation_sig_with_none_defaults: + raise RuntimeError( + f"dispatcher for {implementation} has the wrong function " + "signature:\n" + " expected: {implementation_sig_with_none_defaults}\n" + " got: {dispatcher_sig}" + ) def set_module(module): From 31e806883e28222e4b2ea87b6c86e86e70d3c01c Mon Sep 17 00:00:00 2001 From: Ross Barnowski Date: Thu, 9 Jul 2020 14:50:16 -0700 Subject: [PATCH 4/6] Fixups from code review. --- numpy/core/overrides.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/numpy/core/overrides.py b/numpy/core/overrides.py index 524227062bec..22b7a1fab595 100644 --- a/numpy/core/overrides.py +++ b/numpy/core/overrides.py @@ -74,11 +74,16 @@ def verify_matching_signatures(implementation, dispatcher): implementation_sig_with_none_defaults = implementation_sig.replace( parameters=[ p.replace( - annotation=p.empty, - default=p.empty if p.default is p.empty else None + annotation=inspect.Parameter.empty, + default=( + inspect.Parameter.empty + if p.default is inspect.Parameter.empty + else None + ), ) for p in implementation_sig.parameters.values() - ] + ], + return_annotation=inspect.Signature.empty ) if dispatcher_sig != implementation_sig_with_none_defaults: From c1eeb824f7d927d53abf6aef72f93c05d414e2d2 Mon Sep 17 00:00:00 2001 From: Ross Barnowski Date: Thu, 9 Jul 2020 15:03:29 -0700 Subject: [PATCH 5/6] Incorporate more comments from review. --- numpy/core/overrides.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/numpy/core/overrides.py b/numpy/core/overrides.py index 22b7a1fab595..ada9ffae4b4d 100644 --- a/numpy/core/overrides.py +++ b/numpy/core/overrides.py @@ -71,7 +71,7 @@ def verify_matching_signatures(implementation, dispatcher): implementation_sig = inspect.signature(implementation) dispatcher_sig = inspect.signature(dispatcher) - implementation_sig_with_none_defaults = implementation_sig.replace( + implementation_sig_with_none_defaults = inspect.Signature( parameters=[ p.replace( annotation=inspect.Parameter.empty, @@ -83,7 +83,6 @@ def verify_matching_signatures(implementation, dispatcher): ) for p in implementation_sig.parameters.values() ], - return_annotation=inspect.Signature.empty ) if dispatcher_sig != implementation_sig_with_none_defaults: From 6e35c2a5a6113e3c1820ee6cb78b9dd04ffa4e02 Mon Sep 17 00:00:00 2001 From: Ross Barnowski Date: Mon, 3 Aug 2020 13:21:09 -0700 Subject: [PATCH 6/6] Apply suggestions from code review --- numpy/core/overrides.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/numpy/core/overrides.py b/numpy/core/overrides.py index ada9ffae4b4d..569910fcad86 100644 --- a/numpy/core/overrides.py +++ b/numpy/core/overrides.py @@ -66,6 +66,10 @@ """) +# Avoid extra getattr calls in verify_matching_signatures +_Parameter_empty = inspect.Parameter.empty + + def verify_matching_signatures(implementation, dispatcher): """Verify that a dispatcher function has the right signature.""" implementation_sig = inspect.signature(implementation) @@ -74,10 +78,10 @@ def verify_matching_signatures(implementation, dispatcher): implementation_sig_with_none_defaults = inspect.Signature( parameters=[ p.replace( - annotation=inspect.Parameter.empty, + annotation=_Parameter_empty, default=( - inspect.Parameter.empty - if p.default is inspect.Parameter.empty + _Parameter_empty + if p.default is _Parameter_empty else None ), )