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-12-01 19:54 +0000
« prev ^ index » next coverage.py v6.5.0, created at 2022-12-01 19:54 +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 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/>.
22from __future__ import annotations
24__all__ = ['TreeVisitor']
26from abc import abstractmethod
27from typing import Generic, List, Optional, Tuple, TYPE_CHECKING, TypeVar
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
34T = TypeVar("T")
37class TreeVisitor(Generic[T]):
38 """Definition of interface for visitor classes.
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.
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.
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 """
63 @abstractmethod
64 def visitStringLiteral(self, value: str, node: Node) -> T:
65 """Visit StringLiteral node.
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 """
75 @abstractmethod
76 def visitTimeLiteral(self, value: astropy.time.Time, node: Node) -> T:
77 """Visit TimeLiteral node.
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 """
87 @abstractmethod
88 def visitRangeLiteral(self, start: int, stop: int, stride: Optional[int], node: Node) -> T:
89 """Visit RangeLiteral node.
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 """
104 @abstractmethod
105 def visitIdentifier(self, name: str, node: Node) -> T:
106 """Visit Identifier node.
108 Parameters
109 ----------
110 name : `str`
111 Identifier name.
112 node : `Node`
113 Corresponding tree node, mostly useful for diagnostics.
114 """
116 @abstractmethod
117 def visitUnaryOp(self, operator: str, operand: T, node: Node) -> T:
118 """Visit UnaryOp node.
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 """
131 @abstractmethod
132 def visitBinaryOp(self, operator: str, lhs: T, rhs: T, node: Node) -> T:
133 """Visit BinaryOp node.
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 """
151 @abstractmethod
152 def visitIsIn(self, lhs: T, values: List[T], not_in: bool, node: Node) -> T:
153 """Visit IsIn node.
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 """
170 @abstractmethod
171 def visitParens(self, expression: T, node: Node) -> T:
172 """Visit Parens node.
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 """
184 @abstractmethod
185 def visitTupleNode(self, items: Tuple[T, ...], node: Node) -> T:
186 """Visit TupleNode node.
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 """
198 def visitFunctionCall(self, name: str, args: List[T], node: Node) -> T:
199 """Visit FunctionCall node.
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.
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")
222 @abstractmethod
223 def visitPointNode(self, ra: T, dec: T, node: Node) -> T:
224 """Visit PointNode node.
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 """