pytrilogy 0.0.3.65__py3-none-any.whl → 0.0.3.66__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.65
3
+ Version: 0.0.3.66
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.65.dist-info/licenses/LICENSE.md,sha256=5ZRvtTyCCFwz1THxDTjAu3Lidds9WjPvvzgVwPSYNDo,1042
2
- trilogy/__init__.py,sha256=5PSTzzhWYk76xlzO_XJek4S4HFPOp41QHzTT_y75mqk,303
1
+ pytrilogy-0.0.3.66.dist-info/licenses/LICENSE.md,sha256=5ZRvtTyCCFwz1THxDTjAu3Lidds9WjPvvzgVwPSYNDo,1042
2
+ trilogy/__init__.py,sha256=aRLUllOSoHKDIW__yBx1aitL_E96Qtj4AGz-mFHB16g,303
3
3
  trilogy/compiler.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
4
  trilogy/constants.py,sha256=lv_aJWP6dn6e2aF4BAE72jbnNtceFddfqtiDSsvzno0,1692
5
5
  trilogy/engine.py,sha256=OK2RuqCIUId6yZ5hfF8J1nxGP0AJqHRZiafcowmW0xc,1728
@@ -20,11 +20,11 @@ trilogy/core/functions.py,sha256=poVfAwet1xdxTkC7WL38UmGRDpUVO9iSMNWSagl9_r4,293
20
20
  trilogy/core/graph_models.py,sha256=wIT-oBchHWE46GLDkgN5K7EzhOBEo8LfaeWV5G5cYcE,3302
21
21
  trilogy/core/internal.py,sha256=iicDBlC6nM8d7e7jqzf_ZOmpUsW8yrr2AA8AqEiLx-s,1577
22
22
  trilogy/core/optimization.py,sha256=ojpn-p79lr03SSVQbbw74iPCyoYpDYBmj1dbZ3oXCjI,8860
23
- trilogy/core/query_processor.py,sha256=QiE_w5HgheT4GLZFnaLssJ4plf4voK0TeTd6N3jhR6A,20188
23
+ trilogy/core/query_processor.py,sha256=kBvQex0Xi2-u8DvAbAo_LXFTMKzMkFvwL-SCrIXU41k,20310
24
24
  trilogy/core/utility.py,sha256=3VC13uSQWcZNghgt7Ot0ZTeEmNqs__cx122abVq9qhM,410
25
25
  trilogy/core/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
26
- trilogy/core/models/author.py,sha256=8XbIsQr6cQrgo9uzee5qRoYiMdEG7yKF4FiiWImW7U0,77490
27
- trilogy/core/models/build.py,sha256=80v9rxwl41O8_7uIJoHK4tnTUfgR6u8EPrwHg4ySqO4,63323
26
+ trilogy/core/models/author.py,sha256=44VyEInWied287lJp99T14Ahq8RSQK4q3Y-AzAByMTY,77818
27
+ trilogy/core/models/build.py,sha256=yR3GtkIgLrT88B_wu9geqHWxnEI4joUWQSYW7_9Gjk0,63489
28
28
  trilogy/core/models/build_environment.py,sha256=s_C9xAHuD3yZ26T15pWVBvoqvlp2LdZ8yjsv2_HdXLk,5363
29
29
  trilogy/core/models/core.py,sha256=EMAuWTngoNVGCdfNrAY7_k6g528iodNQLwPRVip-8DA,10980
30
30
  trilogy/core/models/datasource.py,sha256=6RjJUd2u4nYmEwFBpJlM9LbHVYDv8iHJxqiBMZqUrwI,9422
@@ -93,7 +93,7 @@ trilogy/hooks/graph_hook.py,sha256=5BfR7Dt0bgEsCLgwjowgCsVkboGYfVJGOz8g9mqpnos,4
93
93
  trilogy/hooks/query_debugger.py,sha256=1npRjww94sPV5RRBBlLqMJRaFkH9vhEY6o828MeoEcw,5583
94
94
  trilogy/metadata/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
95
95
  trilogy/parsing/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
96
- trilogy/parsing/common.py,sha256=yuKN3fQEtftRMZlJb0ESUX4TLOVFcAE0vw2CfImYG1A,29980
96
+ trilogy/parsing/common.py,sha256=_-KWPP3NvNAHiB4B6jyGSnYKqlLs2XqXeTZiX4MCtWU,30861
97
97
  trilogy/parsing/config.py,sha256=Z-DaefdKhPDmSXLgg5V4pebhSB0h590vI0_VtHnlukI,111
98
98
  trilogy/parsing/exceptions.py,sha256=Xwwsv2C9kSNv2q-HrrKC1f60JNHShXcCMzstTSEbiCw,154
99
99
  trilogy/parsing/helpers.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
@@ -104,14 +104,14 @@ trilogy/scripts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
104
104
  trilogy/scripts/trilogy.py,sha256=1L0XrH4mVHRt1C9T1HnaDv2_kYEfbWTb5_-cBBke79w,3774
