-
-
Notifications
You must be signed in to change notification settings - Fork 10.9k
API: Rename numpy/core
to numpy/_core
[NEP 52]
#24634
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
Conversation
a55293f
to
59c8309
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @mtsokol! Wow, this turned out to be a large PR. A few initial comments. Let's see what is needed in downstream PRs to stop using numpy.core
completely. I believe we have to put numpy/core/__init__.py
back with a deprecation warning emitted when accessed, and a __getattr__
to forward imports to the relevant numpy._core
items. Otherwise this will probably be the most disruptive change in the release.
It's not actually obvious to me why this is failing, we don't import The failure is on import of a C-extension module, which does depend on the Numpy C API via: #include <numpy/ndarrayobject.h>
and
#include "numpy/arrayobject.h" None of our C source files refer to "core" directly, either. So quite possibly it is "just" a matter of recompiling... but that is itself a potential problem if this affects the ability to have binaries compatible with different numpy versions. (keeping existing binaries forward-compatible would be ideal, if possible) I do suspect that PyBind11 will have problems that need to be addressed (which may be prerequisites for even testing what, if anything, needs to be done for mpl specifically). A quick scan of the source there shows that they do refer to |
Pandas also appears to be affected (there are some tests which refer to |
I think that that should be possible for this PR, and that's probably the number one prio to sort out here. However, I do want to point out that the plan is for NumPy 2.0 to break ABI compatibility - so keeping existing binaries forward-compatible during this release cycle is highly unlikely to happen. See the guidance in gh-24300. |
Hmmm... well that raises some infrastructure/CI questions during the transition... if matplotlib (and pandas) is required for numpy docs, but matplotlib needs to be rebuilt due to ABI changes. Perhaps as backwards incompatible changes roll in, you need to install from source to avoid a chicken/egg problem. (Though if/when changes are needed to pybind11/cython, etc, we may not escape the problem entirely) Perhaps the way to do it for mpl is to pin to |
We won't be breaking things all the time - C API/ABI changes are being prepared behind a switch.
Yes, that sounds exactly right. I just checked the latest Matplotlib release (3.7.2), and it uses |
24b4b19
to
eab5a88
Compare
@ksunden I managed to solve the issue - it was due to the fact that matplotlib used in docs is compiled against numpy with |
This LGTM: >>> np.core.multiarray.concatenate
<ipython-input-4-423c639bb0c0>:1: DeprecationWarning: `numpy.core` has been made officially private and renamed to `numpy._core`. Accessing `_core` directly is discouraged, you should use a public module instead that exports the attribute in question. If you still would like to access an attribute from it, please use `np._core.multiarray`.
np.core.multiarray.concatenate
<function concatenate at 0x7f5ecca17630>
>>> np.core._multiarray_umath.arange
<ipython-input-5-10613df9b3ac>:1: DeprecationWarning: `numpy.core` has been made officially private and renamed to `numpy._core`. Accessing `_core` directly is discouraged, you should use a public module instead that exports the attribute in question. If you still would like to access an attribute from it, please use `np._core._multiarray_umath`.
np.core._multiarray_umath.arange
<built-in function arange> Everything I tried still works, with a deprecation message appearing. The thing I'm wondering about too is if the reverse is going to keep working. If the one problem here was: PyObject *numpy = PyImport_ImportModule("numpy.core._multiarray_umath"); and now we rebuild MPL against a new numpy version where that extension is in |
@rgommers I don't think there's anything that needs to be fixed. If a C file imports |
Not quite, I meant the reverse. If we build Matplotlib against NumPy 2.0, and hence the C code (after this PR) uses Another thought: it could be done through try-except logic in the C code: if |
Ah, now it's clear: Then it can be done either by trying to import |
Changing from where we import based on NumPy is not a problem. It would be good if the old place keeps working modulo a possible deprecation warning. That just makes our life easier right now where we are not actually forcing recompilation (but just hoping that the ABI changes are small enough that downstream is fine). |
cdebcf3
to
d4a334c
Compare
95b767d
to
031e551
Compare
4ee7e57
to
a7e8659
Compare
9bb283c
to
179f441
Compare
numpy/core/multiarray.py
Outdated
|
||
""" | ||
_raise_warning("*") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The warning I get from this is not great:
DeprecationWarning: `numpy.core` has been made officially private and renamed to `numpy._core`. Accessing `_core` directly is discouraged, as members of `_core` can change without any warning at any time. You should use a public module instead that exports the attribute in question. If you still would like to access an attribute from it, please use `np._core.*`.
Note that the suggestion is wrong (it should point to np.core.multiarray, not np.core). But also it's not giving me the name of the symbol causing this issue, which it could.
Can we replace this with a module-level getattr please? Also customize the warning for submodules of np.core
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Based on our discussions, file-level warnings have been removed, so file-wise imports, such as:
from numpy.core.multiarray import _reconstruct
raise no warning (allowing undisturbed loading of 1.x pickle files).
The warning is still present when accessing via np.core.*
. Therefore:
import numpy as np
np.core.multiarray
gives:
<ipython-input-1-725e8a67566f>:1: DeprecationWarning: `numpy.core` has been made officially private and renamed to `numpy._core`. Accessing `_core` directly is discouraged, as members of `_core` can change without any warning at any time. You should use a public module instead that exports the attribute in question. If you still would like to access an attribute from it, please use `np._core.multiarray`.
numpy/core/_multiarray_umath.py
Outdated
from numpy._core import _multiarray_umath | ||
from ._utils import _raise_warning | ||
|
||
_raise_warning("*") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed - explained in the previous comment.
179f441
to
897e7f6
Compare
I removed |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a few more comments to tweak some of the errors and to catch some stuff that might break existing fixes for really old pickle files.
numpy/core/arrayprint.py
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For this and all of the other submodules in np.core
(even the private ones!), can you add module-level __getattr__
implementations saying that accessing things via np.core
is deprecated. Along with a nice message explaining exactly what was accessed and what the migration is.
Just as an example, right now you can do this without ever seeing a warning:
In [1]: import numpy.core.multiarray
In [2]: numpy.core.multiarray.ndarray
Out[2]: numpy.ndarray
Whereas I would expect to see a deprecation warning like
numpy.core has been made officially private and renamed to numpy._core. Accessing _core directly is discouraged, as members of _core can change without any warning at any time. You should use a public module instead that exports the attribute in question. If you still would like to access this attribute without a warning despite the lack of backward compatibility guarantees, please use numpy._core.multiarray.ndarray.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure about this change - when I add a custom __getattr__
for numpy.core.multiarray
submodule that shows a warning, then:
from numpy.core.multiarray import _reconstruct
Also gives a warning, as _reconstruct
is accessed with getattr(numpy.core.multiarray, "_reconstruct")
internally.
This will cause pickles to also raise warnings that we want to avoid. I think the only way to have warnings is when user does np.core.*
which triggers core
's __getattr__
, so as it's implemented right now. Do I understand it correctly?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That sounds mostly right. When imported explicitly, a submodule import will (normally?) side-step the parents module __getattr__
. But that I suspect that is the only special path you can (ab)use here.
Once import of the submodule finished it has the same effect as __getattr__()
having being called: the submodule is added to the module __dict__()
and __getattr__()
will never be called again (even by attribute access as is the case above).
But... if you like, I suspect you can implement a warning __getattr__()
for all symbols that are imported from elsewhere. Note that multiarray._reconstruct
is special there because its __module__
is explicitly replaced to be np.core.multiarray
.
For some of those, they will not have a __module__
, but in that case the submodule presumably is listed earlier in sys.modules
so pickle will have used the submodule.
(I am not 100% sure this cannot ever be broken, but I will bet it is OK in practice.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do I understand it correctly?
Hmm, I thought I had a version where a module-level __getattr__
would work a few days ago while I was messing around with his, but now I can't get that to work. I'm going to try a little more to see where I'm not understanding things.
218b64f
to
7ad9288
Compare
OK I think this is really ready and I'd like to merge it tomorrow. @mtsokol I think you mentioned you'd like to do some history rewriting before I merge? I think keeping the mechanical |
MAINT: Update git submodules, fix test_format
Match x86-simd-sort with the main branch Add remaining shims and a test Adjust docstrings and imports for isalpha Match svml version with the main branch Apply review changes Rework np.core stubs to generate warnings more often Co-authored-by: Nathan Goldbaum <[email protected]>
7ad9288
to
7d4f488
Compare
@ngoldbaum Sure! I squashed it into five commits:
|
Thanks for pushing this through @mtsokol! If you're reading this because you are seeing new warnings about deprecations and are unsure what to do, read on. The The most common usage of If it turns out that you are importing something from If you feel that you are using something that should be public but is not, please open an issue describing your need. |
Hi @rgommers,
This PR introduces a breaking change of renaming
numpy/core
module tonumpy/_core
. The first commit renames the module, where following ones adjust the codebase to this change.Some stages will fail for now (e.g. building docs, as matplotlib needs to have some changes introduced), but I checked all 2500 occurrences of
core
in the code 😄 and this PR should cover all of the relevant ones.