Coverage for python/lsst/daf/butler/tests/_dummyRegistry.py: 31%
Shortcuts 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
Shortcuts 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/>.
22__all__ = ("DummyRegistry", )
25from typing import Any, Iterable, Iterator, Optional, Type
27import sqlalchemy
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
43class DummyOpaqueTableStorage(OpaqueTableStorage):
45 def __init__(self, name: str, spec: ddl.TableSpec):
46 super().__init__(name=name)
47 self._rows = []
48 self._spec = spec
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)
62 def fetch(self, **where: Any) -> Iterator[dict]:
63 # Docstring inherited from OpaqueTableStorage.
64 where = where.copy() # May need to modify it.
66 # Can support an IN operator if given list.
67 wherein = {}
68 for k in list(where):
69 if isinstance(where[k], (tuple, list, set)):
70 wherein[k] = set(where[k])
71 del where[k]
73 for d in self._rows:
74 if all(d[k] == v for k, v in where.items()):
75 if wherein:
76 match = True
77 for k, v in wherein.items():
78 if d[k] not in v:
79 match = False
80 break
81 if match:
82 yield d
83 else:
84 yield d
86 def delete(self, columns: Iterable[str], *rows: dict):
87 # Docstring inherited from OpaqueTableStorage.
88 kept_rows = []
89 for table_row in self._rows:
90 for where_row in rows:
91 if all(table_row[k] == v for k, v in where_row.items()):
92 break
93 else:
94 kept_rows.append(table_row)
95 self._rows = kept_rows
98class DummyOpaqueTableStorageManager(OpaqueTableStorageManager):
100 def __init__(self):
101 self._storages = {}
103 @classmethod
104 def initialize(cls, db: Database, context: StaticTablesContext) -> OpaqueTableStorageManager:
105 # Docstring inherited from OpaqueTableStorageManager.
106 # Not used, but needed to satisfy ABC requirement.
107 return cls()
109 def get(self, name: str) -> Optional[OpaqueTableStorage]:
110 # Docstring inherited from OpaqueTableStorageManager.
111 return self._storage.get(name)
113 def register(self, name: str, spec: ddl.TableSpec) -> OpaqueTableStorage:
114 # Docstring inherited from OpaqueTableStorageManager.
115 return self._storages.setdefault(name, DummyOpaqueTableStorage(name, spec))
117 @classmethod
118 def currentVersion(cls) -> Optional[VersionTuple]:
119 # Docstring inherited from VersionedExtension.
120 return None
122 def schemaDigest(self) -> Optional[str]:
123 # Docstring inherited from VersionedExtension.
124 return None
127class DummyDatastoreRegistryBridgeManager(DatastoreRegistryBridgeManager):
129 def __init__(self, opaque: OpaqueTableStorageManager, universe: DimensionUniverse,
130 datasetIdColumnType: type):
131 super().__init__(opaque=opaque, universe=universe, datasetIdColumnType=datasetIdColumnType)
132 self._bridges = {}
134 @classmethod
135 def initialize(cls, db: Database, context: StaticTablesContext, *,
136 opaque: OpaqueTableStorageManager,
137 datasets: Type[DatasetRecordStorageManager],
138 universe: DimensionUniverse,
139 ) -> DatastoreRegistryBridgeManager:
140 # Docstring inherited from DatastoreRegistryBridgeManager
141 # Not used, but needed to satisfy ABC requirement.
142 return cls(opaque=opaque, universe=universe, datasetIdColumnType=datasets.getIdColumnType())
144 def refresh(self):
145 # Docstring inherited from DatastoreRegistryBridgeManager
146 pass
148 def register(self, name: str, *, ephemeral: bool = False) -> DatastoreRegistryBridge:
149 # Docstring inherited from DatastoreRegistryBridgeManager
150 return self._bridges.setdefault(name, EphemeralDatastoreRegistryBridge(name))
152 def findDatastores(self, ref: DatasetRef) -> Iterable[str]:
153 # Docstring inherited from DatastoreRegistryBridgeManager
154 for name, bridge in self._bridges.items():
155 if ref in bridge:
156 yield name
158 @classmethod
159 def currentVersion(cls) -> Optional[VersionTuple]:
160 # Docstring inherited from VersionedExtension.
161 return None
163 def schemaDigest(self) -> Optional[str]:
164 # Docstring inherited from VersionedExtension.
165 return None
168class DummyRegistry:
169 """Dummy Registry, for Datastore test purposes.
170 """
171 def __init__(self):
172 self._opaque = DummyOpaqueTableStorageManager()
173 self.dimensions = DimensionUniverse()
174 self._datastoreBridges = DummyDatastoreRegistryBridgeManager(
175 self._opaque, self.dimensions, sqlalchemy.BigInteger)
177 def getDatastoreBridgeManager(self):
178 return self._datastoreBridges