tellaro-query-language 0.1.7__py3-none-any.whl → 0.1.9__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: tellaro-query-language
3
- Version: 0.1.7
3
+ Version: 0.1.9
4
4
  Summary: A flexible, human-friendly query language for searching and filtering structured data
5
5
  Home-page: https://github.com/tellaro/tellaro-query-language
6
6
  License: MIT
@@ -4,14 +4,14 @@ tql/cache/__init__.py,sha256=GIzIEMZUZEYJj72sAhuVLEG-OJEKUG2srUWNM3Ix-T8,213
4
4
  tql/cache/base.py,sha256=0b-8uyh3JltayGmXQI45snTqsM5sQu9u0KcNvZIRa-I,687
5
5
  tql/cache/memory.py,sha256=ibcmQSAxNvqCy6DksbU7gLu6UArYp1u3fW-oLubxtV0,2056
6
6
  tql/cache/redis.py,sha256=ZU_IsVDvpSYpNvPfnZ4iulJDODpEGx3c4dkXLzPzPVc,2309
7
- tql/core.py,sha256=zAkTStN_3logY9ARABDZNsQJfXV5rITiiTKoX5bo274,40859
7
+ tql/core.py,sha256=zIihZijiwqejG78EIRikTtaDvzMgcy2cwBCL3-HwZy8,40797
8
8
  tql/core_components/README.md,sha256=Rm7w4UHdQ0vPBEFybE5b62IOvSA5Nzq2GRvtBHOapmc,3068
9
9
  tql/core_components/__init__.py,sha256=v8BBybPlqV7dkVY9mw1mblvqyAFJZ7Pf_bEc-jAL7FI,643
10
10
  tql/core_components/file_operations.py,sha256=Jr0kkxz_OP2KHOAsIr7KMtYe_lbu8LuBUySt2LQbjJw,3925
11
- tql/core_components/opensearch_operations.py,sha256=X9xtVnrC37O-9eSTbdilvi_cjvm0jXHZIPdldM0yM7g,38028
11
+ tql/core_components/opensearch_operations.py,sha256=HIiSosL2uek88H6aPkX_QDnlgV8bT1fbotG652Z2vdE,37900
12
12
  tql/core_components/stats_operations.py,sha256=zAfDhVOFFPMrRIMw6Qtjxbobbdi7ao_HuHBCcVc3BGY,7579
13
13
  tql/core_components/validation_operations.py,sha256=_VPXh0HABBjsXF99jFT7B6-5QAPsADOCy6poinGrxeE,22454
14
- tql/evaluator.py,sha256=YdgS1vuxUEPAHhUsZey-Y4NydeS8CTYOy_O8R5_K8cE,15421
14
+ tql/evaluator.py,sha256=kjqf2rkjdfPhrX2gyNtiBpdnBpob3LFkTuvplLtc-Ww,15542
15
15
  tql/evaluator_components/README.md,sha256=c59yf2au34yPhrru7JWgGop_ORteB6w5vfMhsac8j3k,3882
16
16
  tql/evaluator_components/__init__.py,sha256=DourRUSYXWPnCghBFj7W0YfMeymT3X8YTDCwnLIyP1c,535
17
17
  tql/evaluator_components/field_access.py,sha256=BuXvL9jlv4H77neT70Vh7_qokmzs-d4EbSDA2FB1IT0,6435
@@ -33,11 +33,11 @@ tql/opensearch.py,sha256=J7LhfVJfaXEWtyZqVDqNZaeIbIcUYJr2cQtfKzdyIhM,3362
33
33
  tql/opensearch_components/README.md,sha256=gt-qLmmach8Kh7-QwLZmoAxxIL79XIG1EDqJum8PMZE,3756
34
34
  tql/opensearch_components/__init__.py,sha256=_zIZY8Fns7mkEcY6w2p9FNRBXtEmmPFFJEcFRfrVyXA,514
35
35
  tql/opensearch_components/field_mapping.py,sha256=N4r7VkzNeXjIhNDt2cfnd1LbkvaS_9O298PIDAcR_Hw,17569
36
- tql/opensearch_components/lucene_converter.py,sha256=ZbupWZ2smGhWfE9cSIrNo7MZVY35l2t86HYM-bd7nKw,12436
37
- tql/opensearch_components/query_converter.py,sha256=9Nkhehb8X7jIQcyRaHCa5WCKWtovdRGKuSdDsBulrG0,36722
36
+ tql/opensearch_components/lucene_converter.py,sha256=ke1cMCeGVf5UorjwhN3y9x-GO-AHJ7FmbuTPSNMxYJo,12570
37
+ tql/opensearch_components/query_converter.py,sha256=QodPaRJf5fI_DpMzRGINFIdpmcZZ_3Umlw1h33zsrZE,36858
38
38
  tql/opensearch_mappings.py,sha256=zJCCdMrxK7mswrkxd5LiOhunQ9GIJNZdhktVoGXgVgk,11529
