-
Notifications
You must be signed in to change notification settings - Fork 10
WIP: ENH/TST: xp_assert_
enhancements
#267
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
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.
Easier to review with "Hide whitespace". @lucascolley do you see what is going on with
FAILED tests/test_testing.py::test_assert_close_equal_shape[sparse-True-xp_assert_close]
FAILED tests/test_testing.py::test_assert_close_equal_dtype[sparse-True-xp_assert_close]
?
Also, it looks to me like the codecov failures are misleading. It doesn't look to me like the new code is actually missing coverage if tests are run with all backends.
@@ -9,13 +9,15 @@ | |||
from types import ModuleType | |||
from typing import cast | |||
|
|||
import numpy as np |
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.
Is this OK? Sometimes it was imported within test functions below.
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.
Today it is OK, as this module is not imported automatically from the outer scope.
In the long run though, we want to move this module to public at which point it won't be a good design anymore (although it remains to be seen if any Array library in real life can achieve not to have numpy as a hard dependency...)
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.
Yes, I think it would be fine to make these public API once they are ready, with the caveat that NumPy is required. We are really striving for minimal runtime dependencies rather than test time dependencies downstream, at least for now.
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.
This module heavily relies on np.testing.assert*
anyway.
We'll just need to add a test that import array_api_extra
doesn't import numpy.
msg = f"dtypes do not match: {actual.dtype} != {desired.dtype}" | ||
assert actual.dtype == desired.dtype, msg | ||
|
||
if is_numpy_namespace(actual_xp) and check_scalar: |
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.
if is_numpy_namespace(actual_xp) and check_scalar: | |
if is_numpy_namespace(actual_xp) and check_arrayness: |
?
I seem to remember some discussion about naming this parameter when adding to SciPy (check_0d
). I don't really care what it is called. check_type
is also on the table.
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.
scalar sounds fine to me.
Yeah, this is a constant problem. It eventually flips to passed once it registers the backends run. I think initial investigation didn't find a solution, but there is probably some sort of config/workaround to fix it. |
The failures are XPASSes: Judging by the message, we're expecting the test to fail due to |
That's what I figured, which is why I tried to set the xfail The trouble is that when xp = _check_ns_shape_dtype(actual, desired, check_dtype, check_shape, check_scalar)
floating = xp.isdtype(actual.dtype, ("real floating", "complex floating"))
# AttributeError: module 'sparse' has no attribute 'isdtype'. Did you mean: 'astype'? So whether the test will fail with sparse arrays due to the So what would you prefer:
If it were me, I would just do option 1. I have no qualms about using |
Multiple of those options seem fine with me (at least for now), but I'll ping @crusaderky as the original author first |
xp_assert_
enhancementsxp_assert_
enhancements
xp_assert_
enhancementsxp_assert_
enhancements
We recently released |
@hameerabbasi If so, it does not appear to be documented at https://sparse.pydata.org/en/stable/api/. Is that where I should be looking? Also - I'm not very familiar with the |
Whoops: It's in a non-standard experimental part of the codebase; not exposed to the user. My bad. |
https://labs.quansight.org/blog/sparse-array-ecosystem is probably a good start |
src/array_api_extra/_lib/_testing.py
Outdated
assert (np.isscalar(actual) and np.isscalar(desired)) or ( | ||
not np.isscalar(actual) and not np.isscalar(desired) | ||
), _msg |
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.
assert (np.isscalar(actual) and np.isscalar(desired)) or ( | |
not np.isscalar(actual) and not np.isscalar(desired) | |
), _msg | |
assert np.isscalar(actual) == np.isscalar(desired), _msg |
check_scalar : bool, default: False | ||
NumPy only: whether to check agreement between actual and desired types - | ||
0d array vs scalar. |
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 default for this is the opposite as in scipy
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 meant to mention that, so thanks for bringing it up. I think it should be True
, but that would make a lot of tests fail internally. I figured that could be fixed in a follow-up.
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.
array-api-extra tests? If so, yes, that sounds fine, but we should open an issue for that before merging this
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.
Yes. Sure, I'll open an issue.
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.
src/array_api_extra/_lib/_testing.py
Outdated
err_msg=err_msg, | ||
) | ||
# JAX/Dask arrays work directly with `np.testing` | ||
assert isinstance(rtol, float) |
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.
isinstance(0, float)
returns False
assert isinstance(rtol, float) | |
assert isinstance(rtol, int | float) |
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's fine, but that code was here - do we even need it?
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.
It wasn't here. Maybe in scipy? Agree that the assert is overkill.
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.
it was:
assert isinstance(rtol, float) |
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 stand corrected. 🙏
marks=pytest.mark.xfail_xp_backend( | ||
Backend.SPARSE, reason="no isdtype", strict=False | ||
), |
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.
#269 adds support for strict=False
, which was previously quietly ignored.
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.
now merged
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.
Used.
actual_shape = actual.shape | ||
desired_shape = desired.shape |
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.
This may fail if we start using it in scipy, because scipy overrides array_namespace to return numpy for scalars and lists. Maybe out of scope for this PR I though?
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.
Huh. Yeah let's do l consider that in a SciPy PR that attempts to use this there. Then we can decide whether/what changes are needed.
marks=pytest.mark.xfail_xp_backend( | ||
Backend.SPARSE, reason="no isdtype", strict=False | ||
), |
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.
#269 adds support for strict=False
, which was previously quietly ignored.
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 leaving the pyright failures so you can decide how you want to deal with them. I think all of them are false positives, as usual with static type checking.
check_scalar : bool, default: False | ||
NumPy only: whether to check agreement between actual and desired types - | ||
0d array vs scalar. |
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.
import numpy as np # pylint: disable=import-outside-toplevel | ||
|
||
# JAX/Dask arrays work directly with `np.testing` | ||
assert isinstance(rtol, float) |
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.
This was probably added to avoid the pyright error below? I don't think pyright should make us do this sort of thing.
marks=pytest.mark.xfail_xp_backend( | ||
Backend.SPARSE, reason="no isdtype", strict=False | ||
), |
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.
Used.
else nullcontext() | ||
) | ||
with context: | ||
func(xp.asarray([xp.nan, xp.nan]), xp.asarray(xp.nan), check_shape=check_shape) |
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.
NaNs pass NumPy's _close
, _equal
, and _less
checks, so using NaNs here (and below) allows us to parametrize over all three functions.
Toward #17. As discussed in mdhaber/marray#110 (comment).
This adds a few of the features from SciPy's
xp_assert_
functions to thexpx
xp_assert
functions. Tests will probably fail in this first commit; I'll comment inline.I decided not to add a
check_namespace
toggle: ifcheck_namespace
is False and the namespaces don't match, other operations might fail. I didn't want to work on fixing this if it's not an important feature. There is only one file in SciPy that usescheck_namespace=False
, and it probably shouldn't.Once this is looking good, I'll add
xp_assert_less
as a clone ofxp_assert_equal
.