Coverage for tests/test_ndf_format_version.py: 93%
69 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-08-20 02:04 -0700
« prev ^ index » next coverage.py v7.15.2, created at 2026-08-20 02:04 -0700
1# This file is part of lsst-images.
2#
3# Developed for the LSST Data Management System.
4# This product includes software developed by the LSST Project
5# (https://www.lsst.org).
6# See the COPYRIGHT file at the top-level directory of this distribution
7# for details of code ownership.
8#
9# Use of this source code is governed by a 3-clause BSD-style
10# license that can be found in the LICENSE file.
12from __future__ import annotations
14from pathlib import Path
16import numpy as np
17import pytest
19from lsst.images import Image
20from lsst.images.serialization import ArchiveReadError
22try:
23 import h5py
25 from lsst.images.ndf import write as ndf_write
27 HAVE_H5PY = True
28except ImportError:
29 HAVE_H5PY = False
32def _write_simple_image_ndf(path: Path | str) -> None:
33 """Write a tiny Image to ``path`` as an NDF."""
34 image = Image(0.0, shape=(4, 4), dtype="float32")
35 ndf_write(image, path)
38skip_no_h5py = pytest.mark.skipif(not HAVE_H5PY, reason="NDF backend requires h5py")
41@skip_no_h5py
42def test_write_emits_data_model_and_format_version(tmp_path: Path) -> None:
43 """Verify a freshly-written NDF carries DATA_MODEL and FORMAT_VERSION."""
44 path = tmp_path / "x.sdf"
45 _write_simple_image_ndf(path)
46 with h5py.File(path, "r") as f:
47 assert "FORMAT_VERSION" in f["/MORE/LSST"]
48 assert "DATA_MODEL" in f["/MORE/LSST"]
51@skip_no_h5py
52def test_read_succeeds_when_format_version_matches(tmp_path: Path) -> None:
53 """Verify a freshly-written NDF reads successfully."""
54 from lsst.images.ndf import NdfInputArchive
56 path = tmp_path / "x.sdf"
57 _write_simple_image_ndf(path)
58 with NdfInputArchive.open(path):
59 pass
62@skip_no_h5py
63def test_read_fails_when_format_version_too_high(tmp_path: Path) -> None:
64 """Verify a file with a newer FORMAT_VERSION raises ArchiveReadError."""
65 from lsst.images.ndf import NdfInputArchive
67 path = tmp_path / "x.sdf"
68 _write_simple_image_ndf(path)
69 with h5py.File(path, "r+") as f:
70 if "FORMAT_VERSION" in f["/MORE/LSST"]: 70 ↛ 72line 70 didn't jump to line 72 because the condition on line 70 was always true
71 del f["/MORE/LSST/FORMAT_VERSION"]
72 f["/MORE/LSST"].create_dataset("FORMAT_VERSION", data=np.int32(2))
73 with pytest.raises(ArchiveReadError):
74 with NdfInputArchive.open(path):
75 pass
78@skip_no_h5py
79def test_read_fails_when_format_version_absent(tmp_path: Path) -> None:
80 """Verify an LSST-written file lacking FORMAT_VERSION is rejected.
82 Every file this package writes stamps the container layout, so its
83 absence alongside an LSST JSON tree is a damaged file rather than a
84 legacy one, and guessing version 1 would guess at the layout.
85 """
86 from lsst.images.ndf import NdfInputArchive
88 path = tmp_path / "x.sdf"
89 _write_simple_image_ndf(path)
90 with h5py.File(path, "r+") as f:
91 del f["/MORE/LSST/FORMAT_VERSION"]
92 with pytest.raises(ArchiveReadError, match="FORMAT_VERSION"):
93 with NdfInputArchive.open(path):
94 pass
97@skip_no_h5py
98def test_get_basic_info_fails_when_format_version_absent(tmp_path: Path) -> None:
99 """Verify the info-only read requires the stamp as well.
101 ``get_basic_info`` already refuses a file with no ``DATA_MODEL``, so by
102 the time it reads the container version the LSST extension is known to be
103 present and the stamp must be there too.
104 """
105 from lsst.images.ndf import NdfInputArchive
107 path = tmp_path / "x.sdf"
108 _write_simple_image_ndf(path)
109 with h5py.File(path, "r+") as f:
110 del f["/MORE/LSST/FORMAT_VERSION"]
111 with pytest.raises(ArchiveReadError, match="FORMAT_VERSION"):
112 NdfInputArchive.get_basic_info(path)
115@skip_no_h5py
116def test_read_starlink_needs_no_format_version(tmp_path: Path) -> None:
117 """Verify a Starlink NDF still reads without any LSST extension.
119 A file with no LSST extension has no container layout of ours to
120 version, so the required stamp applies only to our own files; these go
121 through ``read_starlink`` rather than the generic archive read.
122 """
123 from lsst.images.ndf import read_starlink
125 path = tmp_path / "x.sdf"
126 _write_simple_image_ndf(path)
127 with h5py.File(path, "r+") as f:
128 del f["/MORE/LSST"]
129 assert read_starlink(Image, path).bbox.area == 16