Coverage for python / lsst / obs / base / cli / butler_cmd_test.py: 50%
36 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-04-30 08:52 +0000
« prev ^ index » next coverage.py v7.13.5, created at 2026-04-30 08:52 +0000
1# This file is part of obs_base.
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# This program is free software: you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation, either version 3 of the License, or
12# (at your option) any later version.
13#
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with this program. If not, see <https://www.gnu.org/licenses/>.
22"""Base class for writing CLI butler command tests."""
24from __future__ import annotations
26__all__ = ("ButlerCmdTestBase",)
28import abc
29from typing import TYPE_CHECKING
31from lsst.daf.butler.cli import butler
32from lsst.daf.butler.cli.utils import LogCliRunner
33from lsst.utils import doImportType
35from .._instrument import Instrument
37if TYPE_CHECKING:
38 from collections.abc import Callable
41class ButlerCmdTestBase(metaclass=abc.ABCMeta):
42 """Base class for tests of butler command line interface subcommands.
43 Subclass from this, then `unittest.TestCase` to get a working test suite.
44 """
46 if TYPE_CHECKING:
47 assertEqual: Callable
49 @property
50 @abc.abstractmethod
51 def instrumentClassName(self) -> str:
52 """The fully qualified instrument class name.
54 Returns
55 -------
56 `str`
57 The fully qualified instrument class name.
58 """
59 pass
61 @property
62 def secondInstrumentClassName(self) -> str | None:
63 """Optional; if provided the register-instrument test will try to
64 register two instruments.
66 Returns
67 -------
68 `str` or `None`
69 The fully qualified instrument class name.
70 """
71 return None
73 @property
74 def instrument(self) -> type[Instrument]:
75 """The instrument class."""
76 inst_class = doImportType(self.instrumentClassName)
77 assert issubclass(inst_class, Instrument)
78 return inst_class
80 @property
81 def instrumentName(self) -> str:
82 """The name of the instrument.
84 Returns
85 -------
86 `str`
87 The name of the instrument.
88 """
89 return self.instrument.getName()
91 def test_cli(self) -> None:
92 runner = LogCliRunner()
93 with runner.isolated_filesystem():
94 result = runner.invoke(butler.cli, ["create", "here"])
95 self.assertEqual(result.exit_code, 0, f"output: {result.output} exception: {result.exception}")
96 registerInstrumentArgs = ["register-instrument", "here", self.instrumentClassName]
97 if self.secondInstrumentClassName is not None:
98 registerInstrumentArgs.append(self.secondInstrumentClassName)
99 result = runner.invoke(butler.cli, registerInstrumentArgs)
100 self.assertEqual(result.exit_code, 0, f"output: {result.output} exception: {result.exception}")
101 result = runner.invoke(
102 butler.cli,
103 ["write-curated-calibrations", "here", self.instrumentName, "--collection", "collection"],
104 )
105 self.assertEqual(result.exit_code, 0, f"output: {result.output} exception: {result.exception}")