pytrilogy 0.0.2.35__tar.gz → 0.0.2.36__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.

Potentially problematic release.


This version of pytrilogy might be problematic. Click here for more details.

Files changed (111) hide show
  1. {pytrilogy-0.0.2.35/pytrilogy.egg-info → pytrilogy-0.0.2.36}/PKG-INFO +1 -1
  2. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36/pytrilogy.egg-info}/PKG-INFO +1 -1
  3. pytrilogy-0.0.2.36/tests/test_executor.py +27 -0
  4. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/tests/test_parsing.py +22 -0
  5. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/__init__.py +1 -1
  6. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/core/models.py +5 -1
  7. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/executor.py +32 -1
  8. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/parsing/parse_engine.py +4 -1
  9. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/parsing/render.py +9 -3
  10. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/parsing/trilogy.lark +2 -1
  11. pytrilogy-0.0.2.35/tests/test_executor.py +0 -8
  12. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/LICENSE.md +0 -0
  13. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/README.md +0 -0
  14. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/pyproject.toml +0 -0
  15. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/pytrilogy.egg-info/SOURCES.txt +0 -0
  16. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/pytrilogy.egg-info/dependency_links.txt +0 -0
  17. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/pytrilogy.egg-info/entry_points.txt +0 -0
  18. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/pytrilogy.egg-info/requires.txt +0 -0
  19. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/pytrilogy.egg-info/top_level.txt +0 -0
  20. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/setup.cfg +0 -0
  21. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/setup.py +0 -0
  22. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/tests/test_datatypes.py +0 -0
  23. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/tests/test_declarations.py +0 -0
  24. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/tests/test_derived_concepts.py +0 -0
  25. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/tests/test_discovery_nodes.py +0 -0
  26. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/tests/test_enums.py +0 -0
  27. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/tests/test_environment.py +0 -0
  28. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/tests/test_functions.py +0 -0
  29. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/tests/test_imports.py +0 -0
  30. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/tests/test_metadata.py +0 -0
  31. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/tests/test_models.py +0 -0
  32. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/tests/test_multi_join_assignments.py +0 -0
  33. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/tests/test_parse_engine.py +0 -0
  34. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/tests/test_partial_handling.py +0 -0
  35. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/tests/test_query_processing.py +0 -0
  36. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/tests/test_select.py +0 -0
  37. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/tests/test_show.py +0 -0
  38. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/tests/test_statements.py +0 -0
  39. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/tests/test_undefined_concept.py +0 -0
  40. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/tests/test_where_clause.py +0 -0
  41. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/compiler.py +0 -0
  42. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/constants.py +0 -0
  43. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/core/__init__.py +0 -0
  44. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/core/constants.py +0 -0
  45. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/core/enums.py +0 -0
  46. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/core/env_processor.py +0 -0
  47. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/core/environment_helpers.py +0 -0
  48. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/core/ergonomics.py +0 -0
  49. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/core/exceptions.py +0 -0
  50. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/core/functions.py +0 -0
  51. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/core/graph_models.py +0 -0
  52. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/core/internal.py +0 -0
  53. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/core/optimization.py +0 -0
  54. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/core/optimizations/__init__.py +0 -0
  55. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/core/optimizations/base_optimization.py +0 -0
  56. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/core/optimizations/inline_constant.py +0 -0
  57. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/core/optimizations/inline_datasource.py +0 -0
  58. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/core/optimizations/predicate_pushdown.py +0 -0
  59. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/core/processing/__init__.py +0 -0
  60. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/core/processing/concept_strategies_v3.py +0 -0
  61. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/core/processing/graph_utils.py +0 -0
  62. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/core/processing/node_generators/__init__.py +0 -0
  63. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/core/processing/node_generators/basic_node.py +0 -0
  64. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/core/processing/node_generators/common.py +0 -0
  65. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/core/processing/node_generators/filter_node.py +0 -0
  66. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/core/processing/node_generators/group_node.py +0 -0
  67. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/core/processing/node_generators/group_to_node.py +0 -0
  68. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/core/processing/node_generators/multiselect_node.py +0 -0
  69. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/core/processing/node_generators/node_merge_node.py +0 -0
  70. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/core/processing/node_generators/rowset_node.py +0 -0
  71. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/core/processing/node_generators/select_merge_node.py +0 -0
  72. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/core/processing/node_generators/select_node.py +0 -0
  73. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/core/processing/node_generators/unnest_node.py +0 -0
  74. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/core/processing/node_generators/window_node.py +0 -0
  75. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/core/processing/nodes/__init__.py +0 -0
  76. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/core/processing/nodes/base_node.py +0 -0
  77. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/core/processing/nodes/filter_node.py +0 -0
  78. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/core/processing/nodes/group_node.py +0 -0
  79. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/core/processing/nodes/merge_node.py +0 -0
  80. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/core/processing/nodes/select_node_v2.py +0 -0
  81. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/core/processing/nodes/unnest_node.py +0 -0
  82. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/core/processing/nodes/window_node.py +0 -0
  83. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/core/processing/utility.py +0 -0
  84. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/core/query_processor.py +0 -0
  85. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/dialect/__init__.py +0 -0
  86. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/dialect/base.py +0 -0
  87. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/dialect/bigquery.py +0 -0
  88. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/dialect/common.py +0 -0
  89. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/dialect/config.py +0 -0
  90. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/dialect/duckdb.py +0 -0
  91. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/dialect/enums.py +0 -0
  92. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/dialect/postgres.py +0 -0
  93. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/dialect/presto.py +0 -0
  94. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/dialect/snowflake.py +0 -0
  95. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/dialect/sql_server.py +0 -0
  96. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/engine.py +0 -0
  97. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/hooks/__init__.py +0 -0
  98. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/hooks/base_hook.py +0 -0
  99. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/hooks/graph_hook.py +0 -0
  100. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/hooks/query_debugger.py +0 -0
  101. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/metadata/__init__.py +0 -0
  102. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/parser.py +0 -0
  103. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/parsing/__init__.py +0 -0
  104. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/parsing/common.py +0 -0
  105. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/parsing/config.py +0 -0
  106. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/parsing/exceptions.py +0 -0
  107. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/parsing/helpers.py +0 -0
  108. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/py.typed +0 -0
  109. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/scripts/__init__.py +0 -0
  110. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/scripts/trilogy.py +0 -0
  111. {pytrilogy-0.0.2.35 → pytrilogy-0.0.2.36}/trilogy/utility.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pytrilogy
