Skip to content

array_function_dispatch() breaks inspect.getargspec/getfullargspec #12225

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

Closed
shoyer opened this issue Oct 20, 2018 · 8 comments
Closed

array_function_dispatch() breaks inspect.getargspec/getfullargspec #12225

shoyer opened this issue Oct 20, 2018 · 8 comments

Comments

@shoyer
Copy link
Member

shoyer commented Oct 20, 2018

xref #12028

Even though assuredly this isn't really guaranteed by our API, introspection into NumPy function arguments appears to be used by a number of our dependencies. Unfortunately, although inspect.signature has a follow_wrapped argument this isn't the case for inspect.getfullargspec or the old inspect.getargspec (still used for Python 2.7 compatibility in many cases).

Behavior on master:

>>> inspect.getfullargspec(np.sum)
FullArgSpec(args=[], varargs='args', varkw='kwargs', defaults=None, kwonlyargs=[], kwonlydefaults=None, annotations={})

Behavior with the released version of NumPy:

>>> inspect.getfullargspec(np.sum)
FullArgSpec(args=['a', 'axis', 'dtype', 'out', 'keepdims'], varargs=None, varkw=None, defaults=(None, None, None, <class 'numpy._globals._NoValue'>), kwonlyargs=[], kwonlydefaults=None, annotations={})

This results in test failures in dask (dask/dask#4111) and is my best guess for pandas test failures (pandas-dev/pandas#23172).

We have a few options for fixing this:

  1. Don't. Tell dependencies to figure out a more robust way of handling this.
  2. Use some sort of eval/exec based magic to build real function objects with the right signature Tracking issue for implementation of NEP-18 (__array_function__) #12028 (comment)
  3. Stop using a decorator in favor of writing functions with explicit signatures.

(1) seems quite unfriendly to users. (3) would result in a lot of more boilerplate code in NumPy and would break extensibility.

(2) might have a negative impact on import performance, but may be our best bet.

@eric-wieser
Copy link
Member

Option 4: Roll back __array_function__ changes and postpone them till after we drop python 2, where inspect.signature is guaranteed to exist

@shoyer
Copy link
Member Author

shoyer commented Oct 20, 2018

Testing suggests that this would fix the Dask issue, but something else appears to be causing the pandas issue -- #12226 didn't fix it.

@eric-wieser Unfortunately, the mere availability of inspect.signature would not be enough -- it actually has to always be used instead of inspect.getfullargspec. This seems unlikely to be the case for at least some time.

@mhvk
Copy link
Contributor

mhvk commented Oct 20, 2018

I guess the point of waiting for python3 only is that option (1) becomes more palatable - we can tell users how to solve the introspection problem.

p.s. There may be some independent value in not rolling out something major for our last python2 version, which perhaps argues for waiting. Or, maybe more crazily, one could proceed with the wrapper not doing anything by default, i.e., have one release in which even having __array_function__ is strictly opt-in (there was some discussion about this on the mailing list).

@shoyer
Copy link
Member Author

shoyer commented Oct 22, 2018

I finally understand exactly what the decorator library is doing.

It dynamically creates a function with the appropriate signature, e.g., for np.sum it could create:

def sum(a, axis=None, dtype=None, out=None, keepdims=np._NoValue, initial=np._NoValue):
    return _public_api_for_sum(a, axis, dtype, out, keepdims, initial)

where _public_api_for_sum is the public_api function that calls dispatcher and array_function_implementation_or_override (defined inside array_function_dispatch).

The problem with this version of the decorator is that inevitably this breaks extensibility -- implementations of np.sum will always need to know how to handle all the optional arguments for np.sum. This feels like a real non-starter, because it makes these overrides much harder to use.

So I think I'm -1 on using decorator now.

I guess the point of waiting for python3 only is that option (1) becomes more palatable - we can tell users how to solve the introspection problem.

Yeah, I'm starting to come around to this option. Another option would be to point users to the inspect.signature backport found in funcsigs.

@rgommers
Copy link
Member

@shoyer did you delete your own comment from 5 hours ago? I was going to respond to it, but it's not here anymore.

Or, maybe more crazily, one could proceed with the wrapper not doing anything by default, i.e., have one release in which even having array_function is strictly opt-in (there was some discussion about this on the mailing list).

Not crazy - that seems much better than removing everything and putting it back after the 1.16.x branch

@shoyer
Copy link
Member Author

shoyer commented Oct 22, 2018

@rgommers It looks like my comment is still there? Maybe some temporary glitch related to the GitHub data outage last night?

@shoyer
Copy link
Member Author

shoyer commented Oct 22, 2018

Or, maybe more crazily, one could proceed with the wrapper not doing anything by default, i.e., have one release in which even having array_function is strictly opt-in (there was some discussion about this on the mailing list).

Not crazy - that seems much better than removing everything and putting it back after the 1.16.x branch

Yes, if there is no way avoid breaking some edge cases it is certainly better to roll this out slowly. It would be a reasonable use-case for @njsmith's NUMPY_EXPERIMENTAL_ARRAY_FUNCTION environment variable.

@seberg
Copy link
Member

seberg commented Jan 28, 2024

I think we can close this, as we have the signature works and the discussion was: On python 3 that will fix it, Python 2 is a problem... But Python 2 isn't a problem anymore.

@seberg seberg closed this as completed Jan 28, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants