Coverage for python/lsst/daf/butler/remote_butler/_ref_utils.py: 0%

39 statements  

« prev     ^ index     » next       coverage.py v7.15.2, created at 2026-07-16 14:47 -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/>. 

27 

28from __future__ import annotations 

29 

30__all__ = ( 

31 "apply_storage_class_override", 

32 "get_component_override", 

33 "normalize_dataset_type_name", 

34 "simplify_dataId", 

35 "split_dataset_type_name", 

36) 

37 

38from pydantic import TypeAdapter 

39 

40from .._dataset_ref import DatasetRef 

41from .._dataset_type import DatasetType, get_dataset_type_name 

42from .._storage_class import StorageClass 

43from ..dimensions import DataCoordinate, DataId, DataIdValue, SerializedDataId 

44from .server_models import DatasetTypeName 

45 

46_SERIALIZED_DATA_ID_TYPE_ADAPTER = TypeAdapter(SerializedDataId) 

47 

48 

49def apply_storage_class_override( 

50 ref: DatasetRef, 

51 original_dataset_ref_or_type: DatasetRef | DatasetType | str, 

52 explicit_storage_class: StorageClass | str | None, 

53) -> DatasetRef: 

54 """Return a DatasetRef with its storage class overridden to match the 

55 StorageClass supplied by the user as input to one of the search functions. 

56 

57 Parameters 

58 ---------- 

59 ref : `DatasetRef` 

60 The ref to which we will apply the StorageClass override. 

61 original_dataset_ref_or_type : `DatasetRef` | `DatasetType` | `str` 

62 The ref or type that was input to the search, which may contain a 

63 storage class override. 

64 explicit_storage_class : `StorageClass` | `str` | `None` 

65 A storage class that the user explicitly requested as an override. 

66 """ 

67 if explicit_storage_class is not None: 

68 return ref.overrideStorageClass(explicit_storage_class) 

69 

70 # If the caller provided a DatasetRef or DatasetType, they may have 

71 # overridden the storage class on it, and we need to propagate that to the 

72 # output. 

73 dataset_type = _extract_dataset_type(original_dataset_ref_or_type) 

74 if dataset_type is not None: 

75 return ref.overrideStorageClass(dataset_type.storageClass) 

76 

77 return ref 

78 

79 

80def normalize_dataset_type_name(datasetTypeOrName: DatasetType | str) -> DatasetTypeName: 

81 """Convert DatasetType parameters in the format used by Butler methods 

82 to a standardized string name for the REST API. 

83 

84 Parameters 

85 ---------- 

86 datasetTypeOrName : `DatasetType` | `str` 

87 A DatasetType, or the name of a DatasetType. This union is a common 

88 parameter in many `Butler` methods. 

89 """ 

90 return DatasetTypeName(get_dataset_type_name(datasetTypeOrName)) 

91 

92 

93def split_dataset_type_name( 

94 datasetTypeOrName: DatasetType | str, 

95) -> tuple[DatasetTypeName, str | None]: 

96 """Split a dataset type parameter into a parent dataset type name and an 

97 optional component name. 

98 

99 Component dataset type names must never be sent to the server -- the 

100 server cannot construct a component `DatasetType` unless it has the 

101 parent's storage class definition available, and storage classes are 

102 often defined by science pipelines packages that are only installed on 

103 the client. Callers should request the parent dataset type from the 

104 server and re-apply the component on the client side. 

105 

106 Parameters 

107 ---------- 

108 datasetTypeOrName : `DatasetType` | `str` 

109 A DatasetType, or the name of a DatasetType. 

110 

111 Returns 

112 ------- 

113 parent_name : `DatasetTypeName` 

114 Name of the parent dataset type, suitable for sending to the server. 

115 component : `str` | `None` 

116 Component name, or `None` if this is not a component dataset type. 

117 """ 

118 parent_name, component = DatasetType.splitDatasetTypeName(get_dataset_type_name(datasetTypeOrName)) 

119 return DatasetTypeName(parent_name), component 

120 

121 

122def get_component_override(datasetRefOrType: DatasetRef | DatasetType | str) -> str | None: 

123 """Return the component name from a ref or dataset type provided by the 

124 user, or `None` if it does not refer to a component. 

125 

126 Parameters 

127 ---------- 

128 datasetRefOrType : `DatasetRef` | `DatasetType` | `str` 

129 A DatasetRef, DatasetType, or name of a DatasetType. This union is a 

130 common parameter in many `Butler` methods. 

131 """ 

132 if isinstance(datasetRefOrType, DatasetRef): 

133 return datasetRefOrType.datasetType.component() 

134 _, component = split_dataset_type_name(datasetRefOrType) 

135 return component 

136 

137 

138def simplify_dataId(dataId: DataId | None, kwargs: dict[str, DataIdValue]) -> SerializedDataId: 

139 """Take a generic Data ID and convert it to a serializable form. 

140 

141 Parameters 

142 ---------- 

143 dataId : `dict`, `None`, `DataCoordinate` 

144 The data ID to serialize. 

145 kwargs : `dict` 

146 Additional entries to augment or replace the values in ``dataId``. 

147 

148 Returns 

149 ------- 

150 data_id : `SerializedDataId` 

151 A serializable form. 

152 """ 

153 if dataId is None: 

154 dataId = {} 

155 elif isinstance(dataId, DataCoordinate): 

156 dataId = dataId.to_simple(minimal=True).dataId 

157 else: 

158 dataId = dict(dataId) 

159 

160 return _SERIALIZED_DATA_ID_TYPE_ADAPTER.validate_python(dataId | kwargs) 

161 

162 

163def _extract_dataset_type(datasetRefOrType: DatasetRef | DatasetType | str) -> DatasetType | None: 

164 """Return the DatasetType associated with the argument, or None if the 

165 argument is not an object that contains a DatasetType object. 

166 

167 Parameters 

168 ---------- 

169 datasetRefOrType : `DatasetRef` | `DatasetType` | `str` 

170 A DatasetRef, DatasetType, or name of a DatasetType. This union is a 

171 common parameter in many `Butler` methods. 

172 """ 

173 if isinstance(datasetRefOrType, DatasetType): 

174 return datasetRefOrType 

175 elif isinstance(datasetRefOrType, DatasetRef): 

176 return datasetRefOrType.datasetType 

177 else: 

178 return None