vtlengine 1.0__py3-none-any.whl → 1.0.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of vtlengine might be problematic. Click here for more details.
- vtlengine/API/_InternalApi.py +159 -102
- vtlengine/API/__init__.py +110 -68
- vtlengine/AST/ASTConstructor.py +188 -98
- vtlengine/AST/ASTConstructorModules/Expr.py +402 -205
- vtlengine/AST/ASTConstructorModules/ExprComponents.py +248 -104
- vtlengine/AST/ASTConstructorModules/Terminals.py +158 -95
- vtlengine/AST/ASTEncoders.py +1 -1
- vtlengine/AST/ASTTemplate.py +24 -9
- vtlengine/AST/ASTVisitor.py +8 -12
- vtlengine/AST/DAG/__init__.py +43 -35
- vtlengine/AST/DAG/_words.py +4 -4
- vtlengine/AST/Grammar/Vtl.g4 +49 -20
- vtlengine/AST/Grammar/VtlTokens.g4 +13 -1
- vtlengine/AST/Grammar/lexer.py +2012 -1312
- vtlengine/AST/Grammar/parser.py +7524 -4343
- vtlengine/AST/Grammar/tokens.py +140 -128
- vtlengine/AST/VtlVisitor.py +16 -5
- vtlengine/AST/__init__.py +41 -11
- vtlengine/DataTypes/NumericTypesHandling.py +5 -4
- vtlengine/DataTypes/TimeHandling.py +196 -301
- vtlengine/DataTypes/__init__.py +304 -218
- vtlengine/Exceptions/__init__.py +96 -27
- vtlengine/Exceptions/messages.py +149 -69
- vtlengine/Interpreter/__init__.py +817 -497
- vtlengine/Model/__init__.py +172 -121
- vtlengine/Operators/Aggregation.py +156 -95
- vtlengine/Operators/Analytic.py +167 -79
- vtlengine/Operators/Assignment.py +7 -4
- vtlengine/Operators/Boolean.py +27 -32
- vtlengine/Operators/CastOperator.py +177 -131
- vtlengine/Operators/Clause.py +137 -99
- vtlengine/Operators/Comparison.py +148 -117
- vtlengine/Operators/Conditional.py +290 -98
- vtlengine/Operators/General.py +68 -47
- vtlengine/Operators/HROperators.py +91 -72
- vtlengine/Operators/Join.py +217 -118
- vtlengine/Operators/Numeric.py +129 -46
- vtlengine/Operators/RoleSetter.py +16 -15
- vtlengine/Operators/Set.py +61 -36
- vtlengine/Operators/String.py +213 -139
- vtlengine/Operators/Time.py +467 -215
- vtlengine/Operators/Validation.py +117 -76
- vtlengine/Operators/__init__.py +340 -213
- vtlengine/Utils/__init__.py +232 -41
- vtlengine/__init__.py +1 -1
- vtlengine/files/output/__init__.py +15 -6
- vtlengine/files/output/_time_period_representation.py +10 -9
- vtlengine/files/parser/__init__.py +79 -52
- vtlengine/files/parser/_rfc_dialect.py +6 -5
- vtlengine/files/parser/_time_checking.py +48 -37
- vtlengine-1.0.2.dist-info/METADATA +245 -0
- vtlengine-1.0.2.dist-info/RECORD +58 -0
- {vtlengine-1.0.dist-info → vtlengine-1.0.2.dist-info}/WHEEL +1 -1
- vtlengine-1.0.dist-info/METADATA +0 -104
- vtlengine-1.0.dist-info/RECORD +0 -58
- {vtlengine-1.0.dist-info → vtlengine-1.0.2.dist-info}/LICENSE.md +0 -0
|
@@ -1,28 +1,31 @@
|
|
|
1
1
|
from copy import copy
|
|
2
|
-
from typing import Optional, Any
|
|
2
|
+
from typing import Optional, Any, Union, Type
|
|
3
3
|
|
|
4
4
|
import vtlengine.Operators as Operator
|
|
5
5
|
import pandas as pd
|
|
6
|
-
from vtlengine.DataTypes import (
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
6
|
+
from vtlengine.DataTypes import (
|
|
7
|
+
COMP_NAME_MAPPING,
|
|
8
|
+
EXPLICIT_WITH_MASK_TYPE_PROMOTION_MAPPING,
|
|
9
|
+
EXPLICIT_WITHOUT_MASK_TYPE_PROMOTION_MAPPING,
|
|
10
|
+
IMPLICIT_TYPE_PROMOTION_MAPPING,
|
|
11
|
+
String,
|
|
12
|
+
Number,
|
|
13
|
+
TimeInterval,
|
|
14
|
+
Date,
|
|
15
|
+
TimePeriod,
|
|
16
|
+
Duration,
|
|
17
|
+
SCALAR_TYPES_CLASS_REVERSE,
|
|
18
|
+
ScalarType,
|
|
19
|
+
)
|
|
12
20
|
from vtlengine.DataTypes.TimeHandling import str_period_to_date
|
|
13
21
|
|
|
14
22
|
from vtlengine.AST.Grammar.tokens import CAST
|
|
15
23
|
from vtlengine.Exceptions import SemanticError
|
|
16
24
|
from vtlengine.Model import Component, Dataset, Role, Scalar, DataComponent
|
|
17
25
|
|
|
18
|
-
duration_mapping = {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
"Q": 4,
|
|
22
|
-
"M": 3,
|
|
23
|
-
"W": 2,
|
|
24
|
-
"D": 1
|
|
25
|
-
}
|
|
26
|
+
duration_mapping = {"A": 6, "S": 5, "Q": 4, "M": 3, "W": 2, "D": 1}
|
|
27
|
+
|
|
28
|
+
ALL_MODEL_DATA_TYPES = Union[Dataset, Scalar, DataComponent]
|
|
26
29
|
|
|
27
30
|
|
|
28
31
|
class Cast(Operator.Unary):
|
|
@@ -31,7 +34,7 @@ class Cast(Operator.Unary):
|
|
|
31
34
|
# CASTS VALUES
|
|
32
35
|
# Converts the value from one type to another in a way that is according to the mask
|
|
33
36
|
@classmethod
|
|
34
|
-
def cast_string_to_number(cls,
|
|
37
|
+
def cast_string_to_number(cls, *args: Any) -> Any:
|
|
35
38
|
"""
|
|
36
39
|
This method casts a string to a number, according to the mask.
|
|
37
40
|
|
|
@@ -40,7 +43,7 @@ class Cast(Operator.Unary):
|
|
|
40
43
|
raise NotImplementedError("How this cast should be implemented is not yet defined.")
|
|
41
44
|
|
|
42
45
|
@classmethod
|
|
43
|
-
def cast_string_to_date(cls,
|
|
46
|
+
def cast_string_to_date(cls, *args: Any) -> Any:
|
|
44
47
|
"""
|
|
45
48
|
This method casts a string to a number, according to the mask.
|
|
46
49
|
|
|
@@ -49,7 +52,7 @@ class Cast(Operator.Unary):
|
|
|
49
52
|
raise NotImplementedError("How this cast should be implemented is not yet defined.")
|
|
50
53
|
|
|
51
54
|
@classmethod
|
|
52
|
-
def cast_string_to_duration(cls,
|
|
55
|
+
def cast_string_to_duration(cls, *args: Any) -> Any:
|
|
53
56
|
"""
|
|
54
57
|
This method casts a string to a duration, according to the mask.
|
|
55
58
|
|
|
@@ -58,7 +61,7 @@ class Cast(Operator.Unary):
|
|
|
58
61
|
raise NotImplementedError("How this cast should be implemented is not yet defined.")
|
|
59
62
|
|
|
60
63
|
@classmethod
|
|
61
|
-
def cast_string_to_time_period(cls,
|
|
64
|
+
def cast_string_to_time_period(cls, *args: Any) -> Any:
|
|
62
65
|
"""
|
|
63
66
|
This method casts a string to a time period, according to the mask.
|
|
64
67
|
|
|
@@ -67,7 +70,7 @@ class Cast(Operator.Unary):
|
|
|
67
70
|
raise NotImplementedError("How this cast should be implemented is not yet defined.")
|
|
68
71
|
|
|
69
72
|
@classmethod
|
|
70
|
-
def cast_string_to_time(cls,
|
|
73
|
+
def cast_string_to_time(cls, *args: Any) -> Any:
|
|
71
74
|
"""
|
|
72
75
|
This method casts a string to a time, according to the mask.
|
|
73
76
|
|
|
@@ -76,37 +79,37 @@ class Cast(Operator.Unary):
|
|
|
76
79
|
raise NotImplementedError("How this cast should be implemented is not yet defined.")
|
|
77
80
|
|
|
78
81
|
@classmethod
|
|
79
|
-
def cast_date_to_string(cls,
|
|
80
|
-
"""
|
|
81
|
-
"""
|
|
82
|
+
def cast_date_to_string(cls, *args: Any) -> Any:
|
|
83
|
+
""" """
|
|
82
84
|
return NotImplementedError("How this cast should be implemented is not yet defined.")
|
|
83
85
|
|
|
84
86
|
@classmethod
|
|
85
|
-
def cast_duration_to_string(cls,
|
|
86
|
-
"""
|
|
87
|
-
"""
|
|
87
|
+
def cast_duration_to_string(cls, *args: Any) -> Any:
|
|
88
|
+
""" """
|
|
88
89
|
return NotImplementedError("How this cast should be implemented is not yet defined.")
|
|
89
90
|
|
|
90
91
|
@classmethod
|
|
91
|
-
def cast_time_to_string(cls,
|
|
92
|
-
"""
|
|
93
|
-
"""
|
|
92
|
+
def cast_time_to_string(cls, *args: Any) -> Any:
|
|
93
|
+
""" """
|
|
94
94
|
return NotImplementedError("How this cast should be implemented is not yet defined.")
|
|
95
95
|
|
|
96
96
|
@classmethod
|
|
97
|
-
def cast_time_period_to_date(cls, value, mask_value):
|
|
98
|
-
"""
|
|
99
|
-
|
|
97
|
+
def cast_time_period_to_date(cls, value: Any, mask_value: str) -> Any:
|
|
98
|
+
""" """
|
|
99
|
+
|
|
100
100
|
start = mask_value == "START"
|
|
101
101
|
return str_period_to_date(value, start)
|
|
102
102
|
|
|
103
103
|
invalid_mask_message = "At op {op}: Invalid mask to cast from type {type_1} to {type_2}."
|
|
104
104
|
|
|
105
105
|
@classmethod
|
|
106
|
-
def check_mask_value(
|
|
106
|
+
def check_mask_value(
|
|
107
|
+
cls, from_type: Type[ScalarType], to_type: Type[ScalarType], mask_value: str
|
|
108
|
+
) -> None:
|
|
107
109
|
"""
|
|
108
110
|
This method checks if the mask value is valid for the cast operation.
|
|
109
111
|
"""
|
|
112
|
+
|
|
110
113
|
if from_type == TimeInterval and to_type == String:
|
|
111
114
|
return cls.check_mask_value_from_time_to_string(mask_value)
|
|
112
115
|
# from = Date
|
|
@@ -129,141 +132,160 @@ class Cast(Operator.Unary):
|
|
|
129
132
|
# from = Duration
|
|
130
133
|
if from_type == Duration and to_type == String:
|
|
131
134
|
return cls.check_mask_value_from_duration_to_string(mask_value)
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
+
raise SemanticError(
|
|
136
|
+
"1-1-5-5",
|
|
137
|
+
op=cls.op,
|
|
138
|
+
type_1=SCALAR_TYPES_CLASS_REVERSE[from_type],
|
|
139
|
+
type_2=SCALAR_TYPES_CLASS_REVERSE[to_type],
|
|
140
|
+
mask_value=mask_value,
|
|
141
|
+
)
|
|
135
142
|
|
|
136
143
|
@classmethod
|
|
137
|
-
def check_mask_value_from_time_period_to_date(cls, mask_value) -> None:
|
|
144
|
+
def check_mask_value_from_time_period_to_date(cls, mask_value: str) -> None:
|
|
145
|
+
|
|
138
146
|
if mask_value not in ["START", "END"]:
|
|
139
147
|
raise SemanticError("1-1-5-4", op=cls.op, type_1="Time_Period", type_2="Date")
|
|
140
148
|
|
|
141
149
|
@classmethod
|
|
142
|
-
def check_mask_value_from_time_to_string(cls,
|
|
150
|
+
def check_mask_value_from_time_to_string(cls, *args: Any) -> None:
|
|
143
151
|
raise NotImplementedError("How this mask should be implemented is not yet defined.")
|
|
144
152
|
|
|
145
153
|
@classmethod
|
|
146
|
-
def check_mask_value_from_date_to_string(cls,
|
|
154
|
+
def check_mask_value_from_date_to_string(cls, *args: Any) -> None:
|
|
147
155
|
raise NotImplementedError("How this mask should be implemented is not yet defined.")
|
|
148
156
|
|
|
149
157
|
@classmethod
|
|
150
|
-
def check_mask_value_from_string_to_number(cls,
|
|
158
|
+
def check_mask_value_from_string_to_number(cls, *args: Any) -> None:
|
|
151
159
|
raise NotImplementedError("How this mask should be implemented is not yet defined.")
|
|
152
160
|
|
|
153
161
|
@classmethod
|
|
154
|
-
def check_mask_value_from_string_to_time(cls,
|
|
162
|
+
def check_mask_value_from_string_to_time(cls, *args: Any) -> None:
|
|
155
163
|
raise NotImplementedError("How this mask should be implemented is not yet defined.")
|
|
156
164
|
|
|
157
165
|
@classmethod
|
|
158
|
-
def check_mask_value_from_string_to_date(cls,
|
|
166
|
+
def check_mask_value_from_string_to_date(cls, *args: Any) -> None:
|
|
159
167
|
raise NotImplementedError("How this mask should be implemented is not yet defined.")
|
|
160
168
|
|
|
161
169
|
@classmethod
|
|
162
|
-
def check_mask_value_from_string_to_time_period(cls,
|
|
170
|
+
def check_mask_value_from_string_to_time_period(cls, *args: Any) -> None:
|
|
163
171
|
raise NotImplementedError("How this mask should be implemented is not yet defined.")
|
|
164
172
|
|
|
165
173
|
@classmethod
|
|
166
|
-
def check_mask_value_from_string_to_duration(cls,
|
|
174
|
+
def check_mask_value_from_string_to_duration(cls, *args: Any) -> None:
|
|
167
175
|
raise NotImplementedError("How this mask should be implemented is not yet defined.")
|
|
168
176
|
|
|
169
177
|
@classmethod
|
|
170
|
-
def check_mask_value_from_duration_to_string(cls,
|
|
178
|
+
def check_mask_value_from_duration_to_string(cls, *args: Any) -> None:
|
|
171
179
|
raise NotImplementedError("How this mask should be implemented is not yet defined.")
|
|
172
180
|
|
|
173
181
|
@classmethod
|
|
174
|
-
def check_cast(
|
|
182
|
+
def check_cast(
|
|
183
|
+
cls, from_type: Type[ScalarType], to_type: Type[ScalarType], mask_value: Optional[str]
|
|
184
|
+
) -> None:
|
|
185
|
+
|
|
175
186
|
if mask_value is not None:
|
|
176
187
|
cls.check_with_mask(from_type, to_type, mask_value)
|
|
177
188
|
else:
|
|
178
189
|
cls.check_without_mask(from_type, to_type)
|
|
179
190
|
|
|
180
191
|
@classmethod
|
|
181
|
-
def check_with_mask(
|
|
192
|
+
def check_with_mask(
|
|
193
|
+
cls, from_type: Type[ScalarType], to_type: Type[ScalarType], mask_value: str
|
|
194
|
+
) -> None:
|
|
195
|
+
|
|
182
196
|
explicit_promotion = EXPLICIT_WITH_MASK_TYPE_PROMOTION_MAPPING[from_type]
|
|
183
197
|
if to_type.is_included(explicit_promotion):
|
|
184
198
|
return cls.check_mask_value(from_type, to_type, mask_value)
|
|
185
199
|
|
|
186
|
-
raise SemanticError(
|
|
187
|
-
|
|
188
|
-
|
|
200
|
+
raise SemanticError(
|
|
201
|
+
"1-1-5-5",
|
|
202
|
+
op=cls.op,
|
|
203
|
+
type_1=SCALAR_TYPES_CLASS_REVERSE[from_type],
|
|
204
|
+
type_2=SCALAR_TYPES_CLASS_REVERSE[to_type],
|
|
205
|
+
mask_value=mask_value,
|
|
206
|
+
)
|
|
189
207
|
|
|
190
208
|
@classmethod
|
|
191
|
-
def check_without_mask(cls, from_type: ScalarType, to_type: ScalarType):
|
|
209
|
+
def check_without_mask(cls, from_type: Type[ScalarType], to_type: Type[ScalarType]) -> None:
|
|
210
|
+
|
|
192
211
|
explicit_promotion = EXPLICIT_WITHOUT_MASK_TYPE_PROMOTION_MAPPING[from_type]
|
|
193
212
|
implicit_promotion = IMPLICIT_TYPE_PROMOTION_MAPPING[from_type]
|
|
194
213
|
if not (to_type.is_included(explicit_promotion) or to_type.is_included(implicit_promotion)):
|
|
195
214
|
explicit_with_mask = EXPLICIT_WITH_MASK_TYPE_PROMOTION_MAPPING[from_type]
|
|
196
215
|
if to_type.is_included(explicit_with_mask):
|
|
197
|
-
raise SemanticError(
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
216
|
+
raise SemanticError(
|
|
217
|
+
"1-1-5-3",
|
|
218
|
+
op=cls.op,
|
|
219
|
+
type_1=SCALAR_TYPES_CLASS_REVERSE[from_type],
|
|
220
|
+
type_2=SCALAR_TYPES_CLASS_REVERSE[to_type],
|
|
221
|
+
)
|
|
222
|
+
raise SemanticError(
|
|
223
|
+
"1-1-5-4",
|
|
224
|
+
op=cls.op,
|
|
225
|
+
type_1=SCALAR_TYPES_CLASS_REVERSE[from_type],
|
|
226
|
+
type_2=SCALAR_TYPES_CLASS_REVERSE[to_type],
|
|
227
|
+
)
|
|
228
|
+
|
|
229
|
+
@classmethod
|
|
230
|
+
def cast_component(
|
|
231
|
+
cls, data: Any, from_type: Type[ScalarType], to_type: Type[ScalarType]
|
|
232
|
+
) -> Any:
|
|
206
233
|
"""
|
|
207
234
|
cast the component to the type to_type without mask
|
|
208
|
-
|
|
209
235
|
"""
|
|
236
|
+
|
|
210
237
|
if to_type.is_included(IMPLICIT_TYPE_PROMOTION_MAPPING[from_type]):
|
|
211
|
-
result = data.map(lambda x: to_type.implicit_cast(x, from_type), na_action=
|
|
238
|
+
result = data.map(lambda x: to_type.implicit_cast(x, from_type), na_action="ignore")
|
|
212
239
|
else:
|
|
213
|
-
result = data.map(lambda x: to_type.explicit_cast(x, from_type), na_action=
|
|
214
|
-
|
|
240
|
+
result = data.map(lambda x: to_type.explicit_cast(x, from_type), na_action="ignore")
|
|
215
241
|
return result
|
|
216
242
|
|
|
217
243
|
@classmethod
|
|
218
|
-
def cast_mask_component(cls, data:
|
|
219
|
-
mask: str) -> pd.Series:
|
|
220
|
-
|
|
221
|
-
result = data.map(lambda x: cls.cast_value(x, from_type, to_type, mask), na_action='ignore')
|
|
244
|
+
def cast_mask_component(cls, data: Any, from_type: Any, to_type: Any, mask: str) -> Any:
|
|
222
245
|
|
|
246
|
+
result = data.map(lambda x: cls.cast_value(x, from_type, to_type, mask), na_action="ignore")
|
|
223
247
|
return result
|
|
224
248
|
|
|
225
249
|
@classmethod
|
|
226
|
-
def cast_value(
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
"""
|
|
250
|
+
def cast_value(
|
|
251
|
+
cls, value: Any, provided_type: Type[ScalarType], to_type: Type[ScalarType], mask_value: str
|
|
252
|
+
) -> Any:
|
|
231
253
|
|
|
232
254
|
if provided_type == String and to_type == Number:
|
|
233
255
|
return cls.cast_string_to_number(value, mask_value)
|
|
234
|
-
|
|
235
256
|
if provided_type == String and to_type == Date:
|
|
236
257
|
return cls.cast_string_to_date(value, mask_value)
|
|
237
|
-
|
|
238
258
|
if provided_type == String and to_type == Duration:
|
|
239
259
|
return cls.cast_string_to_duration(value, mask_value)
|
|
240
|
-
|
|
241
260
|
if provided_type == String and to_type == TimePeriod:
|
|
242
261
|
return cls.cast_string_to_time_period(value, mask_value)
|
|
243
|
-
|
|
244
262
|
if provided_type == String and to_type == TimeInterval:
|
|
245
263
|
return cls.cast_string_to_time(value, mask_value)
|
|
246
|
-
|
|
247
264
|
if provided_type == Date and to_type == String:
|
|
248
265
|
return cls.cast_date_to_string(value, mask_value)
|
|
249
|
-
|
|
250
266
|
if provided_type == Duration and to_type == String:
|
|
251
267
|
return cls.cast_duration_to_string(value, mask_value)
|
|
252
|
-
|
|
253
268
|
if provided_type == TimeInterval and to_type == String:
|
|
254
269
|
return cls.cast_time_to_string(value, mask_value)
|
|
255
|
-
|
|
256
270
|
if provided_type == TimePeriod and to_type == Date:
|
|
257
271
|
return cls.cast_time_period_to_date(value, mask_value)
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
272
|
+
|
|
273
|
+
raise SemanticError(
|
|
274
|
+
"2-1-5-1",
|
|
275
|
+
op=cls.op,
|
|
276
|
+
value=value,
|
|
277
|
+
type_1=SCALAR_TYPES_CLASS_REVERSE[provided_type],
|
|
278
|
+
type_2=SCALAR_TYPES_CLASS_REVERSE[to_type],
|
|
279
|
+
)
|
|
261
280
|
|
|
262
281
|
@classmethod
|
|
263
|
-
def validate(
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
282
|
+
def validate( # type: ignore[override]
|
|
283
|
+
cls,
|
|
284
|
+
operand: ALL_MODEL_DATA_TYPES,
|
|
285
|
+
scalarType: Type[ScalarType],
|
|
286
|
+
mask: Optional[str] = None,
|
|
287
|
+
) -> Any:
|
|
288
|
+
|
|
267
289
|
if mask is not None:
|
|
268
290
|
if not isinstance(mask, str):
|
|
269
291
|
raise Exception(f"{cls.op} mask must be a string")
|
|
@@ -276,11 +298,16 @@ class Cast(Operator.Unary):
|
|
|
276
298
|
return cls.scalar_validation(operand, scalarType, mask)
|
|
277
299
|
|
|
278
300
|
@classmethod
|
|
279
|
-
def dataset_validation(
|
|
280
|
-
|
|
301
|
+
def dataset_validation( # type: ignore[override]
|
|
302
|
+
cls,
|
|
303
|
+
operand: Dataset,
|
|
304
|
+
to_type: Type[ScalarType],
|
|
305
|
+
mask: Optional[str] = None,
|
|
306
|
+
) -> Dataset:
|
|
281
307
|
"""
|
|
282
308
|
This method validates the operation when the operand is a Dataset.
|
|
283
309
|
"""
|
|
310
|
+
|
|
284
311
|
# monomeasure
|
|
285
312
|
if len(operand.get_measures()) != 1:
|
|
286
313
|
raise Exception(f"{cls.op} can only be applied to a Dataset with one measure")
|
|
@@ -288,51 +315,58 @@ class Cast(Operator.Unary):
|
|
|
288
315
|
from_type = measure.data_type
|
|
289
316
|
|
|
290
317
|
cls.check_cast(from_type, to_type, mask)
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
318
|
+
result_components = {
|
|
319
|
+
comp_name: copy(comp)
|
|
320
|
+
for comp_name, comp in operand.components.items()
|
|
321
|
+
if comp.role != Role.MEASURE
|
|
322
|
+
}
|
|
295
323
|
|
|
296
324
|
if not to_type.is_included(IMPLICIT_TYPE_PROMOTION_MAPPING[from_type]):
|
|
297
325
|
measure_name = COMP_NAME_MAPPING[to_type]
|
|
298
326
|
else:
|
|
299
327
|
measure_name = measure.name
|
|
300
|
-
result_components[measure_name] = Component(
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
nullable=measure.nullable)
|
|
304
|
-
|
|
328
|
+
result_components[measure_name] = Component(
|
|
329
|
+
name=measure_name, data_type=to_type, role=Role.MEASURE, nullable=measure.nullable
|
|
330
|
+
)
|
|
305
331
|
return Dataset(name="result", components=result_components, data=None)
|
|
306
332
|
|
|
307
333
|
@classmethod
|
|
308
|
-
def component_validation(
|
|
309
|
-
|
|
334
|
+
def component_validation( # type: ignore[override]
|
|
335
|
+
cls,
|
|
336
|
+
operand: DataComponent,
|
|
337
|
+
to_type: Type[ScalarType],
|
|
338
|
+
mask: Optional[str] = None,
|
|
339
|
+
) -> DataComponent:
|
|
310
340
|
"""
|
|
311
341
|
This method validates the operation when the operand is a DataComponent.
|
|
312
342
|
"""
|
|
343
|
+
|
|
313
344
|
from_type = operand.data_type
|
|
314
345
|
cls.check_cast(from_type, to_type, mask)
|
|
315
|
-
|
|
316
|
-
return DataComponent(
|
|
317
|
-
name=operand.name, data=None,
|
|
318
|
-
data_type=to_type, role=operand.role
|
|
319
|
-
)
|
|
346
|
+
return DataComponent(name=operand.name, data=None, data_type=to_type, role=operand.role)
|
|
320
347
|
|
|
321
348
|
@classmethod
|
|
322
|
-
def scalar_validation(
|
|
323
|
-
|
|
349
|
+
def scalar_validation( # type: ignore[override]
|
|
350
|
+
cls,
|
|
351
|
+
operand: Scalar,
|
|
352
|
+
to_type: Type[ScalarType],
|
|
353
|
+
mask: Optional[str] = None,
|
|
354
|
+
) -> Scalar:
|
|
324
355
|
"""
|
|
325
356
|
This method validates the operation when the operand is a DataComponent.
|
|
326
357
|
"""
|
|
358
|
+
|
|
327
359
|
from_type = operand.data_type
|
|
328
360
|
cls.check_cast(from_type, to_type, mask)
|
|
329
|
-
|
|
330
361
|
return Scalar(name=operand.name, data_type=to_type, value=None)
|
|
331
362
|
|
|
332
363
|
@classmethod
|
|
333
|
-
def evaluate(
|
|
334
|
-
|
|
335
|
-
|
|
364
|
+
def evaluate( # type: ignore[override]
|
|
365
|
+
cls,
|
|
366
|
+
operand: ALL_MODEL_DATA_TYPES,
|
|
367
|
+
scalarType: Type[ScalarType],
|
|
368
|
+
mask: Optional[str] = None,
|
|
369
|
+
) -> Any:
|
|
336
370
|
|
|
337
371
|
if isinstance(operand, Dataset):
|
|
338
372
|
return cls.dataset_evaluation(operand, scalarType, mask)
|
|
@@ -342,31 +376,42 @@ class Cast(Operator.Unary):
|
|
|
342
376
|
return cls.component_evaluation(operand, scalarType, mask)
|
|
343
377
|
|
|
344
378
|
@classmethod
|
|
345
|
-
def dataset_evaluation(
|
|
346
|
-
|
|
379
|
+
def dataset_evaluation( # type: ignore[override]
|
|
380
|
+
cls,
|
|
381
|
+
operand: Dataset,
|
|
382
|
+
to_type: Type[ScalarType],
|
|
383
|
+
mask: Optional[str] = None,
|
|
384
|
+
) -> Dataset:
|
|
385
|
+
|
|
347
386
|
from_type = operand.get_measures()[0].data_type
|
|
348
387
|
original_measure = operand.get_measures()[0]
|
|
349
388
|
result_dataset = cls.dataset_validation(operand, to_type, mask)
|
|
350
389
|
new_measure = result_dataset.get_measures()[0]
|
|
351
|
-
|
|
352
|
-
result_dataset.data = operand.data.copy()
|
|
390
|
+
result_dataset.data = operand.data.copy() if operand.data is not None else pd.DataFrame()
|
|
353
391
|
|
|
354
392
|
if original_measure.name != new_measure.name:
|
|
355
|
-
result_dataset.data.rename(
|
|
356
|
-
|
|
393
|
+
result_dataset.data.rename(
|
|
394
|
+
columns={original_measure.name: new_measure.name}, inplace=True
|
|
395
|
+
)
|
|
357
396
|
measure_data = result_dataset.data[new_measure.name]
|
|
358
397
|
if mask:
|
|
359
|
-
result_dataset.data[new_measure.name] = cls.cast_mask_component(
|
|
360
|
-
|
|
398
|
+
result_dataset.data[new_measure.name] = cls.cast_mask_component(
|
|
399
|
+
measure_data, from_type, to_type, mask
|
|
400
|
+
)
|
|
361
401
|
else:
|
|
362
|
-
result_dataset.data[new_measure.name] = cls.cast_component(
|
|
363
|
-
|
|
364
|
-
|
|
402
|
+
result_dataset.data[new_measure.name] = cls.cast_component(
|
|
403
|
+
measure_data, from_type, to_type
|
|
404
|
+
)
|
|
365
405
|
return result_dataset
|
|
366
406
|
|
|
367
407
|
@classmethod
|
|
368
|
-
def scalar_evaluation(
|
|
369
|
-
|
|
408
|
+
def scalar_evaluation( # type: ignore[override]
|
|
409
|
+
cls,
|
|
410
|
+
operand: Scalar,
|
|
411
|
+
to_type: Type[ScalarType],
|
|
412
|
+
mask: Optional[str] = None,
|
|
413
|
+
) -> Scalar:
|
|
414
|
+
|
|
370
415
|
from_type = operand.data_type
|
|
371
416
|
result_scalar = cls.scalar_validation(operand, to_type, mask)
|
|
372
417
|
if pd.isna(operand.value):
|
|
@@ -378,20 +423,21 @@ class Cast(Operator.Unary):
|
|
|
378
423
|
casted_data = to_type.implicit_cast(operand.value, from_type)
|
|
379
424
|
else:
|
|
380
425
|
casted_data = to_type.explicit_cast(operand.value, from_type)
|
|
381
|
-
|
|
382
426
|
return Scalar(name=result_scalar.name, data_type=to_type, value=casted_data)
|
|
383
427
|
|
|
384
428
|
@classmethod
|
|
385
|
-
def component_evaluation(
|
|
386
|
-
|
|
429
|
+
def component_evaluation( # type: ignore[override]
|
|
430
|
+
cls,
|
|
431
|
+
operand: DataComponent,
|
|
432
|
+
to_type: Type[ScalarType],
|
|
433
|
+
mask: Optional[str] = None,
|
|
434
|
+
) -> DataComponent:
|
|
435
|
+
|
|
387
436
|
from_type = operand.data_type
|
|
388
437
|
result_component = cls.component_validation(operand, to_type, mask)
|
|
389
|
-
# result_component.data = cls.apply_operation_component(operand.data.copy())
|
|
390
438
|
if mask:
|
|
391
439
|
casted_data = cls.cast_mask_component(operand.data, from_type, to_type, mask)
|
|
392
440
|
else:
|
|
393
441
|
casted_data = cls.cast_component(operand.data, from_type, to_type)
|
|
394
|
-
|
|
395
442
|
result_component.data = casted_data
|
|
396
|
-
|
|
397
443
|
return result_component
|