pytrilogy 0.0.3.22__tar.gz → 0.0.3.24__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.
- {pytrilogy-0.0.3.22/pytrilogy.egg-info → pytrilogy-0.0.3.24}/PKG-INFO +1 -1
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24/pytrilogy.egg-info}/PKG-INFO +1 -1
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/tests/test_typing.py +71 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/__init__.py +1 -1
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/environment_helpers.py +2 -2
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/functions.py +0 -1
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/models/author.py +7 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/models/build.py +13 -1
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/models/core.py +5 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/models/environment.py +7 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/models/execute.py +1 -1
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/processing/concept_strategies_v3.py +10 -8
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/processing/utility.py +2 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/dialect/base.py +4 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/parsing/parse_engine.py +15 -4
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/LICENSE.md +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/README.md +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/pyproject.toml +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/pytrilogy.egg-info/SOURCES.txt +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/pytrilogy.egg-info/dependency_links.txt +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/pytrilogy.egg-info/entry_points.txt +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/pytrilogy.egg-info/requires.txt +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/pytrilogy.egg-info/top_level.txt +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/setup.cfg +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/setup.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/tests/test_datatypes.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/tests/test_declarations.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/tests/test_derived_concepts.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/tests/test_discovery_nodes.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/tests/test_enums.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/tests/test_environment.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/tests/test_executor.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/tests/test_functions.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/tests/test_imports.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/tests/test_metadata.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/tests/test_models.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/tests/test_multi_join_assignments.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/tests/test_parse_engine.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/tests/test_parsing.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/tests/test_partial_handling.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/tests/test_query_processing.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/tests/test_query_render.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/tests/test_select.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/tests/test_show.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/tests/test_statements.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/tests/test_undefined_concept.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/tests/test_user_functions.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/tests/test_where_clause.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/authoring/__init__.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/compiler.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/constants.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/__init__.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/constants.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/enums.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/env_processor.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/ergonomics.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/exceptions.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/graph_models.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/internal.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/models/__init__.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/models/build_environment.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/models/datasource.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/optimization.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/optimizations/__init__.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/optimizations/base_optimization.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/optimizations/inline_constant.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/optimizations/inline_datasource.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/optimizations/predicate_pushdown.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/processing/__init__.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/processing/graph_utils.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/processing/node_generators/__init__.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/processing/node_generators/basic_node.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/processing/node_generators/common.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/processing/node_generators/filter_node.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/processing/node_generators/group_node.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/processing/node_generators/group_to_node.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/processing/node_generators/multiselect_node.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/processing/node_generators/node_merge_node.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/processing/node_generators/rowset_node.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/processing/node_generators/select_helpers/__init__.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/processing/node_generators/select_helpers/datasource_injection.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/processing/node_generators/select_merge_node.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/processing/node_generators/select_node.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/processing/node_generators/synonym_node.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/processing/node_generators/union_node.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/processing/node_generators/unnest_node.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/processing/node_generators/window_node.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/processing/nodes/__init__.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/processing/nodes/base_node.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/processing/nodes/filter_node.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/processing/nodes/group_node.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/processing/nodes/merge_node.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/processing/nodes/select_node_v2.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/processing/nodes/union_node.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/processing/nodes/unnest_node.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/processing/nodes/window_node.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/query_processor.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/statements/__init__.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/statements/author.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/statements/build.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/statements/common.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/statements/execute.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/dialect/__init__.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/dialect/bigquery.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/dialect/common.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/dialect/config.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/dialect/dataframe.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/dialect/duckdb.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/dialect/enums.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/dialect/postgres.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/dialect/presto.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/dialect/snowflake.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/dialect/sql_server.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/engine.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/executor.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/hooks/__init__.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/hooks/base_hook.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/hooks/graph_hook.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/hooks/query_debugger.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/metadata/__init__.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/parser.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/parsing/__init__.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/parsing/common.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/parsing/config.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/parsing/exceptions.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/parsing/helpers.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/parsing/render.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/parsing/trilogy.lark +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/py.typed +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/render.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/scripts/__init__.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/scripts/trilogy.py +0 -0
- {pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/utility.py +0 -0
|
@@ -1,6 +1,25 @@
|
|
|
1
1
|
from decimal import Decimal
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
from pytest import raises
|
|
2
5
|
|
|
3
6
|
from trilogy import Dialects
|
|
7
|
+
from trilogy.parsing.exceptions import ParseError
|
|
8
|
+
|
|
9
|
+
FILE = Path(__file__)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def test_invalid_typing():
|
|
13
|
+
env = Dialects.DUCK_DB.default_executor()
|
|
14
|
+
with raises(ParseError):
|
|
15
|
+
env.environment.parse(
|
|
16
|
+
"""
|
|
17
|
+
key customer_id int;
|
|
18
|
+
property customer_id.email string::email;
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
"""
|
|
22
|
+
)
|
|
4
23
|
|
|
5
24
|
|
|
6
25
|
def test_typing():
|
|
@@ -44,6 +63,58 @@ customer_id,
|
|
|
44
63
|
assert env.environment.concepts["email"].datatype.traits == ["email"]
|
|
45
64
|
|
|
46
65
|
|
|
66
|
+
def test_type_import_and_cast():
|
|
67
|
+
env = Dialects.DUCK_DB.default_executor()
|
|
68
|
+
env.environment.add_file_import(FILE.parent / "test_env_types.preql", "dtypes")
|
|
69
|
+
env.environment.parse(
|
|
70
|
+
"""
|
|
71
|
+
|
|
72
|
+
type year int;
|
|
73
|
+
key customer_id int;
|
|
74
|
+
property customer_id.signup_date date;
|
|
75
|
+
|
|
76
|
+
datasource customers (
|
|
77
|
+
id:customer_id,
|
|
78
|
+
signup_date: signup_date
|
|
79
|
+
)
|
|
80
|
+
grain (customer_id)
|
|
81
|
+
query '''
|
|
82
|
+
select 1 as id, cast('2023-01-01' as date) as signup_date
|
|
83
|
+
union all
|
|
84
|
+
select 2 as id, cast('2023-01-02' as date) as signup_date
|
|
85
|
+
''';
|
|
86
|
+
|
|
87
|
+
"""
|
|
88
|
+
)
|
|
89
|
+
assert env.environment.concepts["signup_date"].keys == {"local.customer_id"}
|
|
90
|
+
assert env.environment.concepts["signup_date.year"].keys == {"local.signup_date"}
|
|
91
|
+
results = env.execute_query(
|
|
92
|
+
"""SELECT
|
|
93
|
+
signup_date.year::int::year as signup_year;"""
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
for row in results.fetchall():
|
|
97
|
+
assert row.signup_year == 2023
|
|
98
|
+
|
|
99
|
+
assert "year" in env.environment.data_types
|
|
100
|
+
|
|
101
|
+
assert env.environment.concepts["signup_year"].datatype.traits == ["year"]
|
|
102
|
+
|
|
103
|
+
results = env.execute_query(
|
|
104
|
+
"""SELECT
|
|
105
|
+
signup_date.year::int::dtypes.year as signup_year_two;"""
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
for row in results.fetchall():
|
|
109
|
+
assert row.signup_year_two == 2023
|
|
110
|
+
|
|
111
|
+
assert "dtypes.year" in env.environment.data_types
|
|
112
|
+
|
|
113
|
+
assert env.environment.concepts["signup_year_two"].datatype.traits == [
|
|
114
|
+
"dtypes.year"
|
|
115
|
+
]
|
|
116
|
+
|
|
117
|
+
|
|
47
118
|
def test_typing_aggregate():
|
|
48
119
|
env = Dialects.DUCK_DB.default_executor()
|
|
49
120
|
env.environment.parse(
|
|
@@ -54,7 +54,7 @@ def generate_date_concepts(concept: Concept, environment: Environment):
|
|
|
54
54
|
grain=concept.grain,
|
|
55
55
|
namespace=concept.namespace,
|
|
56
56
|
keys=set(
|
|
57
|
-
concept.address,
|
|
57
|
+
[concept.address],
|
|
58
58
|
),
|
|
59
59
|
metadata=Metadata(
|
|
60
60
|
description=f"Auto-derived from {base_description}. {FUNCTION_DESCRIPTION_MAPS.get(ftype, ftype.value)}. ",
|
|
@@ -102,7 +102,7 @@ def generate_datetime_concepts(concept: Concept, environment: Environment):
|
|
|
102
102
|
grain=concept.grain,
|
|
103
103
|
namespace=concept.namespace,
|
|
104
104
|
keys=set(
|
|
105
|
-
concept.address,
|
|
105
|
+
[concept.address],
|
|
106
106
|
),
|
|
107
107
|
metadata=Metadata(
|
|
108
108
|
description=f"Auto-derived from {base_description}. {FUNCTION_DESCRIPTION_MAPS.get(ftype, ftype.value)}.",
|
|
@@ -1035,6 +1035,7 @@ class Concept(Addressable, DataTyped, ConceptArgs, Mergeable, Namespaced, BaseMo
|
|
|
1035
1035
|
pkeys.update(parent_keys)
|
|
1036
1036
|
raw_keys = pkeys
|
|
1037
1037
|
# deduplicate
|
|
1038
|
+
|
|
1038
1039
|
final_grain = Grain.from_concepts(raw_keys, environment)
|
|
1039
1040
|
keys = final_grain.components
|
|
1040
1041
|
return new_lineage, final_grain, keys
|
|
@@ -2244,6 +2245,11 @@ class CustomType(BaseModel):
|
|
|
2244
2245
|
name: str
|
|
2245
2246
|
type: DataType
|
|
2246
2247
|
|
|
2248
|
+
def with_namespace(self, namespace: str) -> "CustomType":
|
|
2249
|
+
return CustomType.model_construct(
|
|
2250
|
+
name=address_with_namespace(self.name, namespace), type=self.type
|
|
2251
|
+
)
|
|
2252
|
+
|
|
2247
2253
|
|
|
2248
2254
|
Expr = (
|
|
2249
2255
|
MagicConstants
|
|
@@ -2284,6 +2290,7 @@ FuncArgs = (
|
|
|
2284
2290
|
| date
|
|
2285
2291
|
| datetime
|
|
2286
2292
|
| MapWrapper[Any, Any]
|
|
2293
|
+
| TraitDataType
|
|
2287
2294
|
| DataType
|
|
2288
2295
|
| ListType
|
|
2289
2296
|
| MapType
|
|
@@ -77,6 +77,7 @@ from trilogy.core.models.core import (
|
|
|
77
77
|
MapWrapper,
|
|
78
78
|
NumericType,
|
|
79
79
|
StructType,
|
|
80
|
+
TraitDataType,
|
|
80
81
|
TupleWrapper,
|
|
81
82
|
arg_to_datatype,
|
|
82
83
|
)
|
|
@@ -1066,7 +1067,9 @@ class BuildFunction(DataTyped, BuildConceptArgs, BaseModel):
|
|
|
1066
1067
|
# class BuildFunction(Function):
|
|
1067
1068
|
operator: FunctionType
|
|
1068
1069
|
arg_count: int = Field(default=1)
|
|
1069
|
-
output_datatype:
|
|
1070
|
+
output_datatype: (
|
|
1071
|
+
DataType | ListType | StructType | MapType | NumericType | TraitDataType
|
|
1072
|
+
)
|
|
1070
1073
|
output_purpose: Purpose
|
|
1071
1074
|
valid_inputs: Optional[
|
|
1072
1075
|
Union[
|
|
@@ -1082,6 +1085,7 @@ class BuildFunction(DataTyped, BuildConceptArgs, BaseModel):
|
|
|
1082
1085
|
date,
|
|
1083
1086
|
datetime,
|
|
1084
1087
|
MapWrapper[Any, Any],
|
|
1088
|
+
TraitDataType,
|
|
1085
1089
|
DataType,
|
|
1086
1090
|
ListType,
|
|
1087
1091
|
MapType,
|
|
@@ -1721,6 +1725,10 @@ class Factory:
|
|
|
1721
1725
|
components=base.components, where_clause=where
|
|
1722
1726
|
)
|
|
1723
1727
|
|
|
1728
|
+
@build.register
|
|
1729
|
+
def _(self, base: TupleWrapper) -> TupleWrapper:
|
|
1730
|
+
return TupleWrapper(val=[self.build(x) for x in base.val], type=base.type)
|
|
1731
|
+
|
|
1724
1732
|
@build.register
|
|
1725
1733
|
def _(self, base: FilterItem) -> BuildFilterItem:
|
|
1726
1734
|
return BuildFilterItem.model_construct(
|
|
@@ -1869,6 +1877,10 @@ class Factory:
|
|
|
1869
1877
|
new.gen_concept_list_caches()
|
|
1870
1878
|
return new
|
|
1871
1879
|
|
|
1880
|
+
@build.register
|
|
1881
|
+
def _(self, base: TraitDataType):
|
|
1882
|
+
return base
|
|
1883
|
+
|
|
1872
1884
|
@build.register
|
|
1873
1885
|
def _(self, base: Datasource):
|
|
1874
1886
|
local_cache: dict[str, BuildConcept] = {}
|
|
@@ -111,6 +111,9 @@ class TraitDataType(BaseModel):
|
|
|
111
111
|
def __hash__(self):
|
|
112
112
|
return hash(self.type)
|
|
113
113
|
|
|
114
|
+
def __str__(self) -> str:
|
|
115
|
+
return f"Trait<{self.type}, {self.traits}>"
|
|
116
|
+
|
|
114
117
|
def __eq__(self, other):
|
|
115
118
|
if isinstance(other, DataType):
|
|
116
119
|
return self.type == other
|
|
@@ -382,6 +385,8 @@ def arg_to_datatype(arg) -> CONCRETE_TYPES:
|
|
|
382
385
|
return DataType.FLOAT
|
|
383
386
|
elif isinstance(arg, NumericType):
|
|
384
387
|
return arg
|
|
388
|
+
elif isinstance(arg, TraitDataType):
|
|
389
|
+
return arg
|
|
385
390
|
elif isinstance(arg, ListWrapper):
|
|
386
391
|
return ListType(type=arg.type)
|
|
387
392
|
elif isinstance(arg, DataTyped):
|
|
@@ -442,6 +442,13 @@ class Environment(BaseModel):
|
|
|
442
442
|
self.functions[address_with_namespace(key, alias)] = (
|
|
443
443
|
function.with_namespace(alias)
|
|
444
444
|
)
|
|
445
|
+
for key, type in source.data_types.items():
|
|
446
|
+
if same_namespace:
|
|
447
|
+
self.data_types[key] = type
|
|
448
|
+
else:
|
|
449
|
+
self.data_types[address_with_namespace(key, alias)] = (
|
|
450
|
+
type.with_namespace(alias)
|
|
451
|
+
)
|
|
445
452
|
return self
|
|
446
453
|
|
|
447
454
|
def add_file_import(
|
|
@@ -788,14 +788,16 @@ def _search_concepts(
|
|
|
788
788
|
# if anything we need to get is in the filter set and it's a computed value
|
|
789
789
|
# we need to get _everything_ in this loop
|
|
790
790
|
required_filters = [
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
791
|
+
x
|
|
792
|
+
for x in mandatory_list
|
|
793
|
+
if x.derivation not in (Derivation.ROOT, Derivation.CONSTANT)
|
|
794
|
+
and not (
|
|
795
|
+
x.derivation == Derivation.AGGREGATE
|
|
796
|
+
and x.granularity == Granularity.SINGLE_ROW
|
|
797
|
+
)
|
|
798
|
+
and x.address in conditions.row_arguments
|
|
799
|
+
]
|
|
800
|
+
if any(required_filters):
|
|
799
801
|
logger.info(
|
|
800
802
|
f"{depth_to_prefix(depth)}{LOGGER_PREFIX} derived condition row inputs {[x.address for x in required_filters]} present in mandatory list, forcing condition evaluation at this level. "
|
|
801
803
|
)
|
|
@@ -38,6 +38,7 @@ from trilogy.core.models.core import (
|
|
|
38
38
|
MapType,
|
|
39
39
|
MapWrapper,
|
|
40
40
|
NumericType,
|
|
41
|
+
TraitDataType,
|
|
41
42
|
TupleWrapper,
|
|
42
43
|
)
|
|
43
44
|
from trilogy.core.models.execute import (
|
|
@@ -441,6 +442,7 @@ def is_scalar_condition(
|
|
|
441
442
|
| BuildCaseWhen
|
|
442
443
|
| BuildCaseElse
|
|
443
444
|
| MagicConstants
|
|
445
|
+
| TraitDataType
|
|
444
446
|
| DataType
|
|
445
447
|
| MapWrapper[Any, Any]
|
|
446
448
|
| ListType
|
|
@@ -36,6 +36,7 @@ from trilogy.core.models.core import (
|
|
|
36
36
|
MapWrapper,
|
|
37
37
|
NumericType,
|
|
38
38
|
StructType,
|
|
39
|
+
TraitDataType,
|
|
39
40
|
TupleWrapper,
|
|
40
41
|
)
|
|
41
42
|
from trilogy.core.models.datasource import Datasource, RawColumnExpr
|
|
@@ -510,6 +511,7 @@ class BaseDialect:
|
|
|
510
511
|
date,
|
|
511
512
|
datetime,
|
|
512
513
|
DataType,
|
|
514
|
+
TraitDataType,
|
|
513
515
|
MagicConstants,
|
|
514
516
|
MapWrapper[Any, Any],
|
|
515
517
|
MapType,
|
|
@@ -677,6 +679,8 @@ class BaseDialect:
|
|
|
677
679
|
return self.FUNCTION_MAP[FunctionType.DATE_LITERAL](e)
|
|
678
680
|
elif isinstance(e, datetime):
|
|
679
681
|
return self.FUNCTION_MAP[FunctionType.DATETIME_LITERAL](e)
|
|
682
|
+
elif isinstance(e, TraitDataType):
|
|
683
|
+
return self.DATATYPE_MAP.get(e.type, e.type.value)
|
|
680
684
|
else:
|
|
681
685
|
raise ValueError(f"Unable to render type {type(e)} {e}")
|
|
682
686
|
|
|
@@ -443,8 +443,9 @@ class ParseToObjects(Transformer):
|
|
|
443
443
|
def map_type(self, args) -> MapType:
|
|
444
444
|
return MapType(key_type=args[0], value_type=args[1])
|
|
445
445
|
|
|
446
|
+
@v_args(meta=True)
|
|
446
447
|
def data_type(
|
|
447
|
-
self, args
|
|
448
|
+
self, meta: Meta, args
|
|
448
449
|
) -> DataType | TraitDataType | ListType | StructType | MapType | NumericType:
|
|
449
450
|
resolved = args[0]
|
|
450
451
|
traits = args[2:]
|
|
@@ -458,7 +459,13 @@ class ParseToObjects(Transformer):
|
|
|
458
459
|
return resolved
|
|
459
460
|
base = DataType(args[0].lower())
|
|
460
461
|
if traits:
|
|
462
|
+
for trait in traits:
|
|
463
|
+
if trait not in self.environment.data_types:
|
|
464
|
+
raise ParseError(
|
|
465
|
+
f"Invalid type trait {trait} for {base}, line {meta.line}"
|
|
466
|
+
)
|
|
461
467
|
return TraitDataType(type=base, traits=traits)
|
|
468
|
+
|
|
462
469
|
return base
|
|
463
470
|
|
|
464
471
|
def array_comparison(self, args) -> ComparisonOperator:
|
|
@@ -1238,8 +1245,9 @@ class ParseToObjects(Transformer):
|
|
|
1238
1245
|
def type_declaration(self, meta: Meta, args) -> TypeDeclaration:
|
|
1239
1246
|
key = args[0]
|
|
1240
1247
|
datatype = args[1]
|
|
1241
|
-
|
|
1242
|
-
|
|
1248
|
+
new = CustomType(name=key, type=datatype)
|
|
1249
|
+
self.environment.data_types[key] = new
|
|
1250
|
+
return TypeDeclaration(type=new)
|
|
1243
1251
|
|
|
1244
1252
|
def int_lit(self, args):
|
|
1245
1253
|
return int("".join(args))
|
|
@@ -1342,7 +1350,10 @@ class ParseToObjects(Transformer):
|
|
|
1342
1350
|
)
|
|
1343
1351
|
|
|
1344
1352
|
def expr_tuple(self, args):
|
|
1345
|
-
|
|
1353
|
+
datatypes = set([arg_to_datatype(x) for x in args])
|
|
1354
|
+
if len(datatypes) != 1:
|
|
1355
|
+
raise ParseError("Tuple must have same type for all elements")
|
|
1356
|
+
return TupleWrapper(val=tuple(args), type=datatypes.pop())
|
|
1346
1357
|
|
|
1347
1358
|
def parenthetical(self, args):
|
|
1348
1359
|
return Parenthetical(content=args[0])
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/processing/node_generators/__init__.py
RENAMED
|
File without changes
|
{pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/processing/node_generators/basic_node.py
RENAMED
|
File without changes
|
|
File without changes
|
{pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/processing/node_generators/filter_node.py
RENAMED
|
File without changes
|
{pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/processing/node_generators/group_node.py
RENAMED
|
File without changes
|
{pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/processing/node_generators/group_to_node.py
RENAMED
|
File without changes
|
|
File without changes
|
{pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/processing/node_generators/node_merge_node.py
RENAMED
|
File without changes
|
{pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/processing/node_generators/rowset_node.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/processing/node_generators/select_node.py
RENAMED
|
File without changes
|
{pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/processing/node_generators/synonym_node.py
RENAMED
|
File without changes
|
{pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/processing/node_generators/union_node.py
RENAMED
|
File without changes
|
{pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/processing/node_generators/unnest_node.py
RENAMED
|
File without changes
|
{pytrilogy-0.0.3.22 → pytrilogy-0.0.3.24}/trilogy/core/processing/node_generators/window_node.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|