Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

TYP: Typenp.ma.squeeze andnp.ma.{mask_rows, mask_cols, mask_rowcols}#28794

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Draft
MarcoGorelli wants to merge5 commits intonumpy:main
base:main
Choose a base branch
Loading
fromMarcoGorelli:ma-squeeze

Conversation

MarcoGorelli
Copy link
Member

No description provided.

Comment on lines +111 to +119
@overload
def mask_rows(a: _ArrayLike[_ScalarT_co]) -> MaskedArray[tuple[int, int], np.dtype[_ScalarT_co]]: ...
@overload
def mask_rows(a: ArrayLike) -> MaskedArray[tuple[int, int], np.dtype[Any]]: ...

@overload
def mask_cols(a: _ArrayLike[_ScalarT_co]) -> MaskedArray[tuple[int, int], np.dtype[_ScalarT_co]]: ...
@overload
def mask_cols(a: ArrayLike) -> MaskedArray[tuple[int, int], np.dtype[Any]]: ...
Copy link
MemberAuthor

Choose a reason for hiding this comment

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

technically these both accept aaxis argument, but it emits a deprecationwarning, so i've left it out of the stops so as to discourage its usage

Copy link
MemberAuthor

Choose a reason for hiding this comment

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

*stubs

Copy link
Member

Choose a reason for hiding this comment

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

Hmmstubtest won't like that. What I usually do in these situations, is add another@overloadwith theaxis kwarg that has no default, and mark it as@deprecated. See e.g.

