Coverage for python/lsst/daf/butler/script/queryCollections.py: 8%
68 statements
« prev ^ index » next coverage.py v7.4.4, created at 2024-04-19 10:53 +0000
« prev ^ index » next coverage.py v7.4.4, created at 2024-04-19 10:53 +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 software is dual licensed under the GNU General Public License and also
10# under a 3-clause BSD license. Recipients may choose which of these licenses
11# to use; please see the files gpl-3.0.txt and/or bsd_license.txt,
12# respectively. If you choose the GPL option then the following text applies
13# (but note that there is still no warranty even if you opt for BSD instead):
14#
15# This program is free software: you can redistribute it and/or modify
16# it under the terms of the GNU General Public License as published by
17# the Free Software Foundation, either version 3 of the License, or
18# (at your option) any later version.
19#
20# This program is distributed in the hope that it will be useful,
21# but WITHOUT ANY WARRANTY; without even the implied warranty of
22# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23# GNU General Public License for more details.
24#
25# You should have received a copy of the GNU General Public License
26# along with this program. If not, see <http://www.gnu.org/licenses/>.
28from __future__ import annotations
30from collections.abc import Iterable
32from astropy.table import Table
34from .._butler import Butler
35from ..registry import CollectionType
38def _getTable(
39 repo: str,
40 glob: Iterable[str],
41 collection_type: Iterable[CollectionType],
42 inverse: bool,
43) -> Table:
44 """Run queryCollections and return the results in Table form.
46 Only lists the first child (or parent if `inverse` is `True`) in the
47 description column.
49 Parameters
50 ----------
51 repo : `str`
52 The Butler repository location.
53 glob : `collections.abc.Iterable` of `str`
54 Wildcard to pass to ``queryCollections``.
55 collection_type
56 Same as `queryCollections`
57 inverse : `bool`
58 True if parent CHAINED datasets of each dataset should be listed in the
59 description column, False if children of CHAINED datasets should be
60 listed.
62 Returns
63 -------
64 collections : `astropy.table.Table`
65 Same as `queryCollections`
66 """
67 typeCol = "Type"
68 descriptionCol = "Parents" if inverse else "Children"
69 table = Table(
70 names=("Name", typeCol, descriptionCol),
71 dtype=(str, str, str),
72 )
73 butler = Butler.from_config(repo)
74 names = sorted(
75 butler.registry.queryCollections(collectionTypes=frozenset(collection_type), expression=glob or ...)
76 )
77 if inverse:
78 for name in names:
79 type = butler.registry.getCollectionType(name)
80 parentNames = butler.registry.getCollectionParentChains(name)
81 if parentNames:
82 first = True
83 for parentName in sorted(parentNames):
84 table.add_row((name if first else "", type.name if first else "", parentName))
85 first = False
86 else:
87 table.add_row((name, type.name, ""))
88 # If none of the datasets has a parent dataset then remove the
89 # description column.
90 if not any(c for c in table[descriptionCol]):
91 del table[descriptionCol]
92 else:
93 for name in names:
94 type = butler.registry.getCollectionType(name)
95 if type == CollectionType.CHAINED:
96 children = butler.registry.getCollectionChain(name)
97 if children:
98 first = True
99 for child in children:
100 table.add_row((name if first else "", type.name if first else "", child))
101 first = False
102 else:
103 table.add_row((name, type.name, ""))
104 else:
105 table.add_row((name, type.name, ""))
106 # If there aren't any CHAINED datasets in the results then remove the
107 # description column.
108 if not any(columnVal == CollectionType.CHAINED.name for columnVal in table[typeCol]):
109 del table[descriptionCol]
111 return table
114def _getTree(
115 repo: str,
116 glob: Iterable[str],
117 collection_type: Iterable[CollectionType],
118 inverse: bool,
119) -> Table:
120 """Run queryCollections and return the results in a table representing tree
121 form.
123 Recursively lists children (or parents if `inverse` is `True`)
125 Parameters
126 ----------
127 repo : `str`
128 Butler repository location.
129 glob : `collections.abc.Iterable` of `str`
130 Wildcards to pass to ``queryCollections``.
131 collection_type
132 Same as `queryCollections`
133 inverse : `bool`
134 True if parent CHAINED datasets of each dataset should be listed in the
135 description column, False if children of CHAINED datasets should be
136 listed.
138 Returns
139 -------
140 collections : `astropy.table.Table`
141 Same as `queryCollections`
142 """
143 table = Table(
144 names=("Name", "Type"),
145 dtype=(str, str),
146 )
147 butler = Butler.from_config(repo, without_datastore=True)
149 def addCollection(name: str, level: int = 0) -> None:
150 collectionType = butler.registry.getCollectionType(name)
151 table.add_row((" " * level + name, collectionType.name))
152 if inverse:
153 parentNames = butler.registry.getCollectionParentChains(name)
154 for pname in sorted(parentNames):
155 addCollection(pname, level + 1)
156 else:
157 if collectionType == CollectionType.CHAINED:
158 childNames = butler.registry.getCollectionChain(name)
159 for name in childNames:
160 addCollection(name, level + 1)
162 collections = butler.registry.queryCollections(
163 collectionTypes=frozenset(collection_type), expression=glob or ...
164 )
165 for collection in sorted(collections):
166 addCollection(collection)
167 return table
170def _getFlatten(
171 repo: str,
172 glob: Iterable[str],
173 collection_type: Iterable[CollectionType],
174) -> Table:
175 butler = Butler.from_config(repo)
176 collectionNames = list(
177 butler.registry.queryCollections(
178 collectionTypes=frozenset(collection_type), flattenChains=True, expression=glob or ...
179 )
180 )
182 collectionTypes = [butler.registry.getCollectionType(c).name for c in collectionNames]
183 return Table((collectionNames, collectionTypes), names=("Name", "Type"))
186def queryCollections(
187 repo: str,
188 glob: Iterable[str],
189 collection_type: Iterable[CollectionType],
190 chains: str,
191) -> Table:
192 """Get the collections whose names match an expression.
194 Parameters
195 ----------
196 repo : `str`
197 URI to the location of the repo or URI to a config file describing the
198 repo and its location.
199 glob : `~collections.abc.Iterable` [`str`]
200 A list of glob-style search string that fully or partially identify
201 the dataset type names to search for.
202 collection_type : `~collections.abc.Iterable` [ `CollectionType` ], \
203 optional
204 If provided, only return collections of these types.
205 chains : `str`
206 Must be one of "FLATTEN", "TABLE", or "TREE" (case sensitive).
207 Affects contents and formatting of results, see
208 ``cli.commands.query_collections``.
210 Returns
211 -------
212 collections : `astropy.table.Table`
213 A table containing information about collections.
214 """
215 if (inverse := chains == "INVERSE-TABLE") or chains == "TABLE":
216 return _getTable(repo, glob, collection_type, inverse)
217 elif (inverse := chains == "INVERSE-TREE") or chains == "TREE":
218 return _getTree(repo, glob, collection_type, inverse)
219 elif chains == "FLATTEN":
220 return _getFlatten(repo, glob, collection_type)
221 raise RuntimeError(f"Value for --chains not recognized: {chains}")