Coverage for python/lsst/daf/butler/dimensions/_governor.py: 67%
43 statements
« prev ^ index » next coverage.py v7.4.4, created at 2024-04-15 02:03 -0700
« prev ^ index » next coverage.py v7.4.4, created at 2024-04-15 02:03 -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 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
30__all__ = ("GovernorDimension",)
32from collections.abc import Mapping
33from types import MappingProxyType
35from .._named import NamedValueAbstractSet, NamedValueSet
36from .._topology import TopologicalFamily, TopologicalSpace
37from ._elements import Dimension, KeyColumnSpec, MetadataColumnSpec
40class GovernorDimension(Dimension):
41 """Governor dimension.
43 A special `Dimension` with no dependencies and a small number of rows,
44 used to group the dimensions that depend on it.
46 Parameters
47 ----------
48 name : `str`
49 Name of the dimension.
50 metadata_columns : `NamedValueAbstractSet` [ `MetadataColumnSpec` ]
51 Field specifications for all non-key fields in this dimension's table.
52 unique_keys : `NamedValueAbstractSet` [ `KeyColumnSpec` ]
53 Fields that can each be used to uniquely identify this dimension (given
54 values for all required dimensions). The first of these is used as
55 (part of) this dimension's table's primary key, while others are used
56 to define unique constraints.
57 doc : `str`
58 Extended description of this element.
60 Notes
61 -----
62 Most dimensions have exactly one governor dimension as a required
63 dependency, and queries that involve those dimensions are always expected
64 to explicitly identify the governor dimension value(s), rather than
65 retrieve all matches from the database. Because governor values are thus
66 almost always known at query-generation time, they can be used there to
67 simplify queries, provide sensible defaults, or check in advance for common
68 mistakes that might otherwise yield confusing (albeit formally correct)
69 results instead of straightforward error messages.
71 Governor dimensions may not be associated with any kind of topological
72 extent.
74 Governor dimension rows are often affiliated with a Python class or
75 instance (e.g. `lsst.obs.base.Instrument`) that is capable of generating
76 the rows of at least some dependent dimensions or providing other related
77 functionality. In the future, we hope to attach these instances to
78 governor dimension records (instantiating them from information in the
79 database row when it is fetched), and use those objects to add additional
80 functionality to governor dimensions, but a number of (code) dependency
81 relationships would need to be reordered first.
82 """
84 def __init__(
85 self,
86 name: str,
87 *,
88 metadata_columns: NamedValueAbstractSet[MetadataColumnSpec],
89 unique_keys: NamedValueAbstractSet[KeyColumnSpec],
90 doc: str,
91 ):
92 self._name = name
93 self._required = NamedValueSet({self}).freeze()
94 self._metadata_columns = metadata_columns
95 self._unique_keys = unique_keys
96 self._doc = doc
97 if self.primaryKey.getPythonType() is not str:
98 raise TypeError(
99 f"Governor dimension '{name}' must have a string primary key (configured type "
100 f"is {self.primaryKey.dtype.__name__})."
101 )
102 if self.primaryKey.length is not None and self.primaryKey.length > self.MAX_KEY_LENGTH:
103 raise TypeError(
104 f"Governor dimension '{name}' must have a string primary key with length <= "
105 f"{self.MAX_KEY_LENGTH} (configured value is {self.primaryKey.length})."
106 )
108 MAX_KEY_LENGTH = 128
110 @property
111 def name(self) -> str:
112 # Docstring inherited from TopologicalRelationshipEndpoint.
113 return self._name
115 @property
116 def required(self) -> NamedValueAbstractSet[Dimension]:
117 # Docstring inherited from DimensionElement.
118 return self._required
120 @property
121 def implied(self) -> NamedValueAbstractSet[Dimension]:
122 # Docstring inherited from DimensionElement.
123 return NamedValueSet().freeze()
125 @property
126 def topology(self) -> Mapping[TopologicalSpace, TopologicalFamily]:
127 # Docstring inherited from TopologicalRelationshipEndpoint
128 return MappingProxyType({})
130 @property
131 def metadata_columns(self) -> NamedValueAbstractSet[MetadataColumnSpec]:
132 # Docstring inherited from DimensionElement.
133 return self._metadata_columns
135 @property
136 def unique_keys(self) -> NamedValueAbstractSet[KeyColumnSpec]:
137 # Docstring inherited from Dimension.
138 return self._unique_keys
140 @property
141 def is_cached(self) -> bool:
142 # Docstring inherited.
143 return True
145 @property
146 def documentation(self) -> str:
147 # Docstring inherited from DimensionElement.
148 return self._doc