pytrilogy 0.0.3.40__py3-none-any.whl → 0.0.3.42__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.

@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pytrilogy
3
- Version: 0.0.3.40
3
+ Version: 0.0.3.42
4
4
  Summary: Declarative, typed query language that compiles to SQL.
5
5
  Home-page:
6
6
  Author:
@@ -1,5 +1,5 @@
1
- pytrilogy-0.0.3.40.dist-info/licenses/LICENSE.md,sha256=5ZRvtTyCCFwz1THxDTjAu3Lidds9WjPvvzgVwPSYNDo,1042
2
- trilogy/__init__.py,sha256=WMnT9BmyaPDH4Ou8mB78VlxkF9bljCJ8DIckl3wCaXw,303
1
+ pytrilogy-0.0.3.42.dist-info/licenses/LICENSE.md,sha256=5ZRvtTyCCFwz1THxDTjAu3Lidds9WjPvvzgVwPSYNDo,1042
2
+ trilogy/__init__.py,sha256=6Oo1hj7rRiJ3WTlh1NH1PAfbHWNk1Zgr5f5DpIefPy8,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
@@ -13,7 +13,7 @@ trilogy/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
13
  trilogy/core/constants.py,sha256=7XaCpZn5mQmjTobbeBn56SzPWq9eMNDfzfsRU-fP0VE,171
14
14
  trilogy/core/enums.py,sha256=JwbWyAHOC2xRTZe2SeEvlIGPvmC1KjcJ4uh1Po5USzQ,7380
15
15
  trilogy/core/env_processor.py,sha256=pFsxnluKIusGKx1z7tTnfsd_xZcPy9pZDungkjkyvI0,3170
16
- trilogy/core/environment_helpers.py,sha256=TKx_Q50iczcW1eiFbnJ1zbcyGst-Xw80EcqYwKyEqg8,9742
16
+ trilogy/core/environment_helpers.py,sha256=UWtF5ZQqFyzHdrjUBEd7c2ZfASBhBWFoa9WkUHBbyHI,9700
17
17
  trilogy/core/ergonomics.py,sha256=e-7gE29vPLFdg0_A1smQ7eOrUwKl5VYdxRSTddHweRA,1631
18
18
  trilogy/core/exceptions.py,sha256=JPYyBcit3T_pRtlHdtKSeVJkIyWUTozW2aaut25A2xI,673
19
19
  trilogy/core/functions.py,sha256=4fEOGgXWDvgrJtCg_5m2Y9iWnHfLbvLQ82RkIMl_1K0,27722
