-
-
Notifications
You must be signed in to change notification settings - Fork 10.8k
TYP: Type np.ma.squeeze
and np.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 our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
@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]]: ... |
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.
technically these both accept a axis
argument, but it emits a deprecationwarning, so i've left it out of the stops so as to discourage its usage
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.
*stubs
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.
Hmm stubtest
won't like that. What I usually do in these situations, is add another @overload
with the axis
kwarg that has no default, and mark it as @deprecated
. See e.g.
numpy/numpy/_core/arrayprint.pyi
Lines 88 to 180 in 1bc8764
# 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: ... |
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 - how do you run stubtest
?
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
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.
At the moment stubtest is only used by numtype. 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's one 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 your np.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 then uv run tool/stubtest.py
(see https://numpy.org/numtype/dev/ for details). It's also an option to first submit your ma
PR's there, and then port them over to numpy. It sounds pretty inefficient, but it ensures that that stubtest
, 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.
@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]]: ... |
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.
Hmm stubtest
won't like that. What I usually do in these situations, is add another @overload
with the axis
kwarg that has no default, and mark it as @deprecated
. See e.g.
numpy/numpy/_core/arrayprint.pyi
Lines 88 to 180 in 1bc8764
# 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: ... |
@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]: ... |
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.
So it turns out that stubtest doesn't accept these being actual functions, and instead requires them to be instances of numpy.ma.core._convert2ma
. You can see this in numpy/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 callable Protocol
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]]: ... |
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.
def mask_rows(a: ArrayLike) -> MaskedArray[tuple[int, int], np.dtype[Any]]: ... | |
def mask_rows(a: ArrayLike) -> MaskedArray[tuple[int, int], np.dtype]: ... |
from .core import ( | ||
MaskedArray, | ||
dot, | ||
_ScalarT_co, | ||
) |
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.
from .core import ( | |
MaskedArray, | |
dot, | |
_ScalarT_co, | |
) | |
from .core import MaskedArray, dot, _ScalarT_co |
from numpy.typing import ArrayLike | ||
from numpy._typing import _ArrayLike |
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.
nitpick: usually we also import ArrayLike
from _typing
internally
from numpy.typing import ArrayLike | |
from numpy._typing import _ArrayLike | |
from numpy._typing import ArrayLike, _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]] |
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.
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] |
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.
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. |
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.
At https://github.com/microsoft/pyright it's written as "Pyright" 🤷🏻
# PyRight detects this one correctly, but mypy doesn't. | |
# Pyright detects this one correctly, but mypy doesn't. |
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.
There are several -> MaskedArray[tuple[int, int], np.dtype[...]]
annotations in this module now. A private type-alias could help make it more dry.
needs a rebase |
No description provided.