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

30 statements  

« prev     ^ index     » next       coverage.py v7.5.0, created at 2024-05-02 10:23 +0000

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 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 <https://www.gnu.org/licenses/>. 

27 

28from __future__ import annotations 

29 

30__all__ = ["TreeVisitor"] 

31 

32from abc import abstractmethod 

33from typing import TYPE_CHECKING, Generic, TypeVar 

34 

35if TYPE_CHECKING: 

36 import astropy.time 

37 

38 from .exprTree import Node 

39 

40 

41T = TypeVar("T") 

42 

43 

44class TreeVisitor(Generic[T]): 

45 """Definition of interface for visitor classes. 

46 

47 Visitors and tree node classes implement Visitor pattern for tree 

48 traversal. Typical use case is to generate different representation 

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

50 

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

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

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

54 to other methods of the visitor. 

55 """ 

56 

57 @abstractmethod 

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

59 """Visit NumericLiteral node. 

60 

61 Parameters 

62 ---------- 

63 value : `str` 

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

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

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

67 node : `Node` 

68 Corresponding tree node, mostly useful for diagnostics. 

69 """ 

70 

71 @abstractmethod 

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

73 """Visit StringLiteral node. 

74 

75 Parameters 

76 ---------- 

77 value : `str` 

78 The value associated with the visited node. 

79 node : `Node` 

80 Corresponding tree node, mostly useful for diagnostics. 

81 """ 

82 

83 @abstractmethod 

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

85 """Visit TimeLiteral node. 

86 

87 Parameters 

88 ---------- 

89 value : `astropy.time.Time` 

90 The value associated with the visited node. 

91 node : `Node` 

92 Corresponding tree node, mostly useful for diagnostics. 

93 """ 

94 

95 @abstractmethod 

96 def visitRangeLiteral(self, start: int, stop: int, stride: int | None, node: Node) -> T: 

97 """Visit RangeLiteral node. 

98 

99 Parameters 

100 ---------- 

101 start : `int` 

102 Range starting value. 

103 stop : `int` 

104 Range final value. 

105 stride : `int` or `None` 

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

107 as 1). 

108 node : `Node` 

109 Corresponding tree node, mostly useful for diagnostics. 

110 """ 

111 

112 @abstractmethod 

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

114 """Visit Identifier node. 

115 

116 Parameters 

117 ---------- 

118 name : `str` 

119 Identifier name. 

120 node : `Node` 

121 Corresponding tree node, mostly useful for diagnostics. 

122 """ 

123 

124 @abstractmethod 

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

126 """Visit UnaryOp node. 

127 

128 Parameters 

129 ---------- 

130 operator : `str` 

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

132 operand : `object` 

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

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

135 node : `Node` 

136 Corresponding tree node, mostly useful for diagnostics. 

137 """ 

138 

139 @abstractmethod 

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

141 """Visit BinaryOp node. 

142 

143 Parameters 

144 ---------- 

145 operator : `str` 

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

147 lhs : `object` 

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

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

150 tree node. 

151 rhs : `object` 

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

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

154 tree node. 

155 node : `Node` 

156 Corresponding tree node, mostly useful for diagnostics. 

157 """ 

158 

159 @abstractmethod 

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

161 """Visit IsIn node. 

162 

163 Parameters 

164 ---------- 

165 lhs : `object` 

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

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

168 tree node. 

169 values : `list` of `object` 

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

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

172 not_in : `bool` 

173 `True` for "NOT IN" expression. 

174 node : `Node` 

175 Corresponding tree node, mostly useful for diagnostics. 

176 """ 

177 

178 @abstractmethod 

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

180 """Visit Parens node. 

181 

182 Parameters 

183 ---------- 

184 expression : `object` 

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

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

187 other tree node. 

188 node : `Node` 

189 Corresponding tree node, mostly useful for diagnostics. 

190 """ 

191 

192 @abstractmethod 

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

194 """Visit TupleNode node. 

195 

196 Parameters 

197 ---------- 

198 items : `tuple` of `object` 

199 Expressions inside parentheses, tuple of objects returned by one 

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

201 tuple items. 

202 node : `Node` 

203 Corresponding tree node, mostly useful for diagnostics. 

204 """ 

205 

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

207 """Visit FunctionCall node. 

208 

209 Parameters 

210 ---------- 

211 name : `str` 

212 Name of the function. 

213 args : `list` of `object` 

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

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

216 node : `Node` 

217 Corresponding tree node, mostly useful for diagnostics. 

218 

219 Notes 

220 ----- 

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

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

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

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

225 is a common implementation for those visitors which raises an 

226 exception. 

227 """ 

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

229 

230 @abstractmethod 

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

232 """Visit PointNode node. 

233 

234 Parameters 

235 ---------- 

236 ra, dec : `object` 

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

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

239 arguments. 

240 node : `Node` 

241 Corresponding tree node, mostly useful for diagnostics. 

242 """