pytrilogy 0.0.2.47__py3-none-any.whl → 0.0.2.49__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.
Potentially problematic release.
This version of pytrilogy might be problematic. Click here for more details.
- {pytrilogy-0.0.2.47.dist-info → pytrilogy-0.0.2.49.dist-info}/METADATA +1 -1
- pytrilogy-0.0.2.49.dist-info/RECORD +85 -0
- trilogy/__init__.py +2 -2
- trilogy/constants.py +4 -2
- trilogy/core/enums.py +7 -1
- trilogy/core/env_processor.py +1 -2
- trilogy/core/environment_helpers.py +5 -5
- trilogy/core/functions.py +11 -10
- trilogy/core/internal.py +2 -3
- trilogy/core/models.py +449 -393
- trilogy/core/optimization.py +37 -21
- trilogy/core/optimizations/__init__.py +1 -1
- trilogy/core/optimizations/base_optimization.py +6 -6
- trilogy/core/optimizations/inline_constant.py +7 -4
- trilogy/core/optimizations/inline_datasource.py +14 -5
- trilogy/core/optimizations/predicate_pushdown.py +20 -10
- trilogy/core/processing/concept_strategies_v3.py +43 -24
- trilogy/core/processing/graph_utils.py +2 -3
- trilogy/core/processing/node_generators/__init__.py +7 -5
- trilogy/core/processing/node_generators/basic_node.py +4 -4
- trilogy/core/processing/node_generators/common.py +10 -11
- trilogy/core/processing/node_generators/filter_node.py +7 -9
- trilogy/core/processing/node_generators/group_node.py +10 -11
- trilogy/core/processing/node_generators/group_to_node.py +5 -5
- trilogy/core/processing/node_generators/multiselect_node.py +10 -12
- trilogy/core/processing/node_generators/node_merge_node.py +7 -9
- trilogy/core/processing/node_generators/rowset_node.py +36 -15
- trilogy/core/processing/node_generators/select_merge_node.py +11 -10
- trilogy/core/processing/node_generators/select_node.py +5 -5
- trilogy/core/processing/node_generators/union_node.py +75 -0
- trilogy/core/processing/node_generators/unnest_node.py +2 -3
- trilogy/core/processing/node_generators/window_node.py +3 -4
- trilogy/core/processing/nodes/__init__.py +9 -5
- trilogy/core/processing/nodes/base_node.py +45 -13
- trilogy/core/processing/nodes/filter_node.py +3 -4
- trilogy/core/processing/nodes/group_node.py +17 -13
- trilogy/core/processing/nodes/merge_node.py +14 -12
- trilogy/core/processing/nodes/select_node_v2.py +13 -9
- trilogy/core/processing/nodes/union_node.py +50 -0
- trilogy/core/processing/nodes/unnest_node.py +2 -3
- trilogy/core/processing/nodes/window_node.py +2 -3
- trilogy/core/processing/utility.py +38 -41
- trilogy/core/query_processor.py +71 -51
- trilogy/dialect/base.py +95 -53
- trilogy/dialect/bigquery.py +2 -3
- trilogy/dialect/common.py +5 -4
- trilogy/dialect/config.py +0 -2
- trilogy/dialect/duckdb.py +2 -2
- trilogy/dialect/enums.py +5 -5
- trilogy/dialect/postgres.py +2 -2
- trilogy/dialect/presto.py +3 -4
- trilogy/dialect/snowflake.py +2 -2
- trilogy/dialect/sql_server.py +3 -4
- trilogy/engine.py +2 -1
- trilogy/executor.py +43 -30
- trilogy/hooks/base_hook.py +5 -4
- trilogy/hooks/graph_hook.py +2 -1
- trilogy/hooks/query_debugger.py +18 -8
- trilogy/parsing/common.py +15 -20
- trilogy/parsing/parse_engine.py +125 -88
- trilogy/parsing/render.py +32 -35
- trilogy/parsing/trilogy.lark +8 -1
- trilogy/scripts/trilogy.py +6 -4
- trilogy/utility.py +1 -1
- pytrilogy-0.0.2.47.dist-info/RECORD +0 -83
- {pytrilogy-0.0.2.47.dist-info → pytrilogy-0.0.2.49.dist-info}/LICENSE.md +0 -0
- {pytrilogy-0.0.2.47.dist-info → pytrilogy-0.0.2.49.dist-info}/WHEEL +0 -0
- {pytrilogy-0.0.2.47.dist-info → pytrilogy-0.0.2.49.dist-info}/entry_points.txt +0 -0
- {pytrilogy-0.0.2.47.dist-info → pytrilogy-0.0.2.49.dist-info}/top_level.txt +0 -0
trilogy/dialect/common.py
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
|
+
from typing import Callable
|
|
2
|
+
|
|
3
|
+
from trilogy.core.enums import Modifier, UnnestMode
|
|
1
4
|
from trilogy.core.models import (
|
|
2
|
-
Join,
|
|
3
|
-
InstantiatedUnnestJoin,
|
|
4
5
|
CTE,
|
|
5
6
|
Concept,
|
|
6
7
|
Function,
|
|
8
|
+
InstantiatedUnnestJoin,
|
|
9
|
+
Join,
|
|
7
10
|
RawColumnExpr,
|
|
8
11
|
)
|
|
9
|
-
from trilogy.core.enums import UnnestMode, Modifier
|
|
10
|
-
from typing import Callable
|
|
11
12
|
|
|
12
13
|
|
|
13
14
|
def null_wrapper(lval: str, rval: str, modifiers: list[Modifier]) -> str:
|
trilogy/dialect/config.py
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
class DialectConfig:
|
|
2
|
-
|
|
3
2
|
def __init__(self):
|
|
4
3
|
pass
|
|
5
4
|
|
|
@@ -101,7 +100,6 @@ class PrestoConfig(DialectConfig):
|
|
|
101
100
|
|
|
102
101
|
|
|
103
102
|
class TrinoConfig(PrestoConfig):
|
|
104
|
-
|
|
105
103
|
def connection_string(self) -> str:
|
|
106
104
|
if self.schema:
|
|
107
105
|
return f"trino://{self.username}:{self.password}@{self.host}:{self.port}/{self.catalog}/{self.schema}"
|
trilogy/dialect/duckdb.py
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
from typing import
|
|
1
|
+
from typing import Any, Callable, Mapping
|
|
2
2
|
|
|
3
3
|
from jinja2 import Template
|
|
4
4
|
|
|
5
|
-
from trilogy.core.enums import FunctionType,
|
|
5
|
+
from trilogy.core.enums import FunctionType, UnnestMode, WindowType
|
|
6
6
|
from trilogy.dialect.base import BaseDialect
|
|
7
7
|
|
|
8
8
|
WINDOW_FUNCTION_MAP: Mapping[WindowType, Callable[[Any, Any, Any], str]] = {}
|
trilogy/dialect/enums.py
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
from enum import Enum
|
|
2
|
-
from typing import
|
|
2
|
+
from typing import TYPE_CHECKING, Callable, List, Optional
|
|
3
3
|
|
|
4
4
|
if TYPE_CHECKING:
|
|
5
|
+
from trilogy import Environment, Executor
|
|
5
6
|
from trilogy.hooks.base_hook import BaseHook
|
|
6
|
-
from trilogy import Executor, Environment
|
|
7
7
|
|
|
8
|
-
from trilogy.dialect.config import DialectConfig
|
|
9
8
|
from trilogy.constants import logger
|
|
9
|
+
from trilogy.dialect.config import DialectConfig
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
def default_factory(conf: DialectConfig, config_type):
|
|
@@ -42,6 +42,7 @@ class Dialects(Enum):
|
|
|
42
42
|
if self == Dialects.BIGQUERY:
|
|
43
43
|
from google.auth import default
|
|
44
44
|
from google.cloud import bigquery
|
|
45
|
+
|
|
45
46
|
from trilogy.dialect.config import BigQueryConfig
|
|
46
47
|
|
|
47
48
|
credentials, project = default()
|
|
@@ -52,7 +53,6 @@ class Dialects(Enum):
|
|
|
52
53
|
BigQueryConfig,
|
|
53
54
|
)
|
|
54
55
|
elif self == Dialects.SQL_SERVER:
|
|
55
|
-
|
|
56
56
|
raise NotImplementedError()
|
|
57
57
|
elif self == Dialects.DUCK_DB:
|
|
58
58
|
from trilogy.dialect.config import DuckDBConfig
|
|
@@ -98,7 +98,7 @@ class Dialects(Enum):
|
|
|
98
98
|
conf: DialectConfig | None = None,
|
|
99
99
|
_engine_factory: Callable | None = None,
|
|
100
100
|
) -> "Executor":
|
|
101
|
-
from trilogy import
|
|
101
|
+
from trilogy import Environment, Executor
|
|
102
102
|
|
|
103
103
|
if _engine_factory is not None:
|
|
104
104
|
return Executor(
|
trilogy/dialect/postgres.py
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
from typing import
|
|
1
|
+
from typing import Any, Callable, Mapping
|
|
2
2
|
|
|
3
3
|
from jinja2 import Template
|
|
4
4
|
|
|
5
|
-
from trilogy.core.enums import FunctionType, WindowType
|
|
5
|
+
from trilogy.core.enums import DatePart, FunctionType, WindowType
|
|
6
6
|
from trilogy.dialect.base import BaseDialect
|
|
7
7
|
|
|
8
8
|
|
trilogy/dialect/presto.py
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
from typing import
|
|
1
|
+
from typing import Any, Callable, Mapping
|
|
2
2
|
|
|
3
3
|
from jinja2 import Template
|
|
4
4
|
|
|
5
|
-
from trilogy.core.enums import FunctionType, WindowType
|
|
6
|
-
from trilogy.dialect.base import BaseDialect
|
|
5
|
+
from trilogy.core.enums import FunctionType, UnnestMode, WindowType
|
|
7
6
|
from trilogy.core.models import DataType
|
|
8
|
-
from trilogy.
|
|
7
|
+
from trilogy.dialect.base import BaseDialect
|
|
9
8
|
|
|
10
9
|
WINDOW_FUNCTION_MAP: Mapping[WindowType, Callable[[Any, Any, Any], str]] = {}
|
|
11
10
|
|
trilogy/dialect/snowflake.py
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
from typing import
|
|
1
|
+
from typing import Any, Callable, Mapping
|
|
2
2
|
|
|
3
3
|
from jinja2 import Template
|
|
4
4
|
|
|
5
|
-
from trilogy.core.enums import FunctionType,
|
|
5
|
+
from trilogy.core.enums import FunctionType, UnnestMode, WindowType
|
|
6
6
|
from trilogy.dialect.base import BaseDialect
|
|
7
7
|
|
|
8
8
|
ENV_SNOWFLAKE_PW = "PREQL_SNOWFLAKE_PW"
|
trilogy/dialect/sql_server.py
CHANGED
|
@@ -1,17 +1,16 @@
|
|
|
1
|
-
from typing import
|
|
1
|
+
from typing import Any, Callable, Mapping
|
|
2
2
|
|
|
3
3
|
from jinja2 import Template
|
|
4
|
-
from trilogy.utility import string_to_hash
|
|
5
|
-
|
|
6
4
|
|
|
7
5
|
from trilogy.core.enums import FunctionType, WindowType
|
|
8
6
|
from trilogy.core.models import (
|
|
9
7
|
ProcessedQuery,
|
|
10
8
|
ProcessedQueryPersist,
|
|
11
|
-
ProcessedShowStatement,
|
|
12
9
|
ProcessedRawSQLStatement,
|
|
10
|
+
ProcessedShowStatement,
|
|
13
11
|
)
|
|
14
12
|
from trilogy.dialect.base import BaseDialect
|
|
13
|
+
from trilogy.utility import string_to_hash
|
|
15
14
|
|
|
16
15
|
WINDOW_FUNCTION_MAP: Mapping[WindowType, Callable[[Any, Any, Any], str]] = {}
|
|
17
16
|
|
trilogy/engine.py
CHANGED
trilogy/executor.py
CHANGED
|
@@ -1,39 +1,40 @@
|
|
|
1
|
-
from
|
|
1
|
+
from dataclasses import dataclass
|
|
2
2
|
from functools import singledispatchmethod
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from typing import Any, Generator, List, Optional, Protocol
|
|
5
|
+
|
|
3
6
|
from sqlalchemy import text
|
|
4
|
-
from sqlalchemy.engine import
|
|
7
|
+
from sqlalchemy.engine import CursorResult, Engine
|
|
5
8
|
|
|
6
9
|
from trilogy.constants import logger
|
|
10
|
+
from trilogy.core.enums import Granularity, IOType
|
|
7
11
|
from trilogy.core.models import (
|
|
12
|
+
Concept,
|
|
13
|
+
ConceptDeclarationStatement,
|
|
14
|
+
CopyStatement,
|
|
15
|
+
Datasource,
|
|
8
16
|
Environment,
|
|
17
|
+
Function,
|
|
18
|
+
FunctionType,
|
|
19
|
+
ImportStatement,
|
|
20
|
+
ListWrapper,
|
|
21
|
+
MapWrapper,
|
|
22
|
+
MergeStatementV2,
|
|
23
|
+
MultiSelectStatement,
|
|
24
|
+
PersistStatement,
|
|
25
|
+
ProcessedCopyStatement,
|
|
9
26
|
ProcessedQuery,
|
|
10
|
-
ProcessedShowStatement,
|
|
11
27
|
ProcessedQueryPersist,
|
|
12
28
|
ProcessedRawSQLStatement,
|
|
13
|
-
|
|
29
|
+
ProcessedShowStatement,
|
|
14
30
|
RawSQLStatement,
|
|
15
|
-
MultiSelectStatement,
|
|
16
31
|
SelectStatement,
|
|
17
|
-
PersistStatement,
|
|
18
32
|
ShowStatement,
|
|
19
|
-
Concept,
|
|
20
|
-
ConceptDeclarationStatement,
|
|
21
|
-
Datasource,
|
|
22
|
-
CopyStatement,
|
|
23
|
-
ImportStatement,
|
|
24
|
-
MergeStatementV2,
|
|
25
|
-
Function,
|
|
26
|
-
FunctionType,
|
|
27
|
-
MapWrapper,
|
|
28
|
-
ListWrapper,
|
|
29
33
|
)
|
|
30
34
|
from trilogy.dialect.base import BaseDialect
|
|
31
35
|
from trilogy.dialect.enums import Dialects
|
|
32
|
-
from trilogy.core.enums import IOType, Granularity
|
|
33
|
-
from trilogy.parser import parse_text
|
|
34
36
|
from trilogy.hooks.base_hook import BaseHook
|
|
35
|
-
from
|
|
36
|
-
from dataclasses import dataclass
|
|
37
|
+
from trilogy.parser import parse_text
|
|
37
38
|
|
|
38
39
|
|
|
39
40
|
class ResultProtocol(Protocol):
|
|
@@ -103,7 +104,6 @@ class Executor(object):
|
|
|
103
104
|
|
|
104
105
|
self.generator = PostgresDialect()
|
|
105
106
|
elif self.dialect == Dialects.SNOWFLAKE:
|
|
106
|
-
|
|
107
107
|
from trilogy.dialect.snowflake import SnowflakeDialect
|
|
108
108
|
|
|
109
109
|
self.generator = SnowflakeDialect()
|
|
@@ -146,7 +146,6 @@ class Executor(object):
|
|
|
146
146
|
|
|
147
147
|
@execute_query.register
|
|
148
148
|
def _(self, query: Datasource) -> CursorResult:
|
|
149
|
-
|
|
150
149
|
return MockResult(
|
|
151
150
|
[
|
|
152
151
|
{
|
|
@@ -232,22 +231,23 @@ class Executor(object):
|
|
|
232
231
|
@execute_query.register
|
|
233
232
|
def _(self, query: ProcessedQuery) -> CursorResult:
|
|
234
233
|
sql = self.generator.compile_statement(query)
|
|
235
|
-
output = self.execute_raw_sql(sql)
|
|
234
|
+
output = self.execute_raw_sql(sql, local_concepts=query.local_concepts)
|
|
236
235
|
return output
|
|
237
236
|
|
|
238
237
|
@execute_query.register
|
|
239
238
|
def _(self, query: ProcessedQueryPersist) -> CursorResult:
|
|
240
|
-
|
|
241
239
|
sql = self.generator.compile_statement(query)
|
|
242
240
|
|
|
243
|
-
output = self.execute_raw_sql(sql)
|
|
241
|
+
output = self.execute_raw_sql(sql, local_concepts=query.local_concepts)
|
|
244
242
|
self.environment.add_datasource(query.datasource)
|
|
245
243
|
return output
|
|
246
244
|
|
|
247
245
|
@execute_query.register
|
|
248
246
|
def _(self, query: ProcessedCopyStatement) -> CursorResult:
|
|
249
247
|
sql = self.generator.compile_statement(query)
|
|
250
|
-
output: CursorResult = self.execute_raw_sql(
|
|
248
|
+
output: CursorResult = self.execute_raw_sql(
|
|
249
|
+
sql, local_concepts=query.local_concepts
|
|
250
|
+
)
|
|
251
251
|
if query.target_type == IOType.CSV:
|
|
252
252
|
import csv
|
|
253
253
|
|
|
@@ -355,7 +355,6 @@ class Executor(object):
|
|
|
355
355
|
| ProcessedRawSQLStatement
|
|
356
356
|
| ProcessedCopyStatement
|
|
357
357
|
]:
|
|
358
|
-
|
|
359
358
|
return list(self.parse_text_generator(command, persist=persist))
|
|
360
359
|
|
|
361
360
|
def parse_text_generator(self, command: str, persist: bool = False) -> Generator[
|
|
@@ -395,12 +394,20 @@ class Executor(object):
|
|
|
395
394
|
if persist and isinstance(x, ProcessedQueryPersist):
|
|
396
395
|
self.environment.add_datasource(x.datasource)
|
|
397
396
|
|
|
398
|
-
def _hydrate_param(
|
|
397
|
+
def _hydrate_param(
|
|
398
|
+
self, param: str, local_concepts: dict[str, Concept] | None = None
|
|
399
|
+
) -> Any:
|
|
399
400
|
matched = [
|
|
400
401
|
v
|
|
401
402
|
for v in self.environment.concepts.values()
|
|
402
403
|
if v.safe_address == param or v.address == param
|
|
403
404
|
]
|
|
405
|
+
if local_concepts and not matched:
|
|
406
|
+
matched = [
|
|
407
|
+
v
|
|
408
|
+
for v in local_concepts.values()
|
|
409
|
+
if v.safe_address == param or v.address == param
|
|
410
|
+
]
|
|
404
411
|
if not matched:
|
|
405
412
|
raise SyntaxError(f"No concept found for parameter {param}")
|
|
406
413
|
|
|
@@ -424,7 +431,10 @@ class Executor(object):
|
|
|
424
431
|
return results[0]
|
|
425
432
|
|
|
426
433
|
def execute_raw_sql(
|
|
427
|
-
self,
|
|
434
|
+
self,
|
|
435
|
+
command: str,
|
|
436
|
+
variables: dict | None = None,
|
|
437
|
+
local_concepts: dict[str, Concept] | None = None,
|
|
428
438
|
) -> CursorResult:
|
|
429
439
|
"""Run a command against the raw underlying
|
|
430
440
|
execution engine"""
|
|
@@ -435,7 +445,10 @@ class Executor(object):
|
|
|
435
445
|
else:
|
|
436
446
|
params = q.compile().params
|
|
437
447
|
if params:
|
|
438
|
-
final_params = {
|
|
448
|
+
final_params = {
|
|
449
|
+
x: self._hydrate_param(x, local_concepts=local_concepts)
|
|
450
|
+
for x in params
|
|
451
|
+
}
|
|
439
452
|
|
|
440
453
|
if final_params:
|
|
441
454
|
return self.connection.execute(text(command), final_params)
|
trilogy/hooks/base_hook.py
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
from trilogy.core.models import (
|
|
2
|
-
QueryDatasource,
|
|
3
2
|
CTE,
|
|
4
|
-
SelectStatement,
|
|
5
|
-
PersistStatement,
|
|
6
3
|
MultiSelectStatement,
|
|
4
|
+
PersistStatement,
|
|
5
|
+
QueryDatasource,
|
|
7
6
|
RowsetDerivationStatement,
|
|
7
|
+
SelectStatement,
|
|
8
|
+
UnionCTE,
|
|
8
9
|
)
|
|
9
10
|
from trilogy.core.processing.nodes import StrategyNode
|
|
10
11
|
|
|
@@ -30,7 +31,7 @@ class BaseHook:
|
|
|
30
31
|
def process_root_datasource(self, datasource: QueryDatasource):
|
|
31
32
|
pass
|
|
32
33
|
|
|
33
|
-
def process_root_cte(self, cte: CTE):
|
|
34
|
+
def process_root_cte(self, cte: CTE | UnionCTE):
|
|
34
35
|
pass
|
|
35
36
|
|
|
36
37
|
def process_root_strategy_node(self, node: StrategyNode):
|
trilogy/hooks/graph_hook.py
CHANGED
trilogy/hooks/query_debugger.py
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
from logging import DEBUG, StreamHandler
|
|
1
3
|
from typing import Union
|
|
2
|
-
from trilogy.core.models import QueryDatasource, CTE, Datasource, SelectStatement
|
|
3
4
|
|
|
4
|
-
from trilogy.hooks.base_hook import BaseHook
|
|
5
5
|
from trilogy.constants import logger
|
|
6
|
-
from
|
|
6
|
+
from trilogy.core.models import (
|
|
7
|
+
CTE,
|
|
8
|
+
Datasource,
|
|
9
|
+
QueryDatasource,
|
|
10
|
+
SelectStatement,
|
|
11
|
+
UnionCTE,
|
|
12
|
+
)
|
|
7
13
|
from trilogy.core.processing.nodes import StrategyNode
|
|
8
|
-
|
|
9
14
|
from trilogy.dialect.bigquery import BigqueryDialect
|
|
10
|
-
|
|
11
|
-
from enum import Enum
|
|
15
|
+
from trilogy.hooks.base_hook import BaseHook
|
|
12
16
|
|
|
13
17
|
|
|
14
18
|
class PrintMode(Enum):
|
|
@@ -85,7 +89,9 @@ def print_recursive_nodes(
|
|
|
85
89
|
return display
|
|
86
90
|
|
|
87
91
|
|
|
88
|
-
def print_recursive_ctes(
|
|
92
|
+
def print_recursive_ctes(
|
|
93
|
+
input: CTE | UnionCTE, depth: int = 0, max_depth: int | None = None
|
|
94
|
+
):
|
|
89
95
|
if max_depth and depth > max_depth:
|
|
90
96
|
return
|
|
91
97
|
select_statement = [c.address for c in input.output_columns]
|
|
@@ -96,6 +102,10 @@ def print_recursive_ctes(input: CTE, depth: int = 0, max_depth: int | None = Non
|
|
|
96
102
|
if isinstance(input, CTE):
|
|
97
103
|
for child in input.parent_ctes:
|
|
98
104
|
print_recursive_ctes(child, depth + 1)
|
|
105
|
+
elif isinstance(input, UnionCTE):
|
|
106
|
+
for child in input.parent_ctes:
|
|
107
|
+
for parent in child.parent_ctes:
|
|
108
|
+
print_recursive_ctes(parent, depth + 1)
|
|
99
109
|
|
|
100
110
|
|
|
101
111
|
class DebuggingHook(BaseHook):
|
|
@@ -128,7 +138,7 @@ class DebuggingHook(BaseHook):
|
|
|
128
138
|
for row in printed:
|
|
129
139
|
print("".join([str(v) for v in row]))
|
|
130
140
|
|
|
131
|
-
def process_root_cte(self, cte: CTE):
|
|
141
|
+
def process_root_cte(self, cte: CTE | UnionCTE):
|
|
132
142
|
if self.process_ctes != PrintMode.OFF:
|
|
133
143
|
print_recursive_ctes(cte, max_depth=self.max_depth)
|
|
134
144
|
|
trilogy/parsing/common.py
CHANGED
|
@@ -1,32 +1,28 @@
|
|
|
1
|
+
from typing import List, Tuple
|
|
2
|
+
|
|
3
|
+
from trilogy.constants import (
|
|
4
|
+
VIRTUAL_CONCEPT_PREFIX,
|
|
5
|
+
)
|
|
6
|
+
from trilogy.core.enums import FunctionType, Modifier, PurposeLineage, WindowType
|
|
7
|
+
from trilogy.core.functions import arg_to_datatype, function_args_to_output_purpose
|
|
1
8
|
from trilogy.core.models import (
|
|
2
9
|
AggregateWrapper,
|
|
3
10
|
Concept,
|
|
11
|
+
DataType,
|
|
12
|
+
Environment,
|
|
13
|
+
FilterItem,
|
|
4
14
|
Function,
|
|
15
|
+
FunctionClass,
|
|
5
16
|
Grain,
|
|
6
|
-
Purpose,
|
|
7
|
-
Metadata,
|
|
8
|
-
FilterItem,
|
|
9
17
|
ListWrapper,
|
|
10
18
|
MapWrapper,
|
|
11
|
-
WindowItem,
|
|
12
19
|
Meta,
|
|
20
|
+
Metadata,
|
|
13
21
|
Parenthetical,
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
DataType,
|
|
17
|
-
)
|
|
18
|
-
from typing import List, Tuple
|
|
19
|
-
from trilogy.core.functions import (
|
|
20
|
-
function_args_to_output_purpose,
|
|
21
|
-
FunctionType,
|
|
22
|
-
arg_to_datatype,
|
|
23
|
-
)
|
|
24
|
-
from trilogy.utility import unique, string_to_hash
|
|
25
|
-
from trilogy.core.enums import PurposeLineage
|
|
26
|
-
from trilogy.constants import (
|
|
27
|
-
VIRTUAL_CONCEPT_PREFIX,
|
|
22
|
+
Purpose,
|
|
23
|
+
WindowItem,
|
|
28
24
|
)
|
|
29
|
-
from trilogy.
|
|
25
|
+
from trilogy.utility import string_to_hash, unique
|
|
30
26
|
|
|
31
27
|
|
|
32
28
|
def get_upstream_modifiers(keys: List[Concept]) -> list[Modifier]:
|
|
@@ -304,7 +300,6 @@ def arbitrary_to_concept(
|
|
|
304
300
|
metadata: Metadata | None = None,
|
|
305
301
|
purpose: Purpose | None = None,
|
|
306
302
|
) -> Concept:
|
|
307
|
-
|
|
308
303
|
if isinstance(parent, AggregateWrapper):
|
|
309
304
|
if not name:
|
|
310
305
|
name = f"{VIRTUAL_CONCEPT_PREFIX}_agg_{parent.function.operator.value}_{string_to_hash(str(parent))}"
|