Coverage for python/astro_metadata_translator/bin/writesidecar.py: 19%
46 statements
« prev ^ index » next coverage.py v7.4.4, created at 2024-04-06 03:48 -0700
« prev ^ index » next coverage.py v7.4.4, created at 2024-04-06 03:48 -0700
1# This file is part of astro_metadata_translator.
2#
3# Developed for the LSST Data Management System.
4# This product includes software developed by the LSST Project
5# (http://www.lsst.org).
6# See the LICENSE 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
14__all__ = ("write_sidecar_files", "write_sidecar_file")
16import logging
17import os
18import traceback
19from collections.abc import Sequence
20from typing import IO
22from ..file_helpers import find_files, read_file_info
24log = logging.getLogger(__name__)
27def _split_ext(file: str) -> tuple[str, str]:
28 """Split the extension from the file name and return it and the root.
30 Parameters
31 ----------
32 file : `str`
33 The file name to examine.
35 Returns
36 -------
37 root : `str`
38 The root of the file name.
39 ext : `str`
40 The file extension. There is special case handling of .gz and other
41 compression extensions.
42 """
43 special = {".gz", ".bz2", ".xz", ".fz"}
45 root, ext = os.path.splitext(file)
47 if ext in special:
48 root, second_ext = os.path.splitext(root)
49 ext = second_ext + ext
51 return root, ext
54def write_sidecar_file(
55 file: str,
56 hdrnum: int,
57 content_mode: str,
58 print_trace: bool,
59 outstream: IO | None = None,
60) -> bool:
61 """Write JSON summary to sidecar file.
63 Parameters
64 ----------
65 file : `str`
66 The file from which the header is to be read.
67 hdrnum : `int`
68 The HDU number to read. The primary header is always read and
69 merged with the header from this HDU.
70 content_mode : `str`
71 Content mode to use when writing JSON to sidecar. Options are:
72 ``metadata`` to write the unmodified header;
73 ``translated`` to write the translated ObservationInfo.
74 print_trace : `bool`
75 If there is an error reading the file and this parameter is `True`,
76 a full traceback of the exception will be reported. If `False` prints
77 a one line summary of the error condition. If `None` the exception
78 will be allowed.
79 outstream : `io.StringIO`, optional
80 Output stream to use for standard messages. Defaults to `None` which
81 uses the default output stream.
83 Returns
84 -------
85 success : `bool`
86 `True` if the file was handled successfully, `False` if the file
87 could not be processed.
88 """
89 if content_mode not in ("metadata", "translated"):
90 raise ValueError(f"Specified content mode '{content_mode}' is not understood.")
92 try:
93 # Calculate the JSON from the file
94 json_str = read_file_info(
95 file,
96 hdrnum,
97 content_mode=content_mode,
98 content_type="json",
99 print_trace=print_trace,
100 outstream=outstream,
101 )
102 if json_str is None:
103 return False
105 # Calculate sidecar file name derived from this file.
106 # Match the ButlerURI behavior in that .fits.gz should be replaced
107 # with .json, and not resulting in .fits.json.
108 root, ext = _split_ext(file)
109 newfile = root + ".json"
110 with open(newfile, "w") as fd:
111 print(json_str, file=fd)
112 log.debug("Writing sidecar file %s", newfile)
114 except Exception as e:
115 if print_trace is None:
116 raise e
117 if print_trace:
118 traceback.print_exc(file=outstream)
119 else:
120 print(repr(e), file=outstream)
121 return False
122 return True
125def write_sidecar_files(
126 files: Sequence[str],
127 regex: str,
128 hdrnum: int,
129 content_mode: str,
130 print_trace: bool,
131 outstream: IO | None = None,
132) -> tuple[list[str], list[str]]:
133 """Process each file and create sidecar file.
135 Parameters
136 ----------
137 files : iterable of `str`
138 The files or directories from which the headers are to be read.
139 regex : `str`
140 Regular expression string used to filter files when a directory is
141 scanned.
142 hdrnum : `int`
143 The HDU number to read. The primary header is always read and
144 merged with the header from this HDU.
145 content_mode : `str`
146 Content mode to use when writing JSON to sidecar. Options are:
147 ``metadata`` to write the unmodified header;
148 ``translated`` to write the translated ObservationInfo.
149 print_trace : `bool`
150 If there is an error reading the file and this parameter is `True`,
151 a full traceback of the exception will be reported. If `False` prints
152 a one line summary of the error condition.
153 outstream : `io.StringIO`, optional
154 Output stream to use for standard messages. Defaults to `None` which
155 uses the default output stream.
157 Returns
158 -------
159 okay : `list` of `str`
160 All the files that were processed successfully.
161 failed : `list` of `str`
162 All the files that could not be processed.
163 """
164 found_files = find_files(files, regex)
166 # Process each file
167 failed = []
168 okay = []
169 for path in sorted(found_files):
170 isok = write_sidecar_file(path, hdrnum, content_mode, print_trace, outstream)
171 if isok:
172 okay.append(path)
173 else:
174 failed.append(path)
176 return okay, failed