Coverage for python/lsst/daf/butler/_butlerRepoIndex.py: 39%

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

43 statements  

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/>. 

21 

22from __future__ import annotations 

23 

24__all__ = ("ButlerRepoIndex",) 

25 

26import os 

27from typing import ClassVar, Dict, Set 

28 

29from .core import ButlerURI, Config 

30 

31 

32class ButlerRepoIndex: 

33 """Index of all known butler repositories. 

34 

35 The index of butler repositories is found by looking for a 

36 configuration file at the URI pointed at by the environment 

37 variable ``$DAF_BUTLER_REPOSITORY_INDEX``. The configuration file 

38 is a simple dictionary lookup of the form: 

39 

40 .. code-block:: yaml 

41 

42 label1: uri1 

43 label2: uri2 

44 

45 and can be in YAML or JSON format. The content of the file will be 

46 cached. 

47 """ 

48 

49 index_env_var: ClassVar[str] = "DAF_BUTLER_REPOSITORY_INDEX" 

50 """The name of the environment variable to read to locate the index.""" 

51 

52 _cache: ClassVar[Dict[ButlerURI, Config]] = {} 

53 """Cache of indexes. In most scenarios only one index will be found 

54 and the environment will not change. In tests this may not be true.""" 

55 

56 @classmethod 

57 def _read_repository_index(cls, index_uri: ButlerURI) -> Config: 

58 """Read the repository index from the supplied URI. 

59 

60 Parameters 

61 ---------- 

62 index_uri : `str` or `ButlerURI` 

63 URI of the repository index. 

64 

65 Returns 

66 ------- 

67 repo_index : `Config` 

68 The index found at this URI. 

69 

70 Raises 

71 ------ 

72 FileNotFoundError 

73 Raised if the URI does not exist. 

74 

75 Notes 

76 ----- 

77 Does check the cache before reading the file. 

78 """ 

79 if index_uri in cls._cache: 

80 return cls._cache[index_uri] 

81 

82 repo_index = Config(index_uri) 

83 cls._cache[index_uri] = repo_index 

84 

85 return repo_index 

86 

87 @classmethod 

88 def _get_index_uri(cls) -> ButlerURI: 

89 """Find the URI to the repository index. 

90 

91 Returns 

92 ------- 

93 index_uri : `ButlerURI` 

94 URI to the repository index. 

95 

96 Raises 

97 ------ 

98 KeyError 

99 Raised if the location of the index could not be determined. 

100 """ 

101 index_uri = os.environ.get(cls.index_env_var) 

102 if index_uri is None: 

103 raise KeyError(f"No repository index defined in enviroment variable {cls.index_env_var}") 

104 return ButlerURI(index_uri) 

105 

106 @classmethod 

107 def _read_repository_index_from_environment(cls) -> Config: 

108 """Look in environment for index location and read it. 

109 

110 Returns 

111 ------- 

112 repo_index : `Config` 

113 The index found in the environment. 

114 """ 

115 index_uri = cls._get_index_uri() 

116 return cls._read_repository_index(index_uri) 

117 

118 @classmethod 

119 def get_known_repos(cls) -> Set[str]: 

120 """Retrieve the list of known repository labels. 

121 

122 Returns 

123 ------- 

124 repos : `set` of `str` 

125 All the known labels. Can be empty if no index can be found. 

126 """ 

127 try: 

128 repo_index = cls._read_repository_index_from_environment() 

129 except (FileNotFoundError, KeyError): 

130 return set() 

131 return set(repo_index) 

132 

133 @classmethod 

134 def get_repo_uri(cls, label: str) -> ButlerURI: 

135 """Look up the label in a butler repository index. 

136 

137 Parameters 

138 ---------- 

139 label : `str` 

140 Label of the Butler repository to look up. 

141 

142 Returns 

143 ------- 

144 uri : `ButlerURI` 

145 URI to the Butler repository associated with the given label. 

146 

147 Raises 

148 ------ 

149 KeyError 

150 Raised if the label is not found in the index, or if an index 

151 can not be found at all. 

152 FileNotFoundError 

153 Raised if an index is defined in the environment but it 

154 can not be found. 

155 """ 

156 repo_index = cls._read_repository_index_from_environment() 

157 repo_uri = repo_index.get(label) 

158 if repo_uri is None: 

159 # This should not raise since it worked earlier. 

160 try: 

161 index_uri = str(cls._get_index_uri()) 

162 except KeyError: 

163 index_uri = "<environment variable not defined>" 

164 raise KeyError(f"Label '{label}' not known to repository index at {index_uri}") 

165 return ButlerURI(repo_uri)