Coverage for tests/test_ndf_format_version.py: 93%

69 statements  

« prev     ^ index     » next       coverage.py v7.15.4, created at 2026-09-09 02:31 -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. 

11 

12from __future__ import annotations 

13 

14from pathlib import Path 

15 

16import numpy as np 

17import pytest 

18 

19from lsst.images import Image 

20from lsst.images.serialization import ArchiveReadError 

21 

22try: 

23 import h5py 

24 

25 from lsst.images.ndf import write as ndf_write 

26 

27 HAVE_H5PY = True 

28except ImportError: 

29 HAVE_H5PY = False 

30 

31 

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) 

36 

37 

38skip_no_h5py = pytest.mark.skipif(not HAVE_H5PY, reason="NDF backend requires h5py") 

39 

40 

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"] 

49 

50 

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 

55 

56 path = tmp_path / "x.sdf" 

57 _write_simple_image_ndf(path) 

58 with NdfInputArchive.open(path): 

59 pass 

60 

61 

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 

66 

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 

76 

77 

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. 

81 

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 

87 

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 

95 

96 

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. 

100 

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 

106 

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) 

113 

114 

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. 

118 

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 

124 

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