Skip to content

Conversation

@hellerve
Copy link
Contributor

@hellerve hellerve commented Oct 30, 2025

This PR fixes #30096 (especially its follow-up comments) by deprecating numpy.fix.

Cheers

@ngoldbaum ngoldbaum changed the title Deprecate numpy.fix DEP: Deprecate numpy.fix Oct 30, 2025
Copy link
Member

@ngoldbaum ngoldbaum left a comment

Choose a reason for hiding this comment

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

Thanks! Probably best to wait for someone else to weigh in before implementing my suggestion. Otherwise this all looks great.

@ngoldbaum ngoldbaum added this to the 2.4.0 release milestone Oct 30, 2025
@hellerve
Copy link
Contributor Author

It seems that my last error is due to this section: https://github.com/numpy/numpy/pull/30098/files#diff-6cdc3b490da76e0f287028f0c0fa780b24100106713a4216594f8d33d162fec6R36-R47

which is test data, but not picked up as tests, and a check complains about warnings.filterwarnings being used outside of tests (full message: AssertionError: ignore filters should only be used in tests; found in C:\hostedtoolcache\windows\Python\3.12.10\x64\Lib\site-packages\numpy\typing\tests\data\pass\ufunclike.py on line 37). Not sure how to resolve that best.

Copy link
Member

@seberg seberg left a comment

Choose a reason for hiding this comment

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

Nice, thanks. LGTM, two nits to change docs and maybe add to test_deprecations.py which would be nice (just to discover it, since this isn't C, I don't care too much about it).

"ignore",
message="The function numpy.fix is deprecated in favor of numpy.trunc",
category=DeprecationWarning,
)
Copy link
Member

Choose a reason for hiding this comment

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

@jorenham is there a proper way to call things that trigger deprecation warnings in the typing test data? this seems to run afoul of the test that checks the codebase for warning filters.

We could also patch that test to skip the typing test data. Maybe it doesn't matter if the typing tests trigger deprecation warnings? I don't actually know.

Copy link
Member

Choose a reason for hiding this comment

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

Completely fine to change ignore it in those tests in principle, I think. The only reason for the filter in other tests was that it is nicer to have another solution (e.g. pytest.warns or @pytest.filterwarnings).

(The test comes from a different time and age and the original purpose is moot, now we just have nicer spellings :))

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I am unsure what this means. Do I get rid of these calls completely or should I look at how to change the test script? I can do the latter, but that seems like a separate PR to me, right?

Copy link
Member

Choose a reason for hiding this comment

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

@jorenham is there a proper way to call things that trigger deprecation warnings in the typing test data? this seems to run afoul of the test that checks the codebase for warning filters.

We could also patch that test to skip the typing test data. Maybe it doesn't matter if the typing tests trigger deprecation warnings? I don't actually know.

Yea there is the typing_extensions.deprecated decorator that can be used in the stubs. It can be applied to classes, functions, or individual overloads. See for example

# public numpy export
@overload # no style
def array2string(
a: NDArray[Any],
max_line_width: int | None = None,
precision: SupportsIndex | None = None,
suppress_small: bool | None = None,
separator: str = " ",
prefix: str = "",
style: _NoValueType = ...,
formatter: _FormatDict | None = None,
threshold: int | None = None,
edgeitems: int | None = None,
sign: _Sign | None = None,
floatmode: _FloatMode | None = None,
suffix: str = "",
*,
legacy: _Legacy | None = None,
) -> str: ...
@overload # style=<given> (positional), legacy="1.13"
def array2string(
a: NDArray[Any],
max_line_width: int | None,
precision: SupportsIndex | None,
suppress_small: bool | None,
separator: str,
prefix: str,
style: _ReprFunc,
formatter: _FormatDict | None = None,
threshold: int | None = None,
edgeitems: int | None = None,
sign: _Sign | None = None,
floatmode: _FloatMode | None = None,
suffix: str = "",
*,
legacy: Literal["1.13"],
) -> str: ...
@overload # style=<given> (keyword), legacy="1.13"
def array2string(
a: NDArray[Any],
max_line_width: int | None = None,
precision: SupportsIndex | None = None,
suppress_small: bool | None = None,
separator: str = " ",
prefix: str = "",
*,
style: _ReprFunc,
formatter: _FormatDict | None = None,
threshold: int | None = None,
edgeitems: int | None = None,
sign: _Sign | None = None,
floatmode: _FloatMode | None = None,
suffix: str = "",
legacy: Literal["1.13"],
) -> str: ...
@overload # style=<given> (positional), legacy!="1.13"
@deprecated("'style' argument is deprecated and no longer functional except in 1.13 'legacy' mode")
def array2string(
a: NDArray[Any],
max_line_width: int | None,
precision: SupportsIndex | None,
suppress_small: bool | None,
separator: str,
prefix: str,
style: _ReprFunc,
formatter: _FormatDict | None = None,
threshold: int | None = None,
edgeitems: int | None = None,
sign: _Sign | None = None,
floatmode: _FloatMode | None = None,
suffix: str = "",
*,
legacy: _LegacyNoStyle | None = None,
) -> str: ...
@overload # style=<given> (keyword), legacy="1.13"
@deprecated("'style' argument is deprecated and no longer functional except in 1.13 'legacy' mode")
def array2string(
a: NDArray[Any],
max_line_width: int | None = None,
precision: SupportsIndex | None = None,
suppress_small: bool | None = None,
separator: str = " ",
prefix: str = "",
*,
style: _ReprFunc,
formatter: _FormatDict | None = None,
threshold: int | None = None,
edgeitems: int | None = None,
sign: _Sign | None = None,
floatmode: _FloatMode | None = None,
suffix: str = "",
legacy: _LegacyNoStyle | None = None,
) -> str: ...

