Coverage for tests/test_serialization_reader.py: 34%
122 statements
« prev ^ index » next coverage.py v7.14.1, created at 2026-06-10 03:25 -0700
« prev ^ index » next coverage.py v7.14.1, created at 2026-06-10 03:25 -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.
11from __future__ import annotations
13import os
14import tempfile
15import unittest
17from lsst.images import fits as images_fits
18from lsst.images import json as images_json
19from lsst.images.fits import FitsInputArchive
20from lsst.images.json import JsonInputArchive
21from lsst.images.serialization import ArchiveTree, backend_for_path, class_for_schema, read
23DATA_DIR = os.path.join(os.path.dirname(__file__), "data", "schema_v1")
26def _visit_image():
27 """Load a VisitImage from the committed JSON fixture."""
28 return read(os.path.join(DATA_DIR, "visit_image.json"))
31class FitsOpenTreeTestCase(unittest.TestCase):
32 """InputArchive.open_tree yields a live (archive, tree) pair."""
34 def setUp(self) -> None:
35 tmp = tempfile.TemporaryDirectory()
36 self.addCleanup(tmp.cleanup)
37 self.path = os.path.join(tmp.name, "v.fits")
38 images_fits.write(_visit_image(), self.path)
40 def test_open_tree_yields_archive_and_tree(self) -> None:
41 info = backend_for_path(self.path).input_archive.get_basic_info(self.path)
42 tree_cls = class_for_schema(info.schema_name)
43 assert tree_cls is not None
44 with FitsInputArchive.open_tree(self.path, tree_cls) as (archive, tree):
45 self.assertIsInstance(tree, ArchiveTree)
46 proj = tree.deserialize_component("sky_projection", archive)
47 self.assertIsNotNone(proj)
49 def test_read_still_works(self) -> None:
50 # read() returns the deserialized object directly, via open().
51 result = read(self.path)
52 self.assertEqual(type(result).__name__, "VisitImage")
55try:
56 import h5py # noqa: F401
58 from lsst.images import ndf as images_ndf
59 from lsst.images.ndf import NdfInputArchive
61 HAVE_H5PY = True
62except ImportError:
63 HAVE_H5PY = False
66@unittest.skipUnless(HAVE_H5PY, "h5py is not available.")
67class NdfOpenTreeTestCase(unittest.TestCase):
68 """open_tree works for the NDF backend."""
70 def setUp(self) -> None:
71 tmp = tempfile.TemporaryDirectory()
72 self.addCleanup(tmp.cleanup)
73 self.path = os.path.join(tmp.name, "v.sdf")
74 images_ndf.write(_visit_image(), self.path)
76 def test_open_tree_yields_archive_and_tree(self) -> None:
77 info = backend_for_path(self.path).input_archive.get_basic_info(self.path)
78 tree_cls = class_for_schema(info.schema_name)
79 assert tree_cls is not None
80 with NdfInputArchive.open_tree(self.path, tree_cls) as (archive, tree):
81 self.assertIsInstance(tree, ArchiveTree)
82 self.assertIsNotNone(tree.deserialize_component("obs_info", archive))
84 def test_read_still_works(self) -> None:
85 self.assertEqual(type(read(self.path)).__name__, "VisitImage")
88class JsonOpenTreeTestCase(unittest.TestCase):
89 """open_tree works for the JSON backend."""
91 def setUp(self) -> None:
92 tmp = tempfile.TemporaryDirectory()
93 self.addCleanup(tmp.cleanup)
94 self.path = os.path.join(tmp.name, "v.json")
95 images_json.write(_visit_image(), self.path)
97 def test_open_tree_yields_archive_and_tree(self) -> None:
98 info = backend_for_path(self.path).input_archive.get_basic_info(self.path)
99 tree_cls = class_for_schema(info.schema_name)
100 assert tree_cls is not None
101 with JsonInputArchive.open_tree(self.path, tree_cls) as (archive, tree):
102 self.assertIsInstance(tree, ArchiveTree)
103 self.assertIsNotNone(tree.deserialize_component("sky_projection", archive))
105 def test_read_still_works(self) -> None:
106 self.assertEqual(type(read(self.path)).__name__, "VisitImage")
109class ReaderApiTestCase(unittest.TestCase):
110 """The user-facing serialization.open() / Reader interface."""
112 def setUp(self) -> None:
113 tmp = tempfile.TemporaryDirectory()
114 self.addCleanup(tmp.cleanup)
115 self.tmp = tmp.name
116 self.vi = _visit_image()
117 self.fits = os.path.join(self.tmp, "v.fits")
118 images_fits.write(self.vi, self.fits)
120 def _check_components_and_read(self, path: str) -> None:
121 import lsst.images.serialization as ser
123 with ser.open(path) as reader:
124 self.assertIsNotNone(reader.get_component("sky_projection"))
125 self.assertIsNotNone(reader.get_component("obs_info"))
126 full = reader.read()
127 self.assertEqual(type(full).__name__, "VisitImage")
129 def test_components_and_read_fits(self) -> None:
130 self._check_components_and_read(self.fits)
132 def test_components_and_read_json(self) -> None:
133 path = os.path.join(self.tmp, "v.json")
134 images_json.write(self.vi, path)
135 self._check_components_and_read(path)
137 @unittest.skipUnless(HAVE_H5PY, "h5py is not available.")
138 def test_components_and_read_ndf(self) -> None:
139 path = os.path.join(self.tmp, "v.sdf")
140 images_ndf.write(self.vi, path)
141 self._check_components_and_read(path)
143 def test_info(self) -> None:
144 import lsst.images.serialization as ser
146 with ser.open(self.fits) as reader:
147 self.assertEqual(reader.info.schema_name, "visit_image")
148 self.assertEqual(reader.info.schema_version, "1.0.0")
149 self.assertIsInstance(reader.metadata, dict)
151 def test_cls_match(self) -> None:
152 import lsst.images.serialization as ser
153 from lsst.images import VisitImage
155 with ser.open(self.fits, cls=VisitImage) as reader:
156 self.assertIsInstance(reader.read(), VisitImage)
158 def test_cls_mismatch_raises(self) -> None:
159 import lsst.images.serialization as ser
160 from lsst.images import Mask
162 with self.assertRaises(TypeError):
163 with ser.open(self.fits, cls=Mask):
164 pass
166 def test_unknown_component(self) -> None:
167 import lsst.images.serialization as ser
168 from lsst.images.serialization import InvalidComponentError
170 with ser.open(self.fits) as reader:
171 with self.assertRaises(InvalidComponentError):
172 reader.get_component("does_not_exist")
174 def test_use_after_close_raises(self) -> None:
175 import lsst.images.serialization as ser
177 with ser.open(self.fits) as reader:
178 pass
179 with self.assertRaises(RuntimeError):
180 reader.get_component("sky_projection")
183if __name__ == "__main__":
184 unittest.main()