Overview
test_autoarray writes test output into tracked paths, so any change to the
autonerves FITS writer rewrites a committed binary and dirties the tree for every
contributor. This was demonstrated on PyAutoArray#483, where the PyAutoNerves#155
header-comment fix ([""] -> "") silently modified
test_autoarray/structures/arrays/files/array/output_test/array.fits the moment the
autonerves floor moved — identical cards, values, data and byte size, but a modified
tracked file that had to be committed into an unrelated PR.
The convention to prevent this already exists and was applied inconsistently:
.gitignore names two individual generated files rather than the pattern. This task
applies the durable fix (pytest's tmp_path) uniformly, so no test writes into the
source tree at all, and untracks the 13 exposed artifacts.
Audit correction to the original prompt. Of the 13 tracked files, only one is a
live output — structures/arrays/files/array/output_test/array.fits, the file #483
flipped. The other 12 are orphans: no test in the repo references their paths, and a
repo-wide grep for their basenames returns nothing. They are residue from tests that were
since deleted (the two .gitignore lines are gravestones for one such test). The prompt's
open question about test_uniform_1d.py:12 resolves the same way: that path is written,
not read — no file in the set is a real input.
Plan
- Convert every
output_test writer to pytest's tmp_path — the prompt's preferred,
durable fix — so no test writes into the source tree.
- Delete the one live tracked artifact and the twelve orphans, untracking all thirteen.
- Replace the two file-by-file
.gitignore lines with one directory pattern as a backstop
against a future writer regressing this.
- Remove a dead
test_data_path fixture in the imaging tests that no test requests.
- Verify from a clean checkout: full suite twice in a row,
git status clean after each.
- Check PyAutoGalaxy/PyAutoLens for the same pattern and file separately — do not widen
this PR.
Detailed implementation plan
Work Classification
Library
Affected Repositories
Branch Survey
| Repository |
Current Branch |
Dirty? |
| ./PyAutoArray |
main |
clean |
Suggested branch: feature/untrack-fits-test-artifacts
Worktree root: ~/Code/PyAutoLabs-wt/untrack-fits-test-artifacts/
Inventory: what is actually tracked
| Tracked path |
Written by |
Verdict |
structures/arrays/files/array/output_test/array.fits |
test_uniform_2d.py:208 and test_uniform_1d.py:166 (same dir; both rmtree it) |
live output |
dataset/files/array/output_test/noise_map.fits |
— |
orphan |
dataset/files/arrays/output_test/{background_noise_map,background_sky_map,exposure_time_map,image,noise_map,poisson_noise_map,psf}.fits |
— |
orphan (7 files) |
structures/arrays/files/output_test/{array,masked_array}.fits, values_test.dat |
— |
orphan (3 files) |
structures/arrays/files/values/output_test/values_test.dat |
— |
orphan |
Only six test modules reference output_test at all; four already resolve into
.gitignored directories (mask/files/array/, dataset/{imaging,interferometer}/files/array/).
Two extras the audit turned up:
structures/test_visibilities.py writes structures/files/output_test/data.fits —
untracked and un-ignored, so it dirties the tree as an untracked file today.
dataset/imaging/test_dataset.py:16-25 defines a test_data_path fixture that no test
ever requests — dead code shadowing the module-level constant.
Implementation Steps
-
Convert writers to tmp_path. In each, drop the shutil.rmtree / os.makedirs
preamble and write to tmp_path / <name>, reading back from the same path. Inputs keep
reading from their committed files/ fixtures.
test_autoarray/structures/arrays/test_uniform_2d.py —
test__output_to_fits__3x3_ones__fits_file_has_ones_and_correct_pixel_scale_header
(lines 194-216).
test_autoarray/structures/arrays/test_uniform_1d.py — the output test at lines
~158-176; also delete the module-level test_data_path constant (line 12). Leave
create_fits / clean_fits / fits_path alone — those target files/array_1d, a
separate concern.
test_autoarray/structures/test_visibilities.py — test__output_to_fits (lines 89-111).
test_autoarray/mask/test_mask_2d.py —
test__from_fits__output_to_fits__roundtrip_preserves_values_pixel_scales_and_header
(lines 410-440).
test_autoarray/dataset/interferometer/test_dataset.py — test__output_all_arrays
(lines 130-168): keep the first test_data_path (input files/), replace the rebound
output path with tmp_path.
test_autoarray/dataset/imaging/test_dataset.py — delete the unused
make_test_data_path fixture (lines 16-25).
Prune import os / import shutil only where they become genuinely unused.
-
Untrack and delete the 13 files (git rm, not --cached — nothing reads them), then
remove the five emptied output_test/ directories and any parent left empty
(dataset/files/arrays/, structures/arrays/files/values/).
-
.gitignore — delete the two individual lines
(test_autoarray/dataset/files/array/output_test/{uv_wavelengths,visibilities}.fits) and
add one pattern in their place:
# Test output: tests write into output_test/ dirs; never track the results
test_autoarray/**/output_test/
This also covers structures/files/output_test/ from the visibilities test. It is a
backstop only — after step 1 no test should write into the tree at all.
-
Verify. source activate.sh then python3 -m pytest -q -n auto from a clean
checkout, run twice in a row, asserting git status --porcelain empty after each. The
second run is what catches a test that silently depended on a committed artifact — it
would fail on run 1, not run 2.
-
Siblings. Grep PyAutoGalaxy/PyAutoLens for the same pattern and route findings through
/intake as separate prompts. No changes to those repos in this PR.
Key Files
test_autoarray/structures/arrays/test_uniform_2d.py — writer of the one live tracked artifact
test_autoarray/structures/arrays/test_uniform_1d.py — second writer of the same directory
test_autoarray/structures/test_visibilities.py — writer of the untracked-but-un-ignored artifact
test_autoarray/mask/test_mask_2d.py — writer into an already-ignored directory
test_autoarray/dataset/interferometer/test_dataset.py — writer into an already-ignored directory
test_autoarray/dataset/imaging/test_dataset.py — dead test_data_path fixture
.gitignore — the two file-by-file lines replaced by the directory pattern
Trade-offs
tmp_path over a .gitignore-only fix is the prompt's own preference and the only option
that stops tests writing into the source tree; it costs six small test edits. It also
removes an existing ordering hazard, since test_uniform_1d and test_uniform_2d currently
rmtree the same shared directory.
- Deleting the 12 orphans is beyond the prompt as written. They are provably dead, they are
the same defect's accumulated residue, and leaving them would mean a second PR for one
git rm.
Original Prompt
Click to expand starting prompt
Untrack the generated FITS test artifacts in autoarray
Type: maintenance
Target: libraries
Repos:
- @PyAutoArray
Difficulty: small
Autonomy: supervised
Priority: medium
Status: formalised
Filed: 2026-08-22 (backfilled from git)
Filed 2026-08-23 from the PyAutoArray#482/#483 floor bump, which tripped over
this. Not a bug — a git-hygiene defect that converts unrelated upstream changes
into binary diffs.
The defect
test_autoarray writes test output into tracked paths. The tests rmtree
the directory, recreate it, write a FITS, and read it back — the file is never an
input expectation, yet it is committed. So any change to the autonerves FITS
writer rewrites a tracked binary and dirties the tree for every contributor.
Demonstrated on #483: the PyAutoNerves#155 header-comment fix ([""] -> "")
silently changed test_autoarray/structures/arrays/files/array/output_test/array.fits
the moment the autonerves floor moved to a release carrying it —
HEAD : PIXSCAY = 1.0 / ['']
WORKING : PIXSCAY = 1.0
— identical cards, values, data and byte size, but a modified tracked file that
had to be either committed into an unrelated PR or left dirtying the tree. It
was committed there; that was the least-bad option, not a good one.
Why this is worth fixing rather than absorbing
The convention already exists and is applied inconsistently. .gitignore
lines 9-10 name two individual generated files:
test_autoarray/dataset/files/array/output_test/uv_wavelengths.fits
test_autoarray/dataset/files/array/output_test/visibilities.fits
so someone already hit this and patched the two files in front of them rather
than the pattern. 13 tracked files across five output_test/ directories are
still exposed:
test_autoarray/dataset/files/array/output_test/noise_map.fits
test_autoarray/dataset/files/arrays/output_test/{background_noise_map,background_sky_map,
exposure_time_map,image,noise_map,poisson_noise_map,psf}.fits
test_autoarray/structures/arrays/files/array/output_test/array.fits
test_autoarray/structures/arrays/files/output_test/{array,masked_array}.fits
test_autoarray/structures/arrays/files/output_test/values_test.dat
test_autoarray/structures/arrays/files/values/output_test/values_test.dat
Writers: structures/arrays/test_uniform_2d.py:201-211,
structures/test_visibilities.py:96-107, mask/test_mask_2d.py:417,
dataset/interferometer/test_dataset.py:140, dataset/imaging/test_dataset.py:18,
structures/arrays/test_uniform_1d.py:12.
Suggested scope
- Pick one of the two fixes and apply it uniformly — do not patch
file-by-file again:
tmp_path (preferred): the tests already rmtree/recreate their output
dir, so pytest's tmp_path fixture is a near-drop-in and removes the
tracked path entirely. This is the durable fix.
.gitignore the directories (test_autoarray/**/output_test/) plus
git rm --cached the 13 files, if converting the tests is judged too wide.
Cheaper, but leaves the tests writing into the source tree.
- Confirm each candidate file is genuinely output before untracking it. The
inventory above was read off the writers, but
structures/arrays/test_uniform_1d.py:12 reads from an output_test path —
check whether it consumes a file another test produced (ordering dependency)
or a committed one. If any file is a real input, it is not in scope and should
be moved out of output_test/ instead.
- Verify the suite passes from a clean checkout and twice in a row (a test
that silently depended on a committed artifact will fail on the first run
after untracking, not the second).
- Leave the sibling repos alone. PyAutoGalaxy/PyAutoLens likely share the
pattern; check, and file separately rather than widening this.
Note
The equivalent problem in the workspaces was solved differently — an autouse
conftest fixture per repo (see complete/2026/08/small-datasets-regime-stamp.md,
"Committed FITS fixtures became regime-DEPENDENT"). That solved regime
dependence of fixtures that are genuinely inputs. This is the different case:
files that are outputs and should not be tracked at all.
Overview
test_autoarraywrites test output into tracked paths, so any change to theautonerves FITS writer rewrites a committed binary and dirties the tree for every
contributor. This was demonstrated on PyAutoArray#483, where the PyAutoNerves#155
header-comment fix (
[""]->"") silently modifiedtest_autoarray/structures/arrays/files/array/output_test/array.fitsthe moment theautonerves floor moved — identical cards, values, data and byte size, but a modified
tracked file that had to be committed into an unrelated PR.
The convention to prevent this already exists and was applied inconsistently:
.gitignorenames two individual generated files rather than the pattern. This taskapplies the durable fix (pytest's
tmp_path) uniformly, so no test writes into thesource tree at all, and untracks the 13 exposed artifacts.
Audit correction to the original prompt. Of the 13 tracked files, only one is a
live output —
structures/arrays/files/array/output_test/array.fits, the file #483flipped. The other 12 are orphans: no test in the repo references their paths, and a
repo-wide grep for their basenames returns nothing. They are residue from tests that were
since deleted (the two
.gitignorelines are gravestones for one such test). The prompt'sopen question about
test_uniform_1d.py:12resolves the same way: that path is written,not read — no file in the set is a real input.
Plan
output_testwriter to pytest'stmp_path— the prompt's preferred,durable fix — so no test writes into the source tree.
.gitignorelines with one directory pattern as a backstopagainst a future writer regressing this.
test_data_pathfixture in the imaging tests that no test requests.git statusclean after each.this PR.
Detailed implementation plan
Work Classification
Library
Affected Repositories
Branch Survey
Suggested branch:
feature/untrack-fits-test-artifactsWorktree root:
~/Code/PyAutoLabs-wt/untrack-fits-test-artifacts/Inventory: what is actually tracked
structures/arrays/files/array/output_test/array.fitstest_uniform_2d.py:208andtest_uniform_1d.py:166(same dir; bothrmtreeit)dataset/files/array/output_test/noise_map.fitsdataset/files/arrays/output_test/{background_noise_map,background_sky_map,exposure_time_map,image,noise_map,poisson_noise_map,psf}.fitsstructures/arrays/files/output_test/{array,masked_array}.fits,values_test.datstructures/arrays/files/values/output_test/values_test.datOnly six test modules reference
output_testat all; four already resolve into.gitignored directories (mask/files/array/,dataset/{imaging,interferometer}/files/array/).Two extras the audit turned up:
structures/test_visibilities.pywritesstructures/files/output_test/data.fits—untracked and un-ignored, so it dirties the tree as an untracked file today.
dataset/imaging/test_dataset.py:16-25defines atest_data_pathfixture that no testever requests — dead code shadowing the module-level constant.
Implementation Steps
Convert writers to
tmp_path. In each, drop theshutil.rmtree/os.makedirspreamble and write to
tmp_path / <name>, reading back from the same path. Inputs keepreading from their committed
files/fixtures.test_autoarray/structures/arrays/test_uniform_2d.py—test__output_to_fits__3x3_ones__fits_file_has_ones_and_correct_pixel_scale_header(lines 194-216).
test_autoarray/structures/arrays/test_uniform_1d.py— the output test at lines~158-176; also delete the module-level
test_data_pathconstant (line 12). Leavecreate_fits/clean_fits/fits_pathalone — those targetfiles/array_1d, aseparate concern.
test_autoarray/structures/test_visibilities.py—test__output_to_fits(lines 89-111).test_autoarray/mask/test_mask_2d.py—test__from_fits__output_to_fits__roundtrip_preserves_values_pixel_scales_and_header(lines 410-440).
test_autoarray/dataset/interferometer/test_dataset.py—test__output_all_arrays(lines 130-168): keep the first
test_data_path(inputfiles/), replace the reboundoutput path with
tmp_path.test_autoarray/dataset/imaging/test_dataset.py— delete the unusedmake_test_data_pathfixture (lines 16-25).Prune
import os/import shutilonly where they become genuinely unused.Untrack and delete the 13 files (
git rm, not--cached— nothing reads them), thenremove the five emptied
output_test/directories and any parent left empty(
dataset/files/arrays/,structures/arrays/files/values/)..gitignore— delete the two individual lines(
test_autoarray/dataset/files/array/output_test/{uv_wavelengths,visibilities}.fits) andadd one pattern in their place:
This also covers
structures/files/output_test/from the visibilities test. It is abackstop only — after step 1 no test should write into the tree at all.
Verify.
source activate.shthenpython3 -m pytest -q -n autofrom a cleancheckout, run twice in a row, asserting
git status --porcelainempty after each. Thesecond run is what catches a test that silently depended on a committed artifact — it
would fail on run 1, not run 2.
Siblings. Grep PyAutoGalaxy/PyAutoLens for the same pattern and route findings through
/intakeas separate prompts. No changes to those repos in this PR.Key Files
test_autoarray/structures/arrays/test_uniform_2d.py— writer of the one live tracked artifacttest_autoarray/structures/arrays/test_uniform_1d.py— second writer of the same directorytest_autoarray/structures/test_visibilities.py— writer of the untracked-but-un-ignored artifacttest_autoarray/mask/test_mask_2d.py— writer into an already-ignored directorytest_autoarray/dataset/interferometer/test_dataset.py— writer into an already-ignored directorytest_autoarray/dataset/imaging/test_dataset.py— deadtest_data_pathfixture.gitignore— the two file-by-file lines replaced by the directory patternTrade-offs
tmp_pathover a.gitignore-only fix is the prompt's own preference and the only optionthat stops tests writing into the source tree; it costs six small test edits. It also
removes an existing ordering hazard, since
test_uniform_1dandtest_uniform_2dcurrentlyrmtreethe same shared directory.the same defect's accumulated residue, and leaving them would mean a second PR for one
git rm.Original Prompt
Click to expand starting prompt
Untrack the generated FITS test artifacts in autoarray
Type: maintenance
Target: libraries
Repos:
Difficulty: small
Autonomy: supervised
Priority: medium
Status: formalised
Filed: 2026-08-22 (backfilled from git)
Filed 2026-08-23 from the PyAutoArray#482/#483 floor bump, which tripped over
this. Not a bug — a git-hygiene defect that converts unrelated upstream changes
into binary diffs.
The defect
test_autoarraywrites test output into tracked paths. The tests rmtreethe directory, recreate it, write a FITS, and read it back — the file is never an
input expectation, yet it is committed. So any change to the autonerves FITS
writer rewrites a tracked binary and dirties the tree for every contributor.
Demonstrated on #483: the PyAutoNerves#155 header-comment fix (
[""]->"")silently changed
test_autoarray/structures/arrays/files/array/output_test/array.fitsthe moment the autonerves floor moved to a release carrying it —
— identical cards, values, data and byte size, but a modified tracked file that
had to be either committed into an unrelated PR or left dirtying the tree. It
was committed there; that was the least-bad option, not a good one.
Why this is worth fixing rather than absorbing
The convention already exists and is applied inconsistently.
.gitignorelines 9-10 name two individual generated files:
so someone already hit this and patched the two files in front of them rather
than the pattern. 13 tracked files across five
output_test/directories arestill exposed:
Writers:
structures/arrays/test_uniform_2d.py:201-211,structures/test_visibilities.py:96-107,mask/test_mask_2d.py:417,dataset/interferometer/test_dataset.py:140,dataset/imaging/test_dataset.py:18,structures/arrays/test_uniform_1d.py:12.Suggested scope
file-by-file again:
tmp_path(preferred): the tests already rmtree/recreate their outputdir, so pytest's
tmp_pathfixture is a near-drop-in and removes thetracked path entirely. This is the durable fix.
.gitignorethe directories (test_autoarray/**/output_test/) plusgit rm --cachedthe 13 files, if converting the tests is judged too wide.Cheaper, but leaves the tests writing into the source tree.
inventory above was read off the writers, but
structures/arrays/test_uniform_1d.py:12reads from anoutput_testpath —check whether it consumes a file another test produced (ordering dependency)
or a committed one. If any file is a real input, it is not in scope and should
be moved out of
output_test/instead.that silently depended on a committed artifact will fail on the first run
after untracking, not the second).
pattern; check, and file separately rather than widening this.
Note
The equivalent problem in the workspaces was solved differently — an autouse
conftest fixture per repo (see
complete/2026/08/small-datasets-regime-stamp.md,"Committed FITS fixtures became regime-DEPENDENT"). That solved regime
dependence of fixtures that are genuinely inputs. This is the different case:
files that are outputs and should not be tracked at all.