Copy link
Member

Choose a reason for hiding this comment

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

Ah, I see, that's what's missing. This PR also needs to update the type stubs for np.fix:

@overload
def fix( # type: ignore[misc]
x: _FloatLike_co,
out: None = None,
) -> floating: ...
@overload
def fix(
x: _ArrayLikeFloat_co,
out: None = None,
) -> NDArray[floating]: ...
@overload
def fix(
x: _ArrayLikeObject_co,
out: None = None,
) -> NDArray[object_]: ...
@overload
def fix(
x: _ArrayLikeFloat_co | _ArrayLikeObject_co,
out: _ArrayT,
) -> _ArrayT: ...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If I use that decorator locally (after importing of course 🤦 ), I still seem to be getting the errors on the deprecation message. So I suppose the question remains whether the checks should be dropped from numpy/typing/tests/data/pass/ufunclike.py and numpy/typing/tests/data/reveal/ufunclike.pyi?

@hellerve
Copy link
Contributor Author

So, it seems like the easiest way to deal with this deprecation is to

  1. remove the examples from the doc string (those get checked and currently fail), and
  2. remove the typing tests.

Both of these mean losing fidelity, but I’m not well-versed enough in the codebase to propose alternatives, unfortunately.

@jorenham
Copy link
Member

2. remove the typing tests.

You could also smack a # type: ignore[deprecated] onto them, AFAIK.

@github-actions

This comment has been minimized.

@hellerve
Copy link
Contributor Author

You could also smack a # type: ignore[deprecated] onto them, AFAIK.

I might be misunderstanding, but doesn’t that then defeat the prupose of the tests?

@jorenham
Copy link
Member

You could also smack a # type: ignore[deprecated] onto them, AFAIK.

I might be misunderstanding, but doesn’t that then defeat the prupose of the tests?

it would only suppress the deprecated errors; so any other mypy errors would still be reported

Copy link
Member

@rgommers rgommers left a comment

Choose a reason for hiding this comment

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

This deprecation looks justified (despite us not removing this for 2.0 because of concerns of widespread usage), but a blocking comment for merge with a few comments:

  • This should be proposed on the NumPy mailing list before it can proceed, like all deprecations.
  • This should not be merged this late in a release cycle, so please make it 2.5.0 not 2.4.0
  • This cannot be merged before downstream users of our nightlies have been updated. E.g., I see usages in scikit-image and in PyWavelets. PRs to replace those usages would be nice to help this move along.

@ngoldbaum ngoldbaum removed this from the 2.4.0 release milestone Nov 3, 2025
@hellerve
Copy link
Contributor Author

hellerve commented Nov 3, 2025

You could also smack a # type: ignore[deprecated] onto them, AFAIK.

I might be misunderstanding, but doesn’t that then defeat the prupose of the tests?

it would only suppress the deprecated errors; so any other mypy errors would still be reported

Looks like that has the same issue, since now the assertion error is: AssertionError: ignore filters should only be used in tests; found in /numpy/venv/lib/python3.11/site-packages/numpy/typing/tests/data/pass/ufunclike.py on line 37. So neither using warning filters nor ignore filters seems to work here.

@ngoldbaum
Copy link
Member

This should not be merged this late in a release cycle, so please make it 2.5.0 not 2.4.0

Fair enough - I cleared the 2.4.0 milestone.

@hellerve - if you're interested, it might be a fun exercise to contribute to a bunch of other popular projects as well if you could take a shot at doing the migration in a few popular packages. In addition to PyWavelets and scikit-image, which both looks like they use fix in a way that can be straightforwardly replaced by trunc, It looks like pandas has two uses that can be replaced by trunc and explicitly tests support for fix in one spot. That test will likely need to handle the new deprecation warning.

It also looks like astropy has a few uses, but only to test or support wrapping of NumPy. That code might also need to handle the deprecation warning. Probably worth raising an issue over in astropy.

It looks like jax implements np.fix - maybe they care about this change. Pythran also has some tests that will need updating.

SciPy and matplotlib don't use it, as far as I can see.

@ngoldbaum
Copy link
Member

Looks like that has the same issue, since now the assertion error is: AssertionError: ignore filters should only be used in tests; found in /numpy/venv/lib/python3.11/site-packages/numpy/typing/tests/data/pass/ufunclike.py on line 37. So neither using warning filters nor ignore filters seems to work here.