3
- Version: 0.0.2.35
3
+ Version: 0.0.2.36
4
4
  Summary: Declarative, typed query language that compiles to SQL.
5
5
  Home-page:
6
6
  Author:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pytrilogy
3
- Version: 0.0.2.35
3
+ Version: 0.0.2.36
4
4
  Summary: Declarative, typed query language that compiles to SQL.
5
5
  Home-page:
6
6
  Author:
@@ -0,0 +1,27 @@
1
+ from trilogy import Dialects, parse, Environment
2
+ from pathlib import Path
3
+
4
+
5
+ def test_file_parsing():
6
+ target = Path(__file__).parent / "test_env.preql"
7
+ parsed = Dialects.DUCK_DB.default_executor().parse_file(target)
8
+ assert len(list(parsed)) == 1
9
+
10
+
11
+ def test_can_handle_everything():
12
+ env = Environment(working_path=Path(__file__).parent)
13
+ env, queries = parse(
14
+ """
15
+ import test_env as test_env;
16
+
17
+ key x int;
18
+
19
+ merge test_env.id into x;
20
+
21
+ RAW_SQL('''select 1 ''');
22
+ """,
23
+ environment=env,
24
+ )
25
+ execs = Dialects.DUCK_DB.default_executor(environment=env)
26
+ for q in queries:
27
+ execs.execute_query(q)
@@ -523,6 +523,28 @@ address `abc:def`
523
523
  assert ds.non_partial_for.conditional.right == 10
524
524
 
525
525
 
526
+ def test_datasource_quoted():
527
+
528
+ text = """
529
+ key x int;
530
+ key y int;
531
+
532
+ datasource test (
533
+ `x 2`:x,
534
+ `y`:~y)
535
+ grain(x)
536
+ complete where y > 10
537
+ address `abc:def`
538
+ ;
539
+
540
+
541
+ """
542
+ env, parsed = parse_text(text)
543
+
544
+ ds = parsed[-1]
545
+ assert ds.columns[0].alias == "x 2"
546
+
547
+
526
548
  def test_datasource_from_persist():
527
549
 
