Fix numpy-isms in strict-backend test bodies (test hygiene) - #990
Merged
Conversation
Many array-api-strict test failures were caused by numpy-only idioms in the test bodies themselves rather than bugs in ccdproc source: .copy() method calls on backend arrays, raw np.zeros_like mixed with backend arrays, xp.allclose (not in the array-API standard), numpy-only .mean()/.sum()/.std()/.all() method calls, int/float mixed arithmetic that strict's dtype promotion rejects, and single-axis indexing on arrays with ndim > 1 (which needs an explicit ellipsis under the standard). This is a test-only hygiene change; no CHANGES.rst entry. Fixes astropy#969 Fixes astropy#970 Part of astropy#971 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RQMJZUaaxfqGDk41GLSaFK
54 tasks
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #990 +/- ##
=======================================
Coverage 97.42% 97.42%
=======================================
Files 9 9
Lines 1749 1749
=======================================
Hits 1704 1704
Misses 45 45
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
mwcraig
commented
Aug 24, 2026
Review feedback on astropy#990: the explicit dtype at every literal reference array was noise. Float literals give the same float64 arrays, so the strict backend still sees floating input to xp.std and no int64/float64 promotion in the comparisons. The one dtype= left in the PR is the crpix line in test_ccdproc.py, whose input is ccd_data.shape. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RQMJZUaaxfqGDk41GLSaFK
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Test-only hygiene batch for the array-API migration (#971). Many
array-api-stricttest failures were caused by numpy-only idioms in thetest bodies, not by bugs in ccdproc source. This PR fixes only files
under
ccdproc/tests/.Strict suite: 85 failed, 366 passed → 65 failed, 386 passed (36
skipped / 46 xfailed / 5 xpassed unchanged). Numpy backend stays at 0
failed (503 passed); dask backend on the four changed test files also
stays at 0 failed.
No CHANGES.rst entry — this is a test-only change.
Fixed causes (itemized)
.copy()is not an array-API method. Replacedarr.copy()withxp.asarray(arr, copy=True)intest_ccdproc.py::test_subtract_overscan. Closes all 6 parametrizedfailures for that test as numpy-isms; two of the six
(
[True-False-False],[True-False-True], themedian=Truecases)still fail afterward because they hit the separate, already-tracked
xp.mediangap atcore.py:629(another agent is fixing that on adifferent branch) — the
.copy()fix itself is still correct and iskept per the issue's scope.
np.zeros_likemixed with backend arrays.test_ccdproc_logging.py::test_implicit_loggingnow builds its biasframe with
xp.zeros_like(now passes).test_rebin.py::test_rebin_ccddata[True-True]was updated the same way, but it still fails afterward: astropy's
CCDData.masksetter (astropy/nddata/compat.py) forcesnp.asarray(value, dtype=np.bool_), which can't convert an array ona non-default strict device. That's an astropy-internals limitation
outside a test-only fix, so it's kept per the issue's scope and noted
as a residual failure.
test__overscan_schangeusedxp.allclose, which isn't in thearray-API standard. Replaced with
xp.all(xpx.isclose(...)).test_combiner.pynumpy-only method calls (.mean(),.all()) onbackend arrays, replaced with
xp.mean(...)/xp.all(...):test_combiner_minmax,test_combiner_minmax_max,test_combiner_minmax_min.arr[i]) on arrays withndim > 1, whichthe array-API standard requires an explicit ellipsis for
(
arr[i, ...]):test_subtract_overscan_fails,test_user_supplied_combine_func_that_relies_on_masks[sum_combine].test_trim_with_wcs_alters_wcs(xp.asarray(shape) / 2on an intarray),
test_pixelwise_weights,test_combiner_sum_weighted,test_combiner_sum_weighted_by_pixel,test_combiner_sum_weighted_with_mask,test_combiner_uncertainty_average,test_combiner_uncertainty_average_mask,test_combiner_uncertainty_median_mask,test_combiner_uncertainty_sum_mask(int-literal arrays passed toxp.std/xp.sqrt, and an unwrappednp.float64fromastropy.stats.median_absolute_deviationmultiplied against astrict
Array, following the existingfloat(...)cast patternalready used elsewhere in that file).
xp.asarray(list_of_arrays)("Nested Arrays are not allowed"),replaced with
xp.stack(...):test_user_supplied_combine_func_that_relies_on_masks[sum_combine].Failures examined and deliberately left (with why)
test_ccd_process[*],test_ccd_process_gain_corrected,test_subtract_overscan[True-False-*](median path) — the known,already-tracked
xp.mediangap atcore.py:629; another agent isfixing this on a separate branch, explicitly out of scope here.
test_flat_correct*,test_gain_correct*,test_gain.py::*— sourcebugs in
gain_correct/flat_correct(core.py:934,core.py:1023,core.py:1037):xp.asarray(...)called withoutdevice=, causing"Arrays from two different devices" errors from ccdproc source, not
the test body.
test_flat_correct_data_uncertainty— intentionally uses a raw numpyarray as uncertainty; the test's own comment documents this as a
regression test for astropy's
NDUncertaintyexplicitly checking fornumpy.ndarray, to be removed once that's fixed upstream.test_flat_correct_deviation,test_sigma_func_for_ccddata,test_combiner_median/average/sum/dtype,test_average_combine_uncertainty,test_median_combine_uncertainty,test_sum_combine_uncertainty,test_combine_result_uncertainty_and_mask[*]—fail inside
astropy.stats.median_absolute_deviationorCCDData.mask/Quantityconstruction forcing numpy conversion of anon-default-device strict array; astropy-internals, not test-body.
test_combiner_sigmaclip_high/low/single_pix— the test intentionallypasses
astropy.stats.median_absolute_deviationasdev_func, whichforces a numpy conversion inside
combiner.py'ssigma_clipping;same astropy-internals limitation.
test_combine_average_fitsimages,test_combine_numpyndarray,test_combiner_image_file_collection_input,test_combine_image_file_collection_input,test_combine_average_ccddata,test_combine_limitedmem_fitsimages,test_combine_limitedmem_scale_fitsimages,test_combine_ccd_with_uncertainty_and_mask_from_fits[*]— explicitlyout of scope per the task brief (
combine()file-input handlingreturns plain numpy arrays).
test_clip_extrema_3d/alone/via_combine/with_other_rejection—explicitly out of scope per the task brief (clip_extrema fancy
indexing).
test_combiner_with_scaling,test_combiner_result_dtype,test_combine_overwrite_output,test_combiner_with_scaling_uncertainty[*]—astropy
ndarithmetic'snp.result_type(ref, operand)can't converta strict
Array's dtype; astropy-internals ("Could not convert Array"pattern named as out of scope in the task brief).
test_writeable_after_combine[*]—CCDData.write/mask conversionforcing numpy on a non-default device; source/astropy-internals.
test_3d_combiner_with_scaling,test_combiner_with_scaling(helperscale_by_mean) — tried fixing the.mean()numpy-ism, but it thenexposed a genuine ccdproc source bug:
Combiner.scaling's setter(
combiner.py:327) callsxp.asarray(list_of_arrays)on a list ofstrict
Arrays ("Nested Arrays are not allowed. Usestackinstead."),and for
test_combiner_with_scalingthe test is blocked even earlierby the astropy
ndarithmeticissue above. Per the task's revertpolicy for non-numbered items, these test-body changes were reverted
back to the pre-existing (still-numpy) form and left failing.
test_transform_image[True-True]— the test's user-suppliedtran = lambda arr: 10 * arris applied generically to data, uncertainty, andmask by
transform_image; ccdproc's array-API wrapper coerces themask to
boolbefore this call, so10 * bool_arrayhits strict's"Only numeric dtypes are allowed in
__rmul__". Making the test'stransform function dtype-aware would change what the test exercises
rather than being a simple hygiene fix, so left as-is.
test_unit_mismatch_behaves_as_expected— fails inside astropy'sQuantity.__new__forcing a numpy conversion via_arithmetic_data/_prepare_then_do_arithmetic; astropy-internals.test_image_collection.py::test_generator_ccds_without_unit— failsonly when run as part of the full suite (passes in isolation),
indicating cross-test state leakage unrelated to array-API numpy-isms;
left as a pre-existing, order-dependent issue outside this batch's
scope.
Test plan
CCDPROC_ARRAY_LIBRARY=array-api-strict tox -e strict(from themain checkout's tox env): 85 failed, 366 passed → 65 failed, 386
passed.
CCDPROC_ARRAY_LIBRARY=numpyfull suite: 503 passed, 0 failed (noregression).
CCDPROC_ARRAY_LIBRARY=daskon the four changed test files: 181passed, 0 failed.
ruff check/ruff format --checkclean on changed files.Part of #971
🤖 Generated with Claude Code
https://claude.ai/code/session_01RQMJZUaaxfqGDk41GLSaFK