IMO it's fine to add an exception to the test that checks for warning filters to ignore code in the typing/tests/data directory. You'd have to add a new if block here:

if base / "testing" in path.parents:
continue
if path == base / "__init__.py":
continue
if path == base / "random" / "__init__.py":
continue
if path == base / "conftest.py":
continue

@hellerve
Copy link
Contributor Author

hellerve commented Nov 3, 2025

This should not be merged this late in a release cycle, so please make it 2.5.0 not 2.4.0

Fair enough - I cleared the 2.4.0 milestone.

@hellerve - if you're interested, it might be a fun exercise to contribute to a bunch of other popular projects as well if you could take a shot at doing the migration in a few popular packages. In addition to PyWavelets and scikit-image, which both looks like they use fix in a way that can be straightforwardly replaced by trunc, It looks like pandas has two uses that can be replaced by trunc and explicitly tests support for fix in one spot. That test will likely need to handle the new deprecation warning.

It also looks like astropy has a few uses, but only to test or support wrapping of NumPy. That code might also need to handle the deprecation warning. Probably worth raising an issue over in astropy.

It looks like jax implements np.fix - maybe they care about this change. Pythran also has some tests that will need updating.

SciPy and matplotlib don't use it, as far as I can see.

I feel totally up to it (more than for the mailing list proposal, anyway 😅). I’ll take a look and start contributing PRs. Is there a script you use to check for usages or just go through a set of known repositories and check?

@hellerve
Copy link
Contributor Author

hellerve commented Nov 3, 2025

Looks like that has the same issue, since now the assertion error is: AssertionError: ignore filters should only be used in tests; found in /numpy/venv/lib/python3.11/site-packages/numpy/typing/tests/data/pass/ufunclike.py on line 37. So neither using warning filters nor ignore filters seems to work here.

IMO it's fine to add an exception to the test that checks for warning filters to ignore code in the typing/tests/data directory. You'd have to add a new if block here:

if base / "testing" in path.parents:
continue
if path == base / "__init__.py":
continue
if path == base / "random" / "__init__.py":
continue
if path == base / "conftest.py":
continue

As part of this PR or a different one (since it’s more or less unconcerned with this particular deprecation)?

@rgommers
Copy link
Member

rgommers commented Nov 3, 2025

Is there a script you use to check for usages or just go through a set of known repositories and check?

I just search known downstream projects first to get a sense, and then I may check what https://github.com/search?type=code says.

@ngoldbaum
Copy link
Member

As part of this PR or a different one (since it’s more or less unconcerned with this particular deprecation)?

Doing it in this one is fine. I doubt it will come up again before this is merged.

@ngoldbaum
Copy link
Member

I just pinged the mailing list: https://mail.python.org/archives/list/[email protected]/thread/LYRHETXPN32S7FNHKNLJFDIYWGQHLODJ/

@hellerve
Copy link
Contributor Author

hellerve commented Nov 3, 2025

Alright, looks like we got the tests green, and I also adjusted the code comments to make the target 2.5.0. I will go through the important downstream projects I can find in the coming days and submit PRs.

@hellerve
Copy link
Contributor Author

hellerve commented Nov 9, 2025

I did an (admittedly small) amount of digging for references. I unfortunately don’t have good insight into what repositories are considered "important", and Github search limits me to 5 largely unordered pages of results.

I did submit 4 PRs just now, among others to pywt and scikit-image. I also checked a few others but couldn’t find much. (No guarantees, though)

@ngoldbaum
Copy link
Member

It looks like there are also a couple other uses in pandas that can be straightforwardly updated, if you want another easy contribution:

pandas/_libs/tslibs/timestamps.pyx
3495:                np.fix((153 * month - 457) / 5) +

pandas/core/arrays/datetimes.py
2290:            + np.fix((153 * month - 457) / 5)

There's another use in the tests that's testing explicitly for support of np.fix and probably shouldn't be updated.

@hellerve
Copy link
Contributor Author

It looks like there are also a couple other uses in pandas that can be straightforwardly updated, if you want another easy contribution [...]

Contributed a PR there too.

@seberg
Copy link
Member

seberg commented Nov 11, 2025

Thanks @hellerve, it's cool to see that you updated things there!

There was a small unintended regression in np.fix but I guess we'll wait for one release to actually add the deprecation.
Because of that, I think we should split out the change to np.trunc into a separate PR to be merged quickly. I can just do that, but if you are interested in that, that would also be great!

@hellerve
Copy link
Contributor Author

I’ll solve the merge conflicts once #30168 has also been merged (I’m assuming it will be merged before this PR is even considered).

@charris
Copy link
Member

charris commented Nov 17, 2025

Needs rebase. #30168 is in.

@jorenham jorenham added this to the 2.5.0 Release milestone Nov 17, 2025
@hellerve hellerve force-pushed the 30096-deprecate-np-fix branch from d9398a1 to 44b7c57 Compare November 17, 2025 21:11
@hellerve
Copy link
Contributor Author

@charris Thanks for the heads-up! Done!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

DEP: Deprecate np.fix

6 participants