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