Coverage for python/lsst/daf/butler/registry/queries/expressions/parser/treeVisitor.py: 97%
30 statements
« prev ^ index » next coverage.py v7.2.5, created at 2023-05-18 09:12 +0000
« prev ^ index » next coverage.py v7.2.5, created at 2023-05-18 09:12 +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 TYPE_CHECKING, Generic, List, Optional, Tuple, TypeVar
29if TYPE_CHECKING:
30 import astropy.time
32 from .exprTree import Node
35T = TypeVar("T")
38class TreeVisitor(Generic[T]):
39 """Definition of interface for visitor classes.
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.
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 """
51 @abstractmethod
52 def visitNumericLiteral(self, value: str, node: Node) -> T:
53 """Visit NumericLiteral node.
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 """
65 @abstractmethod
66 def visitStringLiteral(self, value: str, node: Node) -> T:
67 """Visit StringLiteral node.
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 """
77 @abstractmethod
78 def visitTimeLiteral(self, value: astropy.time.Time, node: Node) -> T:
79 """Visit TimeLiteral node.
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 """
89 @abstractmethod
90 def visitRangeLiteral(self, start: int, stop: int, stride: Optional[int], node: Node) -> T:
91 """Visit RangeLiteral node.
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 """
106 @abstractmethod
107 def visitIdentifier(self, name: str, node: Node) -> T:
108 """Visit Identifier node.
110 Parameters
111 ----------
112 name : `str`
113 Identifier name.
114 node : `Node`
115 Corresponding tree node, mostly useful for diagnostics.
116 """
118 @abstractmethod
119 def visitUnaryOp(self, operator: str, operand: T, node: Node) -> T:
120 """Visit UnaryOp node.
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 """
133 @abstractmethod
134 def visitBinaryOp(self, operator: str, lhs: T, rhs: T, node: Node) -> T:
135 """Visit BinaryOp node.
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 """
153 @abstractmethod
154 def visitIsIn(self, lhs: T, values: List[T], not_in: bool, node: Node) -> T:
155 """Visit IsIn node.
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 """
172 @abstractmethod
173 def visitParens(self, expression: T, node: Node) -> T:
174 """Visit Parens node.
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 """
186 @abstractmethod
187 def visitTupleNode(self, items: Tuple[T, ...], node: Node) -> T:
188 """Visit TupleNode node.
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 """
200 def visitFunctionCall(self, name: str, args: List[T], node: Node) -> T:
201 """Visit FunctionCall node.
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.
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")
224 @abstractmethod
225 def visitPointNode(self, ra: T, dec: T, node: Node) -> T:
226 """Visit PointNode node.
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 """