pytrilogy 0.0.3.109__py3-none-any.whl → 0.0.3.110__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,16 +1,14 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pytrilogy
3
- Version: 0.0.3.109
3
+ Version: 0.0.3.110
4
4
  Summary: Declarative, typed query language that compiles to SQL.
5
- Home-page:
6
- Author:
7
- Author-email: preql-community@gmail.com
8
5
  Classifier: Programming Language :: Python
9
6
  Classifier: Programming Language :: Python :: 3
10
7
  Classifier: Programming Language :: Python :: 3.9
11
8
  Classifier: Programming Language :: Python :: 3.10
12
9
  Classifier: Programming Language :: Python :: 3.11
13
10
  Classifier: Programming Language :: Python :: 3.12
11
+ Classifier: Programming Language :: Python :: 3.13
14
12
  Description-Content-Type: text/markdown
15
13
  License-File: LICENSE.md
16
14
  Requires-Dist: lark
@@ -30,14 +28,7 @@ Provides-Extra: snowflake
30
28
  Requires-Dist: snowflake-sqlalchemy; extra == "snowflake"
31
29
  Provides-Extra: ai
32
30
  Requires-Dist: httpx; extra == "ai"
33
- Dynamic: author-email
34
- Dynamic: classifier
35
- Dynamic: description
36
- Dynamic: description-content-type
37
31
  Dynamic: license-file
38
- Dynamic: provides-extra
39
- Dynamic: requires-dist
40
- Dynamic: summary
41
32
 
42
33
  # Trilogy
43
34
  **SQL with superpowers for analytics**
@@ -1,5 +1,5 @@
1
- pytrilogy-0.0.3.109.dist-info/licenses/LICENSE.md,sha256=5ZRvtTyCCFwz1THxDTjAu3Lidds9WjPvvzgVwPSYNDo,1042
2
- trilogy/__init__.py,sha256=KT6UoNoE4ZPq_JfCkzB6yZ8a543YyAWsBDGNZxY8LEg,304
1
+ pytrilogy-0.0.3.110.dist-info/licenses/LICENSE.md,sha256=5ZRvtTyCCFwz1THxDTjAu3Lidds9WjPvvzgVwPSYNDo,1042
2
+ trilogy/__init__.py,sha256=eQXK52ADInFKSjwAH2CwNZJ13e5H52e9Jr2wLo7cJkk,304
3
3
  trilogy/constants.py,sha256=g_zkVCNjGop6coZ1kM8eXXAzCnUN22ldx3TYFz0E9sc,1747
4
4
  trilogy/engine.py,sha256=3MiADf5MKcmxqiHBuRqiYdsXiLj7oitDfVvXvHrfjkA,2178
5
5
  trilogy/executor.py,sha256=-VeOV0bTGmchHRHpRwFJDyl8FElUxDpwUTUix7hhIFM,17429
@@ -95,12 +95,12 @@ trilogy/core/validation/datasource.py,sha256=nJeEFyb6iMBwlEVdYVy1vLzAbdRZwOsUjGx
95
95
  trilogy/core/validation/environment.py,sha256=ymvhQyt7jLK641JAAIQkqjQaAmr9C5022ILzYvDgPP0,2835
96
96
  trilogy/core/validation/fix.py,sha256=Z818UFNLxndMTLiyhB3doLxIfnOZ-16QGvVFWuD7UsA,3750
97
97
  trilogy/dialect/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
98
- trilogy/dialect/base.py,sha256=hFX0_3N-m3ZRTCyv1S650a8OPlx9qjp5Zh8wzTBx6E8,50338
98
+ trilogy/dialect/base.py,sha256=Qk4HkjKlnAnhcZwwLte9Arb_1pVnBmkgRlwRFX1A_GQ,50680
99
99
  trilogy/dialect/bigquery.py,sha256=XS3hpybeowgfrOrkycAigAF3NX2YUzTzfgE6f__2fT4,4316
100
- trilogy/dialect/common.py,sha256=cUI7JMmpG_A5KcaxRI-GoyqwLMD6jTf0JJhgcOdwQK4,5833
100
+ trilogy/dialect/common.py,sha256=n9sQeXQ0bOXHDN_jQRuxr1rG7xPBRwaizvSz16MjIDY,5663
101
101
  trilogy/dialect/config.py,sha256=olnyeVU5W5T6b9-dMeNAnvxuPlyc2uefb7FRME094Ec,3834
102
102
  trilogy/dialect/dataframe.py,sha256=RUbNgReEa9g3pL6H7fP9lPTrAij5pkqedpZ99D8_5AE,1522
103
- trilogy/dialect/duckdb.py,sha256=JoUvQ19WvgxoaJkGLM7DPXOd1H0394k3vBiblksQzOI,5631
103
+ trilogy/dialect/duckdb.py,sha256=cRPyqnuMgjhZVaW9BYA360p-5OXle_1Xt65Yy0Vzbr4,5901
104
104
  trilogy/dialect/enums.py,sha256=FRNYQ5-w-B6-X0yXKNU5g9GowsMlERFogTC5u2nxL_s,4740
105
105
  trilogy/dialect/metadata.py,sha256=p_V-MYPQ2iR6fcTjagnptCIWtsZe4fTfoS_iXpavPzY,7098
106
106
  trilogy/dialect/postgres.py,sha256=el2PKwfyvWGk5EZtLudqAH5ewLitY1sFHJiocBSyxyM,3393
@@ -132,8 +132,8 @@ trilogy/std/money.preql,sha256=XWwvAV3WxBsHX9zfptoYRnBigcfYwrYtBHXTME0xJuQ,2082
132
132
  trilogy/std/net.preql,sha256=WZCuvH87_rZntZiuGJMmBDMVKkdhTtxeHOkrXNwJ1EE,416
133
133
  trilogy/std/ranking.preql,sha256=LDoZrYyz4g3xsII9XwXfmstZD-_92i1Eox1UqkBIfi8,83
134
134
  trilogy/std/report.preql,sha256=LbV-XlHdfw0jgnQ8pV7acG95xrd1-p65fVpiIc-S7W4,202
135
- pytrilogy-0.0.3.109.dist-info/METADATA,sha256=U_r100YWYUQoWKW48qdPDL2eZVxvDOia7fKkfOOiK3I,13460
136
- pytrilogy-0.0.3.109.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
137
- pytrilogy-0.0.3.109.dist-info/entry_points.txt,sha256=ewBPU2vLnVexZVnB-NrVj-p3E-4vukg83Zk8A55Wp2w,56
138
- pytrilogy-0.0.3.109.dist-info/top_level.txt,sha256=cAy__NW_eMAa_yT9UnUNlZLFfxcg6eimUAZ184cdNiE,8
139
- pytrilogy-0.0.3.109.dist-info/RECORD,,
135
+ pytrilogy-0.0.3.110.dist-info/METADATA,sha256=WPrZFC0_2AmSkZqYb0Aefl8XPAlNXyQ3dohVqIGDicU,13289
136
+ pytrilogy-0.0.3.110.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
137
+ pytrilogy-0.0.3.110.dist-info/entry_points.txt,sha256=ewBPU2vLnVexZVnB-NrVj-p3E-4vukg83Zk8A55Wp2w,56
138
+ pytrilogy-0.0.3.110.dist-info/top_level.txt,sha256=cAy__NW_eMAa_yT9UnUNlZLFfxcg6eimUAZ184cdNiE,8
139
+ pytrilogy-0.0.3.110.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.109"
7
+ __version__ = "0.0.3.110"
8
8
 
9
9
  __all__ = ["parse", "Executor", "Dialects", "Environment", "CONFIG"]
