Skip to content

BUG: Do not forward descending unless explicitly passed - #31458

Merged
seberg merged 3 commits into
numpy:mainfrom
pllim:dark-descent
May 19, 2026
Merged

seberg merged 3 commits into
numpy:mainfrom
pllim:dark-descent

Conversation

@pllim

@pllim pllim commented May 18, 2026 •

Copy link
Copy Markdown
Contributor

PR summary

My interpretation of #31345 (comment) from @seberg

First time committer introduction

👋 from Astropy to fix downstream failure (astropy/astropy#19760)

AI Disclosure

I hate AI and also too cheap to pay for one.

@jorenham jorenham changed the title Do no pass descending if False BUG: Do not pass descending if False May 18, 2026
Comment thread numpy/_core/fromnumeric.py Outdated
extra_kw = {"descending": descending}
else:
extra_kw = {}
a.sort(axis=axis, kind=kind, order=order, stable=stable, **extra_kw)

@seberg seberg May 18, 2026 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Awesome, thanks @pllim. I would be tempted to just duplicating the return a.sort(...) (to avoid creating a dict just to unpack it immediately).
A test would be great, but I am also fine if not. (Needs a small dummy object -- I guess in test_multiarray although that file is annoying large.)

(We sometimes use np._NoValue, but I think in this case it should be fine to just not pass on if the user passes descending=False explicitly.)

Both are somewhat nits though, I admit :).

We probably should do the same change to argsort(). (It uses wrapfunc, but that is just because it doesn't work in-place mainly, I guess. We can do just the same and duplicate.)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Thanks for the detailed feedback! I implemented the functional code changes, hopefully as you requested.

However, I noticed there are already a bunch of test_sort_descending tests in numpy/_core/tests/test_multiarray.py. I am not sure how to write another test that would trigger this error without introducing that class from astropy. 😬

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thank you for fixing this @pllim! About the test, I think you could create a small dummy class (does not need to have any real functionality or mirror astropy) that implements argsort with the right (kw)args, then write a test that instantiates an object and checks there is no error when calling np.argsort(a, descending=False).

but also do not unpack kwargs so just duplicate the call.
@jorisvandenbossche

Copy link
Copy Markdown
Contributor

For the argsort case (just dispatching to the object, and not going through __array_func__), you could add a test with a small dummy class with just an argsort method with the old signature. I don't know how useful that would be, though (or how long numpy would like to keep the back compat for adding the descending keyword)

@seberg

seberg commented May 19, 2026

Copy link
Copy Markdown
Member

I pushed a test, but someone should have a quick look (verified that it failed for both sort and argsort before).
Was worth it already for noticing the dark-descent branch name ;).

Comment thread numpy/_core/fromnumeric.py Outdated
a = asanyarray(a).copy(order="K")
a.sort(axis=axis, kind=kind, order=order, stable=stable, descending=descending)
# Sanitize for backward-compatibility
if descending:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

In other code, we would set the argument to np._NoValue and pass on the argument if it is not that (see, e.g., argmax in the same file). I think that is better, because then if someone explicitly passes in descending=False, they get the correct error that the argument does not exist.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Hmmmm, yeah, let's go with this. I somewhat thought that here the default may be unambiguous enough, but really... it is also for keepdims= probably and safer.

@pllim

pllim commented May 19, 2026

Copy link
Copy Markdown
Contributor Author

Thank you for adding the test here, @seberg ! Given I am unfamiliar with your testing setup, it is more elegant than what I could have come up with. Is there anything else you need from me? If not, I'll let you do your thing. And thanks for appreciating the branch name.

This is just a bit more precise to not pass things on when explicitly
passed as `descending=False`.
@seberg

seberg commented May 19, 2026

Copy link
Copy Markdown
Member

OK, changed to np._NoValue.

@mhvk mhvk left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks good, thanks both!!

@pllim

pllim commented May 19, 2026

Copy link
Copy Markdown
Contributor Author

Hmm CI is failing. Is that related?

@seberg seberg changed the title BUG: Do not pass descending if False BUG: Do not forward descending unless explicitly passed May 19, 2026
@seberg
seberg merged commit 723f2fb into numpy:main May 19, 2026
107 of 113 checks passed
@pllim
pllim deleted the dark-descent branch May 19, 2026 19:01
@pllim

pllim commented May 19, 2026

Copy link
Copy Markdown
Contributor Author

Thank you for cleaning up my PR and bringing it over the finish line! I appreciate the timely response.

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 this pull request may close these issues.

6 participants