Coverage for python/lsst/daf/butler/registry/_collection_type.py: 68%

28 statements  

« prev     ^ index     » next       coverage.py v7.5.1, created at 2024-05-08 02:51 -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/>. 

27 

28from __future__ import annotations 

29 

30__all__ = [ 

31 "CollectionType", 

32] 

33 

34import enum 

35from collections.abc import Iterable 

36 

37 

38class CollectionType(enum.IntEnum): 

39 """Enumeration used to label different types of collections.""" 

40 

41 RUN = 1 

42 """A ``RUN`` collection (also just called a 'run') is the initial 

43 collection a dataset is inserted into and the only one it can never be 

44 removed from. 

45 

46 Within a particular run, there may only be one dataset with a particular 

47 dataset type and data ID. 

48 """ 

49 

50 TAGGED = 2 

51 """Datasets can be associated with and removed from ``TAGGED`` collections 

52 arbitrarily. 

53 

54 Within a particular tagged collection, there may only be one dataset with 

55 a particular dataset type and data ID. 

56 """ 

57 

58 CHAINED = 3 

59 """A ``CHAINED`` collection is simply an ordered list of other collections 

60 to be searched. These may include other ``CHAINED`` collections. 

61 """ 

62 

63 CALIBRATION = 4 

64 """A ``CALIBRATION`` collection operates like a ``TAGGED`` collection, but 

65 also associates each dataset with a validity range as well. Queries 

66 against calibration collections must include a timestamp as an input. 

67 

68 It is difficult (perhaps impossible) to enforce a constraint that there be 

69 one dataset with a particular dataset type and data ID at any particular 

70 timestamp in the database, so higher-level tools that populate calibration 

71 collections are expected to maintain that invariant instead. 

72 """ 

73 

74 @classmethod 

75 def all(cls) -> frozenset[CollectionType]: 

76 """Return a `frozenset` containing all members.""" 

77 return frozenset(cls.__members__.values()) 

78 

79 @classmethod 

80 def from_name(cls, name: str) -> CollectionType: 

81 """Return the `CollectionType` given its name. 

82 

83 Parameters 

84 ---------- 

85 name : `str` 

86 Name of the collection type. Case insensitive. 

87 

88 Returns 

89 ------- 

90 collection_type : `CollectionType` 

91 The matching collection type. 

92 

93 Raises 

94 ------ 

95 KeyError 

96 Raised if the name does not match a collection type. 

97 """ 

98 name = name.upper() 

99 try: 

100 return CollectionType.__members__[name] 

101 except KeyError: 

102 raise KeyError(f"Collection type of '{name}' not known to Butler.") from None 

103 

104 @classmethod 

105 def from_names(cls, names: Iterable[str] | None) -> frozenset[CollectionType]: 

106 """Return a `frozenset` containing the `CollectionType` instances 

107 corresponding to the names. 

108 

109 Parameters 

110 ---------- 

111 names : iterable of `str`, or `None` 

112 Names of collection types. Case insensitive. If `None` or empty, 

113 all collection types will be returned. 

114 

115 Returns 

116 ------- 

117 types : `frozenset` of `CollectionType` 

118 The matching types. 

119 

120 Raises 

121 ------ 

122 KeyError 

123 Raised if the name does not correspond to a collection type. 

124 """ 

125 if not names: 

126 return CollectionType.all() 

127 

128 # Convert to real collection types 

129 return frozenset({CollectionType.from_name(name) for name in names})