trilogy/dialect/base.py CHANGED
@@ -17,6 +17,7 @@ from trilogy.core.enums import (
17
17
  DatePart,
18
18
  FunctionType,
19
19
  GroupMode,
20
+ Modifier,
20
21
  Ordering,
21
22
  ShowCategory,
22
23
  UnnestMode,
@@ -89,6 +90,14 @@ from trilogy.core.utility import safe_quote
89
90
  from trilogy.dialect.common import render_join, render_unnest
90
91
  from trilogy.hooks.base_hook import BaseHook
91
92
 
93
+
94
+ def null_wrapper(lval: str, rval: str, modifiers: list[Modifier]) -> str:
95
+
96
+ if Modifier.NULLABLE in modifiers:
97
+ return f"({lval} = {rval} or ({lval} is null and {rval} is null))"
98
+ return f"{lval} = {rval}"
99
+
100
+
92
101
  LOGGER_PREFIX = "[RENDERING]"
93
102
 
94
103
  WINDOW_ITEMS = (BuildWindowItem,)
@@ -353,6 +362,7 @@ class BaseDialect:
353
362
  UNNEST_MODE = UnnestMode.CROSS_APPLY
354
363
  GROUP_MODE = GroupMode.AUTO
355
364
  EXPLAIN_KEYWORD = "EXPLAIN"
365
+ NULL_WRAPPER = staticmethod(null_wrapper)
356
366
 
357
367
  def __init__(self, rendering: Rendering | None = None):
358
368
  self.rendering = rendering or CONFIG.rendering
@@ -964,6 +974,7 @@ class BaseDialect:
964
974
  cte,
965
975
  use_map=self.used_map,
966
976
  unnest_mode=self.UNNEST_MODE,
977
+ null_wrapper=self.NULL_WRAPPER,
967
978
  )
968
979
  for join in final_joins
969
980
  ]
trilogy/dialect/common.py CHANGED
@@ -18,13 +18,6 @@ from trilogy.core.models.execute import (
18
18
  )
19
19
 
20
20
 
21
- def null_wrapper(lval: str, rval: str, modifiers: list[Modifier]) -> str:
22
-
23
- if Modifier.NULLABLE in modifiers:
24
- return f"({lval} = {rval} or ({lval} is null and {rval} is null))"
25
- return f"{lval} = {rval}"
26
-
27
-
28
21
  def render_unnest(
29
22
  unnest_mode: UnnestMode,
30
23
  quote_character: str,
@@ -88,6 +81,7 @@ def render_join(
88
81
  ],
89
82
  cte: CTE,
90
83
  use_map: dict[str, set[str]],
84
+ null_wrapper: Callable[[str, str, list[Modifier]], str],
91
85
  unnest_mode: UnnestMode = UnnestMode.CROSS_APPLY,
92
86
  ) -> str | None:
93
87
  # {% for key in join.joinkeys %}{{ key.inner }} = {{ key.outer}}{% endfor %}
@@ -135,7 +129,7 @@ def render_join(
135
129
  join.inlined_ctes,
136
130
  use_map=use_map,
137
131
  ),
138
- modifiers=pair.modifiers
132
+ pair.modifiers
139
133
  + (pair.left.modifiers or [])
140
134
  + (pair.right.modifiers or []),
141
135
  )
trilogy/dialect/duckdb.py CHANGED
@@ -3,7 +3,7 @@ from typing import Any, Callable, Mapping
3
3
 
4
4
  from jinja2 import Template
5
5
 
6
- from trilogy.core.enums import FunctionType, UnnestMode, WindowType
6
+ from trilogy.core.enums import FunctionType, Modifier, UnnestMode, WindowType
7
7
  from trilogy.core.models.core import DataType
8
8
  from trilogy.dialect.base import BaseDialect
9
9
 
@@ -12,6 +12,17 @@ WINDOW_FUNCTION_MAP: Mapping[WindowType, Callable[[Any, Any, Any], str]] = {}
12
12
  SENTINAL_AUTO_CAPTURE_GROUP_VALUE = "-1"
13
13
 
14
14
 
15
+ def null_wrapper(
16
+ lval: str,
17
+ rval: str,
18
+ modifiers: list[Modifier],
19
+ ) -> str:
20
+
21
+ if Modifier.NULLABLE in modifiers:
22
+ return f"{lval} is not distinct from {rval}"
23
+ return f"{lval} = {rval}"
24
+
25
+
15
26
  def generate_regex_extract(x: list[str]) -> str:
16
27
  if str(x[2]) == SENTINAL_AUTO_CAPTURE_GROUP_VALUE:
17
28
  regex = re.compile(x[1])
@@ -151,3 +162,4 @@ class DuckDBDialect(BaseDialect):
151
162
  QUOTE_CHARACTER = '"'
152
163
  SQL_TEMPLATE = DUCKDB_TEMPLATE
153
164
  UNNEST_MODE = UnnestMode.DIRECT
165
+ NULL_WRAPPER = staticmethod(null_wrapper)