Coverage for python/lsst/daf/butler/_butlerRepoIndex.py: 40%
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/>.
22from __future__ import annotations
24__all__ = ("ButlerRepoIndex",)
26import os
27from typing import ClassVar, Dict, Set
29from lsst.resources import ResourcePath, ResourcePathExpression
31from .core import Config
34class ButlerRepoIndex:
35 """Index of all known butler repositories.
37 The index of butler repositories is found by looking for a
38 configuration file at the URI pointed at by the environment
39 variable ``$DAF_BUTLER_REPOSITORY_INDEX``. The configuration file
40 is a simple dictionary lookup of the form:
42 .. code-block:: yaml
44 label1: uri1
45 label2: uri2
47 and can be in YAML or JSON format. The content of the file will be
48 cached.
49 """
51 index_env_var: ClassVar[str] = "DAF_BUTLER_REPOSITORY_INDEX"
52 """The name of the environment variable to read to locate the index."""
54 _cache: ClassVar[Dict[ResourcePath, Config]] = {}
55 """Cache of indexes. In most scenarios only one index will be found
56 and the environment will not change. In tests this may not be true."""
58 @classmethod
59 def _read_repository_index(cls, index_uri: ResourcePathExpression) -> Config:
60 """Read the repository index from the supplied URI.
62 Parameters
63 ----------
64 index_uri : `lsst.resources.ResourcePathExpression`
65 URI of the repository index.
67 Returns
68 -------
69 repo_index : `Config`
70 The index found at this URI.
72 Raises
73 ------
74 FileNotFoundError
75 Raised if the URI does not exist.
77 Notes
78 -----
79 Does check the cache before reading the file.
80 """
81 if index_uri in cls._cache:
82 return cls._cache[index_uri]
84 repo_index = Config(index_uri)
85 cls._cache[index_uri] = repo_index
87 return repo_index
89 @classmethod
90 def _get_index_uri(cls) -> ResourcePath:
91 """Find the URI to the repository index.
93 Returns
94 -------
95 index_uri : `lsst.resources.ResourcePath`
96 URI to the repository index.
98 Raises
99 ------
100 KeyError
101 Raised if the location of the index could not be determined.
102 """
103 index_uri = os.environ.get(cls.index_env_var)
104 if index_uri is None:
105 raise KeyError(f"No repository index defined in enviroment variable {cls.index_env_var}")
106 return ResourcePath(index_uri)
108 @classmethod
109 def _read_repository_index_from_environment(cls) -> Config:
110 """Look in environment for index location and read it.
112 Returns
113 -------
114 repo_index : `Config`
115 The index found in the environment.
116 """
117 index_uri = cls._get_index_uri()
118 return cls._read_repository_index(index_uri)
120 @classmethod
121 def get_known_repos(cls) -> Set[str]:
122 """Retrieve the list of known repository labels.
124 Returns
125 -------
126 repos : `set` of `str`
127 All the known labels. Can be empty if no index can be found.
128 """
129 try:
130 repo_index = cls._read_repository_index_from_environment()
131 except (FileNotFoundError, KeyError):
132 return set()
133 return set(repo_index)
135 @classmethod
136 def get_repo_uri(cls, label: str) -> ResourcePath:
137 """Look up the label in a butler repository index.
139 Parameters
140 ----------
141 label : `str`
142 Label of the Butler repository to look up.
144 Returns
145 -------
146 uri : `lsst.resources.ResourcePath`
147 URI to the Butler repository associated with the given label.
149 Raises
150 ------
151 KeyError
152 Raised if the label is not found in the index, or if an index
153 can not be found at all.
154 FileNotFoundError
155 Raised if an index is defined in the environment but it
156 can not be found.
157 """
158 repo_index = cls._read_repository_index_from_environment()
159 repo_uri = repo_index.get(label)
160 if repo_uri is None:
161 # This should not raise since it worked earlier.
162 try:
163 index_uri = str(cls._get_index_uri())
164 except KeyError:
165 index_uri = "<environment variable not defined>"
166 raise KeyError(f"Label '{label}' not known to repository index at {index_uri}")
167 return ResourcePath(repo_uri)