@@ -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=flDLLFCR0XJ0fpUhkGg-bpDOkH915tDdXaKmrAzNIcg,61828
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=reXqgktFKy5qhm4k6abrs4J16Sovxd4naHrsEcNarEk,43957
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=v2Xl5VjNO2hKJAdmqCbmAOqaRPvxRUbtfhhQXFMifWk,3197
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
@@ -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=yZJ0b77viQktG5vi4CS8kz9KXj2K3nAb17bkDrw4-WI,26204
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=Tagt3zPBViM-GZYuqHb1SnbEIwa8fx12kF07JMgmyV4,65312
94
+ trilogy/parsing/parse_engine.py,sha256=GTraw3-Dbdo36yhprizifZY-wbm_ub8ktI1nMEziee0,64723
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.40.dist-info/METADATA,sha256=3YTyHMFdCeINuBajgMlyAwdYl8-U0Eg0T98UsdorQ8A,9100
106
- pytrilogy-0.0.3.40.dist-info/WHEEL,sha256=SmOxYU7pzNKBqASvQJ7DjX3XGUF92lrGhMb3R6_iiqI,91
107
- pytrilogy-0.0.3.40.dist-info/entry_points.txt,sha256=ewBPU2vLnVexZVnB-NrVj-p3E-4vukg83Zk8A55Wp2w,56
108
- pytrilogy-0.0.3.40.dist-info/top_level.txt,sha256=cAy__NW_eMAa_yT9UnUNlZLFfxcg6eimUAZ184cdNiE,8
109
- pytrilogy-0.0.3.40.dist-info/RECORD,,
105
+ pytrilogy-0.0.3.42.dist-info/METADATA,sha256=L_128KNMAQLKLe33FsvUWvD5NRHCKqzkvmHT1Xx6o4c,9100
106
+ pytrilogy-0.0.3.42.dist-info/WHEEL,sha256=ck4Vq1_RXyvS4Jt6SI0Vz6fyVs4GWg7AINwpsaGEgPE,91
107
+ pytrilogy-0.0.3.42.dist-info/entry_points.txt,sha256=ewBPU2vLnVexZVnB-NrVj-p3E-4vukg83Zk8A55Wp2w,56
108
+ pytrilogy-0.0.3.42.dist-info/top_level.txt,sha256=cAy__NW_eMAa_yT9UnUNlZLFfxcg6eimUAZ184cdNiE,8
109
+ pytrilogy-0.0.3.42.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (79.0.1)
2
+ Generator: setuptools (80.0.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
trilogy/__init__.py CHANGED
@@ -4,6 +4,6 @@ from trilogy.dialect.enums import Dialects
4
4
  from trilogy.executor import Executor
5
5
  from trilogy.parser import parse
6
6
 
7
- __version__ = "0.0.3.40"
7
+ __version__ = "0.0.3.42"
8
8
 
9
9
  __all__ = ["parse", "Executor", "Dialects", "Environment", "CONFIG"]
@@ -1,7 +1,7 @@
1
1
  from trilogy.constants import DEFAULT_NAMESPACE
2
2
  from trilogy.core.enums import ConceptSource, DatePart, FunctionType, Purpose
3
3
  from trilogy.core.functions import AttrAccess
4
- from trilogy.core.models.author import Concept, Function, Metadata, TraitDataType
4
+ from trilogy.core.models.author import Concept, Function, Grain, Metadata, TraitDataType
5
5
  from trilogy.core.models.core import DataType, StructType, arg_to_datatype
6
6
  from trilogy.core.models.environment import Environment
7
7
  from trilogy.parsing.common import Meta
@@ -182,11 +182,9 @@ def generate_key_concepts(concept: Concept, environment: Environment):
182
182
  datatype=DataType.INTEGER,
183
183
  purpose=default_type,
184
184
  lineage=const_function,
185
- grain=concept.grain,
185
+ grain=Grain(),
186
186
  namespace=concept.namespace,
187
- keys={
188
- concept.address,
189
- },
187
+ keys=set(),
190
188
  metadata=Metadata(
191
189
  description=f"Auto-derived integer. The {ftype.value} of {concept.address}, {base_description}",
192
190
  line_number=base_line_number,
@@ -1541,18 +1541,14 @@ class Factory:
1541
1541
  else:
1542
1542
  # constants, etc, can be ignored for group
1543
1543
  continue
1544
- group_base = group_base.model_copy(
1545
- deep=True,
1546
- update={
1547
- "lineage": AggregateWrapper(
1548
- function=group_base.lineage.function,
1549
- by=final_args,
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,
@@ -1697,6 +1694,7 @@ class Factory:
1697
1694
 
1698
1695
  @build.register
1699
1696
  def _(self, base: WhereClause) -> BuildWhereClause:
1697
+
1700
1698
  return BuildWhereClause.model_construct(
1701
1699
  conditional=self.build(base.conditional)
1702
1700
  )
@@ -1756,14 +1754,14 @@ class Factory:
1756
1754
  from trilogy.parsing.common import arbitrary_to_concept
1757
1755
 
1758
1756
  left = base.left
1759
- if isinstance(left, AggregateWrapper):
1757
+ if isinstance(left, (AggregateWrapper, WindowItem, FilterItem)):
1760
1758
  left_c = arbitrary_to_concept(
1761
1759
  left,
1762
1760
  environment=self.environment,
1763
1761
  )
1764
1762
  left = left_c # type: ignore
1765
1763
  right = base.right
1766
- if isinstance(right, AggregateWrapper):
1764
+ if isinstance(right, (AggregateWrapper, WindowItem, FilterItem)):
1767
1765
  right_c = arbitrary_to_concept(
1768
1766
  right,
1769
1767
  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 ValueError(
1124
- f"Could not resolve connections between {error_strings} from environment graph."
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
- [group_arg.address]
60
- if isinstance(group_arg, BuildConcept)
61
- and group_arg.address not in local_optional
62
- else []
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
- if not local_optional:
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
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
- name = f"{VIRTUAL_CONCEPT_PREFIX}_func_{parent.operator.value}_{string_to_hash(str(parent))}"
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,
@@ -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