Coverage for python/lsst/daf/butler/registry/_dataset_type_cache.py: 36%
41 statements
« prev ^ index » next coverage.py v7.4.4, created at 2024-04-05 02:53 -0700
« prev ^ index » next coverage.py v7.4.4, created at 2024-04-05 02:53 -0700
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 software is dual licensed under the GNU General Public License and also
10# under a 3-clause BSD license. Recipients may choose which of these licenses
11# to use; please see the files gpl-3.0.txt and/or bsd_license.txt,
12# respectively. If you choose the GPL option then the following text applies
13# (but note that there is still no warranty even if you opt for BSD instead):
14#
15# This program is free software: you can redistribute it and/or modify
16# it under the terms of the GNU General Public License as published by
17# the Free Software Foundation, either version 3 of the License, or
18# (at your option) any later version.
19#
20# This program is distributed in the hope that it will be useful,
21# but WITHOUT ANY WARRANTY; without even the implied warranty of
22# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23# GNU General Public License for more details.
24#
25# You should have received a copy of the GNU General Public License
26# along with this program. If not, see <http://www.gnu.org/licenses/>.
28from __future__ import annotations
30__all__ = ("DatasetTypeCache",)
32from collections.abc import Iterable, Iterator
33from typing import Generic, TypeVar
35from .._dataset_type import DatasetType
37_T = TypeVar("_T")
40class DatasetTypeCache(Generic[_T]):
41 """Cache for dataset types.
43 Notes
44 -----
45 This class caches mapping of dataset type name to a corresponding
46 `DatasetType` instance. Registry manager also needs to cache corresponding
47 "storage" instance, so this class allows storing additional opaque object
48 along with the dataset type.
50 In come contexts (e.g. ``resolve_wildcard``) a full list of dataset types
51 is needed. To signify that cache content can be used in such contexts,
52 cache defines special ``full`` flag that needs to be set by client.
53 """
55 def __init__(self) -> None:
56 self._cache: dict[str, tuple[DatasetType, _T | None]] = {}
57 self._full = False
59 @property
60 def full(self) -> bool:
61 """`True` if cache holds all known dataset types (`bool`)."""
62 return self._full
64 def add(self, dataset_type: DatasetType, extra: _T | None = None) -> None:
65 """Add one record to the cache.
67 Parameters
68 ----------
69 dataset_type : `DatasetType`
70 Dataset type, replaces any existing dataset type with the same
71 name.
72 extra : `Any`, optional
73 Additional opaque object stored with this dataset type.
74 """
75 self._cache[dataset_type.name] = (dataset_type, extra)
77 def set(self, data: Iterable[DatasetType | tuple[DatasetType, _T | None]], *, full: bool = False) -> None:
78 """Replace cache contents with the new set of dataset types.
80 Parameters
81 ----------
82 data : `~collections.abc.Iterable`
83 Sequence of `DatasetType` instances or tuples of `DatasetType` and
84 an extra opaque object.
85 full : `bool`
86 If `True` then ``data`` contains all known dataset types.
87 """
88 self.clear()
89 for item in data:
90 if isinstance(item, DatasetType):
91 item = (item, None)
92 self._cache[item[0].name] = item
93 self._full = full
95 def clear(self) -> None:
96 """Remove everything from the cache."""
97 self._cache = {}
98 self._full = False
100 def discard(self, name: str) -> None:
101 """Remove named dataset type from the cache.
103 Parameters
104 ----------
105 name : `str`
106 Name of the dataset type to remove.
107 """
108 self._cache.pop(name, None)
110 def get(self, name: str) -> tuple[DatasetType | None, _T | None]:
111 """Return cached info given dataset type name.
113 Parameters
114 ----------
115 name : `str`
116 Dataset type name.
118 Returns
119 -------
120 dataset_type : `DatasetType` or `None`
121 Cached dataset type, `None` is returned if the name is not in the
122 cache.
123 extra : `Any` or `None`
124 Cached opaque data, `None` is returned if the name is not in the
125 cache or no extra info was stored for this dataset type.
126 """
127 item = self._cache.get(name)
128 if item is None:
129 return (None, None)
130 return item
132 def get_dataset_type(self, name: str) -> DatasetType | None:
133 """Return dataset type given its name.
135 Parameters
136 ----------
137 name : `str`
138 Dataset type name.
140 Returns
141 -------
142 dataset_type : `DatasetType` or `None`
143 Cached dataset type, `None` is returned if the name is not in the
144 cache.
145 """
146 item = self._cache.get(name)
147 if item is None:
148 return None
149 return item[0]
151 def items(self) -> Iterator[tuple[DatasetType, _T | None]]:
152 """Return iterator for the set of items in the cache, can only be
153 used if `full` is true.
155 Raises
156 ------
157 RuntimeError
158 Raised if ``self.full`` is `False`.
159 """
160 if not self._full:
161 raise RuntimeError("cannot call items() if cache is not full")
162 return iter(self._cache.values())