Coverage for python/lsst/daf/butler/dimensions/_governor.py: 67%

43 statements  

« prev     ^ index     » next       coverage.py v7.4.1, created at 2024-02-01 11:20 +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/>. 

27 

28from __future__ import annotations 

29 

30__all__ = ("GovernorDimension",) 

31 

32from collections.abc import Mapping 

33from types import MappingProxyType 

34 

35from .._named import NamedValueAbstractSet, NamedValueSet 

36from .._topology import TopologicalFamily, TopologicalSpace 

37from ._elements import Dimension, KeyColumnSpec, MetadataColumnSpec 

38 

39 

40class GovernorDimension(Dimension): 

41 """Governor dimension. 

42 

43 A special `Dimension` with no dependencies and a small number of rows, 

44 used to group the dimensions that depend on it. 

45 

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. 

59 

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. 

70 

71 Governor dimensions may not be associated with any kind of topological 

72 extent. 

73 

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 """ 

83 

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 ) 

107 

108 MAX_KEY_LENGTH = 128 

109 

110 @property 

111 def name(self) -> str: 

112 # Docstring inherited from TopologicalRelationshipEndpoint. 

113 return self._name 

114 

115 @property 

116 def required(self) -> NamedValueAbstractSet[Dimension]: 

117 # Docstring inherited from DimensionElement. 

118 return self._required 

119 

120 @property 

121 def implied(self) -> NamedValueAbstractSet[Dimension]: 

122 # Docstring inherited from DimensionElement. 

123 return NamedValueSet().freeze() 

124 

125 @property 

126 def topology(self) -> Mapping[TopologicalSpace, TopologicalFamily]: 

127 # Docstring inherited from TopologicalRelationshipEndpoint 

128 return MappingProxyType({}) 

129 

130 @property 

131 def metadata_columns(self) -> NamedValueAbstractSet[MetadataColumnSpec]: 

132 # Docstring inherited from DimensionElement. 

133 return self._metadata_columns 

134 

135 @property 

136 def unique_keys(self) -> NamedValueAbstractSet[KeyColumnSpec]: 

137 # Docstring inherited from Dimension. 

138 return self._unique_keys 

139 

140 @property 

141 def is_cached(self) -> bool: 

142 # Docstring inherited. 

143 return True 

144 

145 @property 

146 def documentation(self) -> str: 

147 # Docstring inherited from DimensionElement. 

148 return self._doc