528
550
  text = """
@@ -4,6 +4,6 @@ from trilogy.executor import Executor
4
4
  from trilogy.parser import parse
5
5
  from trilogy.constants import CONFIG
6
6
 
7
- __version__ = "0.0.2.35"
7
+ __version__ = "0.0.2.36"
8
8
 
9
9
  __all__ = ["parse", "Executor", "Dialects", "Environment", "CONFIG"]
@@ -3276,7 +3276,7 @@ class EnvironmentConceptDict(dict):
3276
3276
  return default
3277
3277
 
3278
3278
  def __getitem__(
3279
- self, key, line_no: int | None = None
3279
+ self, key, line_no: int | None = None, file: Path | None = None
3280
3280
  ) -> Concept | UndefinedConcept:
3281
3281
  try:
3282
3282
  return super(EnvironmentConceptDict, self).__getitem__(key)
@@ -3304,6 +3304,10 @@ class EnvironmentConceptDict(dict):
3304
3304
  message += f" Suggestions: {matches}"
3305
3305
 
3306
3306
  if line_no:
3307
+ if file:
3308
+ raise UndefinedConceptException(
3309
+ f"{file}: {line_no}: " + message, matches
3310
+ )
3307
3311
  raise UndefinedConceptException(f"line: {line_no}: " + message, matches)
3308
3312
  raise UndefinedConceptException(message, matches)
3309
3313
 
@@ -20,6 +20,8 @@ from trilogy.core.models import (
20
20
  ConceptDeclarationStatement,
21
21
  Datasource,
22
22
  CopyStatement,
23
+ ImportStatement,
24
+ MergeStatementV2,
23
25
  )
24
26
  from trilogy.dialect.base import BaseDialect
25
27
  from trilogy.dialect.enums import Dialects
@@ -104,6 +106,7 @@ class Executor(object):
104
106
  ProcessedShowStatement,
105
107
  ProcessedQueryPersist,
106
108
  ProcessedCopyStatement,
109
+ ProcessedRawSQLStatement,
107
110
  ),
108
111
  ):
109
112
  return None
@@ -142,7 +145,6 @@ class Executor(object):
142
145
 
143
146
  @execute_query.register
144
147
  def _(self, query: str) -> CursorResult:
145
-
146
148
  return self.execute_text(query)[-1]
147
149
 
148
150
  @execute_query.register
@@ -181,6 +183,35 @@ class Executor(object):
181
183
  ],
182
184
  )
183
185
 
186
+ @execute_query.register
187
+ def _(self, query: ImportStatement) -> CursorResult:
188
+ self.environment.add_file_import(query.path, query.alias)
189
+ return MockResult(
190
+ [
191
+ {
192
+ "path": query.path,
193
+ "alias": query.alias,
194
+ }
195
+ ],
196
+ ["path", "alias"],
197
+ )
198
+
199
+ @execute_query.register
200
+ def _(self, query: MergeStatementV2) -> CursorResult:
201
+
202
+ self.environment.merge_concept(
203
+ query.source, query.target, modifiers=query.modifiers
204
+ )
205
+ return MockResult(
206
+ [
207
+ {
208
+ "source": query.source.address,
209
+ "target": query.target.address,
210
+ }
211
+ ],
212
+ ["source", "target"],
213
+ )
214
+
184
215
  @execute_query.register
185
216
  def _(self, query: ProcessedRawSQLStatement) -> CursorResult:
186
217
  return self.execute_raw_sql(query.text)
@@ -302,6 +302,9 @@ class ParseToObjects(Transformer):
302
302
  def IDENTIFIER(self, args) -> str:
303
303
  return args.value
304
304
 
305
+ def QUOTED_IDENTIFIER(self, args) -> str:
306
+ return args.value[1:-1]
307
+
305
308
  @v_args(meta=True)
306
309
  def concept_lit(self, meta: Meta, args) -> Concept:
307
310
  return self.environment.concepts.__getitem__(args[0], meta.line)
@@ -386,7 +389,7 @@ class ParseToObjects(Transformer):
386
389
  modifiers += concept_list[:-1]
387
390
  concept = concept_list[-1]
388
391
  resolved = self.environment.concepts.__getitem__( # type: ignore
389
- key=concept, line_no=meta.line
392
+ key=concept, line_no=meta.line, file=self.token_address
390
393
  )
391
394
  return ColumnAssignment(alias=alias, modifiers=modifiers, concept=resolved)
392
395
 
@@ -368,9 +368,15 @@ class Renderer:
368
368
 
369
369
  @to_string.register
370
370
  def _(self, arg: "ImportStatement"):
371
- if arg.alias == DEFAULT_NAMESPACE:
372
- return f"import {arg.path};"
373
- return f"import {arg.path} as {arg.alias};"
371
+ path: str = str(arg.path).replace("\\", ".")
372
+ path = path.replace("/", ".")
373
+ if path.endswith(".preql"):
374
+ path = path.rsplit(".", 1)[0]
375
+ if path.startswith("."):
376
+ path = path[1:]
377
+ if arg.alias == DEFAULT_NAMESPACE or not arg.alias:
378
+ return f"import {path};"
379
+ return f"import {path} as {arg.alias};"
374
380
 
375
381
  @to_string.register
376
382
  def _(self, arg: "Concept"):
@@ -49,7 +49,7 @@
49
49
 
50
50
  //column_assignment
51
51
  //figure out if we want static
52
- column_assignment: (raw_column_assignment | IDENTIFIER | _static_functions ) ":" concept_assignment
52
+ column_assignment: (raw_column_assignment | IDENTIFIER | QUOTED_IDENTIFIER | _static_functions ) ":" concept_assignment
53
53
 
54
54
  RAW_ENTRY.1: /raw\s*\(/s
55
55
 
@@ -292,6 +292,7 @@
292
292
  // base language constructs
293
293
  concept_lit: IDENTIFIER
294
294
  IDENTIFIER: /[a-zA-Z\_][a-zA-Z0-9\_\-\.]*/
295
+ QUOTED_IDENTIFIER: /`[a-zA-Z\_][a-zA-Z0-9\_\.\-\*\:\s]*`/
295
296
  QUOTED_ADDRESS: /`[a-zA-Z\_][a-zA-Z0-9\_\.\-\*\:]*`/
296
297
  ADDRESS: IDENTIFIER
297
298
 
@@ -1,8 +0,0 @@
1
- from trilogy import Dialects
2
- from pathlib import Path
3
-
4
-
5
- def test_file_parsing():
6
- target = Path(__file__).parent / "test_env.preql"
7
- parsed = Dialects.DUCK_DB.default_executor().parse_file(target)
8
- assert len(list(parsed)) == 1
File without changes
File without changes
File without changes
File without changes