DEP: Deprecate `.T` property for non-2dim arrays and scalars by mtsokol · Pull Request #28678 · numpy/numpy · GitHub
Skip to content

DEP: Deprecate .T property for non-2dim arrays and scalars#28678

Merged
charris merged 4 commits into
numpy:mainfrom
mtsokol:T-non-2dim-depr
May 16, 2025
Merged

DEP: Deprecate .T property for non-2dim arrays and scalars#28678
charris merged 4 commits into
numpy:mainfrom
mtsokol:T-non-2dim-depr

Conversation

@mtsokol

@mtsokol mtsokol commented Apr 10, 2025

Copy link
Copy Markdown
Member

As the title says, this PR deprecates .T property for non-2dim arrays and scalars, in order to be compatible with the Array API: link.

@mtsokol mtsokol added 03 - Maintenance 40 - array API standard PRs and issues related to support for the array API standard labels Apr 10, 2025
@mtsokol mtsokol added this to the 2.2.5 release milestone Apr 10, 2025
@mtsokol mtsokol self-assigned this Apr 10, 2025
@charris charris modified the milestones: 2.2.5 release, 2.3.0 release Apr 10, 2025
@mtsokol mtsokol force-pushed the T-non-2dim-depr branch 2 times, most recently from 621e40a to 0163784 Compare April 10, 2025 13:15
@mattip

mattip commented Apr 10, 2025

Copy link
Copy Markdown
Member

@mtsokol

mtsokol commented Apr 10, 2025

Copy link
Copy Markdown
Member Author

I agree with @charris’s relabeling: this should not target a point release rather 2.3

That's right - done!

@mtsokol

mtsokol commented Apr 10, 2025

Copy link
Copy Markdown
Member Author

To get docs build green we need matplotlib/matplotlib#29896 in first (and matplotlib bugfix release)

@ngoldbaum ngoldbaum left a comment

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.

Given the number of places the tests needed to be updated, I bet this will be a noisy deprecation. Maybe worth pinging the mailing list?

Comment thread numpy/_core/src/multiarray/getset.c Outdated
Comment thread doc/release/upcoming_changes/28678.deprecation.rst Outdated
Comment thread numpy/_core/src/multiarray/getset.c Outdated
"In the future `.T` property will be supported for "
"2-dim arrays only. Received %d-dim array. Either "
"`np.permute_dims(arr, range(arr.ndim)[::-1])` "
"(compatible with the Array API) or `arr.transpose()` "

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.

I would delete the note and at least re-order this. It nudges users to something less convenient for what seems very little reason to me.
A user who needs array API is a library author and will already not use .T here anyway.

It may be good to note that .mT exists to swap the last two axes only (If just to increase awareness).

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

And what if someone uses .T to reverse axes for ndim>2 cases anyway? I can remove Array API suggestion but how about keeping arr.transpose() for people who want to retain existing behavior.

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.

I think that's what Sebastian is saying - to leave arr.transpose() or at least mention it first and mention .mT as well.

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.

I feel it currently makes it seem that arr.transpose() is somehow a not the preferred solution, but for those users who run into it it will almost certainly be the preferred one.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Thanks for an explanation! I updated the message as you suggested.

Comment thread numpy/_core/tests/test_deprecations.py Outdated

def test_deprecated_T_non_2dim():
# Deprecated in Numpy 2.3, 2025-04
with pytest.warns(UserWarning, match="In the future `.T` property for "

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.

Please use assert_deprecated as all other tests in this file. That ensures that the error path is also tested, even if that is rather trivial here.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I didn't use assert_deprecated because it's missing match= parameter to actually match the warning message, but I can use it instead.

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.

because it's missing match= parameter to actually match the warning message

Seems reasonable to add it, assuming that's easy.

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.

IIRC it does, but takes the message from the class, but not sure. And yeah, I don't actually care about using it but I do care abot a habit of testing the error path.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

because it's missing match= parameter to actually match the warning message

Seems reasonable to add it, assuming that's easy.

I like this idea - added msg_patterns argument to assert_deprecated.

Comment thread numpy/_core/src/multiarray/getset.c
Comment thread numpy/_core/src/multiarray/getset.c Outdated
Comment thread numpy/_core/src/multiarray/getset.c Outdated
{
int ndim = PyArray_NDIM(self);
if (ndim != 2) {
if (PyErr_WarnFormat(PyExc_UserWarning, 1,

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.

Why a UserWarning? Please use a DeprecationWarning, or actually, use the DEPRECATE macro.

We could use a visible deprecation warning if we want to inform new users who accidentally get it wrong. But only if we take the trouble to check that very few libraries use this (i.e. there are few places in existing code where DeprecationWarning would be hidden, but VisibleDeprecationWarning wouldn't be).

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.

Given the number of places the tests needed to be updated, I bet this will be a noisy deprecation.

So, it must clearly be a DeprecationWarning. This should be taken very slowly, i.e. in a year or so a VisibleDeprecationWarning.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Done - for array scalars in scalartypes.c.src I used DEPRECATE macro, but here I kept PyErr_WarnFormat, now with a DeprecationWarning, because it allows formatting contrary to DEPRECATE.

Comment thread doc/release/upcoming_changes/28678.deprecation.rst Outdated
@mtsokol mtsokol force-pushed the T-non-2dim-depr branch from 85cae50 to 4b970ff Compare May 10, 2025 09:00
@mtsokol

mtsokol commented May 10, 2025

Copy link
Copy Markdown
Member Author

@seberg Yesterday new matplotlib version got released. Docs build is passing so this PR can go in as well now.

@ngoldbaum ngoldbaum left a comment

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.

I didn't look carefully at the code but the release notes and deprecation warnings look good to me (after applying some minor grammar fixes).

Comment thread doc/release/upcoming_changes/28678.deprecation.rst Outdated
Comment thread numpy/_core/src/multiarray/getset.c Outdated
Comment thread numpy/_core/src/multiarray/scalartypes.c.src Outdated

@seberg seberg left a comment

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.

Code looks fine, although I don't like the test code addition. It seems unnecessary and thus also unnecessarily complex.
Why not just make two classes and use the already existing mechanism or just use the fact that it is an re matching already probably (we don't need to test that it's the scalar message says scalar)?

Comment thread numpy/_core/tests/test_deprecations.py Outdated
if re.match(pattern, msg) is None:
raise AssertionError(
"expected %s warning message pattern but got: %s" %
(pattern, msg))

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.

This doesn't look nice to me. We already have message = on the class, and that works just fine, it is used as message=self.message below.

It's fair that passing a pattern is maybe nicer (especially with pytest.warns existing now). But we should avoid unnecessary duplication.
(And since we don't need the tuple of patterns)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I gave it another try and indeed msg_patterns wasn't needed after all - I removed it.
Instead I created two separate classes with different message regexes.

Comment thread numpy/_core/tests/test_deprecations.py Outdated
for warning in self.log:
if msg_patterns is not None:
pattern = (msg_patterns if isinstance(msg_patterns, str) else
msg_patterns[num_found])

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.

Also, you don't use this and the num_found was a work-around for identical ones mostly, IIRC?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Right, I got rid of the custom msg_patterns logic after all.

@mtsokol mtsokol force-pushed the T-non-2dim-depr branch from 4b970ff to e411971 Compare May 13, 2025 16:12
@mtsokol mtsokol requested a review from seberg May 13, 2025 16:17
@seberg seberg changed the title MAINT: Deprecate .T property for non-2dim arrays and scalars DEP: Deprecate .T property for non-2dim arrays and scalars May 15, 2025
@charris

charris commented May 16, 2025

Copy link
Copy Markdown
Member

Needs rebase.

@mtsokol mtsokol force-pushed the T-non-2dim-depr branch from e411971 to 13b5692 Compare May 16, 2025 19:49
@mtsokol

mtsokol commented May 16, 2025

Copy link
Copy Markdown
Member Author

Needs rebase.

Done!

@charris charris merged commit d8ba2e7 into numpy:main May 16, 2025
74 checks passed
@charris

charris commented May 16, 2025

Copy link
Copy Markdown
Member

Thanks @mtsokol .

@mtsokol mtsokol deleted the T-non-2dim-depr branch May 16, 2025 20:45
@rgommers

Copy link
Copy Markdown
Member

This broke SciPy CI badly, on the last day before creating the release branch. Hence I'll revert this straight away - let's find a better time to reintroduce this, and ideally after assessing/mitigating downstream damage.

@rgommers

Copy link
Copy Markdown
Member

Reverted in gh-28990. If the 2.3.x branch is close, this should probably wait. We can't merge something like this without doing what we did for 2.0 I think - first testing with SciPy, scikit-learn, Pandas, Matplotlib at least, and addressing the issues there. That will also show whether the impact is actually fine or not.

@mtsokol

mtsokol commented May 16, 2025

Copy link
Copy Markdown
Member Author

I only adjusted matplotlib out of these four. Let's then move this change to 2.4.0 and in the meantime I'll make sure the rest of them are also ready.

@mtsokol mtsokol removed this from the 2.3.0 release milestone May 16, 2025
@rgommers

Copy link
Copy Markdown
Member

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

Labels

03 - Maintenance 40 - array API standard PRs and issues related to support for the array API standard

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants