pylegend 0.2.2__py3-none-any.whl → 0.4.0__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.
Files changed (123) hide show
  1. pylegend/__init__.py +9 -5
  2. pylegend/core/{databse → database}/sql_to_string/__init__.py +3 -3
  3. pylegend/core/{databse → database}/sql_to_string/db_extension.py +11 -5
  4. pylegend/core/{databse → database}/sql_to_string/generator.py +2 -2
  5. pylegend/core/language/__init__.py +10 -10
  6. pylegend/core/language/legacy_api/__init__.py +13 -0
  7. pylegend/core/language/{aggregate_specification.py → legacy_api/aggregate_specification.py} +10 -10
  8. pylegend/core/language/legacy_api/legacy_api_tds_row.py +32 -0
  9. pylegend/core/language/legendql_api/__init__.py +13 -0
  10. pylegend/core/language/legendql_api/legendql_api_custom_expressions.py +541 -0
  11. pylegend/core/language/legendql_api/legendql_api_tds_row.py +292 -0
  12. pylegend/core/language/shared/__init__.py +13 -0
  13. pylegend/core/language/{column_expressions.py → shared/column_expressions.py} +32 -31
  14. pylegend/core/language/{expression.py → shared/expression.py} +8 -0
  15. pylegend/core/language/{functions.py → shared/functions.py} +3 -3
  16. pylegend/core/language/shared/helpers.py +75 -0
  17. pylegend/core/language/{literal_expressions.py → shared/literal_expressions.py} +39 -1
  18. pylegend/core/language/{operations → shared/operations}/binary_expression.py +34 -2
  19. pylegend/core/language/{operations → shared/operations}/boolean_operation_expressions.py +34 -6
  20. pylegend/core/language/{operations → shared/operations}/collection_operation_expressions.py +146 -26
  21. pylegend/core/language/{operations → shared/operations}/date_operation_expressions.py +164 -24
  22. pylegend/core/language/{operations → shared/operations}/float_operation_expressions.py +53 -8
  23. pylegend/core/language/{operations → shared/operations}/integer_operation_expressions.py +62 -9
  24. pylegend/core/language/{operations → shared/operations}/nullary_expression.py +9 -2
  25. pylegend/core/language/{operations → shared/operations}/number_operation_expressions.py +211 -30
  26. pylegend/core/language/{operations → shared/operations}/primitive_operation_expressions.py +42 -3
  27. pylegend/core/language/{operations → shared/operations}/string_operation_expressions.py +169 -21
  28. pylegend/core/language/{operations → shared/operations}/unary_expression.py +10 -2
  29. pylegend/core/language/{primitive_collection.py → shared/primitive_collection.py} +2 -2
  30. pylegend/core/language/{primitives → shared/primitives}/__init__.py +9 -9
  31. pylegend/core/language/{primitives → shared/primitives}/boolean.py +9 -5
  32. pylegend/core/language/{primitives → shared/primitives}/date.py +23 -15
  33. pylegend/core/language/{primitives → shared/primitives}/datetime.py +4 -5
  34. pylegend/core/language/{primitives → shared/primitives}/float.py +6 -6
  35. pylegend/core/language/{primitives → shared/primitives}/integer.py +6 -6
  36. pylegend/core/language/{primitives → shared/primitives}/number.py +16 -13
  37. pylegend/core/language/{primitives → shared/primitives}/primitive.py +25 -5
  38. pylegend/core/language/{primitives → shared/primitives}/strictdate.py +4 -5
  39. pylegend/core/language/{primitives → shared/primitives}/string.py +18 -19
  40. pylegend/core/language/{tds_row.py → shared/tds_row.py} +46 -16
  41. pylegend/core/request/__init__.py +8 -1
  42. pylegend/core/request/auth.py +89 -11
  43. pylegend/core/request/legend_client.py +32 -0
  44. pylegend/core/sql/metamodel_extension.py +16 -0
  45. pylegend/core/tds/abstract/__init__.py +13 -0
  46. pylegend/core/tds/abstract/frames/__init__.py +13 -0
  47. pylegend/core/tds/{legend_api/frames/legend_api_applied_function_tds_frame.py → abstract/frames/applied_function_tds_frame.py} +19 -13
  48. pylegend/core/tds/abstract/frames/base_tds_frame.py +125 -0
  49. pylegend/core/tds/{legend_api/frames/legend_api_input_tds_frame.py → abstract/frames/input_tds_frame.py} +9 -12
  50. pylegend/core/tds/{legend_api/frames/functions → abstract}/function_helpers.py +1 -1
  51. pylegend/core/tds/{legend_api/frames/functions/concatenate_function.py → legacy_api/frames/functions/legacy_api_concatenate_function.py} +25 -13
  52. pylegend/core/tds/{legend_api/frames/functions/distinct_function.py → legacy_api/frames/functions/legacy_api_distinct_function.py} +13 -8
  53. pylegend/core/tds/{legend_api/frames/functions/drop_function.py → legacy_api/frames/functions/legacy_api_drop_function.py} +13 -8
  54. pylegend/core/tds/{legend_api/frames/functions/extend_function.py → legacy_api/frames/functions/legacy_api_extend_function.py} +36 -16
  55. pylegend/core/tds/{legend_api/frames/functions/filter_function.py → legacy_api/frames/functions/legacy_api_filter_function.py} +25 -13
  56. pylegend/core/tds/{legend_api/frames/functions/group_by_function.py → legacy_api/frames/functions/legacy_api_group_by_function.py} +44 -17
  57. pylegend/core/tds/{legend_api/frames/functions/head_function.py → legacy_api/frames/functions/legacy_api_head_function.py} +13 -8
  58. pylegend/core/tds/{legend_api/frames/functions/join_by_columns_function.py → legacy_api/frames/functions/legacy_api_join_by_columns_function.py} +40 -13
  59. pylegend/core/tds/{legend_api/frames/functions/join_function.py → legacy_api/frames/functions/legacy_api_join_function.py} +44 -20
  60. pylegend/core/tds/{legend_api/frames/functions/rename_columns_function.py → legacy_api/frames/functions/legacy_api_rename_columns_function.py} +20 -8
  61. pylegend/core/tds/{legend_api/frames/functions/restrict_function.py → legacy_api/frames/functions/legacy_api_restrict_function.py} +17 -8
  62. pylegend/core/tds/{legend_api/frames/functions/slice_function.py → legacy_api/frames/functions/legacy_api_slice_function.py} +13 -8
  63. pylegend/core/tds/{legend_api/frames/functions/sort_function.py → legacy_api/frames/functions/legacy_api_sort_function.py} +19 -8
  64. pylegend/core/tds/legacy_api/frames/legacy_api_applied_function_tds_frame.py +37 -0
  65. pylegend/core/tds/legacy_api/frames/legacy_api_base_tds_frame.py +204 -0
  66. pylegend/core/tds/legacy_api/frames/legacy_api_input_tds_frame.py +51 -0
  67. pylegend/core/tds/{legend_api/frames/legend_api_tds_frame.py → legacy_api/frames/legacy_api_tds_frame.py} +28 -28
  68. pylegend/core/tds/legendql_api/__init__.py +13 -0
  69. pylegend/core/tds/legendql_api/frames/__init__.py +13 -0
  70. pylegend/core/tds/legendql_api/frames/functions/__init__.py +13 -0
  71. pylegend/core/tds/legendql_api/frames/functions/legendql_api_asofjoin_function.py +156 -0
  72. pylegend/core/tds/legendql_api/frames/functions/legendql_api_concatenate_function.py +139 -0
  73. pylegend/core/tds/legendql_api/frames/functions/legendql_api_distinct_function.py +69 -0
  74. pylegend/core/tds/legendql_api/frames/functions/legendql_api_drop_function.py +74 -0
  75. pylegend/core/tds/legendql_api/frames/functions/legendql_api_extend_function.py +256 -0
  76. pylegend/core/tds/legendql_api/frames/functions/legendql_api_filter_function.py +121 -0
  77. pylegend/core/tds/legendql_api/frames/functions/legendql_api_function_helpers.py +137 -0
  78. pylegend/core/tds/legendql_api/frames/functions/legendql_api_groupby_function.py +256 -0
  79. pylegend/core/tds/legendql_api/frames/functions/legendql_api_head_function.py +74 -0
  80. pylegend/core/tds/legendql_api/frames/functions/legendql_api_join_function.py +214 -0
  81. pylegend/core/tds/legendql_api/frames/functions/legendql_api_project_function.py +169 -0
  82. pylegend/core/tds/legendql_api/frames/functions/legendql_api_rename_function.py +189 -0
  83. pylegend/core/tds/legendql_api/frames/functions/legendql_api_select_function.py +131 -0
  84. pylegend/core/tds/legendql_api/frames/functions/legendql_api_slice_function.py +82 -0
  85. pylegend/core/tds/legendql_api/frames/functions/legendql_api_sort_function.py +93 -0
  86. pylegend/core/tds/legendql_api/frames/functions/legendql_api_window_extend_function.py +283 -0
  87. pylegend/core/tds/legendql_api/frames/legendql_api_applied_function_tds_frame.py +37 -0
  88. pylegend/core/tds/legendql_api/frames/legendql_api_base_tds_frame.py +419 -0
  89. pylegend/core/tds/legendql_api/frames/legendql_api_input_tds_frame.py +50 -0
  90. pylegend/core/tds/legendql_api/frames/legendql_api_tds_frame.py +327 -0
  91. pylegend/core/tds/pandas_api/frames/functions/assign_function.py +6 -6
  92. pylegend/core/tds/pandas_api/frames/pandas_api_applied_function_tds_frame.py +4 -0
  93. pylegend/core/tds/pandas_api/frames/pandas_api_base_tds_frame.py +11 -3
  94. pylegend/core/tds/pandas_api/frames/pandas_api_tds_frame.py +2 -2
  95. pylegend/core/tds/tds_frame.py +32 -2
  96. pylegend/extensions/database/vendors/postgres/postgres_sql_to_string.py +1 -1
  97. pylegend/extensions/tds/abstract/legend_function_input_frame.py +4 -0
  98. pylegend/extensions/tds/abstract/legend_service_input_frame.py +4 -0
  99. pylegend/extensions/tds/abstract/table_spec_input_frame.py +4 -0
  100. pylegend/extensions/tds/{legend_api/frames/legend_api_legend_function_input_frame.py → legacy_api/frames/legacy_api_legend_function_input_frame.py} +5 -5
  101. pylegend/extensions/tds/{legend_api/frames/legend_api_legend_service_input_frame.py → legacy_api/frames/legacy_api_legend_service_input_frame.py} +6 -6
  102. pylegend/extensions/tds/{legend_api/frames/legend_api_table_spec_input_frame.py → legacy_api/frames/legacy_api_table_spec_input_frame.py} +5 -5
  103. pylegend/extensions/tds/legendql_api/__init__.py +13 -0
  104. pylegend/extensions/tds/legendql_api/frames/__init__.py +13 -0
  105. pylegend/extensions/tds/legendql_api/frames/legendql_api_legend_service_input_frame.py +46 -0
  106. pylegend/extensions/tds/legendql_api/frames/legendql_api_table_spec_input_frame.py +36 -0
  107. pylegend/{legend_api_tds_client.py → legacy_api_tds_client.py} +15 -15
  108. {pylegend-0.2.2.dist-info → pylegend-0.4.0.dist-info}/METADATA +7 -8
  109. pylegend-0.4.0.dist-info/NOTICE +5 -0
  110. pylegend-0.4.0.dist-info/RECORD +155 -0
  111. {pylegend-0.2.2.dist-info → pylegend-0.4.0.dist-info}/WHEEL +1 -1
  112. pylegend/core/tds/legend_api/frames/legend_api_base_tds_frame.py +0 -294
  113. pylegend-0.2.2.dist-info/RECORD +0 -115
  114. /pylegend/core/{databse → database}/__init__.py +0 -0
  115. /pylegend/core/{databse → database}/sql_to_string/config.py +0 -0
  116. /pylegend/core/language/{operations → shared/operations}/__init__.py +0 -0
  117. /pylegend/core/tds/{legend_api → legacy_api}/__init__.py +0 -0
  118. /pylegend/core/tds/{legend_api → legacy_api}/frames/__init__.py +0 -0
  119. /pylegend/core/tds/{legend_api → legacy_api}/frames/functions/__init__.py +0 -0
  120. /pylegend/extensions/tds/{legend_api → legacy_api}/__init__.py +0 -0
  121. /pylegend/extensions/tds/{legend_api → legacy_api}/frames/__init__.py +0 -0
  122. {pylegend-0.2.2.dist-info → pylegend-0.4.0.dist-info}/LICENSE +0 -0
  123. {pylegend-0.2.2.dist-info → pylegend-0.4.0.dist-info}/LICENSE.spdx +0 -0
@@ -0,0 +1,541 @@
1
+ # Copyright 2025 Goldman Sachs
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ from abc import ABCMeta
16
+ from enum import Enum
17
+ from pylegend.core.language import (
18
+ PyLegendPrimitive,
19
+ PyLegendBoolean,
20
+ PyLegendString,
21
+ PyLegendNumber,
22
+ PyLegendInteger,
23
+ PyLegendFloat,
24
+ PyLegendDate,
25
+ PyLegendDateTime,
26
+ PyLegendStrictDate,
27
+ PyLegendColumnExpression,
28
+ PyLegendExpressionIntegerReturn,
29
+ PyLegendExpressionFloatReturn,
30
+ )
31
+ from pylegend._typing import (
32
+ PyLegendSequence,
33
+ PyLegendOptional,
34
+ PyLegendList,
35
+ PyLegendDict,
36
+ )
37
+ from pylegend.core.language.shared.helpers import escape_column_name
38
+ from pylegend.core.sql.metamodel import (
39
+ QuerySpecification,
40
+ Expression,
41
+ SingleColumn,
42
+ SortItem,
43
+ SortItemOrdering,
44
+ SortItemNullOrdering,
45
+ Window,
46
+ FunctionCall,
47
+ QualifiedName, IntegerLiteral
48
+ )
49
+ from pylegend.core.tds.tds_frame import FrameToSqlConfig, FrameToPureConfig
50
+ from typing import TYPE_CHECKING
51
+
52
+ __all__: PyLegendSequence[str] = [
53
+ "LegendQLApiPrimitive",
54
+ "LegendQLApiBoolean",
55
+ "LegendQLApiString",
56
+ "LegendQLApiNumber",
57
+ "LegendQLApiInteger",
58
+ "LegendQLApiFloat",
59
+ "LegendQLApiDate",
60
+ "LegendQLApiDateTime",
61
+ "LegendQLApiStrictDate",
62
+ "LegendQLApiSortInfo",
63
+ "LegendQLApiSortDirection",
64
+ "LegendQLApiWindow",
65
+ "LegendQLApiPartialFrame",
66
+ "LegendQLApiWindowReference",
67
+ ]
68
+
69
+
70
+ class LegendQLApiPrimitive(PyLegendPrimitive, metaclass=ABCMeta):
71
+ def ascending(self) -> "LegendQLApiSortInfo":
72
+ val = self.value()
73
+ if isinstance(val, PyLegendColumnExpression):
74
+ return LegendQLApiSortInfo(column_expr=val, direction=LegendQLApiSortDirection.ASC)
75
+ else:
76
+ raise RuntimeError("'ascending' function can only be called on column expressions. "
77
+ "E.g. - r.col1.ascending() / r['col1'].ascending()\n."
78
+ f"Found expression type - {type(val)}")
79
+
80
+ def descending(self) -> "LegendQLApiSortInfo":
81
+ val = self.value()
82
+ if isinstance(val, PyLegendColumnExpression):
83
+ return LegendQLApiSortInfo(column_expr=val, direction=LegendQLApiSortDirection.DESC)
84
+ else:
85
+ raise RuntimeError("'descending' function can only be called on column expressions. "
86
+ "E.g. - r.col1.descending() / r['col1'].descending()\n."
87
+ f"Found expression type - {type(val)}")
88
+
89
+
90
+ class LegendQLApiBoolean(LegendQLApiPrimitive, PyLegendBoolean):
91
+ def __init__(self, expr: PyLegendBoolean):
92
+ PyLegendBoolean.__init__(self, expr.value())
93
+
94
+
95
+ class LegendQLApiString(LegendQLApiPrimitive, PyLegendString):
96
+ def __init__(self, expr: PyLegendString):
97
+ PyLegendString.__init__(self, expr.value())
98
+
99
+
100
+ class LegendQLApiNumber(LegendQLApiPrimitive, PyLegendNumber):
101
+ def __init__(self, expr: PyLegendNumber):
102
+ PyLegendNumber.__init__(self, expr.value())
103
+
104
+
105
+ class LegendQLApiInteger(LegendQLApiPrimitive, PyLegendInteger):
106
+ def __init__(self, expr: PyLegendInteger):
107
+ PyLegendInteger.__init__(self, expr.value())
108
+
109
+
110
+ class LegendQLApiFloat(LegendQLApiPrimitive, PyLegendFloat):
111
+ def __init__(self, expr: PyLegendFloat):
112
+ PyLegendFloat.__init__(self, expr.value())
113
+
114
+
115
+ class LegendQLApiDate(LegendQLApiPrimitive, PyLegendDate):
116
+ def __init__(self, expr: PyLegendDate):
117
+ PyLegendDate.__init__(self, expr.value())
118
+
119
+
120
+ class LegendQLApiDateTime(LegendQLApiPrimitive, PyLegendDateTime):
121
+ def __init__(self, expr: PyLegendDateTime):
122
+ PyLegendDateTime.__init__(self, expr.value())
123
+
124
+
125
+ class LegendQLApiStrictDate(LegendQLApiPrimitive, PyLegendStrictDate):
126
+ def __init__(self, expr: PyLegendStrictDate):
127
+ PyLegendStrictDate.__init__(self, expr.value())
128
+
129
+
130
+ class LegendQLApiSortDirection(Enum):
131
+ ASC = 1,
132
+ DESC = 2
133
+
134
+
135
+ class LegendQLApiSortInfo:
136
+ __column: str
137
+ __direction: LegendQLApiSortDirection
138
+
139
+ def __init__(self, column_expr: PyLegendColumnExpression, direction: LegendQLApiSortDirection) -> None:
140
+ self.__column = column_expr.get_column()
141
+ self.__direction = direction
142
+
143
+ def to_sql_node(
144
+ self,
145
+ query: QuerySpecification,
146
+ config: FrameToSqlConfig
147
+ ) -> SortItem:
148
+ return SortItem(
149
+ sortKey=self.__find_column_expression(query, config),
150
+ ordering=(SortItemOrdering.ASCENDING if self.__direction == LegendQLApiSortDirection.ASC
151
+ else SortItemOrdering.DESCENDING),
152
+ nullOrdering=SortItemNullOrdering.UNDEFINED
153
+ )
154
+
155
+ def __find_column_expression(self, query: QuerySpecification, config: FrameToSqlConfig) -> Expression:
156
+ db_extension = config.sql_to_string_generator().get_db_extension()
157
+ filtered = [
158
+ s for s in query.select.selectItems
159
+ if (isinstance(s, SingleColumn) and
160
+ s.alias == db_extension.quote_identifier(self.__column))
161
+ ]
162
+ if len(filtered) == 0:
163
+ raise RuntimeError("Cannot find column: " + self.__column) # pragma: no cover
164
+ return filtered[0].expression
165
+
166
+ def to_pure_expression(self, config: FrameToPureConfig) -> str:
167
+ func = 'ascending' if self.__direction == LegendQLApiSortDirection.ASC else 'descending'
168
+ return f"{func}(~{escape_column_name(self.__column)})"
169
+
170
+
171
+ class LegendQLApiWindowFrame(metaclass=ABCMeta):
172
+ pass
173
+
174
+
175
+ class LegendQLApiWindow:
176
+ __partition_by: PyLegendOptional[PyLegendList[str]]
177
+ __order_by: PyLegendOptional[PyLegendList[LegendQLApiSortInfo]]
178
+ __frame: PyLegendOptional[LegendQLApiWindowFrame]
179
+
180
+ def __init__(
181
+ self,
182
+ partition_by: PyLegendOptional[PyLegendList[str]] = None,
183
+ order_by: PyLegendOptional[PyLegendList[LegendQLApiSortInfo]] = None,
184
+ frame: PyLegendOptional[LegendQLApiWindowFrame] = None
185
+ ) -> None:
186
+ self.__partition_by = partition_by
187
+ self.__order_by = order_by
188
+ self.__frame = frame
189
+
190
+ def get_partition_by(self) -> PyLegendOptional[PyLegendList[str]]:
191
+ return self.__partition_by
192
+
193
+ def get_order_by(self) -> PyLegendOptional[PyLegendList[LegendQLApiSortInfo]]:
194
+ return self.__order_by
195
+
196
+ def get_frame(self) -> PyLegendOptional[LegendQLApiWindowFrame]:
197
+ return self.__frame
198
+
199
+ def to_sql_node(
200
+ self,
201
+ query: QuerySpecification,
202
+ config: FrameToSqlConfig
203
+ ) -> Window:
204
+ return Window(
205
+ windowRef=None,
206
+ partitions=(
207
+ [] if self.__partition_by is None else
208
+ [LegendQLApiWindow.__find_column_expression(query, col, config) for col in self.__partition_by]
209
+ ),
210
+ orderBy=(
211
+ [] if self.__order_by is None else
212
+ [sort_info.to_sql_node(query, config) for sort_info in self.__order_by]
213
+ ),
214
+ windowFrame=None
215
+ )
216
+
217
+ @staticmethod
218
+ def __find_column_expression(query: QuerySpecification, col: str, config: FrameToSqlConfig) -> Expression:
219
+ db_extension = config.sql_to_string_generator().get_db_extension()
220
+ filtered = [
221
+ s for s in query.select.selectItems
222
+ if (isinstance(s, SingleColumn) and
223
+ s.alias == db_extension.quote_identifier(col))
224
+ ]
225
+ if len(filtered) == 0:
226
+ raise RuntimeError("Cannot find column: " + col) # pragma: no cover
227
+ return filtered[0].expression
228
+
229
+ def to_pure_expression(self, config: FrameToPureConfig) -> str:
230
+ partitions_str = (
231
+ "[]" if self.__partition_by is None or len(self.__partition_by) == 0
232
+ else "~[" + (', '.join(map(escape_column_name, self.__partition_by))) + "]"
233
+ )
234
+ sorts_str = (
235
+ "[]" if self.__order_by is None or len(self.__order_by) == 0
236
+ else "[" + (', '.join([s.to_pure_expression(config) for s in self.__order_by])) + "]"
237
+ )
238
+ return f"over({partitions_str}, {sorts_str})"
239
+
240
+
241
+ class LegendQLApiPartialFrame:
242
+ if TYPE_CHECKING:
243
+ from pylegend.core.tds.legendql_api.frames.legendql_api_base_tds_frame import LegendQLApiBaseTdsFrame
244
+ from pylegend.core.language.legendql_api.legendql_api_tds_row import LegendQLApiTdsRow
245
+
246
+ __base_frame: "LegendQLApiBaseTdsFrame"
247
+ __var_name: str
248
+
249
+ def __init__(self, base_frame: "LegendQLApiBaseTdsFrame", var_name: str) -> None:
250
+ self.__base_frame = base_frame
251
+ self.__var_name = var_name
252
+
253
+ def row_number(
254
+ self,
255
+ row: "LegendQLApiTdsRow"
256
+ ) -> PyLegendInteger:
257
+ return PyLegendInteger(LegendQLApiRowNumberExpression(self, row))
258
+
259
+ def rank(
260
+ self,
261
+ window: "LegendQLApiWindowReference",
262
+ row: "LegendQLApiTdsRow"
263
+ ) -> PyLegendInteger:
264
+ return PyLegendInteger(LegendQLApiRankExpression(self, window, row))
265
+
266
+ def dense_rank(
267
+ self,
268
+ window: "LegendQLApiWindowReference",
269
+ row: "LegendQLApiTdsRow"
270
+ ) -> PyLegendInteger:
271
+ return PyLegendInteger(LegendQLApiDenseRankExpression(self, window, row))
272
+
273
+ def percent_rank(
274
+ self,
275
+ window: "LegendQLApiWindowReference",
276
+ row: "LegendQLApiTdsRow"
277
+ ) -> PyLegendFloat:
278
+ return PyLegendFloat(LegendQLApiPercentRankExpression(self, window, row))
279
+
280
+ def cume_dist(
281
+ self,
282
+ window: "LegendQLApiWindowReference",
283
+ row: "LegendQLApiTdsRow"
284
+ ) -> PyLegendFloat:
285
+ return PyLegendFloat(LegendQLApiCumeDistExpression(self, window, row))
286
+
287
+ def ntile(
288
+ self,
289
+ row: "LegendQLApiTdsRow",
290
+ num_buckets: int
291
+ ) -> PyLegendInteger:
292
+ return PyLegendInteger(LegendQLApiNtileExpression(self, row, num_buckets))
293
+
294
+ def lead(
295
+ self,
296
+ row: "LegendQLApiTdsRow"
297
+ ) -> "LegendQLApiTdsRow":
298
+ from pylegend.core.language.legendql_api.legendql_api_tds_row import LegendQLApiLeadRow
299
+ return LegendQLApiLeadRow(self, row)
300
+
301
+ def lag(
302
+ self,
303
+ row: "LegendQLApiTdsRow"
304
+ ) -> "LegendQLApiTdsRow":
305
+ from pylegend.core.language.legendql_api.legendql_api_tds_row import LegendQLApiLagRow
306
+ return LegendQLApiLagRow(self, row)
307
+
308
+ def first(
309
+ self,
310
+ window: "LegendQLApiWindowReference",
311
+ row: "LegendQLApiTdsRow"
312
+ ) -> "LegendQLApiTdsRow":
313
+ from pylegend.core.language.legendql_api.legendql_api_tds_row import LegendQLApiFirstRow
314
+ return LegendQLApiFirstRow(self, window, row)
315
+
316
+ def last(
317
+ self,
318
+ window: "LegendQLApiWindowReference",
319
+ row: "LegendQLApiTdsRow"
320
+ ) -> "LegendQLApiTdsRow":
321
+ from pylegend.core.language.legendql_api.legendql_api_tds_row import LegendQLApiLastRow
322
+ return LegendQLApiLastRow(self, window, row)
323
+
324
+ def nth(
325
+ self,
326
+ window: "LegendQLApiWindowReference",
327
+ row: "LegendQLApiTdsRow",
328
+ offset: int
329
+ ) -> "LegendQLApiTdsRow":
330
+ from pylegend.core.language.legendql_api.legendql_api_tds_row import LegendQLApiNthRow
331
+ return LegendQLApiNthRow(self, window, row, offset)
332
+
333
+ def to_pure_expression(self, config: FrameToPureConfig) -> str:
334
+ return f"${self.__var_name}"
335
+
336
+ def get_base_frame(self) -> "LegendQLApiBaseTdsFrame":
337
+ return self.__base_frame
338
+
339
+
340
+ class LegendQLApiWindowReference:
341
+ __window: LegendQLApiWindow
342
+ __var_name: str
343
+
344
+ def __init__(self, window: LegendQLApiWindow, var_name: str) -> None:
345
+ self.__window = window
346
+ self.__var_name = var_name
347
+
348
+ def to_pure_expression(self, config: FrameToPureConfig) -> str:
349
+ return f"${self.__var_name}"
350
+
351
+
352
+ class LegendQLApiRowNumberExpression(PyLegendExpressionIntegerReturn):
353
+ if TYPE_CHECKING:
354
+ from pylegend.core.language.legendql_api.legendql_api_tds_row import LegendQLApiTdsRow
355
+
356
+ __partial_frame: LegendQLApiPartialFrame
357
+ __row: "LegendQLApiTdsRow"
358
+
359
+ def __init__(
360
+ self,
361
+ partial_frame: LegendQLApiPartialFrame,
362
+ row: "LegendQLApiTdsRow"
363
+ ) -> None:
364
+ self.__partial_frame = partial_frame
365
+ self.__row = row
366
+
367
+ def to_sql_expression(
368
+ self,
369
+ frame_name_to_base_query_map: PyLegendDict[str, QuerySpecification],
370
+ config: FrameToSqlConfig
371
+ ) -> Expression:
372
+ return FunctionCall(
373
+ name=QualifiedName(parts=["row_number"]), distinct=False, arguments=[], filter_=None, window=None
374
+ )
375
+
376
+ def to_pure_expression(self, config: FrameToPureConfig) -> str:
377
+ return f"{self.__partial_frame.to_pure_expression(config)}->rowNumber({self.__row.to_pure_expression(config)})"
378
+
379
+
380
+ class LegendQLApiRankExpression(PyLegendExpressionIntegerReturn):
381
+ if TYPE_CHECKING:
382
+ from pylegend.core.language.legendql_api.legendql_api_tds_row import LegendQLApiTdsRow
383
+
384
+ __partial_frame: LegendQLApiPartialFrame
385
+ __window_ref: "LegendQLApiWindowReference"
386
+ __row: "LegendQLApiTdsRow"
387
+
388
+ def __init__(
389
+ self,
390
+ partial_frame: LegendQLApiPartialFrame,
391
+ window_ref: "LegendQLApiWindowReference",
392
+ row: "LegendQLApiTdsRow"
393
+ ) -> None:
394
+ self.__partial_frame = partial_frame
395
+ self.__window_ref = window_ref
396
+ self.__row = row
397
+
398
+ def to_sql_expression(
399
+ self,
400
+ frame_name_to_base_query_map: PyLegendDict[str, QuerySpecification],
401
+ config: FrameToSqlConfig
402
+ ) -> Expression:
403
+ return FunctionCall(
404
+ name=QualifiedName(parts=["rank"]), distinct=False, arguments=[], filter_=None, window=None
405
+ )
406
+
407
+ def to_pure_expression(self, config: FrameToPureConfig) -> str:
408
+ return (f"{self.__partial_frame.to_pure_expression(config)}->rank("
409
+ f"{self.__window_ref.to_pure_expression(config)}, {self.__row.to_pure_expression(config)})")
410
+
411
+
412
+ class LegendQLApiDenseRankExpression(PyLegendExpressionIntegerReturn):
413
+ if TYPE_CHECKING:
414
+ from pylegend.core.language.legendql_api.legendql_api_tds_row import LegendQLApiTdsRow
415
+
416
+ __partial_frame: LegendQLApiPartialFrame
417
+ __window_ref: "LegendQLApiWindowReference"
418
+ __row: "LegendQLApiTdsRow"
419
+
420
+ def __init__(
421
+ self,
422
+ partial_frame: LegendQLApiPartialFrame,
423
+ window_ref: "LegendQLApiWindowReference",
424
+ row: "LegendQLApiTdsRow"
425
+ ) -> None:
426
+ self.__partial_frame = partial_frame
427
+ self.__window_ref = window_ref
428
+ self.__row = row
429
+
430
+ def to_sql_expression(
431
+ self,
432
+ frame_name_to_base_query_map: PyLegendDict[str, QuerySpecification],
433
+ config: FrameToSqlConfig
434
+ ) -> Expression:
435
+ return FunctionCall(
436
+ name=QualifiedName(parts=["dense_rank"]), distinct=False, arguments=[], filter_=None, window=None
437
+ )
438
+
439
+ def to_pure_expression(self, config: FrameToPureConfig) -> str:
440
+ return (f"{self.__partial_frame.to_pure_expression(config)}->denseRank("
441
+ f"{self.__window_ref.to_pure_expression(config)}, {self.__row.to_pure_expression(config)})")
442
+
443
+
444
+ class LegendQLApiPercentRankExpression(PyLegendExpressionFloatReturn):
445
+ if TYPE_CHECKING:
446
+ from pylegend.core.language.legendql_api.legendql_api_tds_row import LegendQLApiTdsRow
447
+
448
+ __partial_frame: LegendQLApiPartialFrame
449
+ __window_ref: "LegendQLApiWindowReference"
450
+ __row: "LegendQLApiTdsRow"
451
+
452
+ def __init__(
453
+ self,
454
+ partial_frame: LegendQLApiPartialFrame,
455
+ window_ref: "LegendQLApiWindowReference",
456
+ row: "LegendQLApiTdsRow"
457
+ ) -> None:
458
+ self.__partial_frame = partial_frame
459
+ self.__window_ref = window_ref
460
+ self.__row = row
461
+
462
+ def to_sql_expression(
463
+ self,
464
+ frame_name_to_base_query_map: PyLegendDict[str, QuerySpecification],
465
+ config: FrameToSqlConfig
466
+ ) -> Expression:
467
+ return FunctionCall(
468
+ name=QualifiedName(parts=["percent_rank"]), distinct=False, arguments=[], filter_=None, window=None
469
+ )
470
+
471
+ def to_pure_expression(self, config: FrameToPureConfig) -> str:
472
+ return (f"{self.__partial_frame.to_pure_expression(config)}->percentRank("
473
+ f"{self.__window_ref.to_pure_expression(config)}, {self.__row.to_pure_expression(config)})")
474
+
475
+
476
+ class LegendQLApiCumeDistExpression(PyLegendExpressionFloatReturn):
477
+ if TYPE_CHECKING:
478
+ from pylegend.core.language.legendql_api.legendql_api_tds_row import LegendQLApiTdsRow
479
+
480
+ __partial_frame: LegendQLApiPartialFrame
481
+ __window_ref: "LegendQLApiWindowReference"
482
+ __row: "LegendQLApiTdsRow"
483
+
484
+ def __init__(
485
+ self,
486
+ partial_frame: LegendQLApiPartialFrame,
487
+ window_ref: "LegendQLApiWindowReference",
488
+ row: "LegendQLApiTdsRow"
489
+ ) -> None:
490
+ self.__partial_frame = partial_frame
491
+ self.__window_ref = window_ref
492
+ self.__row = row
493
+
494
+ def to_sql_expression(
495
+ self,
496
+ frame_name_to_base_query_map: PyLegendDict[str, QuerySpecification],
497
+ config: FrameToSqlConfig
498
+ ) -> Expression:
499
+ return FunctionCall(
500
+ name=QualifiedName(parts=["cume_dist"]), distinct=False, arguments=[], filter_=None, window=None
501
+ )
502
+
503
+ def to_pure_expression(self, config: FrameToPureConfig) -> str:
504
+ return (f"{self.__partial_frame.to_pure_expression(config)}->cumulativeDistribution("
505
+ f"{self.__window_ref.to_pure_expression(config)}, {self.__row.to_pure_expression(config)})")
506
+
507
+
508
+ class LegendQLApiNtileExpression(PyLegendExpressionIntegerReturn):
509
+ if TYPE_CHECKING:
510
+ from pylegend.core.language.legendql_api.legendql_api_tds_row import LegendQLApiTdsRow
511
+
512
+ __partial_frame: LegendQLApiPartialFrame
513
+ __row: "LegendQLApiTdsRow"
514
+ __num_buckets: int
515
+
516
+ def __init__(
517
+ self,
518
+ partial_frame: LegendQLApiPartialFrame,
519
+ row: "LegendQLApiTdsRow",
520
+ num_buckets: int
521
+ ) -> None:
522
+ self.__partial_frame = partial_frame
523
+ self.__row = row
524
+ self.__num_buckets = num_buckets
525
+
526
+ def to_sql_expression(
527
+ self,
528
+ frame_name_to_base_query_map: PyLegendDict[str, QuerySpecification],
529
+ config: FrameToSqlConfig
530
+ ) -> Expression:
531
+ return FunctionCall(
532
+ name=QualifiedName(parts=["ntile"]),
533
+ distinct=False,
534
+ arguments=[IntegerLiteral(self.__num_buckets)],
535
+ filter_=None,
536
+ window=None
537
+ )
538
+
539
+ def to_pure_expression(self, config: FrameToPureConfig) -> str:
540
+ return (f"{self.__partial_frame.to_pure_expression(config)}->ntile({self.__row.to_pure_expression(config)}, "
541
+ f"{self.__num_buckets})")