Coverage for python/lsst/images/serialization/_backends.py: 100%

28 statements  

« prev     ^ index     » next       coverage.py v7.15.0, created at 2026-07-04 17:17 +0000

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 

14__all__ = ("Backend", "backend_for_path") 

15 

16import dataclasses 

17from collections.abc import Callable 

18from typing import TYPE_CHECKING 

19 

20from lsst.resources import ResourcePath, ResourcePathExpression 

21 

22if TYPE_CHECKING: 

23 from ._input_archive import InputArchive 

24 

25 

26@dataclasses.dataclass(frozen=True) 

27class Backend: 

28 """A file-format backend resolved from a path suffix. 

29 

30 Bundles the backend's free ``write`` function and its `InputArchive` 

31 subclass. Reading goes through the generic ``open`` / ``read`` in 

32 `lsst.images.serialization`, which use the `InputArchive`'s 

33 ``get_basic_info`` and ``open_tree``. 

34 """ 

35 

36 name: str 

37 write: Callable[..., object] 

38 input_archive: type[InputArchive] 

39 

40 

41def backend_for_path(path: ResourcePathExpression) -> Backend: 

42 """Return the `Backend` for ``path`` based on its file extension. 

43 

44 Supported extensions: ``.fits`` / ``.fits.gz`` (FITS), ``.h5`` / 

45 ``.sdf`` (NDF), and ``.json`` (JSON). The NDF and FITS backends are 

46 imported lazily so optional dependencies (e.g. ``h5py``) are only 

47 required when actually used. 

48 

49 Parameters 

50 ---------- 

51 path 

52 Path whose file extension selects the backend. 

53 

54 Raises 

55 ------ 

56 ValueError 

57 If the extension is not recognised. 

58 """ 

59 uri = ResourcePath(path) 

60 match uri.getExtension(): 

61 case ".fits" | ".fits.gz": 

62 from ..fits import FitsInputArchive 

63 from ..fits import write as fits_write 

64 

65 return Backend("fits", fits_write, FitsInputArchive) 

66 case ".h5" | ".sdf": 

67 from ..ndf import NdfInputArchive 

68 from ..ndf import write as ndf_write 

69 

70 return Backend("ndf", ndf_write, NdfInputArchive) 

71 case ".json": 

72 from ..json import JsonInputArchive 

73 from ..json import write as json_write 

74 

75 return Backend("json", json_write, JsonInputArchive) 

76 case ext: 

77 raise ValueError( 

78 f"Unrecognised file extension: {ext!r} from {uri!r}; " 

79 "expected one of .fits, .fits.gz, .h5, .sdf, .json." 

80 )