# public numpy export
@overload# no style
defarray2string(
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"
defarray2string(
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"
defarray2string(
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")
defarray2string(
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")
defarray2string(
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
MemberAuthor

Choose a reason for hiding this comment

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

thanks - how do you runstubtest?

I've tried

 spin run python -m mypy.stubtest numpy

but it seems to hang indefinitely. couldn't find anything else about it in the numpy repo

Copy link
Member

@jorenhamjorenhamApr 26, 2025
edited
Loading

Choose a reason for hiding this comment

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

At the moment stubtest is only used bynumtype. If you'd try to run it on numpy's bundled stubs, you'd get thousands of (accurate) errors. But properly fixing those would result in many breaking changes. And that'sone of the reasons for building numtype, actually. The plan is to eventually also be able to use stubtest in numpy, once the other features that I'm developing there (like shape-typing) are functional and sufficiently stable.

And as you've probably noted by now, I've been tracking yournp.ma stubs changes, (numpy/numtype#456) with the intention of porting them over. So with that in mind, I'm trying to anticipate any stubtest errors. Because if those turn up when porting a numpy PR to numtype, then I'll eventually have to port those back from numtype to numpy again.

So to get the stubtest output, you could copy these changes to numtype (https://github.com/numpy/numtype/tree/main/src/numpy-stubs/ma), and thenuv run tool/stubtest.py (seehttps://numpy.org/numtype/dev/ for details). It's also an option to first submit yourma PR's there, and then port them over to numpy. It sounds pretty inefficient, but it ensures that thatstubtest, mypy, and pyright (configured in the strictest of modes), are also happy.
And just to be clear; submitting your pr's to numpy is no problem as far as I'm concerned. It's just that we're a bit more in the dark here, CI-wise.

MarcoGorelli reacted with thumbs up emoji
@jorenhamjorenham self-requested a reviewApril 22, 2025 13:31
@MarcoGorelliMarcoGorelli marked this pull request as ready for reviewApril 22, 2025 14:11
@jorenhamjorenham added the component: numpy.mamasked arrays labelApr 23, 2025
Comment on lines +111 to +119
@overload
def mask_rows(a: _ArrayLike[_ScalarT_co]) -> MaskedArray[tuple[int, int], np.dtype[_ScalarT_co]]: ...
@overload
def mask_rows(a: ArrayLike) -> MaskedArray[tuple[int, int], np.dtype[Any]]: ...

@overload
def mask_cols(a: _ArrayLike[_ScalarT_co]) -> MaskedArray[tuple[int, int], np.dtype[_ScalarT_co]]: ...
@overload
def mask_cols(a: ArrayLike) -> MaskedArray[tuple[int, int], np.dtype[Any]]: ...
Copy link
Member

Choose a reason for hiding this comment

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

Hmmstubtest won't like that. What I usually do in these situations, is add another@overloadwith theaxis kwarg that has no default, and mark it as@deprecated. See e.g.

# public numpy export
@overload# no style
defarray2string(
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"
defarray2string(
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"
defarray2string(
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")
defarray2string(
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")
defarray2string(
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: ...

Comment on lines +1209 to +1223
@overload
def squeeze(
a: _ScalarT,
axis: _ShapeLike | None = ...,
) -> _ScalarT: ...
@overload
def squeeze(
a: _ArrayLike[_ScalarT],
axis: _ShapeLike | None = ...,
) -> _MaskedArray[_ScalarT]: ...
@overload
def squeeze(
a: ArrayLike,
axis: _ShapeLike | None = ...,
) -> _MaskedArray[Any]: ...
Copy link
Member

Choose a reason for hiding this comment

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

So it turns out that stubtest doesn't accept these being actual functions, and instead requires them to be instances ofnumpy.ma.core._convert2ma. You can see this innumpy/numtype#468. It's currently a WIP, but there I (attempted to) explain how the_convert2ma can be made generic on it's__call__ signature, so that a callableProtocol can be used to specify the signature. It's a bit messy, but I'm afraid that it's the only way that stubtest well be able to swallow it.

Are you willing to attempt doing this here as well, or would you prefer that we address this at a later point?

@overload
def mask_rows(a: _ArrayLike[_ScalarT_co]) -> MaskedArray[tuple[int, int], np.dtype[_ScalarT_co]]: ...
@overload
def mask_rows(a: ArrayLike) -> MaskedArray[tuple[int, int], np.dtype[Any]]: ...
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
defmask_rows(a:ArrayLike)->MaskedArray[tuple[int,int],np.dtype[Any]]: ...
defmask_rows(a:ArrayLike)->MaskedArray[tuple[int,int],np.dtype]: ...

Comment on lines +11 to +15
from .core import (
MaskedArray,
dot,
_ScalarT_co,
)
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
from .coreimport (
MaskedArray,
dot,
_ScalarT_co,
)
from .coreimportMaskedArray,dot,_ScalarT_co

Comment on lines +8 to +9
from numpy.typing import ArrayLike
from numpy._typing import _ArrayLike
Copy link
Member

Choose a reason for hiding this comment

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

nitpick: usually we also importArrayLike from_typing internally

Suggested change
fromnumpy.typingimportArrayLike
fromnumpy._typingimport_ArrayLike
fromnumpy._typingimportArrayLike,_ArrayLike

@@ -29,6 +29,8 @@ MAR_V: MaskedNDArray[np.void]
MAR_subclass: MaskedNDArraySubclass

MAR_1d: np.ma.MaskedArray[tuple[int], np.dtype]
MAR_2d: np.ma.MaskedArray[tuple[int, int], np.dtype[Any]]
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
MAR_2d:np.ma.MaskedArray[tuple[int,int],np.dtype[Any]]
MAR_2d:np.ma.MaskedArray[tuple[int,int],np.dtype]

assert_type(np.ma.mask_rows(MAR_f4), np.ma.MaskedArray[tuple[int, int], np.dtype[np.float32]])
assert_type(np.ma.mask_rows([[1,2,3]]), np.ma.MaskedArray[tuple[int, int], np.dtype])
# PyRight detects this one correctly, but mypy doesn't.
assert_type(np.ma.mask_rows(MAR_2d), np.ma.MaskedArray[tuple[int, int], np.dtype]) # type: ignore[assert-type]
Copy link
Member

Choose a reason for hiding this comment

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

what does mypy infer it as?

assert_type(np.ma.mask_rows(MAR_2d_f4), np.ma.MaskedArray[tuple[int, int], np.dtype[np.float32]])
assert_type(np.ma.mask_rows(MAR_f4), np.ma.MaskedArray[tuple[int, int], np.dtype[np.float32]])
assert_type(np.ma.mask_rows([[1,2,3]]), np.ma.MaskedArray[tuple[int, int], np.dtype])
# PyRight detects this one correctly, but mypy doesn't.
Copy link
Member

Choose a reason for hiding this comment

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

Athttps://github.com/microsoft/pyright it's written as "Pyright" 🤷🏻

Suggested change
#PyRight detects this one correctly, but mypy doesn't.
#Pyright detects this one correctly, but mypy doesn't.

Copy link
Member

Choose a reason for hiding this comment

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

There are several-> MaskedArray[tuple[int, int], np.dtype[...]] annotations in this module now. A private type-alias could help make it more dry.

@jorenham
Copy link
Member

needs a rebase

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

@jorenhamjorenhamjorenham left review comments

Assignees
No one assigned
Projects
None yet
Milestone
No milestone
Development

Successfully merging this pull request may close these issues.

2 participants
@MarcoGorelli@jorenham

[8]ページ先頭

©2009-2025 Movatter.jp