105
105
  trilogy/std/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
106
106
  trilogy/std/date.preql,sha256=HWZm4t4HWyxr5geWRsY05RnHBVDMci8z8YA2cu0-OOw,188
107
- trilogy/std/display.preql,sha256=2BbhvqR4rcltyAbOXAUo7SZ_yGFYZgFnurglHMbjW2g,40
107
+ trilogy/std/display.preql,sha256=nm7lox87Xf6lBvXCVCS6x2HskguMKzndEBucJ5pktzk,175
108
108
  trilogy/std/geography.preql,sha256=qLnHmDU5EnvjTbfqZF-NEclSYM5_e9rZra7QjV01rZ4,582
109
109
  trilogy/std/money.preql,sha256=XWwvAV3WxBsHX9zfptoYRnBigcfYwrYtBHXTME0xJuQ,2082
110
110
  trilogy/std/net.preql,sha256=-bMV6dyofskl4Kvows-iQ4JCxjVUwsZOeWCy8JO5Ftw,135
111
111
  trilogy/std/ranking.preql,sha256=LDoZrYyz4g3xsII9XwXfmstZD-_92i1Eox1UqkBIfi8,83
112
112
  trilogy/std/report.preql,sha256=LbV-XlHdfw0jgnQ8pV7acG95xrd1-p65fVpiIc-S7W4,202
113
- pytrilogy-0.0.3.65.dist-info/METADATA,sha256=EzLG1grru3E83dGL_4EkZemWzM8QDjCe-S08QQNVAmk,9095
114
- pytrilogy-0.0.3.65.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
115
- pytrilogy-0.0.3.65.dist-info/entry_points.txt,sha256=ewBPU2vLnVexZVnB-NrVj-p3E-4vukg83Zk8A55Wp2w,56
116
- pytrilogy-0.0.3.65.dist-info/top_level.txt,sha256=cAy__NW_eMAa_yT9UnUNlZLFfxcg6eimUAZ184cdNiE,8
117
- pytrilogy-0.0.3.65.dist-info/RECORD,,
113
+ pytrilogy-0.0.3.66.dist-info/METADATA,sha256=cQJUWN4bTjEYsCxAcAOKmkzEkkmpxB7mBmMQPx0O4Cw,9095
114
+ pytrilogy-0.0.3.66.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
115
+ pytrilogy-0.0.3.66.dist-info/entry_points.txt,sha256=ewBPU2vLnVexZVnB-NrVj-p3E-4vukg83Zk8A55Wp2w,56
116
+ pytrilogy-0.0.3.66.dist-info/top_level.txt,sha256=cAy__NW_eMAa_yT9UnUNlZLFfxcg6eimUAZ184cdNiE,8
117
+ pytrilogy-0.0.3.66.dist-info/RECORD,,
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.65"
7
+ __version__ = "0.0.3.66"
8
8
 
9
9
  __all__ = ["parse", "Executor", "Dialects", "Environment", "CONFIG"]
@@ -271,6 +271,20 @@ class Conditional(Mergeable, ConceptArgs, Namespaced, DataTyped, BaseModel):
271
271
  right: Expr
272
272
  operator: BooleanOperator
273
273
 
274
+ @field_validator("left", mode="before")
275
+ @classmethod
276
+ def left_validator(cls, v, info: ValidationInfo):
277
+ if isinstance(v, Concept):
278
+ return v.reference
279
+ return v
280
+
281
+ @field_validator("right", mode="before")
282
+ @classmethod
283
+ def right_validator(cls, v, info: ValidationInfo):
284
+ if isinstance(v, Concept):
285
+ return v.reference
286
+ return v
287
+
274
288
  def __add__(self, other) -> "Conditional":
275
289
  if other is None:
276
290
  return self
@@ -346,7 +360,6 @@ class Conditional(Mergeable, ConceptArgs, Namespaced, DataTyped, BaseModel):
346
360
 
347
361
  @property
348
362
  def concept_arguments(self) -> Sequence[ConceptRef]:
349
- """Return concepts directly referenced in where clause"""
350
363
  output = []
351
364
  output += get_concept_arguments(self.left)
352
365
  output += get_concept_arguments(self.right)
@@ -575,11 +588,11 @@ class Comparison(ConceptArgs, Mergeable, DataTyped, Namespaced, BaseModel):
575
588
  date,
576
589
  Function,
577
590
  ConceptRef,
578
- "Conditional",
591
+ Conditional,
579
592
  DataType,
580
- "Comparison",
593
+ Comparison,
581
594
  FunctionCallWrapper,
582
- "Parenthetical",
595
+ Parenthetical,
583
596
  MagicConstants,
584
597
  WindowItem,
585
598
  AggregateWrapper,
@@ -1631,7 +1631,10 @@ class Factory:
1631
1631
 
1632
1632
  @build.register
1633
1633
  def _(self, base: CaseElse) -> BuildCaseElse:
