tellaro-query-language 0.1.7__tar.gz → 0.1.9__tar.gz

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.
Files changed (55) hide show
  1. {tellaro_query_language-0.1.7 → tellaro_query_language-0.1.9}/PKG-INFO +1 -1
  2. {tellaro_query_language-0.1.7 → tellaro_query_language-0.1.9}/pyproject.toml +1 -1
  3. {tellaro_query_language-0.1.7 → tellaro_query_language-0.1.9}/src/tql/core.py +2 -3
  4. {tellaro_query_language-0.1.7 → tellaro_query_language-0.1.9}/src/tql/core_components/opensearch_operations.py +3 -7
  5. {tellaro_query_language-0.1.7 → tellaro_query_language-0.1.9}/src/tql/evaluator.py +4 -1
  6. {tellaro_query_language-0.1.7 → tellaro_query_language-0.1.9}/src/tql/opensearch_components/lucene_converter.py +4 -1
  7. {tellaro_query_language-0.1.7 → tellaro_query_language-0.1.9}/src/tql/opensearch_components/query_converter.py +4 -1
  8. {tellaro_query_language-0.1.7 → tellaro_query_language-0.1.9}/src/tql/opensearch_stats.py +1 -1
  9. {tellaro_query_language-0.1.7 → tellaro_query_language-0.1.9}/src/tql/parser.py +5 -0
  10. {tellaro_query_language-0.1.7 → tellaro_query_language-0.1.9}/src/tql/stats_evaluator.py +1 -1
  11. {tellaro_query_language-0.1.7 → tellaro_query_language-0.1.9}/LICENSE +0 -0
  12. {tellaro_query_language-0.1.7 → tellaro_query_language-0.1.9}/README.md +0 -0
  13. {tellaro_query_language-0.1.7 → tellaro_query_language-0.1.9}/src/tql/__init__.py +0 -0
  14. {tellaro_query_language-0.1.7 → tellaro_query_language-0.1.9}/src/tql/analyzer.py +0 -0
  15. {tellaro_query_language-0.1.7 → tellaro_query_language-0.1.9}/src/tql/cache/__init__.py +0 -0
  16. {tellaro_query_language-0.1.7 → tellaro_query_language-0.1.9}/src/tql/cache/base.py +0 -0
  17. {tellaro_query_language-0.1.7 → tellaro_query_language-0.1.9}/src/tql/cache/memory.py +0 -0
  18. {tellaro_query_language-0.1.7 → tellaro_query_language-0.1.9}/src/tql/cache/redis.py +0 -0
  19. {tellaro_query_language-0.1.7 → tellaro_query_language-0.1.9}/src/tql/core_components/README.md +0 -0
  20. {tellaro_query_language-0.1.7 → tellaro_query_language-0.1.9}/src/tql/core_components/__init__.py +0 -0
  21. {tellaro_query_language-0.1.7 → tellaro_query_language-0.1.9}/src/tql/core_components/file_operations.py +0 -0
  22. {tellaro_query_language-0.1.7 → tellaro_query_language-0.1.9}/src/tql/core_components/stats_operations.py +0 -0
  23. {tellaro_query_language-0.1.7 → tellaro_query_language-0.1.9}/src/tql/core_components/validation_operations.py +0 -0
  24. {tellaro_query_language-0.1.7 → tellaro_query_language-0.1.9}/src/tql/evaluator_components/README.md +0 -0
  25. {tellaro_query_language-0.1.7 → tellaro_query_language-0.1.9}/src/tql/evaluator_components/__init__.py +0 -0
  26. {tellaro_query_language-0.1.7 → tellaro_query_language-0.1.9}/src/tql/evaluator_components/field_access.py +0 -0
  27. {tellaro_query_language-0.1.7 → tellaro_query_language-0.1.9}/src/tql/evaluator_components/special_expressions.py +0 -0
  28. {tellaro_query_language-0.1.7 → tellaro_query_language-0.1.9}/src/tql/evaluator_components/value_comparison.py +0 -0
  29. {tellaro_query_language-0.1.7 → tellaro_query_language-0.1.9}/src/tql/exceptions.py +0 -0
  30. {tellaro_query_language-0.1.7 → tellaro_query_language-0.1.9}/src/tql/geoip_normalizer.py +0 -0
  31. {tellaro_query_language-0.1.7 → tellaro_query_language-0.1.9}/src/tql/mutator_analyzer.py +0 -0
  32. {tellaro_query_language-0.1.7 → tellaro_query_language-0.1.9}/src/tql/mutators/__init__.py +0 -0
  33. {tellaro_query_language-0.1.7 → tellaro_query_language-0.1.9}/src/tql/mutators/base.py +0 -0
  34. {tellaro_query_language-0.1.7 → tellaro_query_language-0.1.9}/src/tql/mutators/dns.py +0 -0
  35. {tellaro_query_language-0.1.7 → tellaro_query_language-0.1.9}/src/tql/mutators/encoding.py +0 -0
  36. {tellaro_query_language-0.1.7 → tellaro_query_language-0.1.9}/src/tql/mutators/geo.py +0 -0
  37. {tellaro_query_language-0.1.7 → tellaro_query_language-0.1.9}/src/tql/mutators/list.py +0 -0
  38. {tellaro_query_language-0.1.7 → tellaro_query_language-0.1.9}/src/tql/mutators/network.py +0 -0
  39. {tellaro_query_language-0.1.7 → tellaro_query_language-0.1.9}/src/tql/mutators/security.py +0 -0
  40. {tellaro_query_language-0.1.7 → tellaro_query_language-0.1.9}/src/tql/mutators/string.py +0 -0
  41. {tellaro_query_language-0.1.7 → tellaro_query_language-0.1.9}/src/tql/opensearch.py +0 -0
  42. {tellaro_query_language-0.1.7 → tellaro_query_language-0.1.9}/src/tql/opensearch_components/README.md +0 -0
  43. {tellaro_query_language-0.1.7 → tellaro_query_language-0.1.9}/src/tql/opensearch_components/__init__.py +0 -0
  44. {tellaro_query_language-0.1.7 → tellaro_query_language-0.1.9}/src/tql/opensearch_components/field_mapping.py +0 -0
  45. {tellaro_query_language-0.1.7 → tellaro_query_language-0.1.9}/src/tql/opensearch_mappings.py +0 -0
  46. {tellaro_query_language-0.1.7 → tellaro_query_language-0.1.9}/src/tql/parser_components/README.md +0 -0
  47. {tellaro_query_language-0.1.7 → tellaro_query_language-0.1.9}/src/tql/parser_components/__init__.py +0 -0
  48. {tellaro_query_language-0.1.7 → tellaro_query_language-0.1.9}/src/tql/parser_components/ast_builder.py +0 -0
  49. {tellaro_query_language-0.1.7 → tellaro_query_language-0.1.9}/src/tql/parser_components/error_analyzer.py +0 -0
  50. {tellaro_query_language-0.1.7 → tellaro_query_language-0.1.9}/src/tql/parser_components/field_extractor.py +0 -0
  51. {tellaro_query_language-0.1.7 → tellaro_query_language-0.1.9}/src/tql/parser_components/grammar.py +0 -0
  52. {tellaro_query_language-0.1.7 → tellaro_query_language-0.1.9}/src/tql/post_processor.py +0 -0
  53. {tellaro_query_language-0.1.7 → tellaro_query_language-0.1.9}/src/tql/scripts.py +0 -0
  54. {tellaro_query_language-0.1.7 → tellaro_query_language-0.1.9}/src/tql/stats_transformer.py +0 -0
  55. {tellaro_query_language-0.1.7 → tellaro_query_language-0.1.9}/src/tql/validators.py +0 -0
@@ -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
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "tellaro-query-language"
3
- version = "0.1.7"
3
+ version = "0.1.9"
4
4
  description = "A flexible, human-friendly query language for searching and filtering structured data"
5
5
  authors = ["Justin Henderson <justin@tellaro.io>"]
6
6
  license = "MIT"
@@ -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": []}
@@ -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)
@@ -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:
@@ -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)
@@ -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: