Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions autonerves/fitsable.py
Original file line number Diff line number Diff line change
Expand Up @@ -207,8 +207,10 @@ def ndarray_via_fits_from(
--------
array_2d = ndarray_via_fits_from(file_path='/path/to/file/filename.fits', hdu=0)
"""
hdu_list = fits.open(file_path, do_not_scale_image_data=do_not_scale_image_data)
return ndarray_via_hdu_from(hdu_list[hdu])
with fits.open(
file_path, do_not_scale_image_data=do_not_scale_image_data
) as hdu_list:
return ndarray_via_hdu_from(hdu_list[hdu])


def header_obj_from(file_path: Union[Path, str], hdu: int) -> Dict:
Expand All @@ -233,8 +235,8 @@ def header_obj_from(file_path: Union[Path, str], hdu: int) -> Dict:
--------
array_2d = ndarray_via_fits_from(file_path='/path/to/file/filename.fits', hdu=0)
"""
hdu_list = fits.open(file_path)
return hdu_list[hdu].header
with fits.open(file_path) as hdu_list:
return hdu_list[hdu].header



Expand Down
23 changes: 22 additions & 1 deletion autonerves/workspace.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,22 @@ def _version_date(parsed_version):
return None


def _is_source_checkout(root):
"""
True when ``root`` is a Python package source checkout (a ``setup.py`` or
``pyproject.toml`` at its top level) rather than a workspace clone.

``check_version`` is called unconditionally on library import with
``workspace_root`` defaulting to the current working directory, so any
pytest run or script executed from inside a library's own repo would
otherwise warn "Cannot verify the workspace ..." on every import — a
false positive, since a source checkout is not a workspace and records
no version floor to verify. Workspace clones ship neither file, so a
genuine workspace missing its version keys still warns.
"""
return (root / "setup.py").exists() or (root / "pyproject.toml").exists()


def _library_name_from_workspace(workspace_root):
name = workspace_root.name
suffix = "_workspace"
Expand Down Expand Up @@ -168,7 +184,10 @@ def check_version(library_version, workspace_root=None):
installs) warn on inequality rather than raising.

If no floor source is found, a warning is emitted and the check is
skipped.
skipped — unless ``workspace_root`` is a package source checkout
(``setup.py``/``pyproject.toml`` at its top level), in which case the
check is skipped silently: running from inside a library's own repo is
not a workspace-compatibility question at all.

The check can be disabled in two ways:

Expand Down Expand Up @@ -203,6 +222,8 @@ def check_version(library_version, workspace_root=None):
floor_version = version_file.read_text().strip()

if floor_version is None or floor_version == "":
if _is_source_checkout(root):
return
warnings.warn(_missing_version_warning(root, library_version))
return

Expand Down
16 changes: 16 additions & 0 deletions test_autonerves/test_fitsable.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,22 @@ def test__output_to_fits__header_dict():
assert header["A"] == 1


def test__fits_readers_close_their_file_handles():
"""Regression: `fits.open` without close leaked file handles, emitting
`ResourceWarning: unclosed file` throughout every downstream repo that
loads FITS via these helpers."""
import gc
import warnings

with warnings.catch_warnings():
warnings.simplefilter("error", ResourceWarning)
fitsable.ndarray_via_fits_from(
file_path=test_data_path / "3x3_ones.fits", hdu=0
)
fitsable.header_obj_from(file_path=test_data_path / "3x3_ones.fits", hdu=0)
gc.collect()


def test__header_obj_from():
header_obj = fitsable.header_obj_from(
file_path=test_data_path / "3x3_ones.fits", hdu=0
Expand Down
13 changes: 8 additions & 5 deletions test_autonerves/test_test_mode.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,14 @@

from autonerves.test_mode import (
is_test_mode,
test_mode_level,
test_mode_samples,
with_test_mode_segment,
)

# ``test_mode_samples`` is real API, but its ``test_`` prefix means a bare-name
# import here would be collected by pytest as a test function
# (PytestReturnNotNoneWarning, an ERROR in future pytest) — alias it instead.
from autonerves.test_mode import test_mode_samples as _test_mode_samples


@pytest.fixture(autouse=True)
def _restore_test_mode_env():
Expand Down Expand Up @@ -69,13 +72,13 @@ def _restore_samples_env(self):

def test__env_unset_returns_historical_default_of_four(self):
os.environ.pop("PYAUTO_TEST_MODE_SAMPLES", None)
assert test_mode_samples() == 4
assert _test_mode_samples() == 4

def test__env_set_returns_value(self):
os.environ["PYAUTO_TEST_MODE_SAMPLES"] = "50000"
assert test_mode_samples() == 50000
assert _test_mode_samples() == 50000

def test__values_below_four_raise(self):
os.environ["PYAUTO_TEST_MODE_SAMPLES"] = "3"
with pytest.raises(ValueError):
test_mode_samples()
_test_mode_samples()
20 changes: 20 additions & 0 deletions test_autonerves/test_workspace.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,26 @@ def test_missing_sources_warns(tmp_path):
check_version("2026.7.22.1", workspace_root=tmp_path)


@pytest.mark.parametrize("marker", ["setup.py", "pyproject.toml"])
def test_missing_sources_in_source_checkout_skips_silently(tmp_path, marker):
"""A package source checkout (setup.py/pyproject.toml at the root) is not
a workspace — importing a library from inside its own repo must not warn
that the "workspace" version cannot be verified."""
(tmp_path / marker).write_text("")
with warnings.catch_warnings():
warnings.simplefilter("error")
check_version("2026.7.22.1", workspace_root=tmp_path)


def test_source_checkout_with_version_floor_still_checked(tmp_path):
"""The source-checkout skip only covers the no-floor false positive — a
recorded floor is still enforced even with a setup.py present."""
(tmp_path / "setup.py").write_text("")
(tmp_path / "version.txt").write_text("2026.7.22.1\n")
with pytest.raises(WorkspaceVersionMismatchError):
check_version("2025.1.1.1", workspace_root=tmp_path)


def test_env_override_skips_mismatch(tmp_path, monkeypatch):
monkeypatch.setenv("PYAUTO_SKIP_WORKSPACE_VERSION_CHECK", "1")
(tmp_path / "version.txt").write_text("2025.1.1.1\n")
Expand Down
Loading