1634
- return BuildCaseElse.model_construct(expr=self.build(base.expr))
1634
+ expr: Concept | FuncArgs = base.expr
1635
+ if isinstance(expr, (AggregateWrapper, FilterItem, WindowItem)):
1636
+ expr, _ = self.instantiate_concept(expr)
1637
+ return BuildCaseElse.model_construct(expr=self.build(expr))
1635
1638
 
1636
1639
  @build.register
1637
1640
  def _(self, base: Concept) -> BuildConcept:
@@ -395,6 +395,9 @@ def get_query_node(
395
395
  if not statement.output_components:
396
396
  raise ValueError(f"Statement has no output components {statement}")
397
397
  history = history or History(base_environment=environment)
398
+ print(
399
+ f"{LOGGER_PREFIX} building query node for {statement.output_components} grain {statement.grain}"
400
+ )
398
401
  build_statement: BuildSelectLineage | BuildMultiSelectLineage = Factory(
399
402
  environment=environment,
400
403
  ).build(statement)
trilogy/parsing/common.py CHANGED
@@ -23,9 +23,13 @@ from trilogy.core.models.author import (
23
23
  AggregateWrapper,
24
24
  AlignClause,
25
25
  AlignItem,
26
+ CaseElse,
27
+ CaseWhen,
28
+ Comparison,
26
29
  Concept,
27
30
  ConceptArgs,
28
31
  ConceptRef,
32
+ Conditional,
29
33
  FilterItem,
30
34
  Function,
31
35
  FunctionCallWrapper,
@@ -38,6 +42,7 @@ from trilogy.core.models.author import (
38
42
  Parenthetical,
39
43
  RowsetItem,
40
44
  RowsetLineage,
45
+ SubselectComparison,
41
46
  TraitDataType,
42
47
  UndefinedConcept,
43
48
  WhereClause,
@@ -198,6 +203,7 @@ def atom_is_relevant(
198
203
  others: list[Concept | ConceptRef],
199
204
  environment: Environment | None = None,
200
205
  ):
206
+
201
207
  if isinstance(atom, (ConceptRef, Concept)):
202
208
  # when we are looking at atoms, if there is a concept that is in others
203
209
  # return directly
@@ -210,9 +216,10 @@ def atom_is_relevant(
210
216
  elif isinstance(atom, AggregateWrapper):
211
217
  return any(atom_is_relevant(x, others, environment) for x in atom.by)
212
218
 
213
- if isinstance(atom, Function):
219
+ elif isinstance(atom, Function):
214
220
  relevant = False
215
221
  for arg in atom.arguments:
222
+
216
223
  relevant = relevant or atom_is_relevant(arg, others, environment)
217
224
  return relevant
218
225
  elif isinstance(atom, FunctionCallWrapper):
@@ -220,8 +227,27 @@ def atom_is_relevant(
220
227
  [atom_is_relevant(atom.content, others, environment)]
221
228
  + [atom_is_relevant(x, others, environment) for x in atom.args]
222
229
  )
230
+ elif isinstance(atom, CaseWhen):
231
+ rval = atom_is_relevant(atom.expr, others, environment) or atom_is_relevant(
232
+ atom.comparison, others, environment
233
+ )
234
+ return rval
235
+ elif isinstance(atom, CaseElse):
236
+
237
+ rval = atom_is_relevant(atom.expr, others, environment)
238
+ return rval
239
+ elif isinstance(atom, SubselectComparison):
240
+ return atom_is_relevant(atom.left, others, environment)
241
+ elif isinstance(atom, Comparison):
242
+ return atom_is_relevant(atom.left, others, environment) or atom_is_relevant(
243
+ atom.right, others, environment
244
+ )
245
+ elif isinstance(atom, Conditional):
246
+ return atom_is_relevant(atom.left, others, environment) or atom_is_relevant(
247
+ atom.right, others, environment
248
+ )
223
249
  elif isinstance(atom, ConceptArgs):
224
- # use atom is relevant here to trigger the early exit behavior for concpets in set
250
+ # use atom is relevant here to trigger the early exit behavior for concepts in set
225
251
  return any(
226
252
  [atom_is_relevant(x, others, environment) for x in atom.concept_arguments]
227
253
  )
@@ -233,7 +259,6 @@ def concept_is_relevant(
233
259
  others: list[Concept | ConceptRef],
234
260
  environment: Environment | None = None,
235
261
  ) -> bool:
236
-
237
262
  if isinstance(concept, UndefinedConcept):
238
263
  return False
239
264
  if concept.datatype == DataType.UNKNOWN:
trilogy/std/display.preql CHANGED
@@ -1,3 +1,6 @@
1
1
 
2
2
 
3
- type percent float; # Percentage value
3
+ type percent float; # Percentage value
4
+
5
+ def calc_percent(a, b, digits=-1) -> case when digits =-1 then (a/b):: float::percent
6
+ else round((a/b):: float::percent, digits) end;