pylegend 0.11.0__py3-none-any.whl → 0.13.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.
- pylegend/core/database/sql_to_string/db_extension.py +244 -6
- pylegend/core/language/legendql_api/legendql_api_custom_expressions.py +190 -5
- pylegend/core/language/pandas_api/pandas_api_series.py +3 -0
- pylegend/core/language/shared/expression.py +5 -0
- pylegend/core/language/shared/literal_expressions.py +22 -1
- pylegend/core/language/shared/operations/boolean_operation_expressions.py +144 -0
- pylegend/core/language/shared/operations/date_operation_expressions.py +91 -0
- pylegend/core/language/shared/operations/integer_operation_expressions.py +183 -1
- pylegend/core/language/shared/operations/string_operation_expressions.py +31 -1
- pylegend/core/language/shared/primitives/boolean.py +40 -0
- pylegend/core/language/shared/primitives/date.py +39 -0
- pylegend/core/language/shared/primitives/datetime.py +18 -0
- pylegend/core/language/shared/primitives/integer.py +54 -1
- pylegend/core/language/shared/primitives/strictdate.py +25 -1
- pylegend/core/language/shared/primitives/string.py +16 -2
- pylegend/core/sql/metamodel.py +54 -2
- pylegend/core/sql/metamodel_extension.py +77 -1
- pylegend/core/tds/legendql_api/frames/functions/legendql_api_distinct_function.py +53 -7
- pylegend/core/tds/legendql_api/frames/legendql_api_base_tds_frame.py +146 -4
- pylegend/core/tds/legendql_api/frames/legendql_api_tds_frame.py +33 -2
- pylegend/core/tds/pandas_api/frames/functions/assign_function.py +65 -23
- pylegend/core/tds/pandas_api/frames/functions/drop.py +3 -3
- pylegend/core/tds/pandas_api/frames/functions/dropna.py +167 -0
- pylegend/core/tds/pandas_api/frames/functions/fillna.py +162 -0
- pylegend/core/tds/pandas_api/frames/functions/filter.py +10 -5
- pylegend/core/tds/pandas_api/frames/functions/iloc.py +99 -0
- pylegend/core/tds/pandas_api/frames/functions/loc.py +136 -0
- pylegend/core/tds/pandas_api/frames/functions/truncate_function.py +151 -120
- pylegend/core/tds/pandas_api/frames/pandas_api_applied_function_tds_frame.py +7 -3
- pylegend/core/tds/pandas_api/frames/pandas_api_base_tds_frame.py +340 -34
- pylegend/core/tds/pandas_api/frames/pandas_api_tds_frame.py +90 -9
- pylegend/extensions/tds/pandas_api/frames/pandas_api_legend_function_input_frame.py +9 -4
- pylegend/extensions/tds/pandas_api/frames/pandas_api_legend_service_input_frame.py +12 -5
- pylegend/extensions/tds/pandas_api/frames/pandas_api_table_spec_input_frame.py +12 -4
- {pylegend-0.11.0.dist-info → pylegend-0.13.0.dist-info}/METADATA +1 -1
- {pylegend-0.11.0.dist-info → pylegend-0.13.0.dist-info}/RECORD +40 -36
- {pylegend-0.11.0.dist-info → pylegend-0.13.0.dist-info}/WHEEL +1 -1
- {pylegend-0.11.0.dist-info → pylegend-0.13.0.dist-info}/licenses/LICENSE +0 -0
- {pylegend-0.11.0.dist-info → pylegend-0.13.0.dist-info}/licenses/LICENSE.spdx +0 -0
- {pylegend-0.11.0.dist-info → pylegend-0.13.0.dist-info}/licenses/NOTICE +0 -0
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# Copyright 2026 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 typing import TYPE_CHECKING
|
|
16
|
+
|
|
17
|
+
import pandas as pd
|
|
18
|
+
|
|
19
|
+
from pylegend._typing import (
|
|
20
|
+
PyLegendUnion,
|
|
21
|
+
PyLegendSequence,
|
|
22
|
+
PyLegendTuple,
|
|
23
|
+
PyLegendCallable
|
|
24
|
+
)
|
|
25
|
+
from pylegend.core.language import PyLegendBoolean
|
|
26
|
+
from pylegend.core.tds.pandas_api.frames.functions.filtering import PandasApiFilteringFunction
|
|
27
|
+
from pylegend.core.tds.pandas_api.frames.pandas_api_applied_function_tds_frame import PandasApiAppliedFunctionTdsFrame
|
|
28
|
+
|
|
29
|
+
if TYPE_CHECKING:
|
|
30
|
+
from pylegend.core.tds.pandas_api.frames.pandas_api_base_tds_frame import PandasApiBaseTdsFrame
|
|
31
|
+
from pylegend.core.tds.pandas_api.frames.pandas_api_tds_frame import PandasApiTdsFrame
|
|
32
|
+
|
|
33
|
+
__all__: PyLegendSequence[str] = [
|
|
34
|
+
"PandasApiLocIndexer"
|
|
35
|
+
]
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class PandasApiLocIndexer:
|
|
39
|
+
_frame: "PandasApiBaseTdsFrame"
|
|
40
|
+
|
|
41
|
+
def __init__(self, frame: "PandasApiBaseTdsFrame") -> None:
|
|
42
|
+
self._frame = frame
|
|
43
|
+
|
|
44
|
+
def __getitem__( # type: ignore
|
|
45
|
+
self,
|
|
46
|
+
key: PyLegendUnion[
|
|
47
|
+
slice,
|
|
48
|
+
PyLegendBoolean,
|
|
49
|
+
PyLegendCallable[["PandasApiBaseTdsFrame"], PyLegendBoolean],
|
|
50
|
+
PyLegendTuple[
|
|
51
|
+
PyLegendUnion[slice, PyLegendBoolean, PyLegendCallable[["PandasApiBaseTdsFrame"], PyLegendBoolean]],
|
|
52
|
+
PyLegendUnion[str, slice, PyLegendSequence[str], PyLegendSequence[bool]]
|
|
53
|
+
]
|
|
54
|
+
]
|
|
55
|
+
) -> "PandasApiTdsFrame":
|
|
56
|
+
rows: PyLegendUnion[ # type: ignore
|
|
57
|
+
slice,
|
|
58
|
+
PyLegendBoolean,
|
|
59
|
+
PyLegendCallable[["PandasApiBaseTdsFrame"], PyLegendBoolean]
|
|
60
|
+
]
|
|
61
|
+
cols: PyLegendUnion[str, slice, PyLegendSequence[str], PyLegendSequence[bool]] # type: ignore
|
|
62
|
+
|
|
63
|
+
if isinstance(key, tuple):
|
|
64
|
+
if len(key) == 1:
|
|
65
|
+
rows, cols = key[0], slice(None, None, None)
|
|
66
|
+
elif len(key) == 2:
|
|
67
|
+
rows, cols = key[0], key[1]
|
|
68
|
+
else:
|
|
69
|
+
raise IndexError("Too many indexers")
|
|
70
|
+
else:
|
|
71
|
+
rows, cols = key, slice(None, None, None)
|
|
72
|
+
|
|
73
|
+
row_frame = self._handle_row_selection(rows)
|
|
74
|
+
return self._handle_column_selection(row_frame, cols)
|
|
75
|
+
|
|
76
|
+
def _handle_row_selection( # type: ignore
|
|
77
|
+
self,
|
|
78
|
+
rows: PyLegendUnion[slice, PyLegendBoolean, PyLegendCallable[["PandasApiBaseTdsFrame"], PyLegendBoolean]]
|
|
79
|
+
) -> "PandasApiTdsFrame":
|
|
80
|
+
if isinstance(rows, slice):
|
|
81
|
+
if rows.start is None and rows.stop is None and rows.step is None:
|
|
82
|
+
return self._frame
|
|
83
|
+
else:
|
|
84
|
+
raise TypeError(
|
|
85
|
+
"loc supports only ':' for row slicing. "
|
|
86
|
+
"Label-based slicing for rows is not supported."
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
if isinstance(rows, PyLegendBoolean):
|
|
90
|
+
return PandasApiAppliedFunctionTdsFrame(
|
|
91
|
+
PandasApiFilteringFunction(self._frame, filter_expr=rows)
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
if callable(rows):
|
|
95
|
+
new_key = rows(self._frame)
|
|
96
|
+
return self._handle_row_selection(new_key)
|
|
97
|
+
|
|
98
|
+
raise TypeError(f"Unsupported key type for .loc row selection: {type(rows)}")
|
|
99
|
+
|
|
100
|
+
def _handle_column_selection( # type: ignore
|
|
101
|
+
self,
|
|
102
|
+
frame: "PandasApiTdsFrame",
|
|
103
|
+
cols: PyLegendUnion[str, slice, PyLegendSequence[str], PyLegendSequence[bool]]
|
|
104
|
+
) -> "PandasApiTdsFrame":
|
|
105
|
+
if isinstance(cols, slice) and cols.start is None and cols.stop is None and cols.step is None:
|
|
106
|
+
return frame
|
|
107
|
+
|
|
108
|
+
if isinstance(cols, str):
|
|
109
|
+
return frame.filter(items=[cols])
|
|
110
|
+
|
|
111
|
+
if isinstance(cols, (list, tuple)):
|
|
112
|
+
all_columns = [c.get_name() for c in frame.columns()]
|
|
113
|
+
is_boolean_list = all(isinstance(k, bool) for k in cols)
|
|
114
|
+
|
|
115
|
+
if is_boolean_list:
|
|
116
|
+
if len(cols) != len(all_columns):
|
|
117
|
+
raise IndexError(f"Boolean index has wrong length: {len(cols)} instead of {len(all_columns)}")
|
|
118
|
+
selected_columns = [col for col, select in zip(all_columns, cols) if select]
|
|
119
|
+
return frame.filter(items=selected_columns)
|
|
120
|
+
else:
|
|
121
|
+
missing_cols = [c for c in cols if c not in all_columns]
|
|
122
|
+
if missing_cols:
|
|
123
|
+
raise KeyError(f"{missing_cols} not in index")
|
|
124
|
+
return frame.filter(items=cols) # type: ignore
|
|
125
|
+
|
|
126
|
+
if isinstance(cols, slice):
|
|
127
|
+
all_columns = [c.get_name() for c in frame.columns()]
|
|
128
|
+
pd_index = pd.Index(all_columns)
|
|
129
|
+
|
|
130
|
+
slicer = pd_index.slice_indexer(start=cols.start, end=cols.stop, step=cols.step)
|
|
131
|
+
selected_columns = pd_index[slicer].tolist()
|
|
132
|
+
if not selected_columns:
|
|
133
|
+
return frame.head(0)
|
|
134
|
+
return frame.filter(items=selected_columns)
|
|
135
|
+
|
|
136
|
+
raise TypeError(f"Unsupported key type for .loc column selection: {type(cols)}")
|
|
@@ -1,120 +1,151 @@
|
|
|
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
|
-
|
|
16
|
-
from datetime import date
|
|
17
|
-
from pylegend._typing import (
|
|
18
|
-
PyLegendList,
|
|
19
|
-
PyLegendSequence,
|
|
20
|
-
PyLegendUnion,
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
from pylegend.core.
|
|
25
|
-
from pylegend.core.tds.
|
|
26
|
-
from pylegend.core.tds.
|
|
27
|
-
from pylegend.core.tds.
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
self.
|
|
52
|
-
self.
|
|
53
|
-
self.
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
if
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
return self.__base_frame
|
|
74
|
-
|
|
75
|
-
def
|
|
76
|
-
return
|
|
77
|
-
|
|
78
|
-
def
|
|
79
|
-
return [
|
|
80
|
-
|
|
81
|
-
def
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
if self.
|
|
91
|
-
self.
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
)
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
if
|
|
119
|
-
|
|
120
|
-
|
|
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
|
+
|
|
16
|
+
from datetime import date
|
|
17
|
+
from pylegend._typing import (
|
|
18
|
+
PyLegendList,
|
|
19
|
+
PyLegendSequence,
|
|
20
|
+
PyLegendUnion,
|
|
21
|
+
PyLegendTuple,
|
|
22
|
+
PyLegendOptional,
|
|
23
|
+
)
|
|
24
|
+
from pylegend.core.sql.metamodel import LongLiteral, QuerySpecification
|
|
25
|
+
from pylegend.core.tds.pandas_api.frames.pandas_api_applied_function_tds_frame import PandasApiAppliedFunction
|
|
26
|
+
from pylegend.core.tds.pandas_api.frames.pandas_api_base_tds_frame import PandasApiBaseTdsFrame
|
|
27
|
+
from pylegend.core.tds.sql_query_helpers import create_sub_query, copy_query
|
|
28
|
+
from pylegend.core.tds.tds_column import TdsColumn
|
|
29
|
+
from pylegend.core.tds.tds_frame import FrameToPureConfig, FrameToSqlConfig
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class TruncateFunction(PandasApiAppliedFunction):
|
|
33
|
+
__base_frame: PandasApiBaseTdsFrame
|
|
34
|
+
__before: int
|
|
35
|
+
__after: PyLegendUnion[int, None]
|
|
36
|
+
__axis: PyLegendUnion[str, int]
|
|
37
|
+
__copy: bool
|
|
38
|
+
|
|
39
|
+
@classmethod
|
|
40
|
+
def name(cls) -> str:
|
|
41
|
+
return "truncate" # pragma: no cover
|
|
42
|
+
|
|
43
|
+
def __init__(
|
|
44
|
+
self,
|
|
45
|
+
base_frame: PandasApiBaseTdsFrame,
|
|
46
|
+
before: PyLegendUnion[date, str, int, None],
|
|
47
|
+
after: PyLegendUnion[date, str, int, None],
|
|
48
|
+
axis: PyLegendUnion[str, int],
|
|
49
|
+
copy: bool,
|
|
50
|
+
) -> None:
|
|
51
|
+
self.__base_frame = base_frame
|
|
52
|
+
self.__before_input = before
|
|
53
|
+
self.__after_input = after
|
|
54
|
+
self.__axis = axis
|
|
55
|
+
self.__copy = copy
|
|
56
|
+
|
|
57
|
+
def to_sql(self, config: FrameToSqlConfig) -> QuerySpecification:
|
|
58
|
+
base_query: QuerySpecification = self.__base_frame.to_sql_query_object(config)
|
|
59
|
+
should_create_sub_query = (base_query.offset is not None) or (base_query.limit is not None)
|
|
60
|
+
new_query = create_sub_query(base_query, config, "root") if should_create_sub_query else copy_query(base_query)
|
|
61
|
+
new_query.offset = LongLiteral(self.__before)
|
|
62
|
+
|
|
63
|
+
if self.__after is not None:
|
|
64
|
+
new_query.limit = LongLiteral(self.__after - self.__before + 1)
|
|
65
|
+
return new_query
|
|
66
|
+
|
|
67
|
+
def to_pure(self, config: FrameToPureConfig) -> str:
|
|
68
|
+
if self.__after is None:
|
|
69
|
+
return f"{self.__base_frame.to_pure(config)}{config.separator(1)}" f"->drop({self.__before})"
|
|
70
|
+
|
|
71
|
+
start_row = self.__before
|
|
72
|
+
end_row = self.__after + 1
|
|
73
|
+
return f"{self.__base_frame.to_pure(config)}{config.separator(1)}" f"->slice({start_row}, {end_row})"
|
|
74
|
+
|
|
75
|
+
def base_frame(self) -> PandasApiBaseTdsFrame:
|
|
76
|
+
return self.__base_frame
|
|
77
|
+
|
|
78
|
+
def tds_frame_parameters(self) -> PyLegendList["PandasApiBaseTdsFrame"]:
|
|
79
|
+
return []
|
|
80
|
+
|
|
81
|
+
def calculate_columns(self) -> PyLegendSequence["TdsColumn"]:
|
|
82
|
+
return [c.copy() for c in self.__base_frame.columns()]
|
|
83
|
+
|
|
84
|
+
def validate(self) -> bool:
|
|
85
|
+
if self.__axis not in [0, "index"]:
|
|
86
|
+
raise NotImplementedError(
|
|
87
|
+
f"The 'axis' parameter of the truncate function must be 0 or 'index', but got: {self.__axis}"
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
if self.__copy not in [True]:
|
|
91
|
+
raise NotImplementedError(f"The 'copy' parameter of the truncate function must be True, but got: {self.__copy}")
|
|
92
|
+
|
|
93
|
+
self.__before, self.__after = self.__normalize_before_and_after(self.__before_input, self.__after_input)
|
|
94
|
+
return True
|
|
95
|
+
|
|
96
|
+
@staticmethod
|
|
97
|
+
def __normalize_before_and_after(
|
|
98
|
+
before_input: PyLegendUnion[date, str, int, None],
|
|
99
|
+
after_input: PyLegendUnion[date, str, int, None]
|
|
100
|
+
) -> PyLegendTuple[int, PyLegendOptional[int]]:
|
|
101
|
+
|
|
102
|
+
if isinstance(before_input, (date, str)):
|
|
103
|
+
raise NotImplementedError(
|
|
104
|
+
f"The 'before' parameter of the truncate function must be of type integer or None, "
|
|
105
|
+
f"but got: before={before_input} (type: {type(before_input).__name__})")
|
|
106
|
+
|
|
107
|
+
if isinstance(after_input, (date, str)):
|
|
108
|
+
raise NotImplementedError(
|
|
109
|
+
f"The 'after' parameter of the truncate function must be of type integer or None, "
|
|
110
|
+
f"but got: after={after_input} (type: {type(after_input).__name__})")
|
|
111
|
+
|
|
112
|
+
def __raise_error_if_before_gt_after(before_input: int, after_input: int) -> None:
|
|
113
|
+
if before_input > after_input:
|
|
114
|
+
raise ValueError(
|
|
115
|
+
f"The 'before' parameter of the truncate function must be less than or equal to the 'after' parameter, "
|
|
116
|
+
f"but got: before={before_input}, after={after_input}")
|
|
117
|
+
|
|
118
|
+
if before_input is None:
|
|
119
|
+
if after_input is None:
|
|
120
|
+
return 0, None
|
|
121
|
+
|
|
122
|
+
if isinstance(after_input, int) and after_input >= 0:
|
|
123
|
+
return 0, after_input
|
|
124
|
+
|
|
125
|
+
if isinstance(after_input, int) and after_input < 0:
|
|
126
|
+
return 0, -1
|
|
127
|
+
|
|
128
|
+
if isinstance(before_input, int) and before_input >= 0:
|
|
129
|
+
if after_input is None:
|
|
130
|
+
return before_input, None
|
|
131
|
+
|
|
132
|
+
if isinstance(after_input, int) and after_input >= 0:
|
|
133
|
+
__raise_error_if_before_gt_after(before_input, after_input)
|
|
134
|
+
return before_input, after_input
|
|
135
|
+
|
|
136
|
+
if isinstance(after_input, int) and after_input < 0:
|
|
137
|
+
__raise_error_if_before_gt_after(before_input, after_input)
|
|
138
|
+
|
|
139
|
+
if isinstance(before_input, int) and before_input < 0:
|
|
140
|
+
if after_input is None:
|
|
141
|
+
return 0, None
|
|
142
|
+
|
|
143
|
+
if isinstance(after_input, int) and after_input >= 0:
|
|
144
|
+
__raise_error_if_before_gt_after(before_input, after_input)
|
|
145
|
+
return 0, after_input
|
|
146
|
+
|
|
147
|
+
if isinstance(after_input, int) and after_input < 0:
|
|
148
|
+
__raise_error_if_before_gt_after(before_input, after_input)
|
|
149
|
+
return 0, -1
|
|
150
|
+
|
|
151
|
+
return 0, 0 # pragma: no cover
|
|
@@ -13,16 +13,17 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
15
|
from abc import ABCMeta, abstractmethod
|
|
16
|
+
|
|
16
17
|
from pylegend._typing import (
|
|
17
18
|
PyLegendSequence,
|
|
18
19
|
PyLegendList,
|
|
20
|
+
PyLegendType
|
|
19
21
|
)
|
|
20
22
|
from pylegend.core.sql.metamodel import QuerySpecification
|
|
23
|
+
from pylegend.core.tds.pandas_api.frames.pandas_api_base_tds_frame import PandasApiBaseTdsFrame
|
|
21
24
|
from pylegend.core.tds.tds_column import TdsColumn
|
|
22
|
-
from pylegend.core.tds.tds_frame import FrameToSqlConfig
|
|
23
25
|
from pylegend.core.tds.tds_frame import FrameToPureConfig
|
|
24
|
-
from pylegend.core.tds.
|
|
25
|
-
|
|
26
|
+
from pylegend.core.tds.tds_frame import FrameToSqlConfig, PyLegendTdsFrame
|
|
26
27
|
|
|
27
28
|
__all__: PyLegendSequence[str] = [
|
|
28
29
|
"PandasApiAppliedFunctionTdsFrame",
|
|
@@ -69,6 +70,9 @@ class PandasApiAppliedFunctionTdsFrame(PandasApiBaseTdsFrame):
|
|
|
69
70
|
super().__init__(columns=applied_function.calculate_columns())
|
|
70
71
|
self.__applied_function = applied_function
|
|
71
72
|
|
|
73
|
+
def get_super_type(self) -> PyLegendType[PyLegendTdsFrame]:
|
|
74
|
+
return type(self) # pragma: no cover
|
|
75
|
+
|
|
72
76
|
def to_sql_query_object(self, config: FrameToSqlConfig) -> QuerySpecification:
|
|
73
77
|
return self.__applied_function.to_sql(config)
|
|
74
78
|
|