Coverage for python/lsst/daf/butler/registry/interfaces/_opaque.py: 67%
37 statements
« prev ^ index » next coverage.py v6.5.0, created at 2022-12-01 19:55 +0000
« prev ^ index » next coverage.py v6.5.0, created at 2022-12-01 19:55 +0000
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 Iterable,
32 Iterator,
33 Optional,
34)
36from ...core.ddl import TableSpec
37from ._database import Database, StaticTablesContext
38from ._versioning import VersionedExtension
41class OpaqueTableStorage(ABC):
42 """An interface that manages the records associated with a particular
43 opaque table in a `Registry`.
45 Parameters
46 ----------
47 name : `str`
48 Name of the opaque table.
49 """
50 def __init__(self, name: str):
51 self.name = name
53 @abstractmethod
54 def insert(self, *data: dict) -> None:
55 """Insert records into the table
57 Parameters
58 ----------
59 *data
60 Each additional positional argument is a dictionary that represents
61 a single row to be added.
62 """
63 raise NotImplementedError()
65 @abstractmethod
66 def fetch(self, **where: Any) -> Iterator[dict]:
67 """Retrieve records from an opaque table.
69 Parameters
70 ----------
71 **where
72 Additional keyword arguments are interpreted as equality
73 constraints that restrict the returned rows (combined with AND);
74 keyword arguments are column names and values are the values they
75 must have.
77 Yields
78 ------
79 row : `dict`
80 A dictionary representing a single result row.
81 """
82 raise NotImplementedError()
84 @abstractmethod
85 def delete(self, columns: Iterable[str], *rows: dict) -> None:
86 """Remove records from an opaque table.
88 Parameters
89 ----------
90 columns: `~collections.abc.Iterable` of `str`
91 The names of columns that will be used to constrain the rows to
92 be deleted; these will be combined via ``AND`` to form the
93 ``WHERE`` clause of the delete query.
94 *rows
95 Positional arguments are the keys of rows to be deleted, as
96 dictionaries mapping column name to value. The keys in all
97 dictionaries must be exactly the names in ``columns``.
98 """
99 raise NotImplementedError()
101 name: str
102 """The name of the logical table this instance manages (`str`).
103 """
106class OpaqueTableStorageManager(VersionedExtension):
107 """An interface that manages the opaque tables in a `Registry`.
109 `OpaqueTableStorageManager` primarily serves as a container and factory for
110 `OpaqueTableStorage` instances, which each provide access to the records
111 for a different (logical) opaque table.
113 Notes
114 -----
115 Opaque tables are primarily used by `Datastore` instances to manage their
116 internal data in the same database that hold the `Registry`, but are not
117 limited to this.
119 While an opaque table in a multi-layer `Registry` may in fact be the union
120 of multiple tables in different layers, we expect this to be rare, as
121 `Registry` layers will typically correspond to different leaf `Datastore`
122 instances (each with their own opaque table) in a `ChainedDatastore`.
123 """
125 @classmethod
126 @abstractmethod
127 def initialize(cls, db: Database, context: StaticTablesContext) -> OpaqueTableStorageManager:
128 """Construct an instance of the manager.
130 Parameters
131 ----------
132 db : `Database`
133 Interface to the underlying database engine and namespace.
134 context : `StaticTablesContext`
135 Context object obtained from `Database.declareStaticTables`; used
136 to declare any tables that should always be present in a layer
137 implemented with this manager.
139 Returns
140 -------
141 manager : `OpaqueTableStorageManager`
142 An instance of a concrete `OpaqueTableStorageManager` subclass.
143 """
144 raise NotImplementedError()
146 def __getitem__(self, name: str) -> OpaqueTableStorage:
147 """Interface to `get` that raises `LookupError` instead of returning
148 `None` on failure.
149 """
150 r = self.get(name)
151 if r is None:
152 raise LookupError(f"No logical table with name '{name}' found.")
153 return r
155 @abstractmethod
156 def get(self, name: str) -> Optional[OpaqueTableStorage]:
157 """Return an object that provides access to the records associated with
158 an opaque logical table.
160 Parameters
161 ----------
162 name : `str`
163 Name of the logical table.
165 Returns
166 -------
167 records : `OpaqueTableStorage` or `None`
168 The object representing the records for the given table in this
169 layer, or `None` if there are no records for that table in this
170 layer.
172 Notes
173 -----
174 Opaque tables must be registered with the layer (see `register`) by
175 the same client before they can safely be retrieved with `get`.
176 Unlike most other manager classes, the set of opaque tables cannot be
177 obtained from an existing data repository.
178 """
179 raise NotImplementedError()
181 @abstractmethod
182 def register(self, name: str, spec: TableSpec) -> OpaqueTableStorage:
183 """Ensure that this layer can hold records for the given opaque logical
184 table, creating new tables as necessary.
186 Parameters
187 ----------
188 name : `str`
189 Name of the logical table.
190 spec : `TableSpec`
191 Schema specification for the table to be created.
193 Returns
194 -------
195 records : `OpaqueTableStorage`
196 The object representing the records for the given element in this
197 layer.
199 Notes
200 -----
201 This operation may not be invoked within a transaction context block.
202 """
203 raise NotImplementedError()