pylegend 0.12.0__py3-none-any.whl → 0.14.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 +177 -1
- pylegend/core/language/pandas_api/pandas_api_groupby_series.py +357 -0
- pylegend/core/language/pandas_api/pandas_api_series.py +202 -8
- 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 +50 -1
- pylegend/core/sql/metamodel_extension.py +77 -1
- pylegend/core/tds/pandas_api/frames/functions/aggregate_function.py +21 -11
- 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/pandas_api_applied_function_tds_frame.py +3 -0
- pylegend/core/tds/pandas_api/frames/pandas_api_base_tds_frame.py +50 -2
- pylegend/core/tds/pandas_api/frames/pandas_api_groupby_tds_frame.py +87 -27
- pylegend/core/tds/pandas_api/frames/pandas_api_tds_frame.py +12 -0
- {pylegend-0.12.0.dist-info → pylegend-0.14.0.dist-info}/METADATA +1 -1
- {pylegend-0.12.0.dist-info → pylegend-0.14.0.dist-info}/RECORD +30 -27
- {pylegend-0.12.0.dist-info → pylegend-0.14.0.dist-info}/WHEEL +1 -1
- {pylegend-0.12.0.dist-info → pylegend-0.14.0.dist-info}/licenses/LICENSE +0 -0
- {pylegend-0.12.0.dist-info → pylegend-0.14.0.dist-info}/licenses/LICENSE.spdx +0 -0
- {pylegend-0.12.0.dist-info → pylegend-0.14.0.dist-info}/licenses/NOTICE +0 -0
|
@@ -30,10 +30,15 @@ from pylegend.core.sql.metamodel import (
|
|
|
30
30
|
ArithmeticExpression,
|
|
31
31
|
NegativeExpression,
|
|
32
32
|
FunctionCall,
|
|
33
|
-
QualifiedName
|
|
33
|
+
QualifiedName,
|
|
34
|
+
BitwiseBinaryExpression,
|
|
35
|
+
BitwiseBinaryOperator,
|
|
36
|
+
BitwiseShiftExpression,
|
|
37
|
+
BitwiseShiftDirection
|
|
34
38
|
)
|
|
35
39
|
from pylegend.core.sql.metamodel_extension import (
|
|
36
40
|
AbsoluteExpression,
|
|
41
|
+
BitwiseNotExpression,
|
|
37
42
|
)
|
|
38
43
|
from pylegend.core.tds.tds_frame import FrameToSqlConfig
|
|
39
44
|
from pylegend.core.tds.tds_frame import FrameToPureConfig
|
|
@@ -47,6 +52,12 @@ __all__: PyLegendSequence[str] = [
|
|
|
47
52
|
"PyLegendIntegerMultiplyExpression",
|
|
48
53
|
"PyLegendIntegerModuloExpression",
|
|
49
54
|
"PyLegendIntegerCharExpression",
|
|
55
|
+
"PyLegendIntegerBitAndExpression",
|
|
56
|
+
"PyLegendIntegerBitOrExpression",
|
|
57
|
+
"PyLegendIntegerBitXorExpression",
|
|
58
|
+
"PyLegendIntegerBitShiftLeftExpression",
|
|
59
|
+
"PyLegendIntegerBitShiftRightExpression",
|
|
60
|
+
"PyLegendIntegerBitNotExpression"
|
|
50
61
|
]
|
|
51
62
|
|
|
52
63
|
|
|
@@ -253,3 +264,174 @@ class PyLegendIntegerCharExpression(PyLegendUnaryExpression, PyLegendExpressionS
|
|
|
253
264
|
non_nullable=True,
|
|
254
265
|
operand_needs_to_be_non_nullable=True,
|
|
255
266
|
)
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
class PyLegendIntegerBitAndExpression(PyLegendBinaryExpression, PyLegendExpressionIntegerReturn):
|
|
270
|
+
|
|
271
|
+
@staticmethod
|
|
272
|
+
def __to_sql_func(
|
|
273
|
+
expression1: Expression,
|
|
274
|
+
expression2: Expression,
|
|
275
|
+
frame_name_to_base_query_map: PyLegendDict[str, QuerySpecification],
|
|
276
|
+
config: FrameToSqlConfig
|
|
277
|
+
) -> Expression:
|
|
278
|
+
return BitwiseBinaryExpression(expression1, expression2, BitwiseBinaryOperator.AND)
|
|
279
|
+
|
|
280
|
+
@staticmethod
|
|
281
|
+
def __to_pure_func(op1_expr: str, op2_expr: str, config: FrameToPureConfig) -> str:
|
|
282
|
+
return generate_pure_functional_call("bitAnd", [op1_expr, op2_expr])
|
|
283
|
+
|
|
284
|
+
def __init__(self, operand1: PyLegendExpressionIntegerReturn, operand2: PyLegendExpressionIntegerReturn) -> None:
|
|
285
|
+
PyLegendExpressionIntegerReturn.__init__(self)
|
|
286
|
+
PyLegendBinaryExpression.__init__(
|
|
287
|
+
self,
|
|
288
|
+
operand1,
|
|
289
|
+
operand2,
|
|
290
|
+
PyLegendIntegerBitAndExpression.__to_sql_func,
|
|
291
|
+
PyLegendIntegerBitAndExpression.__to_pure_func,
|
|
292
|
+
non_nullable=True,
|
|
293
|
+
first_operand_needs_to_be_non_nullable=True,
|
|
294
|
+
second_operand_needs_to_be_non_nullable=True
|
|
295
|
+
)
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
class PyLegendIntegerBitOrExpression(PyLegendBinaryExpression, PyLegendExpressionIntegerReturn):
|
|
299
|
+
|
|
300
|
+
@staticmethod
|
|
301
|
+
def __to_sql_func(
|
|
302
|
+
expression1: Expression,
|
|
303
|
+
expression2: Expression,
|
|
304
|
+
frame_name_to_base_query_map: PyLegendDict[str, QuerySpecification],
|
|
305
|
+
config: FrameToSqlConfig
|
|
306
|
+
) -> Expression:
|
|
307
|
+
return BitwiseBinaryExpression(expression1, expression2, BitwiseBinaryOperator.OR)
|
|
308
|
+
|
|
309
|
+
@staticmethod
|
|
310
|
+
def __to_pure_func(op1_expr: str, op2_expr: str, config: FrameToPureConfig) -> str:
|
|
311
|
+
return generate_pure_functional_call("bitOr", [op1_expr, op2_expr])
|
|
312
|
+
|
|
313
|
+
def __init__(self, operand1: PyLegendExpressionIntegerReturn, operand2: PyLegendExpressionIntegerReturn) -> None:
|
|
314
|
+
PyLegendExpressionIntegerReturn.__init__(self)
|
|
315
|
+
PyLegendBinaryExpression.__init__(
|
|
316
|
+
self,
|
|
317
|
+
operand1,
|
|
318
|
+
operand2,
|
|
319
|
+
PyLegendIntegerBitOrExpression.__to_sql_func,
|
|
320
|
+
PyLegendIntegerBitOrExpression.__to_pure_func,
|
|
321
|
+
non_nullable=True,
|
|
322
|
+
first_operand_needs_to_be_non_nullable=True,
|
|
323
|
+
second_operand_needs_to_be_non_nullable=True
|
|
324
|
+
)
|
|
325
|
+
|
|
326
|
+
|
|
327
|
+
class PyLegendIntegerBitXorExpression(PyLegendBinaryExpression, PyLegendExpressionIntegerReturn):
|
|
328
|
+
|
|
329
|
+
@staticmethod
|
|
330
|
+
def __to_sql_func(
|
|
331
|
+
expression1: Expression,
|
|
332
|
+
expression2: Expression,
|
|
333
|
+
frame_name_to_base_query_map: PyLegendDict[str, QuerySpecification],
|
|
334
|
+
config: FrameToSqlConfig
|
|
335
|
+
) -> Expression:
|
|
336
|
+
return BitwiseBinaryExpression(expression1, expression2, BitwiseBinaryOperator.XOR)
|
|
337
|
+
|
|
338
|
+
@staticmethod
|
|
339
|
+
def __to_pure_func(op1_expr: str, op2_expr: str, config: FrameToPureConfig) -> str:
|
|
340
|
+
return generate_pure_functional_call("bitXor", [op1_expr, op2_expr])
|
|
341
|
+
|
|
342
|
+
def __init__(self, operand1: PyLegendExpressionIntegerReturn, operand2: PyLegendExpressionIntegerReturn) -> None:
|
|
343
|
+
PyLegendExpressionIntegerReturn.__init__(self)
|
|
344
|
+
PyLegendBinaryExpression.__init__(
|
|
345
|
+
self,
|
|
346
|
+
operand1,
|
|
347
|
+
operand2,
|
|
348
|
+
PyLegendIntegerBitXorExpression.__to_sql_func,
|
|
349
|
+
PyLegendIntegerBitXorExpression.__to_pure_func,
|
|
350
|
+
non_nullable=True,
|
|
351
|
+
first_operand_needs_to_be_non_nullable=True,
|
|
352
|
+
second_operand_needs_to_be_non_nullable=True
|
|
353
|
+
)
|
|
354
|
+
|
|
355
|
+
|
|
356
|
+
class PyLegendIntegerBitShiftLeftExpression(PyLegendBinaryExpression, PyLegendExpressionIntegerReturn):
|
|
357
|
+
|
|
358
|
+
@staticmethod
|
|
359
|
+
def __to_sql_func(
|
|
360
|
+
expression1: Expression,
|
|
361
|
+
expression2: Expression,
|
|
362
|
+
frame_name_to_base_query_map: PyLegendDict[str, QuerySpecification],
|
|
363
|
+
config: FrameToSqlConfig
|
|
364
|
+
) -> Expression:
|
|
365
|
+
return BitwiseShiftExpression(expression1, expression2, BitwiseShiftDirection.LEFT)
|
|
366
|
+
|
|
367
|
+
@staticmethod
|
|
368
|
+
def __to_pure_func(op1_expr: str, op2_expr: str, config: FrameToPureConfig) -> str:
|
|
369
|
+
return generate_pure_functional_call("bitShiftLeft", [op1_expr, op2_expr])
|
|
370
|
+
|
|
371
|
+
def __init__(self, operand1: PyLegendExpressionIntegerReturn, operand2: PyLegendExpressionIntegerReturn) -> None:
|
|
372
|
+
PyLegendExpressionIntegerReturn.__init__(self)
|
|
373
|
+
PyLegendBinaryExpression.__init__(
|
|
374
|
+
self,
|
|
375
|
+
operand1,
|
|
376
|
+
operand2,
|
|
377
|
+
PyLegendIntegerBitShiftLeftExpression.__to_sql_func,
|
|
378
|
+
PyLegendIntegerBitShiftLeftExpression.__to_pure_func,
|
|
379
|
+
non_nullable=True,
|
|
380
|
+
first_operand_needs_to_be_non_nullable=True,
|
|
381
|
+
second_operand_needs_to_be_non_nullable=True
|
|
382
|
+
)
|
|
383
|
+
|
|
384
|
+
|
|
385
|
+
class PyLegendIntegerBitShiftRightExpression(PyLegendBinaryExpression, PyLegendExpressionIntegerReturn):
|
|
386
|
+
|
|
387
|
+
@staticmethod
|
|
388
|
+
def __to_sql_func(
|
|
389
|
+
expression1: Expression,
|
|
390
|
+
expression2: Expression,
|
|
391
|
+
frame_name_to_base_query_map: PyLegendDict[str, QuerySpecification],
|
|
392
|
+
config: FrameToSqlConfig
|
|
393
|
+
) -> Expression:
|
|
394
|
+
return BitwiseShiftExpression(expression1, expression2, BitwiseShiftDirection.RIGHT)
|
|
395
|
+
|
|
396
|
+
@staticmethod
|
|
397
|
+
def __to_pure_func(op1_expr: str, op2_expr: str, config: FrameToPureConfig) -> str:
|
|
398
|
+
return generate_pure_functional_call("bitShiftRight", [op1_expr, op2_expr])
|
|
399
|
+
|
|
400
|
+
def __init__(self, operand1: PyLegendExpressionIntegerReturn, operand2: PyLegendExpressionIntegerReturn) -> None:
|
|
401
|
+
PyLegendExpressionIntegerReturn.__init__(self)
|
|
402
|
+
PyLegendBinaryExpression.__init__(
|
|
403
|
+
self,
|
|
404
|
+
operand1,
|
|
405
|
+
operand2,
|
|
406
|
+
PyLegendIntegerBitShiftRightExpression.__to_sql_func,
|
|
407
|
+
PyLegendIntegerBitShiftRightExpression.__to_pure_func,
|
|
408
|
+
non_nullable=True,
|
|
409
|
+
first_operand_needs_to_be_non_nullable=True,
|
|
410
|
+
second_operand_needs_to_be_non_nullable=True
|
|
411
|
+
)
|
|
412
|
+
|
|
413
|
+
|
|
414
|
+
class PyLegendIntegerBitNotExpression(PyLegendUnaryExpression, PyLegendExpressionIntegerReturn):
|
|
415
|
+
|
|
416
|
+
@staticmethod
|
|
417
|
+
def __to_sql_func(
|
|
418
|
+
expression: Expression,
|
|
419
|
+
frame_name_to_base_query_map: PyLegendDict[str, QuerySpecification],
|
|
420
|
+
config: FrameToSqlConfig
|
|
421
|
+
) -> Expression:
|
|
422
|
+
return BitwiseNotExpression(expression)
|
|
423
|
+
|
|
424
|
+
@staticmethod
|
|
425
|
+
def __to_pure_func(op_expr: str, config: FrameToPureConfig) -> str:
|
|
426
|
+
return generate_pure_functional_call("bitNot", [op_expr])
|
|
427
|
+
|
|
428
|
+
def __init__(self, operand: PyLegendExpressionIntegerReturn) -> None:
|
|
429
|
+
PyLegendExpressionIntegerReturn.__init__(self)
|
|
430
|
+
PyLegendUnaryExpression.__init__(
|
|
431
|
+
self,
|
|
432
|
+
operand,
|
|
433
|
+
PyLegendIntegerBitNotExpression.__to_sql_func,
|
|
434
|
+
PyLegendIntegerBitNotExpression.__to_pure_func,
|
|
435
|
+
non_nullable=True,
|
|
436
|
+
operand_needs_to_be_non_nullable=True,
|
|
437
|
+
)
|
|
@@ -92,7 +92,8 @@ __all__: PyLegendSequence[str] = [
|
|
|
92
92
|
"PyLegendStringSplitPartExpression",
|
|
93
93
|
"PyLegendStringRepeatStringExpression",
|
|
94
94
|
"PyLegendStringFullMatchExpression",
|
|
95
|
-
"PyLegendStringMatchExpression"
|
|
95
|
+
"PyLegendStringMatchExpression",
|
|
96
|
+
"PyLegendStringCoalesceExpression"
|
|
96
97
|
]
|
|
97
98
|
|
|
98
99
|
|
|
@@ -1149,6 +1150,35 @@ class PyLegendStringSplitPartExpression(PyLegendNaryExpression, PyLegendExpressi
|
|
|
1149
1150
|
)
|
|
1150
1151
|
|
|
1151
1152
|
|
|
1153
|
+
class PyLegendStringCoalesceExpression(PyLegendNaryExpression, PyLegendExpressionStringReturn):
|
|
1154
|
+
|
|
1155
|
+
@staticmethod
|
|
1156
|
+
def __to_sql_func(
|
|
1157
|
+
expressions: list[Expression],
|
|
1158
|
+
frame_name_to_base_query_map: PyLegendDict[str, QuerySpecification],
|
|
1159
|
+
config: FrameToSqlConfig
|
|
1160
|
+
) -> Expression:
|
|
1161
|
+
return FunctionCall(
|
|
1162
|
+
name=QualifiedName(parts=["COALESCE"]),
|
|
1163
|
+
distinct=False,
|
|
1164
|
+
arguments=expressions,
|
|
1165
|
+
filter_=None, window=None
|
|
1166
|
+
)
|
|
1167
|
+
|
|
1168
|
+
@staticmethod
|
|
1169
|
+
def __to_pure_func(op_expr: list[str], config: FrameToPureConfig) -> str:
|
|
1170
|
+
return generate_pure_functional_call("meta::pure::functions::flow::coalesce", op_expr)
|
|
1171
|
+
|
|
1172
|
+
def __init__(self, operands: list[PyLegendExpression]) -> None:
|
|
1173
|
+
PyLegendExpressionStringReturn.__init__(self)
|
|
1174
|
+
PyLegendNaryExpression.__init__(
|
|
1175
|
+
self,
|
|
1176
|
+
operands,
|
|
1177
|
+
PyLegendStringCoalesceExpression.__to_sql_func,
|
|
1178
|
+
PyLegendStringCoalesceExpression.__to_pure_func
|
|
1179
|
+
)
|
|
1180
|
+
|
|
1181
|
+
|
|
1152
1182
|
class PyLegendCurrentUserExpression(PyLegendNullaryExpression, PyLegendExpressionStringReturn):
|
|
1153
1183
|
|
|
1154
1184
|
@staticmethod
|
|
@@ -24,6 +24,11 @@ from pylegend.core.language.shared.operations.boolean_operation_expressions impo
|
|
|
24
24
|
PyLegendBooleanOrExpression,
|
|
25
25
|
PyLegendBooleanAndExpression,
|
|
26
26
|
PyLegendBooleanNotExpression,
|
|
27
|
+
PyLegendBooleanLessThanExpression,
|
|
28
|
+
PyLegendBooleanLessThanEqualExpression,
|
|
29
|
+
PyLegendBooleanGreaterThanExpression,
|
|
30
|
+
PyLegendBooleanGreaterThanEqualExpression,
|
|
31
|
+
PyLegendBooleanXorExpression,
|
|
27
32
|
)
|
|
28
33
|
from pylegend.core.sql.metamodel import (
|
|
29
34
|
Expression,
|
|
@@ -83,6 +88,41 @@ class PyLegendBoolean(PyLegendPrimitive):
|
|
|
83
88
|
def __invert__(self) -> "PyLegendBoolean":
|
|
84
89
|
return PyLegendBoolean(PyLegendBooleanNotExpression(self.__value))
|
|
85
90
|
|
|
91
|
+
def __lt__(self, other: PyLegendUnion[bool, "PyLegendBoolean"]) -> "PyLegendBoolean":
|
|
92
|
+
return self._create_binary_expression(other, PyLegendBooleanLessThanExpression, "less than (<)")
|
|
93
|
+
|
|
94
|
+
def __le__(self, other: PyLegendUnion[bool, "PyLegendBoolean"]) -> "PyLegendBoolean":
|
|
95
|
+
return self._create_binary_expression(other, PyLegendBooleanLessThanEqualExpression, "less than equal (<=)")
|
|
96
|
+
|
|
97
|
+
def __gt__(self, other: PyLegendUnion[bool, "PyLegendBoolean"]) -> "PyLegendBoolean":
|
|
98
|
+
return self._create_binary_expression(other, PyLegendBooleanGreaterThanExpression, "greater than (>)")
|
|
99
|
+
|
|
100
|
+
def __ge__(self, other: PyLegendUnion[bool, "PyLegendBoolean"]) -> "PyLegendBoolean":
|
|
101
|
+
return self._create_binary_expression(
|
|
102
|
+
other,
|
|
103
|
+
PyLegendBooleanGreaterThanEqualExpression,
|
|
104
|
+
"greater than equal (>=)")
|
|
105
|
+
|
|
106
|
+
def __xor__(self, other: PyLegendUnion[bool, "PyLegendBoolean"]) -> "PyLegendBoolean":
|
|
107
|
+
return self._create_binary_expression(other, PyLegendBooleanXorExpression, "xor (^)")
|
|
108
|
+
|
|
109
|
+
def __rxor__(self, other: PyLegendUnion[bool, "PyLegendBoolean"]) -> "PyLegendBoolean":
|
|
110
|
+
return self._create_binary_expression(other, PyLegendBooleanXorExpression, "xor (^)", reverse=True)
|
|
111
|
+
|
|
112
|
+
def _create_binary_expression(
|
|
113
|
+
self,
|
|
114
|
+
other: PyLegendUnion[bool, "PyLegendBoolean"],
|
|
115
|
+
expression_class: type,
|
|
116
|
+
operation_name: str,
|
|
117
|
+
reverse: bool = False
|
|
118
|
+
) -> "PyLegendBoolean":
|
|
119
|
+
PyLegendBoolean.__validate__param_to_be_bool(other, f"Boolean {operation_name} parameter")
|
|
120
|
+
other_op = PyLegendBooleanLiteralExpression(other) if isinstance(other, bool) else other.__value
|
|
121
|
+
|
|
122
|
+
if reverse:
|
|
123
|
+
return PyLegendBoolean(expression_class(other_op, self.__value))
|
|
124
|
+
return PyLegendBoolean(expression_class(self.__value, other_op))
|
|
125
|
+
|
|
86
126
|
@staticmethod
|
|
87
127
|
def __validate__param_to_be_bool(param: PyLegendUnion[bool, "PyLegendBoolean"], desc: str) -> None:
|
|
88
128
|
if not isinstance(param, (bool, PyLegendBoolean)):
|
|
@@ -28,6 +28,8 @@ from pylegend.core.language.shared.expression import (
|
|
|
28
28
|
from pylegend.core.language.shared.literal_expressions import (
|
|
29
29
|
PyLegendDateTimeLiteralExpression,
|
|
30
30
|
PyLegendStrictDateLiteralExpression,
|
|
31
|
+
PyLegendIntegerLiteralExpression,
|
|
32
|
+
PyLegendStringLiteralExpression,
|
|
31
33
|
)
|
|
32
34
|
from pylegend.core.language.shared.operations.date_operation_expressions import (
|
|
33
35
|
PyLegendFirstDayOfYearExpression,
|
|
@@ -54,6 +56,8 @@ from pylegend.core.language.shared.operations.date_operation_expressions import
|
|
|
54
56
|
PyLegendDateLessThanEqualExpression,
|
|
55
57
|
PyLegendDateGreaterThanExpression,
|
|
56
58
|
PyLegendDateGreaterThanEqualExpression,
|
|
59
|
+
PyLegendDateAdjustExpression,
|
|
60
|
+
PyLegendDateDiffExpression,
|
|
57
61
|
)
|
|
58
62
|
from pylegend.core.sql.metamodel import (
|
|
59
63
|
Expression,
|
|
@@ -158,6 +162,23 @@ class PyLegendDate(PyLegendPrimitive):
|
|
|
158
162
|
from pylegend.core.language.shared.primitives.strictdate import PyLegendStrictDate
|
|
159
163
|
return PyLegendStrictDate(PyLegendDatePartExpression(self.__value))
|
|
160
164
|
|
|
165
|
+
def timedelta(self, number: PyLegendUnion[int, "PyLegendInteger"], duration_unit: str) -> "PyLegendDate":
|
|
166
|
+
self.validate_param_to_be_int_or_int_expr(number, "timedelta number parameter")
|
|
167
|
+
number_op = PyLegendIntegerLiteralExpression(number) if isinstance(number, int) else number.value()
|
|
168
|
+
self.validate_duration_unit_param(duration_unit)
|
|
169
|
+
duration_unit_op = PyLegendStringLiteralExpression(duration_unit.upper())
|
|
170
|
+
return PyLegendDate(PyLegendDateAdjustExpression([self.__value, number_op, duration_unit_op]))
|
|
171
|
+
|
|
172
|
+
def diff(
|
|
173
|
+
self,
|
|
174
|
+
other: PyLegendUnion[date, datetime, "PyLegendStrictDate", "PyLegendDateTime", "PyLegendDate"],
|
|
175
|
+
duration_unit: str) -> "PyLegendInteger":
|
|
176
|
+
self.validate_param_to_be_date(other, "Diff parameter")
|
|
177
|
+
other_op = PyLegendDate.__convert_to_date_expr(other)
|
|
178
|
+
self.validate_duration_unit_param(duration_unit)
|
|
179
|
+
duration_unit_op = PyLegendStringLiteralExpression(duration_unit.upper())
|
|
180
|
+
return PyLegendInteger(PyLegendDateDiffExpression([self.__value, other_op, duration_unit_op]))
|
|
181
|
+
|
|
161
182
|
def __lt__(
|
|
162
183
|
self,
|
|
163
184
|
other: PyLegendUnion[date, datetime, "PyLegendStrictDate", "PyLegendDateTime", "PyLegendDate"]
|
|
@@ -211,3 +232,21 @@ class PyLegendDate(PyLegendPrimitive):
|
|
|
211
232
|
raise TypeError(desc + " should be a datetime.date/datetime.datetime or a Date expression"
|
|
212
233
|
" (PyLegendDateTime/PyLegendStrictDate/PyLegendDate)."
|
|
213
234
|
" Got value " + str(param) + " of type: " + str(type(param)))
|
|
235
|
+
|
|
236
|
+
@staticmethod
|
|
237
|
+
def validate_duration_unit_param(duration_unit: str) -> None:
|
|
238
|
+
if duration_unit.lower() not in ('years', 'months', 'weeks', 'days', 'hours', 'minutes', 'seconds',
|
|
239
|
+
'milliseconds', 'microseconds', 'nanoseconds'):
|
|
240
|
+
raise ValueError(
|
|
241
|
+
f"Unknown duration unit - {duration_unit}. Supported values are - YEARS, MONTHS, WEEKS, DAYS, HOURS,"
|
|
242
|
+
" MINUTES, SECONDS, MILLISECONDS, MICROSECONDS, NANOSECONDS"
|
|
243
|
+
)
|
|
244
|
+
|
|
245
|
+
@staticmethod
|
|
246
|
+
def validate_param_to_be_int_or_int_expr(
|
|
247
|
+
param: PyLegendUnion[int, "PyLegendInteger"],
|
|
248
|
+
desc: str
|
|
249
|
+
) -> None:
|
|
250
|
+
if not isinstance(param, (int, PyLegendInteger)):
|
|
251
|
+
raise TypeError(desc + " should be a int or an integer expression (PyLegendInteger)."
|
|
252
|
+
" Got value " + str(param) + " of type: " + str(type(param)))
|
|
@@ -18,12 +18,16 @@ from pylegend._typing import (
|
|
|
18
18
|
PyLegendDict,
|
|
19
19
|
PyLegendUnion,
|
|
20
20
|
)
|
|
21
|
+
from pylegend.core.language.shared.operations.date_operation_expressions import PyLegendDateTimeBucketExpression
|
|
22
|
+
from pylegend.core.language.shared.primitives.integer import PyLegendInteger
|
|
21
23
|
from pylegend.core.language.shared.primitives.date import PyLegendDate
|
|
22
24
|
from pylegend.core.language.shared.expression import (
|
|
23
25
|
PyLegendExpressionDateTimeReturn,
|
|
24
26
|
)
|
|
25
27
|
from pylegend.core.language.shared.literal_expressions import (
|
|
26
28
|
PyLegendDateTimeLiteralExpression,
|
|
29
|
+
PyLegendIntegerLiteralExpression,
|
|
30
|
+
PyLegendStringLiteralExpression,
|
|
27
31
|
)
|
|
28
32
|
from pylegend.core.sql.metamodel import (
|
|
29
33
|
Expression,
|
|
@@ -57,6 +61,20 @@ class PyLegendDateTime(PyLegendDate):
|
|
|
57
61
|
def value(self) -> PyLegendExpressionDateTimeReturn:
|
|
58
62
|
return self.__value
|
|
59
63
|
|
|
64
|
+
def time_bucket(
|
|
65
|
+
self,
|
|
66
|
+
quantity: PyLegendUnion[int, "PyLegendInteger"],
|
|
67
|
+
duration_unit: str) -> "PyLegendDate":
|
|
68
|
+
self.validate_param_to_be_int_or_int_expr(quantity, "time bucket quantity parameter")
|
|
69
|
+
quantity_op = PyLegendIntegerLiteralExpression(quantity) if isinstance(quantity, int) else quantity.value()
|
|
70
|
+
self.validate_duration_unit_param(duration_unit)
|
|
71
|
+
duration_unit_op = PyLegendStringLiteralExpression(duration_unit.upper())
|
|
72
|
+
return PyLegendDate(PyLegendDateTimeBucketExpression([
|
|
73
|
+
self.__value,
|
|
74
|
+
quantity_op,
|
|
75
|
+
duration_unit_op,
|
|
76
|
+
PyLegendStringLiteralExpression("DATETIME")]))
|
|
77
|
+
|
|
60
78
|
@staticmethod
|
|
61
79
|
def __convert_to_datetime_expr(
|
|
62
80
|
val: PyLegendUnion[datetime, "PyLegendDateTime"]
|
|
@@ -33,7 +33,13 @@ from pylegend.core.language.shared.operations.integer_operation_expressions impo
|
|
|
33
33
|
PyLegendIntegerSubtractExpression,
|
|
34
34
|
PyLegendIntegerMultiplyExpression,
|
|
35
35
|
PyLegendIntegerModuloExpression,
|
|
36
|
-
PyLegendIntegerCharExpression
|
|
36
|
+
PyLegendIntegerCharExpression,
|
|
37
|
+
PyLegendIntegerBitAndExpression,
|
|
38
|
+
PyLegendIntegerBitOrExpression,
|
|
39
|
+
PyLegendIntegerBitXorExpression,
|
|
40
|
+
PyLegendIntegerBitShiftLeftExpression,
|
|
41
|
+
PyLegendIntegerBitShiftRightExpression,
|
|
42
|
+
PyLegendIntegerBitNotExpression
|
|
37
43
|
)
|
|
38
44
|
if TYPE_CHECKING:
|
|
39
45
|
from pylegend.core.language.shared.primitives import PyLegendFloat
|
|
@@ -159,6 +165,53 @@ class PyLegendInteger(PyLegendNumber):
|
|
|
159
165
|
def __pos__(self) -> "PyLegendInteger":
|
|
160
166
|
return self
|
|
161
167
|
|
|
168
|
+
def __invert__(self) -> "PyLegendInteger":
|
|
169
|
+
return PyLegendInteger(PyLegendIntegerBitNotExpression(self.__value_copy))
|
|
170
|
+
|
|
171
|
+
def __and__(self, other: PyLegendUnion[int, "PyLegendInteger"]) -> "PyLegendInteger":
|
|
172
|
+
return self._create_binary_expression(other, PyLegendIntegerBitAndExpression, "and (&)")
|
|
173
|
+
|
|
174
|
+
def __rand__(self, other: PyLegendUnion[int, "PyLegendInteger"]) -> "PyLegendInteger":
|
|
175
|
+
return self._create_binary_expression(other, PyLegendIntegerBitAndExpression, "and (&)", reverse=True)
|
|
176
|
+
|
|
177
|
+
def __or__(self, other: PyLegendUnion[int, "PyLegendInteger"]) -> "PyLegendInteger":
|
|
178
|
+
return self._create_binary_expression(other, PyLegendIntegerBitOrExpression, "or (|)")
|
|
179
|
+
|
|
180
|
+
def __ror__(self, other: PyLegendUnion[int, "PyLegendInteger"]) -> "PyLegendInteger":
|
|
181
|
+
return self._create_binary_expression(other, PyLegendIntegerBitOrExpression, "or (|)", reverse=True)
|
|
182
|
+
|
|
183
|
+
def __xor__(self, other: PyLegendUnion[int, "PyLegendInteger"]) -> "PyLegendInteger":
|
|
184
|
+
return self._create_binary_expression(other, PyLegendIntegerBitXorExpression, "xor (^)")
|
|
185
|
+
|
|
186
|
+
def __rxor__(self, other: PyLegendUnion[int, "PyLegendInteger"]) -> "PyLegendInteger":
|
|
187
|
+
return self._create_binary_expression(other, PyLegendIntegerBitXorExpression, "xor (^)", reverse=True)
|
|
188
|
+
|
|
189
|
+
def __lshift__(self, other: PyLegendUnion[int, "PyLegendInteger"]) -> "PyLegendInteger":
|
|
190
|
+
return self._create_binary_expression(other, PyLegendIntegerBitShiftLeftExpression, "left shift (<<)")
|
|
191
|
+
|
|
192
|
+
def __rlshift__(self, other: PyLegendUnion[int, "PyLegendInteger"]) -> "PyLegendInteger":
|
|
193
|
+
return self._create_binary_expression(other, PyLegendIntegerBitShiftLeftExpression, "left shift (<<)", reverse=True)
|
|
194
|
+
|
|
195
|
+
def __rshift__(self, other: PyLegendUnion[int, "PyLegendInteger"]) -> "PyLegendInteger":
|
|
196
|
+
return self._create_binary_expression(other, PyLegendIntegerBitShiftRightExpression, "right shift (>>)")
|
|
197
|
+
|
|
198
|
+
def __rrshift__(self, other: PyLegendUnion[int, "PyLegendInteger"]) -> "PyLegendInteger":
|
|
199
|
+
return self._create_binary_expression(other, PyLegendIntegerBitShiftRightExpression, "right shift (>>)", reverse=True)
|
|
200
|
+
|
|
201
|
+
def _create_binary_expression(
|
|
202
|
+
self,
|
|
203
|
+
other: PyLegendUnion[int, "PyLegendInteger"],
|
|
204
|
+
expression_class: type,
|
|
205
|
+
operation_name: str,
|
|
206
|
+
reverse: bool = False
|
|
207
|
+
) -> "PyLegendInteger":
|
|
208
|
+
PyLegendInteger.__validate__param_to_be_integer(other, f"Integer {operation_name} parameter")
|
|
209
|
+
other_op = PyLegendInteger.__convert_to_integer_expr(other)
|
|
210
|
+
|
|
211
|
+
if reverse:
|
|
212
|
+
return PyLegendInteger(expression_class(other_op, self.__value_copy))
|
|
213
|
+
return PyLegendInteger(expression_class(self.__value_copy, other_op))
|
|
214
|
+
|
|
162
215
|
@staticmethod
|
|
163
216
|
def __convert_to_integer_expr(
|
|
164
217
|
val: PyLegendUnion[int, "PyLegendInteger"]
|
|
@@ -24,13 +24,16 @@ from pylegend.core.language.shared.expression import (
|
|
|
24
24
|
)
|
|
25
25
|
from pylegend.core.language.shared.literal_expressions import (
|
|
26
26
|
PyLegendStrictDateLiteralExpression,
|
|
27
|
+
PyLegendIntegerLiteralExpression,
|
|
28
|
+
PyLegendStringLiteralExpression
|
|
27
29
|
)
|
|
28
30
|
from pylegend.core.sql.metamodel import (
|
|
29
31
|
Expression,
|
|
30
32
|
QuerySpecification
|
|
31
33
|
)
|
|
32
34
|
from pylegend.core.tds.tds_frame import FrameToSqlConfig
|
|
33
|
-
|
|
35
|
+
from pylegend.core.language.shared.operations.date_operation_expressions import PyLegendDateTimeBucketExpression
|
|
36
|
+
from pylegend.core.language.shared.primitives.integer import PyLegendInteger
|
|
34
37
|
|
|
35
38
|
__all__: PyLegendSequence[str] = [
|
|
36
39
|
"PyLegendStrictDate"
|
|
@@ -57,6 +60,20 @@ class PyLegendStrictDate(PyLegendDate):
|
|
|
57
60
|
def value(self) -> PyLegendExpressionStrictDateReturn:
|
|
58
61
|
return self.__value
|
|
59
62
|
|
|
63
|
+
def time_bucket(
|
|
64
|
+
self,
|
|
65
|
+
quantity: PyLegendUnion[int, "PyLegendInteger"],
|
|
66
|
+
duration_unit: str) -> "PyLegendDate":
|
|
67
|
+
self.validate_param_to_be_int_or_int_expr(quantity, "time bucket quantity parameter")
|
|
68
|
+
quantity_op = PyLegendIntegerLiteralExpression(quantity) if isinstance(quantity, int) else quantity.value()
|
|
69
|
+
self.validate_duration_unit_param(duration_unit)
|
|
70
|
+
duration_unit_op = PyLegendStringLiteralExpression(duration_unit.upper())
|
|
71
|
+
return PyLegendDate(PyLegendDateTimeBucketExpression([
|
|
72
|
+
self.__value,
|
|
73
|
+
quantity_op,
|
|
74
|
+
duration_unit_op,
|
|
75
|
+
PyLegendStringLiteralExpression("STRICTDATE")]))
|
|
76
|
+
|
|
60
77
|
@staticmethod
|
|
61
78
|
def __convert_to_strictdate_expr(
|
|
62
79
|
val: PyLegendUnion[date, "PyLegendStrictDate"]
|
|
@@ -73,3 +90,10 @@ class PyLegendStrictDate(PyLegendDate):
|
|
|
73
90
|
if not isinstance(param, (date, PyLegendStrictDate)):
|
|
74
91
|
raise TypeError(desc + " should be a datetime.date or a StrictDate expression (PyLegendStrictDate)."
|
|
75
92
|
" Got value " + str(param) + " of type: " + str(type(param)))
|
|
93
|
+
|
|
94
|
+
@staticmethod
|
|
95
|
+
def validate_duration_unit_param(duration_unit: str) -> None:
|
|
96
|
+
if duration_unit.lower() not in ('years', 'months', 'weeks', 'days'):
|
|
97
|
+
raise ValueError(
|
|
98
|
+
f"Unknown duration unit - {duration_unit}. Supported values are - YEARS, MONTHS, WEEKS, DAYS"
|
|
99
|
+
)
|
|
@@ -18,7 +18,10 @@ from pylegend._typing import (
|
|
|
18
18
|
PyLegendUnion,
|
|
19
19
|
PyLegendOptional
|
|
20
20
|
)
|
|
21
|
-
from pylegend.core.language.shared.literal_expressions import
|
|
21
|
+
from pylegend.core.language.shared.literal_expressions import (
|
|
22
|
+
PyLegendIntegerLiteralExpression,
|
|
23
|
+
convert_literal_to_literal_expression
|
|
24
|
+
)
|
|
22
25
|
from pylegend.core.language.shared.primitives.primitive import PyLegendPrimitive
|
|
23
26
|
from pylegend.core.language.shared.primitives.integer import PyLegendInteger
|
|
24
27
|
from pylegend.core.language.shared.primitives.float import PyLegendFloat
|
|
@@ -67,7 +70,8 @@ from pylegend.core.language.shared.operations.string_operation_expressions impor
|
|
|
67
70
|
PyLegendStringSplitPartExpression,
|
|
68
71
|
PyLegendStringFullMatchExpression,
|
|
69
72
|
PyLegendStringRepeatStringExpression,
|
|
70
|
-
PyLegendStringMatchExpression
|
|
73
|
+
PyLegendStringMatchExpression,
|
|
74
|
+
PyLegendStringCoalesceExpression
|
|
71
75
|
)
|
|
72
76
|
|
|
73
77
|
__all__: PyLegendSequence[str] = [
|
|
@@ -242,6 +246,16 @@ class PyLegendString(PyLegendPrimitive):
|
|
|
242
246
|
times_op = PyLegendIntegerLiteralExpression(times) if isinstance(times, int) else times.value()
|
|
243
247
|
return PyLegendString(PyLegendStringRepeatStringExpression(self.__value, times_op))
|
|
244
248
|
|
|
249
|
+
def coalesce(self, *other: PyLegendOptional[PyLegendUnion[str, "PyLegendString"]]) -> "PyLegendString":
|
|
250
|
+
other_op = []
|
|
251
|
+
for op in other:
|
|
252
|
+
if op is not None:
|
|
253
|
+
PyLegendString.__validate_param_to_be_str_or_str_expr(op, "coalesce parameter")
|
|
254
|
+
other_op.append(
|
|
255
|
+
convert_literal_to_literal_expression(op) if not isinstance(op, PyLegendString) else op.__value)
|
|
256
|
+
|
|
257
|
+
return PyLegendString(PyLegendStringCoalesceExpression([self.__value, *other_op]))
|
|
258
|
+
|
|
245
259
|
def __add__(self, other: PyLegendUnion[str, "PyLegendString"]) -> "PyLegendString":
|
|
246
260
|
PyLegendString.__validate_param_to_be_str_or_str_expr(other, "String plus (+) parameter")
|
|
247
261
|
other_op = PyLegendStringLiteralExpression(other) if isinstance(other, str) else other.__value
|
pylegend/core/sql/metamodel.py
CHANGED
|
@@ -87,7 +87,11 @@ __all__: PyLegendSequence[str] = [
|
|
|
87
87
|
'InPredicate',
|
|
88
88
|
'Window',
|
|
89
89
|
'WindowFrame',
|
|
90
|
-
'FrameBound'
|
|
90
|
+
'FrameBound',
|
|
91
|
+
'BitwiseShiftDirection',
|
|
92
|
+
'BitwiseBinaryOperator',
|
|
93
|
+
'BitwiseBinaryExpression',
|
|
94
|
+
'BitwiseShiftExpression',
|
|
91
95
|
]
|
|
92
96
|
|
|
93
97
|
|
|
@@ -179,6 +183,17 @@ class ExtractField(Enum):
|
|
|
179
183
|
EPOCH = 17
|
|
180
184
|
|
|
181
185
|
|
|
186
|
+
class BitwiseShiftDirection(Enum):
|
|
187
|
+
LEFT = 1
|
|
188
|
+
RIGHT = 2
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
class BitwiseBinaryOperator(Enum):
|
|
192
|
+
AND = 1
|
|
193
|
+
OR = 2
|
|
194
|
+
XOR = 3
|
|
195
|
+
|
|
196
|
+
|
|
182
197
|
class Node:
|
|
183
198
|
_type: str
|
|
184
199
|
|
|
@@ -930,3 +945,37 @@ class FrameBound(Node):
|
|
|
930
945
|
self.type_ = type_
|
|
931
946
|
self.value = value
|
|
932
947
|
self.duration_unit = duration_unit
|
|
948
|
+
|
|
949
|
+
|
|
950
|
+
class BitwiseBinaryExpression(Expression):
|
|
951
|
+
left: "Expression"
|
|
952
|
+
right: "Expression"
|
|
953
|
+
operator: "BitwiseBinaryOperator"
|
|
954
|
+
|
|
955
|
+
def __init__(
|
|
956
|
+
self,
|
|
957
|
+
left: "Expression",
|
|
958
|
+
right: "Expression",
|
|
959
|
+
operator: "BitwiseBinaryOperator"
|
|
960
|
+
) -> None:
|
|
961
|
+
super().__init__(_type="bitwiseBinaryExpression")
|
|
962
|
+
self.left = left
|
|
963
|
+
self.right = right
|
|
964
|
+
self.operator = operator
|
|
965
|
+
|
|
966
|
+
|
|
967
|
+
class BitwiseShiftExpression(Expression):
|
|
968
|
+
value: "Expression"
|
|
969
|
+
shift: "Expression"
|
|
970
|
+
direction: "BitwiseShiftDirection"
|
|
971
|
+
|
|
972
|
+
def __init__(
|
|
973
|
+
self,
|
|
974
|
+
value: "Expression",
|
|
975
|
+
shift: "Expression",
|
|
976
|
+
direction: "BitwiseShiftDirection"
|
|
977
|
+
) -> None:
|
|
978
|
+
super().__init__(_type="bitwiseShiftExpression")
|
|
979
|
+
self.value = value
|
|
980
|
+
self.shift = shift
|
|
981
|
+
self.direction = direction
|