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

67 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2023-06-15 02:49 -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 collections.abc import Iterable, Iterator 

31from typing import Protocol 

32 

33 

34class DatasetQueryConstraintVariant(Iterable, Protocol): 

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

36 constraining graph building queries based on dataset type existence. 

37 

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

39 a query. 

40 

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

42 graph building query. 

43 

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

45 in constraining a graph building query. 

46 

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

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

49 

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

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

52 it were an empty instance. 

53 

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

55 `fromExpression` class method given a valid string. 

56 """ 

57 

58 ALL: "type[_ALL]" 

59 OFF: "type[_OFF]" 

60 LIST: "type[_LIST]" 

61 

62 @classmethod 

63 def __subclasshook__(cls, subclass): 

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

65 return True 

66 return False 

67 

68 @classmethod 

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

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

71 expression. 

72 

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

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

75 or comma-separated list of dataset type names. 

76 """ 

77 if not isinstance(expression, str): 

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

79 elif expression == "all": 

80 return cls.ALL 

81 elif expression == "off": 

82 return cls.OFF 

83 else: 

84 if " " in expression: 

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

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

87 members = expression.split(",") 

88 return cls.LIST(members) 

89 

90 

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

92 def __iter__(self) -> Iterator: 

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

94 

95 

96class _ALL(metaclass=_ALLMETA): 

97 def __new__(cls): 

98 return cls 

99 

100 

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

102 def __iter__(self) -> Iterator: 

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

104 

105 

106class _OFF(metaclass=_OFFMETA): 

107 def __new__(cls): 

108 return cls 

109 

110 

111class _LISTMETA(type(Protocol)): 

112 def __iter__(self): 

113 return iter(tuple()) 

114 

115 def __len__(self): 

116 return 0 

117 

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

119 if isinstance(o, self): 

120 return True 

121 return super().__eq__(o) 

122 

123 

124class _LIST(DatasetQueryConstraintVariant, metaclass=_LISTMETA): 

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

126 self.members = list(members) 

127 

128 def __len__(self) -> int: 

129 return len(self.members) 

130 

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

132 return iter(self.members) 

133 

134 def __repr__(self) -> str: 

135 return repr(self.members) 

136 

137 def __str__(self) -> str: 

138 return str(self.members) 

139 

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

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

142 return self.members == o.members 

143 return super().__eq__(o) 

144 

145 

146def suppressInit(self): 

147 raise NotImplementedError( 

148 "DatasetQueryConstraintVariants cannot be directly instantiated. " 

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

150 ) 

151 

152 

153DatasetQueryConstraintVariant.__init__ = suppressInit 

154DatasetQueryConstraintVariant.ALL = _ALL 

155DatasetQueryConstraintVariant.OFF = _OFF 

156DatasetQueryConstraintVariant.LIST = _LIST