Coverage for python/lsst/daf/butler/cli/cmd/_remove_runs.py: 38%
61 statements
« prev ^ index » next coverage.py v6.5.0, created at 2023-02-05 10:07 +0000
« prev ^ index » next coverage.py v6.5.0, created at 2023-02-05 10:07 +0000
1# This file is part of daf_butler.
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 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 <http://www.gnu.org/licenses/>.
21from __future__ import annotations
23__all__ = ["remove_runs"]
25from collections.abc import Mapping, Sequence
26from typing import Any
28import click
30from ... import script
31from ..opt import collection_argument, confirm_option, options_file_option, repo_argument
32from ..utils import ButlerCommand
33from .commands import existingRepoHelp
35# messages emitted by remove-runs, defined separately for use in unit
36# tests.
37noRunCollectionsMsg = "No RUN collections were found."
38willRemoveRunsMsg = "The following RUN collections will be removed:"
39willRemoveDatasetsMsg = "The following datasets will be removed:"
40didRemoveRunsMsg = "The following RUN collections were removed:"
41didRemoveDatasetsMsg = "The following datasets were removed:"
42removedRunsMsg = "Removed collections"
43abortedMsg = "Aborted."
44requiresConfirmationMsg = (
45 "Removing runs that are in parent CHAINED collections requires confirmation. "
46 "\nTry again without --no-confirm to confirm removal of RUN collections from parents, "
47 "or add the --force flag to skip confirmation."
48)
49willUnlinkMsg = "{run}: will be unlinked from {parents}"
50didUnlinkMsg = "{run}: was removed and unlinked from {parents}"
51mustBeUnlinkedMsg = "{run}: must be unlinked from {parents}"
54def _quoted(items: Sequence[str]) -> list[str]:
55 return [f'"{i}"' for i in items]
58def _print_remove(will: bool, runs: Sequence[script.RemoveRun], datasets: Mapping[str, int]) -> None:
59 """Print the formatted remove statement.
61 Parameters
62 ----------
63 will : bool
64 True if remove "will" happen, False if the remove "did" happen.
65 runs : Sequence[str]
66 The RUNs that will be or were removed.
67 datasets : Mapping[str, int]
68 The dataset types & count that will be or were removed.
69 """
70 print(willRemoveRunsMsg if will else didRemoveRunsMsg)
71 unlinkMsg = willUnlinkMsg if will else didUnlinkMsg
72 for run in runs:
73 if run.parents:
74 print(unlinkMsg.format(run=run.name, parents=", ".join(_quoted(run.parents))))
75 else:
76 print(run.name)
77 print("\n" + willRemoveDatasetsMsg if will else didRemoveDatasetsMsg)
78 print(", ".join([f"{i[0]}({i[1]})" for i in datasets.items()]))
81def _print_requires_confirmation(runs: Sequence[script.RemoveRun], datasets: Mapping[str, int]) -> None:
82 print(requiresConfirmationMsg)
83 for run in runs:
84 if run.parents:
85 print(mustBeUnlinkedMsg.format(run=run.name, parents=", ".join(_quoted(run.parents))))
88@click.command(cls=ButlerCommand)
89@click.pass_context
90@repo_argument(
91 help=existingRepoHelp,
92 required=True,
93)
94@collection_argument(
95 help="COLLECTION is a glob-style expression that identifies the RUN collection(s) to remove."
96)
97@confirm_option()
98@click.option(
99 "--force",
100 is_flag=True,
101 help="Required to remove RUN collections from parent collections if using --no-confirm.",
102)
103@options_file_option()
104def remove_runs(context: click.Context, confirm: bool, force: bool, **kwargs: Any) -> None:
105 """Remove one or more RUN collections.
107 This command can be used to remove RUN collections and the datasets within
108 them.
109 """
110 result = script.removeRuns(**kwargs)
111 canRemoveRuns = len(result.runs)
112 if not canRemoveRuns:
113 print(noRunCollectionsMsg)
114 return
115 if confirm:
116 _print_remove(True, result.runs, result.datasets)
117 doContinue = click.confirm(text="Continue?", default=False)
118 if doContinue:
119 result.onConfirmation()
120 print(removedRunsMsg)
121 else:
122 print(abortedMsg)
123 else:
124 # if the user opted out of confirmation but there are runs with
125 # parent collections then they must confirm; print a message
126 # and exit.
127 if any(run.parents for run in result.runs) and not force:
128 _print_requires_confirmation(result.runs, result.datasets)
129 context.exit(1)
130 result.onConfirmation()
131 _print_remove(False, result.runs, result.datasets)