11import re
22from collections import namedtuple
33from datetime import datetime
4+ from typing import NamedTuple , Sequence , Union
45
56from django .utils .functional import cached_property
67from parsimonious .exceptions import IncompleteParseError
138139)
139140
140141
141- def translate (pat ):
142+ def translate (pat ) -> str :
142143 """Translate a shell PATTERN to a regular expression.
143144 modified from: https://github.com/python/cpython/blob/2.7/Lib/fnmatch.py#L85
144145 """
@@ -176,70 +177,42 @@ class ParenExpression(namedtuple("ParenExpression", "children")):
176177 pass
177178
178179
179- class SearchFilter (namedtuple ("SearchFilter" , "key operator value" )):
180- def __str__ (self ):
181- return "" .join (map (str , (self .key .name , self .operator , self .value .raw_value )))
182-
183- @cached_property
184- def is_negation (self ):
185- # Negations are mostly just using != operators. But we also have
186- # negations on has: filters, which translate to = '', so handle that
187- # case as well.
188- return (
189- self .operator == "!="
190- and self .value .raw_value != ""
191- or self .operator == "="
192- and self .value .raw_value == ""
193- or self .operator == "NOT IN"
194- and self .value .raw_value
195- )
180+ class SearchKey (NamedTuple ):
181+ name : str
196182
197- @cached_property
198- def is_in_filter (self ):
199- return self .operator in ("IN" , "NOT IN" )
200-
201-
202- class SearchKey (namedtuple ("SearchKey" , "name" )):
203- @cached_property
204- def is_tag (self ):
183+ @property
184+ def is_tag (self ) -> bool :
205185 return TAG_KEY_RE .match (self .name ) or (
206186 self .name not in SEARCH_MAP
207187 and self .name not in FIELD_ALIASES
208188 and not self .is_measurement
209189 and not self .is_span_op_breakdown
210190 )
211191
212- @cached_property
213- def is_measurement (self ):
192+ @property
193+ def is_measurement (self ) -> bool :
214194 return is_measurement (self .name ) and self .name not in SEARCH_MAP
215195
216- @cached_property
217- def is_span_op_breakdown (self ):
196+ @property
197+ def is_span_op_breakdown (self ) -> bool :
218198 return is_span_op_breakdown (self .name ) and self .name not in SEARCH_MAP
219199
220200
221- class AggregateFilter (namedtuple ("AggregateFilter" , "key operator value" )):
222- def __str__ (self ):
223- return "" .join (map (str , (self .key .name , self .operator , self .value .raw_value )))
224-
225-
226- class AggregateKey (namedtuple ("AggregateKey" , "name" )):
227- pass
201+ class SearchValue (NamedTuple ):
202+ raw_value : Union [str , int , datetime , Sequence [int ], Sequence [str ]]
228203
229-
230- class SearchValue (namedtuple ("SearchValue" , "raw_value" )):
231204 @property
232205 def value (self ):
233206 if self .is_wildcard ():
234207 return translate (self .raw_value )
235208 return self .raw_value
236209
237- def is_wildcard (self ):
210+ def is_wildcard (self ) -> bool :
238211 if not isinstance (self .raw_value , str ):
239212 return False
240213 return bool (WILDCARD_CHARS .search (self .raw_value ))
241214
242- def is_event_id (self ):
215+ def is_event_id (self ) -> bool :
243216 """Return whether the current value is a valid event id
244217
245218 Empty strings are valid, so that it can be used for has:id queries
@@ -249,6 +222,46 @@ def is_event_id(self):
249222 return is_event_id (self .raw_value ) or self .raw_value == ""
250223
251224
225+ class SearchFilter (NamedTuple ):
226+ key : SearchKey
227+ operator : str
228+ value : SearchValue
229+
230+ def __str__ (self ):
231+ return "" .join (map (str , (self .key .name , self .operator , self .value .raw_value )))
232+
233+ @property
234+ def is_negation (self ) -> bool :
235+ # Negations are mostly just using != operators. But we also have
236+ # negations on has: filters, which translate to = '', so handle that
237+ # case as well.
238+ return (
239+ self .operator == "!="
240+ and self .value .raw_value != ""
241+ or self .operator == "="
242+ and self .value .raw_value == ""
243+ or self .operator == "NOT IN"
244+ and self .value .raw_value
245+ )
246+
247+ @property
248+ def is_in_filter (self ) -> bool :
249+ return self .operator in ("IN" , "NOT IN" )
250+
251+
252+ class AggregateFilter (NamedTuple ):
253+ key : SearchKey
254+ operator : str
255+ value : SearchValue
256+
257+ def __str__ (self ):
258+ return "" .join (map (str , (self .key .name , self .operator , self .value .raw_value )))
259+
260+
261+ class AggregateKey (NamedTuple ):
262+ name : str
263+
264+
252265class SearchVisitor (NodeVisitor ):
253266 # A list of mappers that map source keys to a target name. Format is
254267 # <target_name>: [<list of source names>],
0 commit comments