8000 BUG: numpy.core.overrides.verify_matching_signatures ignores keyword-only arguments · Issue #16299 · numpy/numpy · GitHub
[go: up one dir, main page]

Skip to content

BUG: numpy.core.overrides.verify_matching_signatures ignores keyword-only arguments #16299

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
eric-wieser opened this issue May 19, 2020 · 1 comment
Labels

Comments

@eric-wieser
Copy link
Member
eric-wieser commented May 19, 2020

Reproducing code example:

>>> from numpy.core.overrides import verify_matching_signatures
>>> def a(*, foo=1): pass
>>> def b(*, bar=2): pass
>>> verify_matching_signatures(a, b)
# does not fail

A correct implementation could look like:

def verify_matching_signatures(implementation, dispatcher):
    import inspect
    implementation_sig = inspect.signature(implementation)
    dispatcher_sig = inspect.signature(dispatcher)

    # replace defaults with None and remove annotations
    implementation_with_none_sig = implementation_sig.replace(
        parameters=[
            p.replace(
                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_with_none_sig:
        raise RuntimeError(
            'dispatcher for {} has the wrong function signature:\n'
            '  expected: {}\n'
            '  got:      {}'
            .format(
                implementation, implementation_with_none_sig, dispatcher_sig
            )
        )

which gives:

>>> verify_matching_signatures(a, b)
RuntimeError: dispatcher for <function a at 0x0000020080E14B80> has the wrong function signature:
  expected: (*, foo=None)
  got:      (*, bar=2)

Unfortunately, this implementation seems to slow down the import time by 5%.

@surculus12
Copy link

Numpy inspection doesn't handle kwonly arguments. It can either cause the arguments not to output from the inspection, or even mess up to order of * and ** arguments, since the kwonly args aren't counted (messing up the index of the names). Example:

from numpy.compat._inspect import getargspec


def checkargs(a):
    print(getargspec(a))


checkargs(lambda a, foo=1: 0)
# Output:   (['a', 'foo'], None, None, (1,))
# Correct
checkargs(lambda a, *, foo=1: 0)
# Output:   (['a'], None, None, None)
# Expected: (['a', 'foo'], None, None, (1,))
checkargs(lambda *args, **kwargs: 0)
# Output:   ([], 'args', 'kwargs', None)
# Correct
checkargs(lambda a, *args, foo=1, **kwargs: 0)
# Output:   (['a'], 'foo', 'args', None)
# Expected: (['a', 'foo'], 'args', 'kwargs', (1,)

I am fixing the issue in inspection, having it count the code.co_kwonlyargcount and read function.__kwdefaults__, along with adding your test-case for numpy.core.overrides.verify_matching_signatures. It seems more appropriate than bypassing the bug in the inspection functions, but it's possible that it has side effects if something is expecting this (wrong) behaviour somewhere else.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants
0