Coverage for python/lsst/daf/butler/registry/queries/expressions/parser/treeVisitor.py: 89%

33 statements  

« prev     ^ index     » next       coverage.py v6.5.0, created at 2022-10-04 02:18 -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# (https://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 <https://www.gnu.org/licenses/>. 

21 

22from __future__ import annotations 

23 

24__all__ = ["TreeVisitor"] 

25 

26from abc import abstractmethod 

27from typing import TYPE_CHECKING, Generic, List, Optional, Tuple, TypeVar 

28 

29if TYPE_CHECKING: 29 ↛ 30line 29 didn't jump to line 30, because the condition on line 29 was never true

30 import astropy.time 

31 

32 from .exprTree import Node 

33 

34 

35T = TypeVar("T") 

36 

37 

38class TreeVisitor(Generic[T]): 

39 """Definition of interface for visitor classes. 

40 

41 Visitors and tree node classes implement Visitor pattern for tree 

42 traversal. Typical use case is to generate different representation 

43 of the tree, e.g. transforming parsed tree into SQLAlchemy clause. 

44 

45 All methods of the class can (and most likely should) return the 

46 "transformed" value of the visited node. This value will be returned 

47 from the `Node.visit` method and it will also be passed as an argument 

48 to other methods of the visitor. 

49 """ 

50 

51 @abstractmethod 

52 def visitNumericLiteral(self, value: str, node: Node) -> T: 

53 """Visit NumericLiteral node. 

54 

55 Parameters 

56 ---------- 

57 value : `str` 

58 The value associated with the visited node, the value is string, 

59 exactly as it appears in the original expression. Depending on 

60 use case it may need to be converted to `int` or `float`. 

61 node : `Node` 

62 Corresponding tree node, mostly useful for diagnostics. 

63 """ 

64 

65 @abstractmethod 

66 def visitStringLiteral(self, value: str, node: Node) -> T: 

67 """Visit StringLiteral node. 

68 

69 Parameters 

70 ---------- 

71 value : `str` 

72 The value associated with the visited node. 

73 node : `Node` 

74 Corresponding tree node, mostly useful for diagnostics. 

75 """ 

76 

77 @abstractmethod 

78 def visitTimeLiteral(self, value: astropy.time.Time, node: Node) -> T: 

79 """Visit TimeLiteral node. 

80 

81 Parameters 

82 ---------- 

83 value : `astropy.time.Time` 

84 The value associated with the visited node. 

85 node : `Node` 

86 Corresponding tree node, mostly useful for diagnostics. 

87 """ 

88 

89 @abstractmethod 

90 def visitRangeLiteral(self, start: int, stop: int, stride: Optional[int], node: Node) -> T: 

91 """Visit RangeLiteral node. 

92 

93 Parameters 

94 ---------- 

95 start : `int` 

96 Range starting value. 

97 stop : `int` 

98 Range final value. 

99 stride : `int` or `None` 

100 Stride, can be `None` if not specified (should be treated same 

101 as 1). 

102 node : `Node` 

103 Corresponding tree node, mostly useful for diagnostics. 

104 """ 

105 

106 @abstractmethod 

107 def visitIdentifier(self, name: str, node: Node) -> T: 

108 """Visit Identifier node. 

109 

110 Parameters 

111 ---------- 

112 name : `str` 

113 Identifier name. 

114 node : `Node` 

115 Corresponding tree node, mostly useful for diagnostics. 

116 """ 

117 

118 @abstractmethod 

119 def visitUnaryOp(self, operator: str, operand: T, node: Node) -> T: 

120 """Visit UnaryOp node. 

121 

122 Parameters 

123 ---------- 

124 operator : `str` 

125 Operator name, e.g. "NOT" or "+". 

126 operand : `object` 

127 Operand, this object is returned by one of the methods of this 

128 class as a result of transformation of some other tree node. 

129 node : `Node` 

130 Corresponding tree node, mostly useful for diagnostics. 

131 """ 

132 

133 @abstractmethod 

134 def visitBinaryOp(self, operator: str, lhs: T, rhs: T, node: Node) -> T: 

135 """Visit BinaryOp node. 

136 

137 Parameters 

138 ---------- 

139 operator : `str` 

140 Operator name, e.g. "NOT" or "+". 

141 lhs : `object` 

142 Left hand side operand, this object is returned by one of the 

143 methods of this class as a result of transformation of some other 

144 tree node. 

145 rhs : `object` 

146 Right hand side operand, this object is returned by one of the 

147 methods of this class as a result of transformation of some other 

148 tree node. 

149 node : `Node` 

150 Corresponding tree node, mostly useful for diagnostics. 

151 """ 

152 

153 @abstractmethod 

154 def visitIsIn(self, lhs: T, values: List[T], not_in: bool, node: Node) -> T: 

155 """Visit IsIn node. 

156 

157 Parameters 

158 ---------- 

159 lhs : `object` 

160 Left hand side operand, this object is returned by one of the 

161 methods of this class as a result of transformation of some other 

162 tree node. 

163 values : `list` of `object` 

164 Right hand side operand, list of objects returned by methods of 

165 this class as a result of transformation of some other tree nodes. 

166 not_in : `bool` 

167 `True` for "NOT IN" expression. 

168 node : `Node` 

169 Corresponding tree node, mostly useful for diagnostics. 

170 """ 

171 

172 @abstractmethod 

173 def visitParens(self, expression: T, node: Node) -> T: 

174 """Visit Parens node. 

175 

176 Parameters 

177 ---------- 

178 expression : `object` 

179 Expression inside parentheses, this object is returned by one of 

180 the methods of this class as a result of transformation of some 

181 other tree node. 

182 node : `Node` 

183 Corresponding tree node, mostly useful for diagnostics. 

184 """ 

185 

186 @abstractmethod 

187 def visitTupleNode(self, items: Tuple[T, ...], node: Node) -> T: 

188 """Visit TupleNode node. 

189 

190 Parameters 

191 ---------- 

192 items : `tuple` of `object` 

193 Expressions inside parentheses, tuple of objects returned by one 

194 of the methods of this class as a result of transformation of 

195 tuple items. 

196 node : `Node` 

197 Corresponding tree node, mostly useful for diagnostics. 

198 """ 

199 

200 def visitFunctionCall(self, name: str, args: List[T], node: Node) -> T: 

201 """Visit FunctionCall node. 

202 

203 Parameters 

204 ---------- 

205 name : `str` 

206 Name of the function. 

207 args : `list` of `object` 

208 Arguments to function, list of objects returned by methods of 

209 this class as a result of transformation of function arguments. 

210 node : `Node` 

211 Corresponding tree node, mostly useful for diagnostics. 

212 

213 Notes 

214 ----- 

215 For now we only have to support one specific function ``POINT()`` 

216 and for that function we define special node type `PointNode`. 

217 `FunctionCall` node type represents a generic function and regular 

218 visitors do not handle generic function. This non-abstract method 

219 is a common implementation for those visitors which raises an 

220 exception. 

221 """ 

222 raise ValueError(f"Unknown function '{name}' in expression") 

223 

224 @abstractmethod 

225 def visitPointNode(self, ra: T, dec: T, node: Node) -> T: 

226 """Visit PointNode node. 

227 

228 Parameters 

229 ---------- 

230 ra, dec : `object` 

231 Representation of 'ra' and 'dec' values, objects returned by 

232 methods of this class as a result of transformation of function 

233 arguments. 

234 node : `Node` 

235 Corresponding tree node, mostly useful for diagnostics. 

236 """