pylegend 0.3.0__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 +7 -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 +7 -1
  42. pylegend/core/request/auth.py +55 -1
  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.3.0.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.3.0.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.3.0.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.3.0.dist-info → pylegend-0.4.0.dist-info}/LICENSE +0 -0
  123. {pylegend-0.3.0.dist-info → pylegend-0.4.0.dist-info}/LICENSE.spdx +0 -0
@@ -0,0 +1,37 @@
1
+ # Copyright 2023 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, abstractmethod
16
+ from pylegend._typing import (
17
+ PyLegendSequence,
18
+ )
19
+ from pylegend.core.tds.abstract.frames.applied_function_tds_frame import AppliedFunction, AppliedFunctionTdsFrame
20
+ from pylegend.core.tds.legacy_api.frames.legacy_api_base_tds_frame import LegacyApiBaseTdsFrame
21
+
22
+
23
+ __all__: PyLegendSequence[str] = [
24
+ "LegacyApiAppliedFunctionTdsFrame",
25
+ "LegacyApiAppliedFunction",
26
+ ]
27
+
28
+
29
+ class LegacyApiAppliedFunction(AppliedFunction, metaclass=ABCMeta):
30
+ @abstractmethod
31
+ def tds_frame_parameters(self) -> PyLegendSequence["LegacyApiBaseTdsFrame"]:
32
+ pass # pragma: no cover
33
+
34
+
35
+ class LegacyApiAppliedFunctionTdsFrame(LegacyApiBaseTdsFrame, AppliedFunctionTdsFrame):
36
+ def __init__(self, applied_function: LegacyApiAppliedFunction):
37
+ AppliedFunctionTdsFrame.__init__(self, applied_function)
@@ -0,0 +1,204 @@
1
+ # Copyright 2023 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
+
17
+ from pylegend._typing import (
18
+ PyLegendSequence,
19
+ PyLegendTypeVar,
20
+ PyLegendList,
21
+ PyLegendOptional,
22
+ PyLegendCallable,
23
+ PyLegendUnion,
24
+ )
25
+ from pylegend.core.language import (
26
+ LegacyApiTdsRow,
27
+ PyLegendBoolean,
28
+ PyLegendPrimitiveOrPythonPrimitive,
29
+ LegacyApiAggregateSpecification,
30
+ )
31
+ from pylegend.core.tds.abstract.frames.base_tds_frame import BaseTdsFrame
32
+ from pylegend.core.tds.legacy_api.frames.legacy_api_tds_frame import LegacyApiTdsFrame
33
+ from pylegend.core.tds.tds_column import TdsColumn
34
+
35
+ __all__: PyLegendSequence[str] = [
36
+ "LegacyApiBaseTdsFrame"
37
+ ]
38
+
39
+ R = PyLegendTypeVar('R')
40
+
41
+
42
+ class LegacyApiBaseTdsFrame(LegacyApiTdsFrame, BaseTdsFrame, metaclass=ABCMeta):
43
+
44
+ def __init__(self, columns: PyLegendSequence[TdsColumn]) -> None:
45
+ BaseTdsFrame.__init__(self, columns=columns)
46
+
47
+ def head(self, row_count: int = 5) -> "LegacyApiTdsFrame":
48
+ from pylegend.core.tds.legacy_api.frames.legacy_api_applied_function_tds_frame import (
49
+ LegacyApiAppliedFunctionTdsFrame
50
+ )
51
+ from pylegend.core.tds.legacy_api.frames.functions.legacy_api_head_function import (
52
+ LegacyApiHeadFunction
53
+ )
54
+ return LegacyApiAppliedFunctionTdsFrame(LegacyApiHeadFunction(self, row_count))
55
+
56
+ def take(self, row_count: int = 5) -> "LegacyApiTdsFrame":
57
+ return self.head(row_count=row_count)
58
+
59
+ def limit(self, row_count: int = 5) -> "LegacyApiTdsFrame":
60
+ return self.head(row_count=row_count)
61
+
62
+ def drop(self, row_count: int = 5) -> "LegacyApiTdsFrame":
63
+ from pylegend.core.tds.legacy_api.frames.legacy_api_applied_function_tds_frame import (
64
+ LegacyApiAppliedFunctionTdsFrame
65
+ )
66
+ from pylegend.core.tds.legacy_api.frames.functions.legacy_api_drop_function import (
67
+ LegacyApiDropFunction
68
+ )
69
+ return LegacyApiAppliedFunctionTdsFrame(LegacyApiDropFunction(self, row_count))
70
+
71
+ def slice(self, start_row: int, end_row_exclusive: int) -> "LegacyApiTdsFrame":
72
+ from pylegend.core.tds.legacy_api.frames.legacy_api_applied_function_tds_frame import (
73
+ LegacyApiAppliedFunctionTdsFrame
74
+ )
75
+ from pylegend.core.tds.legacy_api.frames.functions.legacy_api_slice_function import (
76
+ LegacyApiSliceFunction
77
+ )
78
+ return LegacyApiAppliedFunctionTdsFrame(LegacyApiSliceFunction(self, start_row, end_row_exclusive))
79
+
80
+ def distinct(self) -> "LegacyApiTdsFrame":
81
+ from pylegend.core.tds.legacy_api.frames.legacy_api_applied_function_tds_frame import (
82
+ LegacyApiAppliedFunctionTdsFrame
83
+ )
84
+ from pylegend.core.tds.legacy_api.frames.functions.legacy_api_distinct_function import (
85
+ LegacyApiDistinctFunction
86
+ )
87
+ return LegacyApiAppliedFunctionTdsFrame(LegacyApiDistinctFunction(self))
88
+
89
+ def restrict(self, column_name_list: PyLegendList[str]) -> "LegacyApiTdsFrame":
90
+ from pylegend.core.tds.legacy_api.frames.legacy_api_applied_function_tds_frame import (
91
+ LegacyApiAppliedFunctionTdsFrame
92
+ )
93
+ from pylegend.core.tds.legacy_api.frames.functions.legacy_api_restrict_function import (
94
+ LegacyApiRestrictFunction
95
+ )
96
+ return LegacyApiAppliedFunctionTdsFrame(LegacyApiRestrictFunction(self, column_name_list))
97
+
98
+ def sort(
99
+ self,
100
+ column_name_list: PyLegendList[str],
101
+ direction_list: PyLegendOptional[PyLegendList[str]] = None
102
+ ) -> "LegacyApiTdsFrame":
103
+ from pylegend.core.tds.legacy_api.frames.legacy_api_applied_function_tds_frame import (
104
+ LegacyApiAppliedFunctionTdsFrame
105
+ )
106
+ from pylegend.core.tds.legacy_api.frames.functions.legacy_api_sort_function import (
107
+ LegacyApiSortFunction
108
+ )
109
+ return LegacyApiAppliedFunctionTdsFrame(LegacyApiSortFunction(self, column_name_list, direction_list))
110
+
111
+ def concatenate(self, other: "LegacyApiTdsFrame") -> "LegacyApiTdsFrame":
112
+ from pylegend.core.tds.legacy_api.frames.legacy_api_applied_function_tds_frame import (
113
+ LegacyApiAppliedFunctionTdsFrame
114
+ )
115
+ from pylegend.core.tds.legacy_api.frames.functions.legacy_api_concatenate_function import (
116
+ LegacyApiConcatenateFunction
117
+ )
118
+ return LegacyApiAppliedFunctionTdsFrame(LegacyApiConcatenateFunction(self, other))
119
+
120
+ def rename_columns(
121
+ self,
122
+ column_names: PyLegendList[str],
123
+ renamed_column_names: PyLegendList[str]
124
+ ) -> "LegacyApiTdsFrame":
125
+ from pylegend.core.tds.legacy_api.frames.legacy_api_applied_function_tds_frame import (
126
+ LegacyApiAppliedFunctionTdsFrame
127
+ )
128
+ from pylegend.core.tds.legacy_api.frames.functions.legacy_api_rename_columns_function import (
129
+ LegacyApiRenameColumnsFunction
130
+ )
131
+ return LegacyApiAppliedFunctionTdsFrame(LegacyApiRenameColumnsFunction(self, column_names, renamed_column_names))
132
+
133
+ def filter(
134
+ self,
135
+ filter_function: PyLegendCallable[[LegacyApiTdsRow], PyLegendUnion[bool, PyLegendBoolean]]
136
+ ) -> "LegacyApiTdsFrame":
137
+ from pylegend.core.tds.legacy_api.frames.legacy_api_applied_function_tds_frame import (
138
+ LegacyApiAppliedFunctionTdsFrame
139
+ )
140
+ from pylegend.core.tds.legacy_api.frames.functions.legacy_api_filter_function import (
141
+ LegacyApiFilterFunction
142
+ )
143
+ return LegacyApiAppliedFunctionTdsFrame(LegacyApiFilterFunction(self, filter_function))
144
+
145
+ def extend(
146
+ self,
147
+ functions_list: PyLegendList[PyLegendCallable[[LegacyApiTdsRow], PyLegendPrimitiveOrPythonPrimitive]],
148
+ column_names_list: PyLegendList[str]
149
+ ) -> "LegacyApiTdsFrame":
150
+ from pylegend.core.tds.legacy_api.frames.legacy_api_applied_function_tds_frame import (
151
+ LegacyApiAppliedFunctionTdsFrame
152
+ )
153
+ from pylegend.core.tds.legacy_api.frames.functions.legacy_api_extend_function import (
154
+ LegacyApiExtendFunction
155
+ )
156
+ return LegacyApiAppliedFunctionTdsFrame(LegacyApiExtendFunction(self, functions_list, column_names_list))
157
+
158
+ def join(
159
+ self,
160
+ other: "LegacyApiTdsFrame",
161
+ join_condition: PyLegendCallable[[LegacyApiTdsRow, LegacyApiTdsRow], PyLegendUnion[bool, PyLegendBoolean]],
162
+ join_type: str = 'LEFT_OUTER'
163
+ ) -> "LegacyApiTdsFrame":
164
+ from pylegend.core.tds.legacy_api.frames.legacy_api_applied_function_tds_frame import (
165
+ LegacyApiAppliedFunctionTdsFrame
166
+ )
167
+ from pylegend.core.tds.legacy_api.frames.functions.legacy_api_join_function import (
168
+ LegacyApiJoinFunction
169
+ )
170
+ return LegacyApiAppliedFunctionTdsFrame(
171
+ LegacyApiJoinFunction(self, other, join_condition, join_type)
172
+ )
173
+
174
+ def join_by_columns(
175
+ self,
176
+ other: "LegacyApiTdsFrame",
177
+ self_columns: PyLegendList[str],
178
+ other_columns: PyLegendList[str],
179
+ join_type: str = 'LEFT_OUTER'
180
+ ) -> "LegacyApiTdsFrame":
181
+ from pylegend.core.tds.legacy_api.frames.legacy_api_applied_function_tds_frame import (
182
+ LegacyApiAppliedFunctionTdsFrame
183
+ )
184
+ from pylegend.core.tds.legacy_api.frames.functions.legacy_api_join_by_columns_function import (
185
+ LegacyApiJoinByColumnsFunction
186
+ )
187
+ return LegacyApiAppliedFunctionTdsFrame(
188
+ LegacyApiJoinByColumnsFunction(self, other, self_columns, other_columns, join_type)
189
+ )
190
+
191
+ def group_by(
192
+ self,
193
+ grouping_columns: PyLegendList[str],
194
+ aggregations: PyLegendList[LegacyApiAggregateSpecification],
195
+ ) -> "LegacyApiTdsFrame":
196
+ from pylegend.core.tds.legacy_api.frames.legacy_api_applied_function_tds_frame import (
197
+ LegacyApiAppliedFunctionTdsFrame
198
+ )
199
+ from pylegend.core.tds.legacy_api.frames.functions.legacy_api_group_by_function import (
200
+ LegacyApiGroupByFunction
201
+ )
202
+ return LegacyApiAppliedFunctionTdsFrame(
203
+ LegacyApiGroupByFunction(self, grouping_columns, aggregations)
204
+ )
@@ -0,0 +1,51 @@
1
+ # Copyright 2023 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 pylegend._typing import (
17
+ PyLegendSequence,
18
+ )
19
+ from pylegend.core.tds.abstract.frames.input_tds_frame import (
20
+ InputTdsFrame,
21
+ ExecutableInputTdsFrame,
22
+ NonExecutableInputTdsFrame,
23
+ )
24
+ from pylegend.core.tds.tds_column import TdsColumn
25
+ from pylegend.core.tds.legacy_api.frames.legacy_api_base_tds_frame import LegacyApiBaseTdsFrame
26
+ from pylegend.core.request.legend_client import LegendClient
27
+
28
+
29
+ __all__: PyLegendSequence[str] = [
30
+ "LegacyApiExecutableInputTdsFrame",
31
+ "LegacyApiNonExecutableInputTdsFrame",
32
+ "LegacyApiInputTdsFrame"
33
+ ]
34
+
35
+
36
+ class LegacyApiInputTdsFrame(LegacyApiBaseTdsFrame, InputTdsFrame, metaclass=ABCMeta):
37
+ def __init__(self, columns: PyLegendSequence[TdsColumn]) -> None:
38
+ LegacyApiBaseTdsFrame.__init__(self, columns=columns)
39
+ InputTdsFrame.__init__(self, columns=columns)
40
+
41
+
42
+ class LegacyApiExecutableInputTdsFrame(LegacyApiInputTdsFrame, ExecutableInputTdsFrame, metaclass=ABCMeta):
43
+ def __init__(self, legend_client: LegendClient, columns: PyLegendSequence[TdsColumn]) -> None:
44
+ LegacyApiInputTdsFrame.__init__(self, columns=columns)
45
+ ExecutableInputTdsFrame.__init__(self, legend_client=legend_client, columns=columns)
46
+
47
+
48
+ class LegacyApiNonExecutableInputTdsFrame(LegacyApiInputTdsFrame, NonExecutableInputTdsFrame, metaclass=ABCMeta):
49
+ def __init__(self, columns: PyLegendSequence[TdsColumn]) -> None:
50
+ LegacyApiInputTdsFrame.__init__(self, columns=columns)
51
+ NonExecutableInputTdsFrame.__init__(self, columns=columns)
@@ -24,45 +24,45 @@ from pylegend._typing import (
24
24
  PyLegendUnion,
25
25
  )
26
26
  from pylegend.core.language import (
27
- TdsRow,
27
+ LegacyApiTdsRow,
28
28
  PyLegendBoolean,
29
29
  PyLegendPrimitiveOrPythonPrimitive,
30
- AggregateSpecification,
30
+ LegacyApiAggregateSpecification,
31
31
  )
32
32
 
33
33
  __all__: PyLegendSequence[str] = [
34
- "LegendApiTdsFrame"
34
+ "LegacyApiTdsFrame"
35
35
  ]
36
36
 
37
37
 
38
- class LegendApiTdsFrame(PyLegendTdsFrame):
38
+ class LegacyApiTdsFrame(PyLegendTdsFrame):
39
39
 
40
40
  @abstractmethod
41
- def head(self, count: int = 5) -> "LegendApiTdsFrame":
41
+ def head(self, count: int = 5) -> "LegacyApiTdsFrame":
42
42
  pass # pragma: no cover
43
43
 
44
44
  @abstractmethod
45
- def take(self, count: int = 5) -> "LegendApiTdsFrame":
45
+ def take(self, count: int = 5) -> "LegacyApiTdsFrame":
46
46
  pass # pragma: no cover
47
47
 
48
48
  @abstractmethod
49
- def limit(self, count: int = 5) -> "LegendApiTdsFrame":
49
+ def limit(self, count: int = 5) -> "LegacyApiTdsFrame":
50
50
  pass # pragma: no cover
51
51
 
52
52
  @abstractmethod
53
- def drop(self, count: int = 5) -> "LegendApiTdsFrame":
53
+ def drop(self, count: int = 5) -> "LegacyApiTdsFrame":
54
54
  pass # pragma: no cover
55
55
 
56
56
  @abstractmethod
57
- def slice(self, start_row: int, end_row_exclusive: int) -> "LegendApiTdsFrame":
57
+ def slice(self, start_row: int, end_row_exclusive: int) -> "LegacyApiTdsFrame":
58
58
  pass # pragma: no cover
59
59
 
60
60
  @abstractmethod
61
- def distinct(self) -> "LegendApiTdsFrame":
61
+ def distinct(self) -> "LegacyApiTdsFrame":
62
62
  pass # pragma: no cover
63
63
 
64
64
  @abstractmethod
65
- def restrict(self, column_name_list: PyLegendList[str]) -> "LegendApiTdsFrame":
65
+ def restrict(self, column_name_list: PyLegendList[str]) -> "LegacyApiTdsFrame":
66
66
  pass # pragma: no cover
67
67
 
68
68
  @abstractmethod
@@ -70,11 +70,11 @@ class LegendApiTdsFrame(PyLegendTdsFrame):
70
70
  self,
71
71
  column_name_list: PyLegendList[str],
72
72
  direction_list: PyLegendOptional[PyLegendList[str]] = None
73
- ) -> "LegendApiTdsFrame":
73
+ ) -> "LegacyApiTdsFrame":
74
74
  pass # pragma: no cover
75
75
 
76
76
  @abstractmethod
77
- def concatenate(self, other: "LegendApiTdsFrame") -> "LegendApiTdsFrame":
77
+ def concatenate(self, other: "LegacyApiTdsFrame") -> "LegacyApiTdsFrame":
78
78
  pass # pragma: no cover
79
79
 
80
80
  @abstractmethod
@@ -82,55 +82,55 @@ class LegendApiTdsFrame(PyLegendTdsFrame):
82
82
  self,
83
83
  column_names: PyLegendList[str],
84
84
  renamed_column_names: PyLegendList[str]
85
- ) -> "LegendApiTdsFrame":
85
+ ) -> "LegacyApiTdsFrame":
86
86
  pass # pragma: no cover
87
87
 
88
88
  @abstractmethod
89
89
  def filter(
90
90
  self,
91
- filter_function: PyLegendCallable[[TdsRow], PyLegendUnion[bool, PyLegendBoolean]]
92
- ) -> "LegendApiTdsFrame":
91
+ filter_function: PyLegendCallable[[LegacyApiTdsRow], PyLegendUnion[bool, PyLegendBoolean]]
92
+ ) -> "LegacyApiTdsFrame":
93
93
  pass # pragma: no cover
94
94
 
95
95
  @abstractmethod
96
96
  def extend(
97
97
  self,
98
- functions_list: PyLegendList[PyLegendCallable[[TdsRow], PyLegendPrimitiveOrPythonPrimitive]],
98
+ functions_list: PyLegendList[PyLegendCallable[[LegacyApiTdsRow], PyLegendPrimitiveOrPythonPrimitive]],
99
99
  column_names_list: PyLegendList[str]
100
- ) -> "LegendApiTdsFrame":
100
+ ) -> "LegacyApiTdsFrame":
101
101
  pass # pragma: no cover
102
102
 
103
103
  @abstractmethod
104
104
  def join(
105
105
  self,
106
- other: "LegendApiTdsFrame",
107
- join_condition: PyLegendCallable[[TdsRow, TdsRow], PyLegendUnion[bool, PyLegendBoolean]],
106
+ other: "LegacyApiTdsFrame",
107
+ join_condition: PyLegendCallable[[LegacyApiTdsRow, LegacyApiTdsRow], PyLegendUnion[bool, PyLegendBoolean]],
108
108
  join_type: str = 'LEFT_OUTER'
109
- ) -> "LegendApiTdsFrame":
109
+ ) -> "LegacyApiTdsFrame":
110
110
  pass # pragma: no cover
111
111
 
112
112
  @abstractmethod
113
113
  def join_by_columns(
114
114
  self,
115
- other: "LegendApiTdsFrame",
115
+ other: "LegacyApiTdsFrame",
116
116
  self_columns: PyLegendList[str],
117
117
  other_columns: PyLegendList[str],
118
118
  join_type: str = 'LEFT_OUTER'
119
- ) -> "LegendApiTdsFrame":
119
+ ) -> "LegacyApiTdsFrame":
120
120
  pass # pragma: no cover
121
121
 
122
122
  def join_by_function(
123
123
  self,
124
- other: "LegendApiTdsFrame",
125
- join_condition: PyLegendCallable[[TdsRow, TdsRow], PyLegendUnion[bool, PyLegendBoolean]],
124
+ other: "LegacyApiTdsFrame",
125
+ join_condition: PyLegendCallable[[LegacyApiTdsRow, LegacyApiTdsRow], PyLegendUnion[bool, PyLegendBoolean]],
126
126
  join_type: str = 'LEFT_OUTER'
127
- ) -> "LegendApiTdsFrame":
127
+ ) -> "LegacyApiTdsFrame":
128
128
  return self.join(other, join_condition, join_type)
129
129
 
130
130
  @abstractmethod
131
131
  def group_by(
132
132
  self,
133
133
  grouping_columns: PyLegendList[str],
134
- aggregations: PyLegendList[AggregateSpecification],
135
- ) -> "LegendApiTdsFrame":
134
+ aggregations: PyLegendList[LegacyApiAggregateSpecification],
135
+ ) -> "LegacyApiTdsFrame":
136
136
  pass # pragma: no cover
@@ -0,0 +1,13 @@
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.
@@ -0,0 +1,13 @@
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.
@@ -0,0 +1,13 @@
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.
@@ -0,0 +1,156 @@
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 pylegend._typing import (
16
+ PyLegendList,
17
+ PyLegendSequence,
18
+ PyLegendUnion,
19
+ PyLegendCallable,
20
+ PyLegendOptional,
21
+ )
22
+ from pylegend.core.language import (
23
+ PyLegendBoolean,
24
+ PyLegendPrimitive,
25
+ convert_literal_to_literal_expression,
26
+ )
27
+ from pylegend.core.language.legendql_api.legendql_api_tds_row import LegendQLApiTdsRow
28
+ from pylegend.core.language.shared.helpers import generate_pure_lambda
29
+ from pylegend.core.sql.metamodel import (
30
+ QuerySpecification,
31
+ )
32
+ from pylegend.core.tds.legendql_api.frames.legendql_api_applied_function_tds_frame import LegendQLApiAppliedFunction
33
+ from pylegend.core.tds.legendql_api.frames.legendql_api_base_tds_frame import LegendQLApiBaseTdsFrame
34
+ from pylegend.core.tds.legendql_api.frames.legendql_api_tds_frame import LegendQLApiTdsFrame
35
+ from pylegend.core.tds.tds_column import TdsColumn
36
+ from pylegend.core.tds.tds_frame import FrameToPureConfig
37
+ from pylegend.core.tds.tds_frame import FrameToSqlConfig
38
+
39
+ __all__: PyLegendSequence[str] = [
40
+ "LegendQLApiAsOfJoinFunction"
41
+ ]
42
+
43
+
44
+ class LegendQLApiAsOfJoinFunction(LegendQLApiAppliedFunction):
45
+ __base_frame: LegendQLApiBaseTdsFrame
46
+ __other_frame: LegendQLApiBaseTdsFrame
47
+ __match_function: PyLegendCallable[[LegendQLApiTdsRow, LegendQLApiTdsRow], PyLegendUnion[bool, PyLegendBoolean]]
48
+ __join_condition: PyLegendOptional[
49
+ PyLegendCallable[[LegendQLApiTdsRow, LegendQLApiTdsRow], PyLegendUnion[bool, PyLegendBoolean]]
50
+ ]
51
+
52
+ @classmethod
53
+ def name(cls) -> str:
54
+ return "asOfJoin"
55
+
56
+ def __init__(
57
+ self,
58
+ base_frame: LegendQLApiBaseTdsFrame,
59
+ other_frame: LegendQLApiTdsFrame,
60
+ match_function: PyLegendCallable[[LegendQLApiTdsRow, LegendQLApiTdsRow], PyLegendUnion[bool, PyLegendBoolean]],
61
+ join_condition: PyLegendOptional[
62
+ PyLegendCallable[[LegendQLApiTdsRow, LegendQLApiTdsRow], PyLegendUnion[bool, PyLegendBoolean]]
63
+ ] = None
64
+ ) -> None:
65
+ self.__base_frame = base_frame
66
+ if not isinstance(other_frame, LegendQLApiBaseTdsFrame):
67
+ raise ValueError("Expected LegendQLApiBaseTdsFrame") # pragma: no cover
68
+ self.__other_frame = other_frame
69
+ self.__match_function = match_function
70
+ self.__join_condition = join_condition
71
+
72
+ def to_sql(self, config: FrameToSqlConfig) -> QuerySpecification:
73
+ raise RuntimeError("AsOfJoin SQL translation not supported yet")
74
+
75
+ def to_pure(self, config: FrameToPureConfig) -> str:
76
+ left_row = LegendQLApiTdsRow.from_tds_frame("l", self.__base_frame)
77
+ right_row = LegendQLApiTdsRow.from_tds_frame("r", self.__other_frame)
78
+ match_expr = self.__match_function(left_row, right_row)
79
+ match_string = (match_expr.to_pure_expression(config.push_indent(2))
80
+ if isinstance(match_expr, PyLegendPrimitive) else
81
+ convert_literal_to_literal_expression(match_expr).to_pure_expression(config.push_indent(2)))
82
+ if self.__join_condition is not None:
83
+ join_expr = self.__join_condition(left_row, right_row)
84
+ join_string = (join_expr.to_pure_expression(config.push_indent(2))
85
+ if isinstance(join_expr, PyLegendPrimitive) else
86
+ convert_literal_to_literal_expression(join_expr).to_pure_expression(config.push_indent(2)))
87
+ join_arg = (
88
+ f",{config.separator(2, True)}"
89
+ f"{generate_pure_lambda('l, r', join_string)}{config.separator(1)}"
90
+ )
91
+ else:
92
+ join_arg = f"{config.separator(1)}"
93
+
94
+ return (f"{self.__base_frame.to_pure(config)}{config.separator(1)}" +
95
+ f"->asOfJoin({config.separator(2)}"
96
+ f"{self.__other_frame.to_pure(config.push_indent(2))},{config.separator(2, True)}"
97
+ f"{generate_pure_lambda('l, r', match_string)}"
98
+ f"{join_arg}"
99
+ f")")
100
+
101
+ def base_frame(self) -> LegendQLApiBaseTdsFrame:
102
+ return self.__base_frame
103
+
104
+ def tds_frame_parameters(self) -> PyLegendList["LegendQLApiBaseTdsFrame"]:
105
+ return [self.__other_frame]
106
+
107
+ def calculate_columns(self) -> PyLegendSequence["TdsColumn"]:
108
+ return (
109
+ [c.copy() for c in self.__base_frame.columns()] +
110
+ [c.copy() for c in self.__other_frame.columns()]
111
+ )
112
+
113
+ def validate(self) -> bool:
114
+ copy = self.__match_function # For MyPy
115
+ if not isinstance(copy, type(lambda x: 0)) or (copy.__code__.co_argcount != 2):
116
+ raise TypeError("AsOfJoin match function should be a lambda which takes two arguments (TDSRow, TDSRow)")
117
+
118
+ left_row = LegendQLApiTdsRow.from_tds_frame("left", self.__base_frame)
119
+ right_row = LegendQLApiTdsRow.from_tds_frame("right", self.__other_frame)
120
+
121
+ try:
122
+ result = self.__match_function(left_row, right_row)
123
+ except Exception as e:
124
+ raise RuntimeError(
125
+ "AsOfJoin match function incompatible. Error occurred while evaluating. Message: " + str(e)
126
+ ) from e
127
+
128
+ if not isinstance(result, (bool, PyLegendBoolean)):
129
+ raise RuntimeError("AsOfJoin match function incompatible. Returns non boolean - " + str(type(result)))
130
+
131
+ if self.__join_condition is not None:
132
+ copy = self.__join_condition # For MyPy
133
+ if not isinstance(copy, type(lambda x: 0)) or (copy.__code__.co_argcount != 2):
134
+ raise TypeError("AsOfJoin join function should be a lambda which takes two arguments (TDSRow, TDSRow)")
135
+
136
+ try:
137
+ result = self.__join_condition(left_row, right_row)
138
+ except Exception as e:
139
+ raise RuntimeError(
140
+ "AsOfJoin join function incompatible. Error occurred while evaluating. Message: " + str(e)
141
+ ) from e
142
+
143
+ if not isinstance(result, (bool, PyLegendBoolean)):
144
+ raise RuntimeError("AsOfJoin join function incompatible. Returns non boolean - " + str(type(result)))
145
+
146
+ left_cols = [c.get_name() for c in self.__base_frame.columns()]
147
+ right_cols = [c.get_name() for c in self.__other_frame.columns()]
148
+
149
+ final_cols = left_cols + right_cols
150
+ if len(final_cols) != len(set(final_cols)):
151
+ raise ValueError(
152
+ "Found duplicate columns in joined frames. Use rename function to ensure there are no duplicate columns "
153
+ f"in joined frames. Columns - Left Frame: {left_cols}, Right Frame: {right_cols}"
154
+ )
155
+
156
+ return True