8000 ENH: `__array_function__` support for most of `numpy.core` by shoyer · Pull Request #12115 · numpy/numpy · GitHub
[go: up one dir, main page]

Skip to content

ENH: __array_function__ support for most of numpy.core #12115

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

Merged
merged 1 commit into from
Oct 11, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions numpy/core/arrayprint.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
from .numeric import concatenate, asarray, errstate
from .numerictypes import (longlong, intc, int_, float_, complex_, bool_,
flexible)
from .overrides import array_function_dispatch
import warnings
import contextlib

Expand Down Expand Up @@ -496,6 +497,16 @@ def _array2string(a, options, separator=' ', prefix=""):
return lst


def _array2string_dispatcher(
a, max_line_width=None, precision=None,
suppress_small=None, separator=None, prefix=None,
style=None, formatter=None, threshold=None,
edgeitems=None, sign=None, floatmode=None, suffix=None,
**kwarg):
return (a,)


@array_function_dispatch(_array2string_dispatcher)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could the dispatcher be written

def default1_dispatcher(*args, **kwargs):
    return args[:1]

Then maybe a few of those could be put into overrides, imported, and reused. Of course there may be cases for a different dispatcher in special cases.

Copy link
Member Author
@shoyer shoyer Oct 9, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a good idea, but even though most numpy functions have a meaningless first argument name, technically you can still use them as a keyword argument, e.g., numpy.sum(a=array), in which args would be empty. So we need to have an exactly matching function signature, including the same argument names.

Copy link
Member
@mattip mattip Oct 9, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At least for python 3.3+, we could use inspect.signature and set the dispatcher.__signature__ as in this stack overflow answer, or is that too magical?

Edit: formatting

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if signature rewriting would let us restore the original traceback when the wrong arguments are supplied. With the current version of NumPy:

In [2]: np.argmax(x=[1, 2, 3])
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-2-d25c18244167> in <module>()
----> 1 np.argmax(x=[1, 2, 3])

TypeError: argmax() got an unexpected keyword argument 'x'

but after this PR:

In [2]: np.argmax(x=[1, 2, 3])
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-2-d25c18244167> in <module>()
----> 1 np.argmax(x=[1, 2, 3])

~/dev/numpy/numpy/core/overrides.py in public_api(*args, **kwargs)
    147         @functools.wraps(implementation)
    148         def public_api(*args, **kwargs):
--> 149             relevant_args = dispatcher(*args, **kwargs)
    150             return array_function_implementation_or_override(
    151                 implementation, public_api, relevant_args, args, kwargs)

TypeError: _argmax_dispatcher() got an unexpected keyword argument 'x'

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replacing public_api.__signature__ doesn't effect the error message, but it looks like this is something that the decorator library would fix. So maybe that's worth doing after all...

def array2string(a, max_line_width=None, precision=None,
suppress_small=None, separator=' ', prefix="",
style=np._NoValue, formatter=None, threshold=None,
Expand Down Expand Up @@ -1370,6 +1381,12 @@ def dtype_short_repr(dtype):
return typename


def _array_repr_dispatcher(
arr, max_line_width=None, precision=None, suppress_small=None):
return (arr,)


@array_function_dispatch(_array_repr_dispatcher)
def array_repr(arr, max_line_width=None, precision=None, suppress_small=None):
"""
Return the string representation of an array.
Expand Down Expand Up @@ -1454,8 +1471,16 @@ def array_repr(arr, max_line_width=None, precision=None, suppress_small=None):

return arr_str + spacer + dtype_str


_guarded_str = _recursive_guard()(str)


def _array_str_dispatcher(
a, max_line_width=None, precision=None, suppress_small=None):
return (a,)


@array_function_dispatch(_array_str_dispatcher)
def array_str(a, max_line_width=None, precision=None, suppress_small=None):
"""
Return a string representation of the data in an array.
Expand Down
Loading
0