Coverage for python/lsst/daf/butler/registry/interfaces/_opaque.py : 61%

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/>.
21from __future__ import annotations
22"""Interfaces for the objects that manage opaque (logical) tables within a
23`Registry`.
24"""
26__all__ = ["OpaqueTableStorageManager", "OpaqueTableStorage"]
28from abc import ABC, abstractmethod
29from typing import (
30 Any,
31 Iterator,
32 Optional,
33)
35from ...core.ddl import TableSpec
36from ._database import Database, StaticTablesContext
37from ._versioning import VersionedExtension
40class OpaqueTableStorage(ABC):
41 """An interface that manages the records associated with a particular
42 opaque table in a `Registry`.
44 Parameters
45 ----------
46 name : `str`
47 Name of the opaque table.
48 """
49 def __init__(self, name: str):
50 self.name = name
52 @abstractmethod
53 def insert(self, *data: dict) -> None:
54 """Insert records into the table
56 Parameters
57 ----------
58 *data
59 Each additional positional argument is a dictionary that represents
60 a single row to be added.
61 """
62 raise NotImplementedError()
64 @abstractmethod
65 def fetch(self, **where: Any) -> Iterator[dict]:
66 """Retrieve records from an opaque table.
68 Parameters
69 ----------
70 **where
71 Additional keyword arguments are interpreted as equality
72 constraints that restrict the returned rows (combined with AND);
73 keyword arguments are column names and values are the values they
74 must have.
76 Yields
77 ------
78 row : `dict`
79 A dictionary representing a single result row.
80 """
81 raise NotImplementedError()
83 @abstractmethod
84 def delete(self, **where: Any) -> None:
85 """Remove records from an opaque table.
87 Parameters
88 ----------
89 **where
90 Additional keyword arguments are interpreted as equality
91 constraints that restrict the deleted rows (combined with AND);
92 keyword arguments are column names and values are the values they
93 must have.
94 """
95 raise NotImplementedError()
97 name: str
98 """The name of the logical table this instance manages (`str`).
99 """
102class OpaqueTableStorageManager(VersionedExtension):
103 """An interface that manages the opaque tables in a `Registry`.
105 `OpaqueTableStorageManager` primarily serves as a container and factory for
106 `OpaqueTableStorage` instances, which each provide access to the records
107 for a different (logical) opaque table.
109 Notes
110 -----
111 Opaque tables are primarily used by `Datastore` instances to manage their
112 internal data in the same database that hold the `Registry`, but are not
113 limited to this.
115 While an opaque table in a multi-layer `Registry` may in fact be the union
116 of multiple tables in different layers, we expect this to be rare, as
117 `Registry` layers will typically correspond to different leaf `Datastore`
118 instances (each with their own opaque table) in a `ChainedDatastore`.
119 """
121 @classmethod
122 @abstractmethod
123 def initialize(cls, db: Database, context: StaticTablesContext) -> OpaqueTableStorageManager:
124 """Construct an instance of the manager.
126 Parameters
127 ----------
128 db : `Database`
129 Interface to the underlying database engine and namespace.
130 context : `StaticTablesContext`
131 Context object obtained from `Database.declareStaticTables`; used
132 to declare any tables that should always be present in a layer
133 implemented with this manager.
135 Returns
136 -------
137 manager : `OpaqueTableStorageManager`
138 An instance of a concrete `OpaqueTableStorageManager` subclass.
139 """
140 raise NotImplementedError()
142 def __getitem__(self, name: str) -> OpaqueTableStorage:
143 """Interface to `get` that raises `LookupError` instead of returning
144 `None` on failure.
145 """
146 r = self.get(name)
147 if r is None:
148 raise LookupError(f"No logical table with name '{name}' found.")
149 return r
151 @abstractmethod
152 def get(self, name: str) -> Optional[OpaqueTableStorage]:
153 """Return an object that provides access to the records associated with
154 an opaque logical table.
156 Parameters
157 ----------
158 name : `str`
159 Name of the logical table.
161 Returns
162 -------
163 records : `OpaqueTableStorage` or `None`
164 The object representing the records for the given table in this
165 layer, or `None` if there are no records for that table in this
166 layer.
168 Notes
169 -----
170 Opaque tables must be registered with the layer (see `register`) by
171 the same client before they can safely be retrieved with `get`.
172 Unlike most other manager classes, the set of opaque tables cannot be
173 obtained from an existing data repository.
174 """
175 raise NotImplementedError()
177 @abstractmethod
178 def register(self, name: str, spec: TableSpec) -> OpaqueTableStorage:
179 """Ensure that this layer can hold records for the given opaque logical
180 table, creating new tables as necessary.
182 Parameters
183 ----------
184 name : `str`
185 Name of the logical table.
186 spec : `TableSpec`
187 Schema specification for the table to be created.
189 Returns
190 -------
191 records : `OpaqueTableStorage`
192 The object representing the records for the given element in this
193 layer.
195 Notes
196 -----
197 This operation may not be invoked within a transaction context block.
198 """
199 raise NotImplementedError()