39
- tql/opensearch_stats.py,sha256=03mjvnUJpNtCDpU-E1ZkugDJMIKC-F76Hekd4gppPxU,17812
40
- tql/parser.py,sha256=dnjgc-sDVihe-VIVPT_SRULeng4OWaLtkbM23dluT6M,75532
39
+ tql/opensearch_stats.py,sha256=h-hA2EZ-sc4S1zxr7jaInmonfrgTXoGBbb9sOYurdFE,17823
40
+ tql/parser.py,sha256=MnY1Gxm8vl2Uw2tU2CyFB26uE3TSeUx6i7APtlwh7Fk,75727
41
41
  tql/parser_components/README.md,sha256=lvQX72ckq2zyotGs8QIHHCIFqaA7bOHwkP44wU8Zoiw,2322
42
42
  tql/parser_components/__init__.py,sha256=zBwHBMPJyHSBbaOojf6qTrJYjJg5A6tPUE8nHFdRiQs,521
43
43
  tql/parser_components/ast_builder.py,sha256=-pbcYhZNoRm0AnjmJRAAlXLCAwHfauchTpX_6KO0plE,6793
@@ -46,11 +46,11 @@ tql/parser_components/field_extractor.py,sha256=TumeuUo2c5gPYVbTPsmU43C3TJFC8chA
46
46
  tql/parser_components/grammar.py,sha256=lSvjABvEBaH29-ad-_UGD4WmofdNwC_pO2OKQJ_It-U,19309
47
47
  tql/post_processor.py,sha256=-vA2wgbuLij2FVnj5I9HDHtw5bKj9Cu3EE9mtoeSWk8,28859
48
48
  tql/scripts.py,sha256=VOr5vCjIvKlW36kwvJx7JGFIRM16IJZlbJcWlBexBtk,3728
49
- tql/stats_evaluator.py,sha256=GtmygLdPPMhAMR5bN1h69cQsNBYqg-jQl6bN5rwEx6Q,15692
49
+ tql/stats_evaluator.py,sha256=lOEbICFuP0krZZqEjREz37xlpm35_P6eRgkHVgJLNI4,15703
50
50
  tql/stats_transformer.py,sha256=MT-4rDWZSySgn4Fuq9H0c-mvwFYLM6FqWpPv2rHX-rE,7588
51
51
  tql/validators.py,sha256=e9MlX-zQ_O3M8YP8vXyMjKU8iiJMTh6mMK0iv0_4gTY,3771
52
- tellaro_query_language-0.1.7.dist-info/LICENSE,sha256=zRhQ85LnW55fWgAjQctckwQ67DX5Jmt64lq343ThZFU,1063
53
- tellaro_query_language-0.1.7.dist-info/METADATA,sha256=IDzVPrFm_GQJTRZRX4iLNw45Nqszf3TqBW6ZW6UUKBo,15109
54
- tellaro_query_language-0.1.7.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
55
- tellaro_query_language-0.1.7.dist-info/entry_points.txt,sha256=H43APfGBMsZkKsUCnFTaqprQPW-Kce2yz2qsBL3dZrw,164
56
- tellaro_query_language-0.1.7.dist-info/RECORD,,
52
+ tellaro_query_language-0.1.9.dist-info/LICENSE,sha256=zRhQ85LnW55fWgAjQctckwQ67DX5Jmt64lq343ThZFU,1063
53
+ tellaro_query_language-0.1.9.dist-info/METADATA,sha256=fChSevkv4sS0e0XQcq4oDH5kP0FZZj7zRHJs84duh_c,15109
54
+ tellaro_query_language-0.1.9.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
55
+ tellaro_query_language-0.1.9.dist-info/entry_points.txt,sha256=H43APfGBMsZkKsUCnFTaqprQPW-Kce2yz2qsBL3dZrw,164
56
+ tellaro_query_language-0.1.9.dist-info/RECORD,,
tql/core.py CHANGED
@@ -167,7 +167,7 @@ class TQL:
167
167
  return f"NOT {operand}"
168
168
  return str(ast)
169
169
 
