Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

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 Generic, List, Optional, Tuple, TYPE_CHECKING, 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 from .exprTree import Node 

32 

33 

34T = TypeVar("T") 

35 

36 

37class TreeVisitor(Generic[T]): 

38 """Definition of interface for visitor classes. 

39 

40 Visitors and tree node classes implement Visitor pattern for tree 

41 traversal. Typical use case is to generate different representation 

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

43 

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

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

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

47 to other methods of the visitor. 

48 """ 

49 @abstractmethod 

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

51 """Visit NumericLiteral node. 

52 

53 Parameters 

54 ---------- 

55 value : `str` 

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

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

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

59 node : `Node` 

60 Corresponding tree node, mostly useful for diagnostics. 

61 """ 

62 

63 @abstractmethod 

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

65 """Visit StringLiteral node. 

66 

67 Parameters 

68 ---------- 

69 value : `str` 

70 The value associated with the visited node. 

71 node : `Node` 

72 Corresponding tree node, mostly useful for diagnostics. 

73 """ 

74 

75 @abstractmethod 

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

77 """Visit TimeLiteral node. 

78 

79 Parameters 

80 ---------- 

81 value : `astropy.time.Time` 

82 The value associated with the visited node. 

83 node : `Node` 

84 Corresponding tree node, mostly useful for diagnostics. 

85 """ 

86 

87 @abstractmethod 

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

89 """Visit RangeLiteral node. 

90 

91 Parameters 

92 ---------- 

93 start : `int` 

94 Range starting value. 

95 stop : `int` 

96 Range final value. 

97 stride : `int` or `None` 

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

99 as 1). 

100 node : `Node` 

101 Corresponding tree node, mostly useful for diagnostics. 

102 """ 

103 

104 @abstractmethod 

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

106 """Visit Identifier node. 

107 

108 Parameters 

109 ---------- 

110 name : `str` 

111 Identifier name. 

112 node : `Node` 

113 Corresponding tree node, mostly useful for diagnostics. 

114 """ 

115 

116 @abstractmethod 

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

118 """Visit UnaryOp node. 

119 

120 Parameters 

121 ---------- 

122 operator : `str` 

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

124 operand : `object` 

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

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

127 node : `Node` 

128 Corresponding tree node, mostly useful for diagnostics. 

129 """ 

130 

131 @abstractmethod 

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

133 """Visit BinaryOp node. 

134 

135 Parameters 

136 ---------- 

137 operator : `str` 

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

139 lhs : `object` 

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

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

142 tree node. 

143 rhs : `object` 

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

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

146 tree node. 

147 node : `Node` 

148 Corresponding tree node, mostly useful for diagnostics. 

149 """ 

150 

151 @abstractmethod 

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

153 """Visit IsIn node. 

154 

155 Parameters 

156 ---------- 

157 lhs : `object` 

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

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

160 tree node. 

161 values : `list` of `object` 

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

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

164 not_in : `bool` 

165 `True` for "NOT IN" expression. 

166 node : `Node` 

167 Corresponding tree node, mostly useful for diagnostics. 

168 """ 

169 

170 @abstractmethod 

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

172 """Visit Parens node. 

173 

174 Parameters 

175 ---------- 

176 expression : `object` 

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

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

179 other tree node. 

180 node : `Node` 

181 Corresponding tree node, mostly useful for diagnostics. 

182 """ 

183 

184 @abstractmethod 

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

186 """Visit TupleNode node. 

187 

188 Parameters 

189 ---------- 

190 items : `tuple` of `object` 

191 Expressions inside parentheses, tuple of objects returned by one 

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

193 tuple items. 

194 node : `Node` 

195 Corresponding tree node, mostly useful for diagnostics. 

196 """ 

197 

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

199 """Visit FunctionCall node. 

200 

201 Parameters 

202 ---------- 

203 name : `str` 

204 Name of the function. 

205 args : `list` of `object` 

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

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

208 node : `Node` 

209 Corresponding tree node, mostly useful for diagnostics. 

210 

211 Notes 

212 ----- 

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

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

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

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

217 is a common implementation for those visitors which raises an 

218 exception. 

219 """ 

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

221 

222 @abstractmethod 

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

224 """Visit PointNode node. 

225 

226 Parameters 

227 ---------- 

228 ra, dec : `object` 

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

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

231 arguments. 

232 node : `Node` 

233 Corresponding tree node, mostly useful for diagnostics. 

234 """