pytrilogy 0.0.3.41__py3-none-any.whl → 0.0.3.43__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.3.41.dist-info → pytrilogy-0.0.3.43.dist-info}/METADATA +1 -1
- {pytrilogy-0.0.3.41.dist-info → pytrilogy-0.0.3.43.dist-info}/RECORD +14 -14
- {pytrilogy-0.0.3.41.dist-info → pytrilogy-0.0.3.43.dist-info}/WHEEL +1 -1
- trilogy/__init__.py +1 -1
- trilogy/core/models/build.py +13 -16
- trilogy/core/processing/concept_strategies_v3.py +3 -2
- trilogy/core/processing/node_generators/group_to_node.py +23 -8
- trilogy/core/processing/node_generators/window_node.py +9 -1
- trilogy/dialect/bigquery.py +1 -1
- trilogy/parsing/common.py +7 -1
- trilogy/parsing/parse_engine.py +24 -22
- {pytrilogy-0.0.3.41.dist-info → pytrilogy-0.0.3.43.dist-info}/entry_points.txt +0 -0
- {pytrilogy-0.0.3.41.dist-info → pytrilogy-0.0.3.43.dist-info}/licenses/LICENSE.md +0 -0
- {pytrilogy-0.0.3.41.dist-info → pytrilogy-0.0.3.43.dist-info}/top_level.txt +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
pytrilogy-0.0.3.
|
|
2
|
-
trilogy/__init__.py,sha256=
|
|
1
|
+
pytrilogy-0.0.3.43.dist-info/licenses/LICENSE.md,sha256=5ZRvtTyCCFwz1THxDTjAu3Lidds9WjPvvzgVwPSYNDo,1042
|
|
2
|
+
trilogy/__init__.py,sha256=4cXB9506hb2gprGWKbo-5R8LE3DuFBSrMfMr82Gwvn4,303
|
|
3
3
|
trilogy/compiler.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
4
|
trilogy/constants.py,sha256=5eQxk1A0pv-TQk3CCvgZCFA9_K-6nxrOm7E5Lxd7KIY,1652
|
|
5
5
|
trilogy/engine.py,sha256=OK2RuqCIUId6yZ5hfF8J1nxGP0AJqHRZiafcowmW0xc,1728
|
|
@@ -23,7 +23,7 @@ trilogy/core/optimization.py,sha256=aihzx4-2-mSjx5td1TDTYGvc7e9Zvy-_xEyhPqLS-Ig,
|
|
|
23
23
|
trilogy/core/query_processor.py,sha256=Vl-u0F0rbqI2liv82yJgiZCB255Kx_KiuzZVHL6aeTM,19459
|
|
24
24
|
trilogy/core/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
25
25
|
trilogy/core/models/author.py,sha256=hS1caD8y7XWRBlHfwgZOrBcz3TisDPba8joFaiEXxX0,77072
|
|
26
|
-
trilogy/core/models/build.py,sha256=
|
|
26
|
+
trilogy/core/models/build.py,sha256=NdDRcgvNoa2CHoXcPvWAUkCA2TRUKYm0zIl5NBx0sfo,61796
|
|
27
27
|
trilogy/core/models/build_environment.py,sha256=s_C9xAHuD3yZ26T15pWVBvoqvlp2LdZ8yjsv2_HdXLk,5363
|
|
28
28
|
trilogy/core/models/core.py,sha256=wx6hJcFECMG-Ij972ADNkr-3nFXkYESr82ObPiC46_U,10875
|
|
29
29
|
trilogy/core/models/datasource.py,sha256=6RjJUd2u4nYmEwFBpJlM9LbHVYDv8iHJxqiBMZqUrwI,9422
|
|
@@ -35,7 +35,7 @@ trilogy/core/optimizations/inline_constant.py,sha256=lvNTIXaLNkw3HseJyXyDNk5R52d
|
|
|
35
35
|
trilogy/core/optimizations/inline_datasource.py,sha256=AHuTGh2x0GQ8usOe0NiFncfTFQ_KogdgDl4uucmhIbI,4241
|
|
36
36
|
trilogy/core/optimizations/predicate_pushdown.py,sha256=g4AYE8Aw_iMlAh68TjNXGP754NTurrDduFECkUjoBnc,9399
|
|
37
37
|
trilogy/core/processing/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
38
|
-
trilogy/core/processing/concept_strategies_v3.py,sha256=
|
|
38
|
+
trilogy/core/processing/concept_strategies_v3.py,sha256=dx6w7euQOozoNv-ugrFOHZcCSEkpG8yhK44QH5-yGt4,44046
|
|
39
39
|
trilogy/core/processing/graph_utils.py,sha256=8QUVrkE9j-9C1AyrCb1nQEh8daCe0u1HuXl-Te85lag,1205
|
|
40
40
|
trilogy/core/processing/utility.py,sha256=rfzdgl-vWkCyhLzXNNuWgPLK59eiYypQb6TdZKymUqk,21469
|
|
41
41
|
trilogy/core/processing/node_generators/__init__.py,sha256=o8rOFHPSo-s_59hREwXMW6gjUJCsiXumdbJNozHUf-Y,800
|
|
@@ -43,7 +43,7 @@ trilogy/core/processing/node_generators/basic_node.py,sha256=UVsXMn6jTjm_ofVFt21
|
|
|
43
43
|
trilogy/core/processing/node_generators/common.py,sha256=ZsDzThjm_mAtdQpKAg8QIJiPVZ4KuUkKyilj4eOhSDs,9439
|
|
44
44
|
trilogy/core/processing/node_generators/filter_node.py,sha256=lT167yBgy3P9sDBM1Cjj0PKSXro8dvGtBmc8nwsUjig,8366
|
|
45
45
|
trilogy/core/processing/node_generators/group_node.py,sha256=kO-ersxIL04rZwX5-vFIFQQnp357PFo_7ZKXoGq3wyc,5989
|
|
46
|
-
trilogy/core/processing/node_generators/group_to_node.py,sha256=
|
|
46
|
+
trilogy/core/processing/node_generators/group_to_node.py,sha256=jKcNCDOY6fNblrdZwaRU0sbUSr9H0moQbAxrGgX6iGA,3832
|
|
47
47
|
trilogy/core/processing/node_generators/multiselect_node.py,sha256=GWV5yLmKTe1yyPhN60RG1Rnrn4ktfn9lYYXi_FVU4UI,7061
|
|
48
48
|
trilogy/core/processing/node_generators/node_merge_node.py,sha256=sv55oynfqgpHEpo1OEtVDri-5fywzPhDlR85qaWikvY,16195
|
|
49
49
|
trilogy/core/processing/node_generators/rowset_node.py,sha256=YmBs6ZQ7azLXRFEmeoecpGjK4pMHsUCovuBxfb3UKZI,6848
|
|
@@ -52,7 +52,7 @@ trilogy/core/processing/node_generators/select_node.py,sha256=Y-zO0AFkTrpi2Lyebj
|
|
|
52
52
|
trilogy/core/processing/node_generators/synonym_node.py,sha256=9LHK2XHDjbyTLjmDQieskG8fqbiSpRnFOkfrutDnOTE,2258
|
|
53
53
|
trilogy/core/processing/node_generators/union_node.py,sha256=VNo6Oey4p8etU9xrOh2oTT2lIOTvY6PULUPRvVa2uxU,2877
|
|
54
54
|
trilogy/core/processing/node_generators/unnest_node.py,sha256=cOEKnMRzXUW3bwmiOlgn3E1-B38osng0dh2pDykwITY,2410
|
|
55
|
-
trilogy/core/processing/node_generators/window_node.py,sha256=
|
|
55
|
+
trilogy/core/processing/node_generators/window_node.py,sha256=lj94LRcJaypyfLEucQwIn65ZQsSAkYV_r1esFhPRUDc,6047
|
|
56
56
|
trilogy/core/processing/node_generators/select_helpers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
57
57
|
trilogy/core/processing/node_generators/select_helpers/datasource_injection.py,sha256=GMW07bb6hXurhF0hZLYoMAKSIS65tat5hwBjvqqPeSA,6516
|
|
58
58
|
trilogy/core/processing/nodes/__init__.py,sha256=Lxr3rs_bqOAtMtn3DHIkY058ZzjyLM5mSfGMKW2z0NY,5555
|
|
@@ -71,7 +71,7 @@ trilogy/core/statements/common.py,sha256=KxEmz2ySySyZ6CTPzn0fJl5NX2KOk1RPyuUSwWh
|
|
|
71
71
|
trilogy/core/statements/execute.py,sha256=cSlvpHFOqpiZ89pPZ5GDp9Hu6j6uj-5_h21FWm_L-KM,1248
|
|
72
72
|
trilogy/dialect/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
73
73
|
trilogy/dialect/base.py,sha256=vp6_9fUkblAWVpCXGBIcoAx6N7vof9M7s9t6-b_waUY,41409
|
|
74
|
-
trilogy/dialect/bigquery.py,sha256=
|
|
74
|
+
trilogy/dialect/bigquery.py,sha256=7LcgPLDkeNBk6YTfaE-RBBi7SjWFV-jjuvZM1VMIXqk,3350
|
|
75
75
|
trilogy/dialect/common.py,sha256=XjHkP8Dqezjkd2JU5xoAlMRS_6HNyXQCF4CykLK3C8o,5011
|
|
76
76
|
trilogy/dialect/config.py,sha256=olnyeVU5W5T6b9-dMeNAnvxuPlyc2uefb7FRME094Ec,3834
|
|
77
77
|
trilogy/dialect/dataframe.py,sha256=RUbNgReEa9g3pL6H7fP9lPTrAij5pkqedpZ99D8_5AE,1522
|
|
@@ -87,11 +87,11 @@ trilogy/hooks/graph_hook.py,sha256=c-vC-IXoJ_jDmKQjxQyIxyXPOuUcLIURB573gCsAfzQ,2
|
|
|
87
87
|
trilogy/hooks/query_debugger.py,sha256=1npRjww94sPV5RRBBlLqMJRaFkH9vhEY6o828MeoEcw,5583
|
|
88
88
|
trilogy/metadata/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
89
89
|
trilogy/parsing/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
90
|
-
trilogy/parsing/common.py,sha256=
|
|
90
|
+
trilogy/parsing/common.py,sha256=2KwR86ZNH04tcs500l02jLPkFaStEYc9wtR1NVO6cYo,26411
|
|
91
91
|
trilogy/parsing/config.py,sha256=Z-DaefdKhPDmSXLgg5V4pebhSB0h590vI0_VtHnlukI,111
|
|
92
92
|
trilogy/parsing/exceptions.py,sha256=92E5i2frv5hj9wxObJZsZqj5T6bglvPzvdvco_vW1Zk,38
|
|
93
93
|
trilogy/parsing/helpers.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
94
|
-
trilogy/parsing/parse_engine.py,sha256=
|
|
94
|
+
trilogy/parsing/parse_engine.py,sha256=tsEBRyG2fzHUdiO1oW2mB_36vNZOfjFA4MXuf0zpF2E,65547
|
|
95
95
|
trilogy/parsing/render.py,sha256=hI4y-xjXrEXvHslY2l2TQ8ic0zAOpN41ADH37J2_FZY,19047
|
|
96
96
|
trilogy/parsing/trilogy.lark,sha256=2Noe58vGYteilKd6w-np3fb4lzWI-G9Gt0AMyOMVw3k,13735
|
|
97
97
|
trilogy/scripts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -102,8 +102,8 @@ trilogy/std/display.preql,sha256=2BbhvqR4rcltyAbOXAUo7SZ_yGFYZgFnurglHMbjW2g,40
|
|
|
102
102
|
trilogy/std/geography.preql,sha256=-fqAGnBL6tR-UtT8DbSek3iMFg66ECR_B_41pODxv-k,504
|
|
103
103
|
trilogy/std/money.preql,sha256=ZHW-csTX-kYbOLmKSO-TcGGgQ-_DMrUXy0BjfuJSFxM,80
|
|
104
104
|
trilogy/std/report.preql,sha256=LbV-XlHdfw0jgnQ8pV7acG95xrd1-p65fVpiIc-S7W4,202
|
|
105
|
-
pytrilogy-0.0.3.
|
|
106
|
-
pytrilogy-0.0.3.
|
|
107
|
-
pytrilogy-0.0.3.
|
|
108
|
-
pytrilogy-0.0.3.
|
|
109
|
-
pytrilogy-0.0.3.
|
|
105
|
+
pytrilogy-0.0.3.43.dist-info/METADATA,sha256=0cC502qzl6dYCgRsnS4Gi8LqcpV1Ozu7JKdYaqc69mM,9100
|
|
106
|
+
pytrilogy-0.0.3.43.dist-info/WHEEL,sha256=wXxTzcEDnjrTwFYjLPcsW_7_XihufBwmpiBeiXNBGEA,91
|
|
107
|
+
pytrilogy-0.0.3.43.dist-info/entry_points.txt,sha256=ewBPU2vLnVexZVnB-NrVj-p3E-4vukg83Zk8A55Wp2w,56
|
|
108
|
+
pytrilogy-0.0.3.43.dist-info/top_level.txt,sha256=cAy__NW_eMAa_yT9UnUNlZLFfxcg6eimUAZ184cdNiE,8
|
|
109
|
+
pytrilogy-0.0.3.43.dist-info/RECORD,,
|
trilogy/__init__.py
CHANGED
trilogy/core/models/build.py
CHANGED
|
@@ -1541,18 +1541,14 @@ class Factory:
|
|
|
1541
1541
|
else:
|
|
1542
1542
|
# constants, etc, can be ignored for group
|
|
1543
1543
|
continue
|
|
1544
|
-
group_base =
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
)
|
|
1551
|
-
},
|
|
1552
|
-
)
|
|
1553
|
-
group_base = group_base.with_grain(
|
|
1554
|
-
Grain.from_concepts(final_args, environment=self.environment)
|
|
1544
|
+
group_base = arbitrary_to_concept(
|
|
1545
|
+
AggregateWrapper(
|
|
1546
|
+
function=group_base.lineage.function,
|
|
1547
|
+
by=final_args,
|
|
1548
|
+
),
|
|
1549
|
+
environment=self.environment,
|
|
1555
1550
|
)
|
|
1551
|
+
|
|
1556
1552
|
rval = self.build(group_base)
|
|
1557
1553
|
return BuildFunction.model_construct(
|
|
1558
1554
|
operator=base.operator,
|
|
@@ -1650,21 +1646,20 @@ class Factory:
|
|
|
1650
1646
|
]
|
|
1651
1647
|
else:
|
|
1652
1648
|
by = [self.build(x) for x in base.by]
|
|
1649
|
+
|
|
1653
1650
|
parent = self.build(base.function)
|
|
1654
1651
|
return BuildAggregateWrapper.model_construct(function=parent, by=by)
|
|
1655
1652
|
|
|
1656
1653
|
@build.register
|
|
1657
1654
|
def _(self, base: ColumnAssignment) -> BuildColumnAssignment:
|
|
1658
|
-
|
|
1655
|
+
fetched = self.environment.concepts[base.concept.address]
|
|
1659
1656
|
return BuildColumnAssignment.model_construct(
|
|
1660
1657
|
alias=(
|
|
1661
1658
|
self.build(base.alias)
|
|
1662
1659
|
if isinstance(base.alias, Function)
|
|
1663
1660
|
else base.alias
|
|
1664
1661
|
),
|
|
1665
|
-
concept=self.build(
|
|
1666
|
-
self.environment.concepts[base.concept.address].with_grain(self.grain)
|
|
1667
|
-
),
|
|
1662
|
+
concept=self.build(fetched.with_grain(self.grain)),
|
|
1668
1663
|
modifiers=base.modifiers,
|
|
1669
1664
|
)
|
|
1670
1665
|
|
|
@@ -1683,7 +1678,9 @@ class Factory:
|
|
|
1683
1678
|
from trilogy.parsing.common import arbitrary_to_concept
|
|
1684
1679
|
|
|
1685
1680
|
bexpr: Any
|
|
1686
|
-
if isinstance(base.expr, AggregateWrapper)
|
|
1681
|
+
if isinstance(base.expr, (AggregateWrapper, WindowItem, FilterItem)) or (
|
|
1682
|
+
isinstance(base.expr, Function) and base.expr.operator == FunctionType.GROUP
|
|
1683
|
+
):
|
|
1687
1684
|
bexpr = arbitrary_to_concept(
|
|
1688
1685
|
base.expr,
|
|
1689
1686
|
environment=self.environment,
|
|
@@ -5,6 +5,7 @@ from typing import List, Optional, Protocol, Union
|
|
|
5
5
|
from trilogy.constants import logger
|
|
6
6
|
from trilogy.core.enums import Derivation, FunctionType, Granularity
|
|
7
7
|
from trilogy.core.env_processor import generate_graph
|
|
8
|
+
from trilogy.core.exceptions import UnresolvableQueryException
|
|
8
9
|
from trilogy.core.graph_models import ReferenceGraph
|
|
9
10
|
from trilogy.core.models.author import (
|
|
10
11
|
UndefinedConcept,
|
|
@@ -1120,8 +1121,8 @@ def source_query_concepts(
|
|
|
1120
1121
|
error_strings = [
|
|
1121
1122
|
f"{c.address}<{c.purpose}>{c.derivation}>" for c in output_concepts
|
|
1122
1123
|
]
|
|
1123
|
-
raise
|
|
1124
|
-
f"Could not resolve connections
|
|
1124
|
+
raise UnresolvableQueryException(
|
|
1125
|
+
f"Could not resolve connections for query with output {error_strings} from current model."
|
|
1125
1126
|
)
|
|
1126
1127
|
final = [x for x in root.output_concepts if x.address not in root.hidden_concepts]
|
|
1127
1128
|
logger.info(
|
|
@@ -31,9 +31,9 @@ def gen_group_to_node(
|
|
|
31
31
|
raise SyntaxError(
|
|
32
32
|
f"Group to should have function lineage, is {type(concept.lineage)}"
|
|
33
33
|
)
|
|
34
|
-
group_arg = concept.lineage.arguments[0]
|
|
35
34
|
|
|
36
35
|
parent_concepts: List[BuildConcept] = concept.lineage.concept_arguments
|
|
36
|
+
root = parent_concepts[0]
|
|
37
37
|
logger.info(
|
|
38
38
|
f"{padding(depth)}{LOGGER_PREFIX} group by node has required parents {[x.address for x in parent_concepts]}"
|
|
39
39
|
)
|
|
@@ -47,7 +47,7 @@ def gen_group_to_node(
|
|
|
47
47
|
conditions=conditions,
|
|
48
48
|
)
|
|
49
49
|
]
|
|
50
|
-
|
|
50
|
+
outputs = parent_concepts + [concept]
|
|
51
51
|
group_node = GroupNode(
|
|
52
52
|
output_concepts=parent_concepts + [concept],
|
|
53
53
|
input_concepts=parent_concepts,
|
|
@@ -56,17 +56,30 @@ def gen_group_to_node(
|
|
|
56
56
|
depth=depth,
|
|
57
57
|
preexisting_conditions=conditions.conditional if conditions else None,
|
|
58
58
|
hidden_concepts=set(
|
|
59
|
-
[
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
59
|
+
[
|
|
60
|
+
x.address
|
|
61
|
+
for x in outputs
|
|
62
|
+
if x.address not in local_optional
|
|
63
|
+
and x.address != concept.address
|
|
64
|
+
and x.address != root.address
|
|
65
|
+
]
|
|
63
66
|
),
|
|
64
67
|
)
|
|
65
68
|
|
|
66
69
|
# early exit if no optional
|
|
67
|
-
|
|
70
|
+
missing_local_option: list[BuildConcept] = [
|
|
71
|
+
x for x in local_optional if x not in group_node.output_concepts
|
|
72
|
+
]
|
|
73
|
+
if not missing_local_option:
|
|
74
|
+
logger.info(
|
|
75
|
+
f"{padding(depth)}{LOGGER_PREFIX} no missing local optional required, returning group node only."
|
|
76
|
+
)
|
|
68
77
|
return group_node
|
|
69
78
|
|
|
79
|
+
logger.info(
|
|
80
|
+
f"{padding(depth)}{LOGGER_PREFIX} group by node is missing required optional {[x.address for x in missing_local_option]}"
|
|
81
|
+
)
|
|
82
|
+
|
|
70
83
|
# the keys we group by
|
|
71
84
|
# are what we can use for enrichment
|
|
72
85
|
enrich_node = source_concepts( # this fetches the parent + join keys
|
|
@@ -83,7 +96,9 @@ def gen_group_to_node(
|
|
|
83
96
|
f"{padding(depth)}{LOGGER_PREFIX} group by node enrich node, returning group node only."
|
|
84
97
|
)
|
|
85
98
|
return group_node
|
|
86
|
-
|
|
99
|
+
logger.info(
|
|
100
|
+
f"{padding(depth)}{LOGGER_PREFIX} returning group to node with enrichment."
|
|
101
|
+
)
|
|
87
102
|
return MergeNode(
|
|
88
103
|
input_concepts=[concept]
|
|
89
104
|
+ local_optional
|
|
@@ -61,6 +61,9 @@ def gen_window_node(
|
|
|
61
61
|
# append in keys to get the right grain
|
|
62
62
|
if concept.keys:
|
|
63
63
|
for item in concept.keys:
|
|
64
|
+
logger.info(
|
|
65
|
+
f"{padding(depth)}{LOGGER_PREFIX} appending search for key {item}"
|
|
66
|
+
)
|
|
64
67
|
targets.append(environment.concepts[item])
|
|
65
68
|
additional_outputs = []
|
|
66
69
|
if equivalent_optional:
|
|
@@ -72,10 +75,15 @@ def gen_window_node(
|
|
|
72
75
|
additional_outputs.append(x)
|
|
73
76
|
|
|
74
77
|
grain_equivalents = [
|
|
75
|
-
x
|
|
78
|
+
x
|
|
79
|
+
for x in local_optional
|
|
80
|
+
if x.keys
|
|
81
|
+
and all([key in targets for key in x.keys])
|
|
82
|
+
and x.grain == concept.grain
|
|
76
83
|
]
|
|
77
84
|
|
|
78
85
|
for x in grain_equivalents:
|
|
86
|
+
logger.info("Appending grain equivalent %s", x)
|
|
79
87
|
targets.append(x)
|
|
80
88
|
|
|
81
89
|
# finally, the ones we'll need to enrich
|
trilogy/dialect/bigquery.py
CHANGED
|
@@ -34,7 +34,7 @@ FUNCTION_MAP = {
|
|
|
34
34
|
|
|
35
35
|
FUNCTION_GRAIN_MATCH_MAP = {
|
|
36
36
|
**FUNCTION_MAP,
|
|
37
|
-
FunctionType.COUNT: lambda args:
|
|
37
|
+
FunctionType.COUNT: lambda args: "1",
|
|
38
38
|
FunctionType.SUM: lambda args: f"{args[0]}",
|
|
39
39
|
FunctionType.AVG: lambda args: f"{args[0]}",
|
|
40
40
|
}
|
trilogy/parsing/common.py
CHANGED
|
@@ -771,7 +771,13 @@ def arbitrary_to_concept(
|
|
|
771
771
|
)
|
|
772
772
|
elif isinstance(parent, Function):
|
|
773
773
|
if not name:
|
|
774
|
-
|
|
774
|
+
if parent.operator == FunctionType.GROUP:
|
|
775
|
+
name = (
|
|
776
|
+
f"{VIRTUAL_CONCEPT_PREFIX}_group_to_{string_to_hash(str(parent))}"
|
|
777
|
+
)
|
|
778
|
+
else:
|
|
779
|
+
name = f"{VIRTUAL_CONCEPT_PREFIX}_func_{parent.operator.value}_{string_to_hash(str(parent))}"
|
|
780
|
+
|
|
775
781
|
if parent.operator == FunctionType.GROUP:
|
|
776
782
|
return group_function_to_concept(
|
|
777
783
|
parent,
|
trilogy/parsing/parse_engine.py
CHANGED
|
@@ -590,6 +590,7 @@ class ParseToObjects(Transformer):
|
|
|
590
590
|
keys=set([x.address for x in parents]),
|
|
591
591
|
modifiers=modifiers,
|
|
592
592
|
)
|
|
593
|
+
|
|
593
594
|
self.environment.add_concept(concept, meta)
|
|
594
595
|
return concept
|
|
595
596
|
|
|
@@ -1367,23 +1368,7 @@ class ParseToObjects(Transformer):
|
|
|
1367
1368
|
def comparison(self, args) -> Comparison:
|
|
1368
1369
|
if args[1] == ComparisonOperator.IN:
|
|
1369
1370
|
raise SyntaxError
|
|
1370
|
-
# if isinstance(args[0], AggregateWrapper):
|
|
1371
|
-
# left_c = arbitrary_to_concept(
|
|
1372
|
-
# args[0],
|
|
1373
|
-
# environment=self.environment,
|
|
1374
|
-
# )
|
|
1375
|
-
# self.environment.add_concept(left_c)
|
|
1376
|
-
# left = left_c.reference
|
|
1377
|
-
# else:
|
|
1378
1371
|
left = args[0]
|
|
1379
|
-
# if isinstance(args[2], AggregateWrapper):
|
|
1380
|
-
# right_c = arbitrary_to_concept(
|
|
1381
|
-
# args[2],
|
|
1382
|
-
# environment=self.environment,
|
|
1383
|
-
# )
|
|
1384
|
-
# self.environment.add_concept(right_c)
|
|
1385
|
-
# right = right_c.reference
|
|
1386
|
-
# else:
|
|
1387
1372
|
right = args[2]
|
|
1388
1373
|
return Comparison(left=left, right=right, operator=args[1])
|
|
1389
1374
|
|
|
@@ -1479,7 +1464,7 @@ class ParseToObjects(Transformer):
|
|
|
1479
1464
|
return DatePart(args.value)
|
|
1480
1465
|
|
|
1481
1466
|
@v_args(meta=True)
|
|
1482
|
-
def window_item(self, meta, args) -> WindowItem:
|
|
1467
|
+
def window_item(self, meta: Meta, args) -> WindowItem:
|
|
1483
1468
|
type: WindowType = args[0]
|
|
1484
1469
|
order_by = []
|
|
1485
1470
|
over = []
|
|
@@ -1501,7 +1486,10 @@ class ParseToObjects(Transformer):
|
|
|
1501
1486
|
else:
|
|
1502
1487
|
concept = arbitrary_to_concept(item, environment=self.environment)
|
|
1503
1488
|
self.environment.add_concept(concept, meta=meta)
|
|
1504
|
-
|
|
1489
|
+
if not concept:
|
|
1490
|
+
raise ParseError(
|
|
1491
|
+
f"Window statements must be on fields, not constants - error in: `{self.text_lookup[self.parse_address][meta.start_pos:meta.end_pos]}`"
|
|
1492
|
+
)
|
|
1505
1493
|
return WindowItem(
|
|
1506
1494
|
type=type,
|
|
1507
1495
|
content=concept.reference,
|
|
@@ -1830,16 +1818,24 @@ class ParseToObjects(Transformer):
|
|
|
1830
1818
|
return self.function_factory.create_function(args, FunctionType.BOOL, meta)
|
|
1831
1819
|
|
|
1832
1820
|
|
|
1833
|
-
def unpack_visit_error(e: VisitError):
|
|
1821
|
+
def unpack_visit_error(e: VisitError, text: str | None = None):
|
|
1834
1822
|
"""This is required to get exceptions from imports, which would
|
|
1835
1823
|
raise nested VisitErrors"""
|
|
1836
1824
|
if isinstance(e.orig_exc, VisitError):
|
|
1837
|
-
unpack_visit_error(e.orig_exc)
|
|
1825
|
+
unpack_visit_error(e.orig_exc, text)
|
|
1838
1826
|
elif isinstance(e.orig_exc, (UndefinedConceptException, ImportError)):
|
|
1839
1827
|
raise e.orig_exc
|
|
1840
1828
|
elif isinstance(e.orig_exc, (SyntaxError, TypeError)):
|
|
1841
1829
|
if isinstance(e.obj, Tree):
|
|
1842
|
-
|
|
1830
|
+
if text:
|
|
1831
|
+
extract = text[e.obj.meta.start_pos - 5 : e.obj.meta.end_pos + 5]
|
|
1832
|
+
raise InvalidSyntaxException(
|
|
1833
|
+
str(e.orig_exc)
|
|
1834
|
+
+ " in "
|
|
1835
|
+
+ str(e.rule)
|
|
1836
|
+
+ f" Line: {e.obj.meta.line} ({extract})"
|
|
1837
|
+
)
|
|
1838
|
+
InvalidSyntaxException(
|
|
1843
1839
|
str(e.orig_exc) + " in " + str(e.rule) + f" Line: {e.obj.meta.line}"
|
|
1844
1840
|
)
|
|
1845
1841
|
raise InvalidSyntaxException(str(e.orig_exc)).with_traceback(
|
|
@@ -1890,7 +1886,7 @@ def parse_text(
|
|
|
1890
1886
|
f"Parse time: {end - start} for {len(text)} characters, {len(output)} objects"
|
|
1891
1887
|
)
|
|
1892
1888
|
except VisitError as e:
|
|
1893
|
-
unpack_visit_error(e)
|
|
1889
|
+
unpack_visit_error(e, text)
|
|
1894
1890
|
# this will never be reached
|
|
1895
1891
|
raise e
|
|
1896
1892
|
except (
|
|
@@ -1901,6 +1897,12 @@ def parse_text(
|
|
|
1901
1897
|
ValidationError,
|
|
1902
1898
|
TypeError,
|
|
1903
1899
|
) as e:
|
|
1900
|
+
if isinstance(
|
|
1901
|
+
e, (UnexpectedCharacters, UnexpectedEOF, UnexpectedInput, UnexpectedToken)
|
|
1902
|
+
):
|
|
1903
|
+
raise InvalidSyntaxException(
|
|
1904
|
+
str(e) + "\nContext:\n" + e.get_context(text.replace("\n", " "), 20)
|
|
1905
|
+
)
|
|
1904
1906
|
raise InvalidSyntaxException(str(e))
|
|
1905
1907
|
|
|
1906
1908
|
return environment, output
|
|
File without changes
|
|
File without changes
|
|
File without changes
|