170
- def query(
170
+ def query( # noqa: C901
171
171
  self, data: Union[List[Dict], str], query: str, size: int = 10, save_enrichment: bool = False
172
172
  ) -> Dict[str, Any]: # noqa: C901
173
173
  """Execute a TQL query against data and return results in execute_opensearch format.
@@ -470,8 +470,7 @@ class TQL:
470
470
  size: Number of results to return (default: 500)
471
471
  from_: Starting offset for pagination (default: 0)
472
472
  timestamp_field: Field name for timestamp filtering (default: "@timestamp")
473
- time_range: Optional time range dict with 'gte' and/or 'lte' keys.
474
- If None, defaults to 'gte': 'now-15m', 'lte': 'now'
473
+ time_range: Optional time range dict with 'gte' and/or 'lte' keys
475
474
  scan_all: If True, use scroll API to retrieve all matching documents
476
475
  scroll_size: Size per scroll when scan_all=True (default: 1000)
477
476
  scroll_timeout: Scroll timeout when scan_all=True (default: "5m")
@@ -311,10 +311,6 @@ class OpenSearchOperations:
311
311
  search_body = opensearch_query.copy()
312
312
 
313
313
  # Handle time range filtering
314
- if time_range is None:
315
- # Default time range: last 15 minutes
316
- time_range = {"gte": "now-15m", "lte": "now"}
317
-
318
314
  # Add time range filter to the query
319
315
  if time_range:
320
316
  base_query = search_body.get("query", {})
@@ -492,7 +488,7 @@ class OpenSearchOperations:
492
488
  }
493
489
  else:
494
490
  # Multiple aggregations
495
- results = {}
491
+ agg_results = {}
496
492
  for i, agg in enumerate(aggregations):
497
493
  func = agg.get("function", "")
498
494
  field = agg.get("field", "*")
@@ -522,11 +518,11 @@ class OpenSearchOperations:
522
518
  value = agg_result
523
519
 
524
520
  key = agg.get("alias") or f"{func}_{field}"
525
- results[key] = value
521
+ agg_results[key] = value
526
522
 
527
523
  stats_results = {
528
524
  "type": "stats",
529
- "results": results,
525
+ "results": agg_results,
530
526
  }
531
527
  else:
532
528
  stats_results = {"type": "stats", "operation": "unknown", "field": "*", "values": 0, "group_by": []}
tql/evaluator.py CHANGED
@@ -81,7 +81,10 @@ class TQLEvaluator:
81
81
  if isinstance(node, dict):
82
82
  node_type = node.get("type")
83
83
 
84
- if node_type == "comparison":
84
+ if node_type == "match_all":
85
+ # Empty query matches all records
86
+ return True
87
+ elif node_type == "comparison":
85
88
  return self._evaluate_comparison(node, record, field_mappings)
86
89
  elif node_type == "logical_op":
87
90
  return self._evaluate_logical_op(node, record, field_mappings)
@@ -31,7 +31,10 @@ class LuceneConverter:
31
31
  if isinstance(node, dict):
32
32
  node_type = node.get("type")
33
33
 
34
- if node_type == "comparison":
34
+ if node_type == "match_all":
35
+ # Empty query matches all documents in Lucene
36
+ return "*:*"
37
+ elif node_type == "comparison":
35
38
  return self._convert_comparison_to_lucene(node)
36
39
  elif node_type == "logical_op":
37
40
  return self._convert_logical_op_to_lucene(node)
@@ -27,7 +27,10 @@ class QueryConverter:
27
27
  if isinstance(node, dict):
28
28
  node_type = node.get("type")
29
29
 
30
- if node_type == "comparison":
30
+ if node_type == "match_all":
31
+ # Empty query matches all documents
32
+ return {"match_all": {}}
33
+ elif node_type == "comparison":
31
34
  return self._convert_comparison(node)
32
35
  elif node_type == "logical_op":
33
36
  return self._convert_logical_op(node)
tql/opensearch_stats.py CHANGED
@@ -404,7 +404,7 @@ class OpenSearchStatsTranslator:
404
404
 
405
405
  def _extract_aggregation_value( # noqa: C901
406
406
  self, agg_result: Dict[str, Any], function: str
407
- ) -> Union[int, float, Dict[str, Any], None]:
407
+ ) -> Union[int, float, Dict[str, Any], List[Any], None]:
408
408
  """Extract value from OpenSearch aggregation result.
409
409
 
410
410
  Args:
tql/parser.py CHANGED
@@ -43,6 +43,11 @@ class TQLParser:
43
43
  Raises:
44
44
  TQLParseError: If the query has invalid syntax
45
45
  """
46
+ # Handle empty or whitespace-only queries
47
+ if not query or not query.strip():
48
+ # Return a special AST that matches all records
49
+ return {"type": "match_all"}
50
+
46
51
  try:
47
52
  # Parse the query
48
53
  parsed_result = self.grammar.tql_expr.parseString(query, parseAll=True)
tql/stats_evaluator.py CHANGED
@@ -198,7 +198,7 @@ class TQLStatsEvaluator:
198
198
 
199
199
  def _calculate_aggregation( # noqa: C901
200
200
  self, records: List[Dict[str, Any]], agg_spec: Dict[str, Any]
201
- ) -> Union[int, float, Dict[str, Any], None]:
201
+ ) -> Union[int, float, Dict[str, Any], List[Any], None]:
202
202
  """Calculate a single aggregation value.
203
203
 
204
204
  Args: