Coverage for python/lsst/daf/butler/registry/interfaces/_dimensions.py : 38%

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
# This file is part of daf_butler. # # Developed for the LSST Data Management System. # This product includes software developed by the LSST Project # (http://www.lsst.org). # See the COPYRIGHT file at the top-level directory of this distribution # for details of code ownership. # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>.
from ...core import ( DataId, DimensionElement, DimensionRecord, DimensionUniverse, Timespan, ) from ...core.utils import NamedKeyDict from ..queries import QueryBuilder from ._database import Database, StaticTablesContext
"""An abstract base class that represents a way of storing the records associated with a single `DimensionElement`.
Concrete `DimensionRecordStorage` instances should generally be constructed via a call to `setupDimensionStorage`, which selects the appropriate subclass for each element according to its configuration.
All `DimensionRecordStorage` methods are pure abstract, even though in some cases a reasonable default implementation might be possible, in order to better guarantee all methods are correctly overridden. All of these potentially-defaultable implementations are extremely trivial, so asking subclasses to provide them is not a significant burden. """
context: Optional[StaticTablesContext] = None) -> DimensionRecordStorage: """Construct an instance of this class using a standardized interface.
Parameters ---------- db : `Database` Interface to the underlying database engine and namespace. element : `DimensionElement` Dimension element the new instance will manage records for. context : `StaticTablesContext`, optional If provided, an object to use to create any new tables. If not provided, ``db.ensureTableExists`` should be used instead.
Returns ------- storage : `DimensionRecordStorage` A new `DimensionRecordStorage` subclass instance. """ raise NotImplementedError()
) -> Type[DimensionRecordStorage]: """Return the default `DimensionRecordStorage` implementation for the given `DimensionElement`.
Parameters ---------- element : `DimensionElement` The element whose properties should be examined to determine the appropriate default implementation class. ignoreCached : `bool`, optional If `True`, ignore `DimensionElement.cached` and always return the storage implementation that would be used without caching.
Returns ------- cls : `type` A concrete subclass of `DimensionRecordStorage`.
Notes ----- At present, these defaults are always used, but we may add support for explicitly setting the class to use in configuration in the future. """ if not ignoreCached and element.cached: from ..dimensions.caching import CachingDimensionRecordStorage return CachingDimensionRecordStorage elif element.hasTable(): if element.viewOf is not None: if element.spatial: raise NotImplementedError("Spatial view dimension storage is not supported.") from ..dimensions.query import QueryDimensionRecordStorage return QueryDimensionRecordStorage elif element.spatial: from ..dimensions.spatial import SpatialDimensionRecordStorage return SpatialDimensionRecordStorage else: from ..dimensions.table import TableDimensionRecordStorage return TableDimensionRecordStorage elif isinstance(element, SkyPixDimension): from ..dimensions.skypix import SkyPixDimensionRecordStorage return SkyPixDimensionRecordStorage raise NotImplementedError(f"No default DimensionRecordStorage class for {element}.")
def element(self) -> DimensionElement: """The element whose records this instance holds (`DimensionElement`). """ raise NotImplementedError()
def clearCaches(self): """Clear any in-memory caches held by the storage instance.
This is called by `Registry` when transactions are rolled back, to avoid in-memory caches from ever containing records that are not present in persistent storage. """ raise NotImplementedError()
self, builder: QueryBuilder, *, regions: Optional[NamedKeyDict[DimensionElement, sqlalchemy.sql.ColumnElement]] = None, timespans: Optional[NamedKeyDict[DimensionElement, Timespan[sqlalchemy.sql.ColumnElement]]] = None, ): """Add the dimension element's logical table to a query under construction.
This is a visitor pattern interface that is expected to be called only by `QueryBuilder.joinDimensionElement`.
Parameters ---------- builder : `QueryBuilder` Builder for the query that should contain this element. regions : `NamedKeyDict`, optional A mapping from `DimensionElement` to a SQLAlchemy column containing the region for that element, which should be updated to include a region column for this element if one exists. If `None`, ``self.element`` is not being included in the query via a spatial join. timespan : `NamedKeyDict`, optional A mapping from `DimensionElement` to a `Timespan` of SQLALchemy columns containing the timespan for that element, which should be updated to include timespan columns for this element if they exist. If `None`, ``self.element`` is not being included in the query via a temporal join.
Notes ----- Elements are only included in queries via spatial and/or temporal joins when necessary to connect them to other elements in the query, so ``regions`` and ``timespans`` cannot be assumed to be not `None` just because an element has a region or timespan. """ raise NotImplementedError()
def insert(self, *records: DimensionRecord): """Insert one or more records into storage.
Parameters ---------- records One or more instances of the `DimensionRecord` subclass for the element this storage is associated with.
Raises ------ TypeError Raised if the element does not support record insertion. sqlalchemy.exc.IntegrityError Raised if one or more records violate database integrity constraints.
Notes ----- As `insert` is expected to be called only by a `Registry`, we rely on `Registry` to provide transactionality, both by using a SQLALchemy connection shared with the `Registry` and by relying on it to call `clearCaches` when rolling back transactions. """ raise NotImplementedError()
def fetch(self, dataId: DataId) -> Optional[DimensionRecord]: """Retrieve a record from storage.
Parameters ---------- dataId : `DataId` A data ID that identifies the record to be retrieved. This may be an informal data ID dict or a validated `DataCoordinate`.
Returns ------- record : `DimensionRecord` or `None` A record retrieved from storage, or `None` if there is no such record. """ raise NotImplementedError()
"""An interface for managing the dimension records in a `Registry`.
`DimensionRecordStorageManager` primarily serves as a container and factory for `DimensionRecordStorage` instances, which each provide access to the records for a different `DimensionElement`.
Parameters ---------- universe : `DimensionUniverse` Universe of all dimensions and dimension elements known to the `Registry`.
Notes ----- In a multi-layer `Registry`, many dimension elements will only have records in one layer (often the base layer). The union of the records across all layers forms the logical table for the full `Registry`. """ self.universe = universe
def initialize(cls, db: Database, context: StaticTablesContext, *, universe: DimensionUniverse) -> DimensionRecordStorageManager: """Construct an instance of the manager.
Parameters ---------- db : `Database` Interface to the underlying database engine and namespace. context : `StaticTablesContext` Context object obtained from `Database.declareStaticTables`; used to declare any tables that should always be present in a layer implemented with this manager. universe : `DimensionUniverse` Universe graph containing dimensions known to this `Registry`.
Returns ------- manager : `DimensionRecordStorageManager` An instance of a concrete `DimensionRecordStorageManager` subclass. """ raise NotImplementedError()
def refresh(self): """Ensure all other operations on this manager are aware of any dataset types that may have been registered by other clients since it was initialized or last refreshed. """ raise NotImplementedError()
"""Interface to `get` that raises `LookupError` instead of returning `None` on failure. """ r = self.get(element) if r is None: raise LookupError(f"No dimension element '{element.name}' found in this registry layer.") return r
def get(self, element: DimensionElement) -> Optional[DimensionRecordStorage]: """Return an object that provides access to the records associated with the given element, if one exists in this layer.
Parameters ---------- element : `DimensionElement` Element for which records should be returned.
Returns ------- records : `DimensionRecordStorage` or `None` The object representing the records for the given element in this layer, or `None` if there are no records for that element in this layer.
Note ---- Dimension elements registered by another client of the same layer since the last call to `initialize` or `refresh` may not be found. """ raise NotImplementedError()
def register(self, element: DimensionElement) -> DimensionRecordStorage: """Ensure that this layer can hold records for the given element, creating new tables as necessary.
Parameters ---------- element : `DimensionElement` Element for which a table should created (as necessary) and an associated `DimensionRecordStorage` returned.
Returns ------- records : `DimensionRecordStorage` The object representing the records for the given element in this layer.
Raises ------ TransactionInterruption Raised if this operation is invoked within a `Database.transaction` context. """ raise NotImplementedError()
def clearCaches(self): """Clear any in-memory caches held by nested `DimensionRecordStorage` instances.
This is called by `Registry` when transactions are rolled back, to avoid in-memory caches from ever containing records that are not present in persistent storage. """ raise NotImplementedError()
`Registry` (`DimensionUniverse`). """ |