Coverage for python/lsst/pipe/base/_datasetQueryConstraints.py: 50%

74 statements  

« prev     ^ index     » next       coverage.py v7.3.2, created at 2023-11-30 12:09 +0000

1# This file is part of pipe_base. 

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 

28"""Module Defining variants for valid values used to constrain datasets in a 

29graph building query. 

30""" 

31 

32from __future__ import annotations 

33 

34__all__ = ("DatasetQueryConstraintVariant",) 

35 

36import sys 

37import warnings 

38from collections.abc import Iterable, Iterator 

39from typing import Protocol 

40 

41from lsst.utils.introspection import find_outside_stacklevel 

42 

43 

44class DatasetQueryConstraintVariant(Iterable, Protocol): 

45 """Base for all the valid variants for controlling 

46 constraining graph building queries based on dataset type existence. 

47 

48 ALL variant corresponds to using all input dataset types to constrain 

49 a query. 

50 

51 OFF variant corresponds to not using any dataset types to constrain a 

52 graph building query. 

53 

54 LIST variant should be used when one or more specific names should be used 

55 in constraining a graph building query. 

56 

57 Normally the ALL and OFF variants are used as as Singletons, attempting to 

58 instantiate them (i.e. ALL()) will return in singleton class itself. 

59 

60 LIST is used as a constructor to the contents (i.e. List(['a', 'b'])). 

61 Using the LIST variant directly as a singleton will behave the same as if 

62 it were an empty instance. 

63 

64 Variants can be directly used, or automatically be selected by using the 

65 `fromExpression` class method given a valid string. 

66 """ 

67 

68 ALL: "type[_ALL]" 

69 OFF: "type[_OFF]" 

70 LIST: "type[_LIST]" 

71 

72 @classmethod 

73 def __subclasshook__(cls, subclass): 

74 if subclass == cls.ALL or subclass == cls.OFF or subclass == cls.LIST: 

75 return True 

76 return False 

77 

78 @classmethod 

79 def fromExpression(cls, expression: str) -> "DatasetQueryConstraintVariant": 

80 """Select and return the correct Variant that corresponds to the input 

81 expression. 

82 

83 Valid values are ``all`` for all inputs dataset types in pipeline, 

84 ``off`` to not consider dataset type existence as a constraint, single 

85 or comma-separated list of dataset type names. 

86 """ 

87 if not isinstance(expression, str): 

88 raise ValueError("Expression must be a string") 

89 elif expression == "all": 

90 return cls.ALL 

91 elif expression == "off": 

92 return cls.OFF 

93 else: 

94 if " " in expression: 

95 warnings.warn( 

96 "Whitespace found in expression will be trimmed", 

97 RuntimeWarning, 

98 stacklevel=find_outside_stacklevel("lsst.pipe.base"), 

99 ) 

100 expression = expression.replace(" ", "") 

101 members = expression.split(",") 

102 return cls.LIST(members) 

103 

104 

105if sys.version_info.minor < 12: 105 ↛ 109line 105 didn't jump to line 109, because the condition on line 105 was never false

106 MetaMeta = type 

107else: 

108 

109 class MetaMeta(type(Protocol)): 

110 def __init__(cls, *args, **kwargs): 

111 return super().__init__(cls, *args, **kwargs) 

112 

113 

114class _ALLMETA(DatasetQueryConstraintVariant, type(Protocol), metaclass=MetaMeta): 

115 def __iter__(self) -> Iterator: # noqa: N804 

116 raise NotImplementedError("This variant cannot be iterated") 

117 

118 

119class _ALL(metaclass=_ALLMETA): 

120 def __new__(cls): 

121 return cls 

122 

123 

124class _OFFMETA(DatasetQueryConstraintVariant, type(Protocol), metaclass=MetaMeta): 

125 def __iter__(self) -> Iterator: # noqa: N804 

126 raise NotImplementedError("This variant cannot be iterated") 

127 

128 

129class _OFF(metaclass=_OFFMETA): 

130 def __new__(cls): 

131 return cls 

132 

133 

134class _LISTMETA(type(Protocol), metaclass=MetaMeta): 

135 def __iter__(self): # noqa: N804 

136 return iter(tuple()) 

137 

138 def __len__(self): # noqa: N804 

139 return 0 

140 

141 def __eq__(self, o: object) -> bool: # noqa: N804 

142 if isinstance(o, self): 

143 return True 

144 return super().__eq__(o) 

145 

146 

147class _LIST(DatasetQueryConstraintVariant, metaclass=_LISTMETA): 

148 def __init__(self, members: Iterable[str]): 

149 self.members = list(members) 

150 

151 def __len__(self) -> int: 

152 return len(self.members) 

153 

154 def __iter__(self) -> Iterable[str]: 

155 return iter(self.members) 

156 

157 def __repr__(self) -> str: 

158 return repr(self.members) 

159 

160 def __str__(self) -> str: 

161 return str(self.members) 

162 

163 def __eq__(self, o: object) -> bool: 

164 if isinstance(o, type(self)): 

165 return self.members == o.members 

166 return super().__eq__(o) 

167 

168 

169def suppressInit(self): 

170 raise NotImplementedError( 

171 "DatasetQueryConstraintVariants cannot be directly instantiated. " 

172 "Please use the variants or the fromExpression class method" 

173 ) 

174 

175 

176DatasetQueryConstraintVariant.__init__ = suppressInit 

177DatasetQueryConstraintVariant.ALL = _ALL 

178DatasetQueryConstraintVariant.OFF = _OFF 

179DatasetQueryConstraintVariant.LIST = _LIST