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

69 statements  

« prev     ^ index     » next       coverage.py v7.2.5, created at 2023-05-11 03:12 -0700

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

21from __future__ import annotations 

22 

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

24graph building query. 

25""" 

26 

27__all__ = ("DatasetQueryConstraintVariant",) 

28 

29import warnings 

30from typing import Iterable, Iterator, Protocol, Type 

31 

32 

33class DatasetQueryConstraintVariant(Iterable, Protocol): 

34 """This class is the base for all the valid variants for controling 

35 constraining graph building queries based on dataset type existence. 

36 

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

38 a query. 

39 

40 OFF variant corrresponds to not using any dataset types to constrain a 

41 graph building query. 

42 

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

44 in constraining a graph building query. 

45 

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

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

48 

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

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

51 it were an empty instance. 

52 

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

54 `fromExpression` class method given a valid string. 

55 """ 

56 

57 ALL: "Type[_ALL]" 

58 OFF: "Type[_OFF]" 

59 LIST: "Type[_LIST]" 

60 

61 @classmethod 

62 def __subclasshook__(cls, subclass): 

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

64 return True 

65 return False 

66 

67 @classmethod 

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

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

70 expression. 

71 

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

73 to not consider dataset type existence as a constraint, single or comma 

74 seperated list of dataset type names. 

75 """ 

76 if not isinstance(expression, str): 

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

78 elif expression == "all": 

79 return cls.ALL 

80 elif expression == "off": 

81 return cls.OFF 

82 else: 

83 if " " in expression: 

84 warnings.warn("Witespace found in expression will be trimmed", RuntimeWarning) 

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

86 members = expression.split(",") 

87 return cls.LIST(members) 

88 

89 

90class _ALLMETA(DatasetQueryConstraintVariant, type(Protocol)): 

91 def __iter__(self) -> Iterator: 

92 raise NotImplementedError("This variant cannot be iteratted") 

93 

94 

95class _ALL(metaclass=_ALLMETA): 

96 def __new__(cls): 

97 return cls 

98 

99 

100class _OFFMETA(DatasetQueryConstraintVariant, type(Protocol)): 

101 def __iter__(self) -> Iterator: 

102 raise NotImplementedError("This variant cannot be iteratted") 

103 

104 

105class _OFF(metaclass=_OFFMETA): 

106 def __new__(cls): 

107 return cls 

108 

109 

110class _LISTMETA(type(Protocol)): 

111 def __iter__(self): 

112 return iter(tuple()) 

113 

114 def __len__(self): 

115 return 0 

116 

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

118 if isinstance(o, self): 

119 return True 

120 return super().__eq__(o) 

121 

122 

123class _LIST(DatasetQueryConstraintVariant, metaclass=_LISTMETA): 

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

125 self.members = list(members) 

126 

127 def __len__(self) -> int: 

128 return len(self.members) 

129 

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

131 return iter(self.members) 

132 

133 def __repr__(self) -> str: 

134 return repr(self.members) 

135 

136 def __str__(self) -> str: 

137 return str(self.members) 

138 

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

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

141 return self.members == o.members 

142 return super().__eq__(o) 

143 

144 

145def suppressInit(self): 

146 raise NotImplementedError( 

147 "DatasetQueryConstraintVariants cannot be directly instantiated. " 

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

149 ) 

150 

151 

152DatasetQueryConstraintVariant.__init__ = suppressInit 

153DatasetQueryConstraintVariant.ALL = _ALL 

154DatasetQueryConstraintVariant.OFF = _OFF 

155DatasetQueryConstraintVariant.LIST = _LIST