Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

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 

22__all__ = ("DummyRegistry", ) 

23 

24 

25from typing import Any, Iterable, Iterator, Optional, Type 

26 

27import sqlalchemy 

28 

29from lsst.daf.butler import ddl, DatasetRef, DimensionUniverse 

30from lsst.daf.butler.registry.interfaces import ( 

31 Database, 

32 DatasetRecordStorageManager, 

33 DatastoreRegistryBridge, 

34 DatastoreRegistryBridgeManager, 

35 OpaqueTableStorageManager, 

36 OpaqueTableStorage, 

37 StaticTablesContext, 

38 VersionTuple 

39) 

40from lsst.daf.butler.registry.bridge.ephemeral import EphemeralDatastoreRegistryBridge 

41 

42 

43class DummyOpaqueTableStorage(OpaqueTableStorage): 

44 

45 def __init__(self, name: str, spec: ddl.TableSpec): 

46 super().__init__(name=name) 

47 self._rows = [] 

48 self._spec = spec 

49 

50 def insert(self, *data: dict): 

51 # Docstring inherited from OpaqueTableStorage. 

52 uniqueConstraints = list(self._spec.unique) 

53 uniqueConstraints.append(tuple(field.name for field in self._spec.fields if field.primaryKey)) 

54 for d in data: 

55 for constraint in uniqueConstraints: 

56 matching = list(self.fetch(**{k: d[k] for k in constraint})) 

57 if len(matching) != 0: 

58 raise RuntimeError(f"Unique constraint {constraint} violation " 

59 "in external table {self.name}.") 

60 self._rows.append(d) 

61 

62 def fetch(self, **where: Any) -> Iterator[dict]: 

63 # Docstring inherited from OpaqueTableStorage. 

64 for d in self._rows: 

65 if all(d[k] == v for k, v in where.items()): 

66 yield d 

67 

68 def delete(self, columns: Iterable[str], *rows: dict): 

69 # Docstring inherited from OpaqueTableStorage. 

70 kept_rows = [] 

71 for table_row in self._rows: 

72 for where_row in rows: 

73 if all(table_row[k] == v for k, v in where_row.items()): 

74 break 

75 else: 

76 kept_rows.append(table_row) 

77 self._rows = kept_rows 

78 

79 

80class DummyOpaqueTableStorageManager(OpaqueTableStorageManager): 

81 

82 def __init__(self): 

83 self._storages = {} 

84 

85 @classmethod 

86 def initialize(cls, db: Database, context: StaticTablesContext) -> OpaqueTableStorageManager: 

87 # Docstring inherited from OpaqueTableStorageManager. 

88 # Not used, but needed to satisfy ABC requirement. 

89 return cls() 

90 

91 def get(self, name: str) -> Optional[OpaqueTableStorage]: 

92 # Docstring inherited from OpaqueTableStorageManager. 

93 return self._storage.get(name) 

94 

95 def register(self, name: str, spec: ddl.TableSpec) -> OpaqueTableStorage: 

96 # Docstring inherited from OpaqueTableStorageManager. 

97 return self._storages.setdefault(name, DummyOpaqueTableStorage(name, spec)) 

98 

99 @classmethod 

100 def currentVersion(cls) -> Optional[VersionTuple]: 

101 # Docstring inherited from VersionedExtension. 

102 return None 

103 

104 def schemaDigest(self) -> Optional[str]: 

105 # Docstring inherited from VersionedExtension. 

106 return None 

107 

108 

109class DummyDatastoreRegistryBridgeManager(DatastoreRegistryBridgeManager): 

110 

111 def __init__(self, opaque: OpaqueTableStorageManager, universe: DimensionUniverse, 

112 datasetIdColumnType: type): 

113 super().__init__(opaque=opaque, universe=universe, datasetIdColumnType=datasetIdColumnType) 

114 self._bridges = {} 

115 

116 @classmethod 

117 def initialize(cls, db: Database, context: StaticTablesContext, *, 

118 opaque: OpaqueTableStorageManager, 

119 datasets: Type[DatasetRecordStorageManager], 

120 universe: DimensionUniverse, 

121 ) -> DatastoreRegistryBridgeManager: 

122 # Docstring inherited from DatastoreRegistryBridgeManager 

123 # Not used, but needed to satisfy ABC requirement. 

124 return cls(opaque=opaque, universe=universe, datasetIdColumnType=datasets.getIdColumnType()) 

125 

126 def refresh(self): 

127 # Docstring inherited from DatastoreRegistryBridgeManager 

128 pass 

129 

130 def register(self, name: str, *, ephemeral: bool = False) -> DatastoreRegistryBridge: 

131 # Docstring inherited from DatastoreRegistryBridgeManager 

132 return self._bridges.setdefault(name, EphemeralDatastoreRegistryBridge(name)) 

133 

134 def findDatastores(self, ref: DatasetRef) -> Iterable[str]: 

135 # Docstring inherited from DatastoreRegistryBridgeManager 

136 for name, bridge in self._bridges.items(): 

137 if ref in bridge: 

138 yield name 

139 

140 @classmethod 

141 def currentVersion(cls) -> Optional[VersionTuple]: 

142 # Docstring inherited from VersionedExtension. 

143 return None 

144 

145 def schemaDigest(self) -> Optional[str]: 

146 # Docstring inherited from VersionedExtension. 

147 return None 

148 

149 

150class DummyRegistry: 

151 """Dummy Registry, for Datastore test purposes. 

152 """ 

153 def __init__(self): 

154 self._opaque = DummyOpaqueTableStorageManager() 

155 self.dimensions = DimensionUniverse() 

156 self._datastoreBridges = DummyDatastoreRegistryBridgeManager( 

157 self._opaque, self.dimensions, sqlalchemy.BigInteger) 

158 

159 def getDatastoreBridgeManager(self): 

160 return self._datastoreBridges