Coverage for python/lsst/daf/butler/registry/queries/_query_backend.py: 40%
39 statements
« prev ^ index » next coverage.py v6.5.0, created at 2022-11-09 02:51 -0800
« prev ^ index » next coverage.py v6.5.0, created at 2022-11-09 02:51 -0800
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__ = ("QueryBackend",)
25from abc import ABC, abstractmethod
26from collections.abc import Set
27from typing import TYPE_CHECKING, Any
29from .._collectionType import CollectionType
30from .._exceptions import DatasetTypeError, MissingDatasetTypeError
32if TYPE_CHECKING: 32 ↛ 33line 32 didn't jump to line 33, because the condition on line 32 was never true
33 from ...core import DatasetType, DimensionUniverse
34 from ..interfaces import CollectionRecord
35 from ..managers import RegistryManagerInstances
38class QueryBackend(ABC):
39 """An interface for constructing and evaluating the
40 `~lsst.daf.relation.Relation` objects that comprise registry queries.
42 This ABC is expected to have a concrete subclass for each concrete registry
43 type.
44 """
46 @property
47 @abstractmethod
48 def managers(self) -> RegistryManagerInstances:
49 """A struct containing the manager instances that back a SQL registry.
51 Notes
52 -----
53 This property is a temporary interface that will be removed in favor of
54 new methods once the manager and storage classes have been integrated
55 with `~lsst.daf.relation.Relation`.
56 """
57 raise NotImplementedError()
59 @property
60 @abstractmethod
61 def universe(self) -> DimensionUniverse:
62 """Definition of all dimensions and dimension elements for this
63 registry.
64 """
65 raise NotImplementedError()
67 @abstractmethod
68 def resolve_collection_wildcard(
69 self,
70 expression: Any,
71 *,
72 collection_types: Set[CollectionType] = CollectionType.all(),
73 done: set[str] | None = None,
74 flatten_chains: bool = True,
75 include_chains: bool | None = None,
76 ) -> list[CollectionRecord]:
77 """Return the collection records that match a wildcard expression.
79 Parameters
80 ----------
81 expression
82 Names and/or patterns for collections; will be passed to
83 `CollectionWildcard.from_expression`.
84 collection_types : `collections.abc.Set` [ `CollectionType` ], optional
85 If provided, only yield collections of these types.
86 done : `set` [ `str` ], optional
87 A set of collection names that should be skipped, updated to
88 include all processed collection names on return.
89 flatten_chains : `bool`, optional
90 If `True` (default) recursively yield the child collections of
91 `~CollectionType.CHAINED` collections.
92 include_chains : `bool`, optional
93 If `False`, return records for `~CollectionType.CHAINED`
94 collections themselves. The default is the opposite of
95 ``flattenChains``: either return records for CHAINED collections or
96 their children, but not both.
98 Returns
99 -------
100 records : `list` [ `CollectionRecord` ]
101 Matching collection records.
102 """
103 raise NotImplementedError()
105 @abstractmethod
106 def resolve_dataset_type_wildcard(
107 self,
108 expression: Any,
109 components: bool | None = None,
110 missing: list[str] | None = None,
111 explicit_only: bool = False,
112 ) -> dict[DatasetType, list[str | None]]:
113 """Return the dataset types that match a wildcard expression.
115 Parameters
116 ----------
117 expression
118 Names and/or patterns for dataset types; will be passed to
119 `DatasetTypeWildcard.from_expression`.
120 components : `bool`, optional
121 If `True`, apply all expression patterns to component dataset type
122 names as well. If `False`, never apply patterns to components. If
123 `None` (default), apply patterns to components only if their parent
124 datasets were not matched by the expression. Fully-specified
125 component datasets (`str` or `DatasetType` instances) are always
126 included.
127 missing : `list` of `str`, optional
128 String dataset type names that were explicitly given (i.e. not
129 regular expression patterns) but not found will be appended to this
130 list, if it is provided.
131 explicit_only : `bool`, optional
132 If `True`, require explicit `DatasetType` instances or `str` names,
133 with `re.Pattern` instances deprecated and ``...`` prohibited.
135 Returns
136 -------
137 dataset_types : `dict` [ `DatasetType`, `list` [ `None`, `str` ] ]
138 A mapping with resolved dataset types as keys and lists of
139 matched component names as values, where `None` indicates the
140 parent composite dataset type was matched.
141 """
142 raise NotImplementedError()
144 def resolve_single_dataset_type_wildcard(
145 self,
146 expression: Any,
147 components: bool | None = None,
148 explicit_only: bool = False,
149 ) -> tuple[DatasetType, list[str | None]]:
150 """Return a single dataset type that matches a wildcard expression.
152 Parameters
153 ----------
154 expression
155 Names and/or patterns for the dataset type; will be passed to
156 `DatasetTypeWildcard.from_expression`.
157 components : `bool`, optional
158 If `True`, apply all expression patterns to component dataset type
159 names as well. If `False`, never apply patterns to components. If
160 `None` (default), apply patterns to components only if their parent
161 datasets were not matched by the expression. Fully-specified
162 component datasets (`str` or `DatasetType` instances) are always
163 included.
165 Values other than `False` are deprecated, and only `False` will be
166 supported after v26. After v27 this argument will be removed
167 entirely.
168 explicit_only : `bool`, optional
169 If `True`, require explicit `DatasetType` instances or `str` names,
170 with `re.Pattern` instances deprecated and ``...`` prohibited.
172 Returns
173 -------
174 single_parent : `DatasetType`
175 The matched parent dataset type.
176 single_components : `list` [ `str` | `None` ]
177 The matched components that correspond to this parent, or `None` if
178 the parent dataset type itself was matched.
180 Notes
181 -----
182 This method really finds a single parent dataset type and any number of
183 components, because it's only the parent dataset type that's known to
184 registry at all; many callers are expected to discard the
185 ``single_components`` return value.
186 """
187 missing: list[str] = []
188 matching = self.resolve_dataset_type_wildcard(
189 expression, components=components, missing=missing, explicit_only=explicit_only
190 )
191 if not matching:
192 if missing:
193 raise MissingDatasetTypeError(
194 "\n".join(
195 f"Dataset type {t!r} is not registered, so no instances of it can exist."
196 for t in missing
197 )
198 )
199 else:
200 raise MissingDatasetTypeError(
201 f"No registered dataset types matched expression {expression!r}, "
202 "so no datasets will be found."
203 )
204 if len(matching) > 1:
205 raise DatasetTypeError(
206 f"Expression {expression!r} matched multiple parent dataset types: "
207 f"{[t.name for t in matching]}, but only one is allowed."
208 )
209 ((single_parent, single_components),) = matching.items()
210 if missing:
211 raise DatasetTypeError(
212 f"Expression {expression!r} appears to involve multiple dataset types, even though only "
213 f"one ({single_parent.name}) is registered, and only one is allowed here."
214 )
215 return single_parent, single_components