Coverage for python/lsst/daf/butler/registry/_defaults.py: 34%

47 statements  

« prev     ^ index     » next       coverage.py v6.5.0, created at 2023-01-07 02:05 -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/>. 

21 

22from __future__ import annotations 

23 

24__all__ = ("RegistryDefaults",) 

25 

26from collections.abc import Sequence 

27from typing import TYPE_CHECKING, AbstractSet, Any, Optional 

28 

29from lsst.utils.classes import immutable 

30 

31from ..core import DataCoordinate 

32from ._collection_summary import CollectionSummary 

33from ._exceptions import MissingCollectionError 

34from .wildcards import CollectionWildcard 

35 

36if TYPE_CHECKING: 36 ↛ 37line 36 didn't jump to line 37, because the condition on line 36 was never true

37 from ._registry import Registry 

38 

39 

40@immutable 

41class RegistryDefaults: 

42 """A struct used to provide the default collections searched or written to 

43 by a `Registry` or `Butler` instance. 

44 

45 Parameters 

46 ---------- 

47 collections : `str` or `Iterable` [ `str` ], optional 

48 An expression specifying the collections to be searched (in order) when 

49 reading datasets. If a default value for a governor dimension is not 

50 given via ``**kwargs``, and exactly one value for that dimension 

51 appears in the datasets in ``collections``, that value is also used as 

52 the default for that dimension. 

53 This may be a `str` collection name or an iterable thereof. 

54 See :ref:`daf_butler_collection_expressions` for more information. 

55 These collections are not registered automatically and must be 

56 manually registered before they are used by any `Registry` or `Butler` 

57 method, but they may be manually registered after a `Registry` or 

58 `Butler` is initialized with this struct. 

59 run : `str`, optional 

60 Name of the `~CollectionType.RUN` collection new datasets should be 

61 inserted into. If ``collections`` is `None` and ``run`` is not `None`, 

62 ``collections`` will be set to ``[run]``. If not `None`, this 

63 collection will automatically be registered when the default struct is 

64 attached to a `Registry` instance. 

65 infer : `bool`, optional 

66 If `True` (default) infer default data ID values from the values 

67 present in the datasets in ``collections``: if all collections have the 

68 same value (or no value) for a governor dimension, that value will be 

69 the default for that dimension. Nonexistent collections are ignored. 

70 If a default value is provided explicitly for a governor dimension via 

71 ``**kwargs``, no default will be inferred for that dimension. 

72 **kwargs : `str` 

73 Default data ID key-value pairs. These may only identify "governor" 

74 dimensions like ``instrument`` and ``skymap``, though this is only 

75 checked when the defaults struct is actually attached to a `Registry`. 

76 """ 

77 

78 def __init__(self, collections: Any = None, run: Optional[str] = None, infer: bool = True, **kwargs: str): 

79 if collections is None: 

80 if run is not None: 

81 collections = (run,) 

82 else: 

83 collections = () 

84 self.collections = CollectionWildcard.from_expression(collections).require_ordered() 

85 self.run = run 

86 self._infer = infer 

87 self._kwargs = kwargs 

88 

89 def finish(self, registry: Registry) -> None: 

90 """Validate the defaults struct and standardize its data ID. 

91 

92 This should be called only by a `Registry` instance when the defaults 

93 struct is first associated with it. 

94 

95 Parameters 

96 ---------- 

97 registry : `Registry` 

98 Registry instance these defaults are being attached to. 

99 

100 Raises 

101 ------ 

102 TypeError 

103 Raised if a non-governor dimension was included in ``**kwargs`` 

104 at construction. 

105 """ 

106 allGovernorDimensions = registry.dimensions.getGovernorDimensions() 

107 if not self._kwargs.keys() <= allGovernorDimensions.names: 

108 raise TypeError( 

109 "Only governor dimensions may be identified by a default data " 

110 f"ID, not {self._kwargs.keys() - allGovernorDimensions.names}. " 

111 "(These may just be unrecognized keyword arguments passed at " 

112 "Butler construction.)" 

113 ) 

114 if self._infer and not self._kwargs.keys() == allGovernorDimensions.names: 

115 summaries = [] 

116 for collection in self.collections: 

117 try: 

118 summaries.append(registry.getCollectionSummary(collection)) 

119 except MissingCollectionError: 

120 pass 

121 if summaries: 

122 summary = CollectionSummary.union(*summaries) 

123 for dimensionName in allGovernorDimensions.names - self._kwargs.keys(): 

124 values: AbstractSet[str] = summary.governors.get(dimensionName, frozenset()) 

125 if len(values) == 1: 

126 (value,) = values 

127 self._kwargs[dimensionName] = value 

128 self.dataId = registry.expandDataId(self._kwargs, withDefaults=False) 

129 

130 collections: Sequence[str] 

131 """The collections to search by default, in order (`Sequence` [ `str` ]). 

132 """ 

133 

134 run: Optional[str] 

135 """Name of the run this butler writes outputs to by default (`str` or 

136 `None`). 

137 """ 

138 

139 dataId: DataCoordinate 

140 """The default data ID (`DataCoordinate`). 

141 

142 Dimensions without defaults are simply not included. Only governor 

143 dimensions are ever included in defaults. 

144 

145 This attribute may not be accessed before the defaults struct is 

146 attached to a `Registry` instance. It always satisfies both ``hasFull`` 

147 and ``hasRecords``. 

148 """