vtlengine 1.0.2__py3-none-any.whl → 1.0.3__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 +12 -5
- vtlengine/API/__init__.py +8 -8
- vtlengine/AST/ASTConstructor.py +23 -43
- vtlengine/AST/ASTConstructorModules/Expr.py +69 -84
- vtlengine/AST/ASTConstructorModules/ExprComponents.py +47 -57
- vtlengine/AST/ASTConstructorModules/Terminals.py +28 -39
- vtlengine/AST/ASTTemplate.py +0 -1
- vtlengine/AST/DAG/__init__.py +12 -15
- vtlengine/AST/Grammar/tokens.py +2 -2
- vtlengine/AST/VtlVisitor.py +0 -1
- vtlengine/AST/__init__.py +2 -3
- vtlengine/DataTypes/TimeHandling.py +10 -7
- vtlengine/DataTypes/__init__.py +17 -24
- vtlengine/Exceptions/__init__.py +3 -5
- vtlengine/Exceptions/messages.py +68 -56
- vtlengine/Interpreter/__init__.py +82 -103
- vtlengine/Model/__init__.py +10 -12
- vtlengine/Operators/Aggregation.py +14 -14
- vtlengine/Operators/Analytic.py +3 -10
- vtlengine/Operators/Assignment.py +2 -3
- vtlengine/Operators/Boolean.py +5 -7
- vtlengine/Operators/CastOperator.py +12 -13
- vtlengine/Operators/Clause.py +11 -13
- vtlengine/Operators/Comparison.py +31 -17
- vtlengine/Operators/Conditional.py +48 -49
- vtlengine/Operators/General.py +4 -4
- vtlengine/Operators/HROperators.py +41 -34
- vtlengine/Operators/Join.py +18 -22
- vtlengine/Operators/Numeric.py +44 -45
- vtlengine/Operators/RoleSetter.py +6 -8
- vtlengine/Operators/Set.py +7 -12
- vtlengine/Operators/String.py +19 -27
- vtlengine/Operators/Time.py +298 -109
- vtlengine/Operators/Validation.py +4 -7
- vtlengine/Operators/__init__.py +38 -41
- vtlengine/Utils/__init__.py +133 -114
- vtlengine/__init__.py +1 -1
- vtlengine/files/output/__init__.py +2 -2
- vtlengine/files/output/_time_period_representation.py +0 -1
- vtlengine/files/parser/__init__.py +16 -18
- vtlengine/files/parser/_time_checking.py +1 -2
- {vtlengine-1.0.2.dist-info → vtlengine-1.0.3.dist-info}/METADATA +5 -2
- vtlengine-1.0.3.dist-info/RECORD +58 -0
- vtlengine-1.0.2.dist-info/RECORD +0 -58
- {vtlengine-1.0.2.dist-info → vtlengine-1.0.3.dist-info}/LICENSE.md +0 -0
- {vtlengine-1.0.2.dist-info → vtlengine-1.0.3.dist-info}/WHEEL +0 -0
vtlengine/Exceptions/messages.py
CHANGED
|
@@ -10,7 +10,7 @@ All exceptions exposed by the Vtl engine.
|
|
|
10
10
|
centralised_messages = {
|
|
11
11
|
# Input Validation errors
|
|
12
12
|
"0-1-2-1": "Invalid json structure because additional properties have been supplied "
|
|
13
|
-
|
|
13
|
+
"on file {filename}.",
|
|
14
14
|
"0-1-2-2": "Errors found on file {filename}: {errors}",
|
|
15
15
|
"0-1-2-3": "Component {component} is duplicated.",
|
|
16
16
|
"0-1-2-4": "Invalid json structure because {err} on file {filename}.",
|
|
@@ -22,18 +22,19 @@ centralised_messages = {
|
|
|
22
22
|
"0-1-1-2": "The provided {source} must have data to can infer the data structure.",
|
|
23
23
|
"0-1-1-3": "Can not infer data structure: {errors}.",
|
|
24
24
|
"0-1-1-4": "On Dataset {name} loading: An identifier cannot have null values, found null "
|
|
25
|
-
|
|
25
|
+
"values on {null_identifier}.",
|
|
26
26
|
"0-1-1-5": "On Dataset {name} loading: Datasets without identifiers must have 0 or "
|
|
27
|
-
|
|
27
|
+
"1 datapoints.",
|
|
28
28
|
"0-1-1-6": "Duplicated records. Combination of identifiers are repeated.",
|
|
29
29
|
"0-1-1-7": "G1 - The provided CSV file is empty.",
|
|
30
30
|
"0-1-1-8": "The following identifiers {ids} were not found , review file {file}.",
|
|
31
31
|
"0-1-1-9": "You have a problem related with commas, review rfc4180 standard, review file "
|
|
32
|
-
|
|
32
|
+
"{file}.",
|
|
33
33
|
"0-1-1-10": "On Dataset {name} loading: Component {comp_name} is missing in Datapoints.",
|
|
34
34
|
"0-1-1-11": "Wrong data in the file for this scalardataset {name}.",
|
|
35
35
|
"0-1-1-12": "On Dataset {name} loading: not possible to cast column {column} to {type}.",
|
|
36
36
|
"0-1-1-13": "Invalid key on {field} field: {key}{closest_key}.",
|
|
37
|
+
"0-1-1-14": "Empty datasets {dataset1} and {dataset2} shape missmatch.",
|
|
37
38
|
"0-1-0-1": " Trying to redefine input datasets {dataset}.", # Semantic Error
|
|
38
39
|
# ------------Operators-------------
|
|
39
40
|
# General Semantic errors
|
|
@@ -58,7 +59,7 @@ centralised_messages = {
|
|
|
58
59
|
"1-1-1-13": "At op {op}: Component {comp_name} role must be '{role_1}', found '{role_2}'.",
|
|
59
60
|
# "1-1-1-14": "At op {op}: Dataset {name} type must be '{type_1}'.",
|
|
60
61
|
"1-1-1-15": "At op {op}: Datasets {name_1} and {name_2} does not contain the same number of "
|
|
61
|
-
|
|
62
|
+
"{type}.",
|
|
62
63
|
"1-1-1-16": "Found structure not nullable and null values.",
|
|
63
64
|
# "1-1-1-17": "At op {op}: Problem with nullability for this components {name_1} and {name_2}.",
|
|
64
65
|
# "1-1-1-18": "No {type} {value} found.",
|
|
@@ -75,36 +76,36 @@ centralised_messages = {
|
|
|
75
76
|
# TODO: Use error message 1-1-1-8
|
|
76
77
|
# "1-1-2-1": "At op {op}: No measures found to aggregate.",
|
|
77
78
|
"1-1-2-2": "At op {op}: Only Identifiers are allowed for grouping, "
|
|
78
|
-
|
|
79
|
+
"found {id_name} - {id_type}.",
|
|
79
80
|
"1-1-2-3": "Having component output type must be boolean, found {type}.",
|
|
80
81
|
# "1-1-2-4": "At op {op}: Component {id_name} not found in dataset",
|
|
81
82
|
# Analytic errors
|
|
82
83
|
# TODO: Use error message 1-1-1-8
|
|
83
84
|
# "1-1-3-1": "At op {op}: No measures found to analyse.",
|
|
84
85
|
"1-1-3-2": "At op {op}: Only Identifiers are allowed for partitioning, "
|
|
85
|
-
|
|
86
|
+
"found {id_name} - {id_type}.",
|
|
86
87
|
# Cast errors
|
|
87
88
|
"1-1-5-1": "Type {type_1}, cannot be cast to {type_2}.",
|
|
88
89
|
"1-1-5-3": "Impossible to cast from type {type_1} to {type_2}, without providing a mask.",
|
|
89
90
|
"1-1-5-4": "Invalid mask to cast from type {type_1} to {type_2}.",
|
|
90
91
|
"1-1-5-5": "A mask can't be provided to cast from type {type_1} to {type_2}. Mask provided: "
|
|
91
|
-
|
|
92
|
+
"{mask_value}.",
|
|
92
93
|
"2-1-5-1": "Impossible to cast {value} from type {type_1} to {type_2}.",
|
|
93
94
|
# Clause errors
|
|
94
95
|
# "1-1-6-1": "At op {op}: Component {comp_name} not found in dataset {dataset_name}.",
|
|
95
96
|
"1-1-6-2": "At op {op}: The identifier {name} in dataset {dataset} could not be included "
|
|
96
|
-
|
|
97
|
+
"in the {op} op.",
|
|
97
98
|
# TODO: This is not possible at all, as calc clause adds a new column and
|
|
98
99
|
# identifiers are still unique
|
|
99
100
|
# "1-1-6-3": "Found duplicated values on identifiers after Calc clause.",
|
|
100
101
|
"1-1-6-4": "At op {op}: Alias symbol cannot have the name of a component symbol: "
|
|
101
|
-
|
|
102
|
+
"{symbol_name} - {comp_name}.",
|
|
102
103
|
"1-1-6-5": "At op {op}: Scalar values are not allowed at sub operator, found {name}.",
|
|
103
104
|
"1-1-6-6": "Membership is not allowed inside a clause, found {dataset_name}#{comp_name}.",
|
|
104
105
|
"1-1-6-7": "Cannot use component {comp_name} as it was generated in another calc expression.",
|
|
105
106
|
# all the components used in calccomp must belong to the operand dataset
|
|
106
107
|
"1-1-6-8": "Cannot use component {comp_name} for rename, it is already in the dataset "
|
|
107
|
-
|
|
108
|
+
"{dataset_name}.",
|
|
108
109
|
# it is the same error that 1-1-8-1 AND similar but not the same 1-3-1
|
|
109
110
|
"1-1-6-9": "At op {op}: The following components are repeated: {from_components}.",
|
|
110
111
|
"1-1-6-10": "At op {op}: Component {operand} in dataset {dataset_name} is not an identifier",
|
|
@@ -115,25 +116,25 @@ centralised_messages = {
|
|
|
115
116
|
# "1-1-6-15": "At op {op}: Component {comp_name} already exists in dataset {dataset_name}",
|
|
116
117
|
# Comparison errors
|
|
117
118
|
"1-1-7-1": "At op {op}: Value in {left_name} of type {left_type} is not comparable to value "
|
|
118
|
-
|
|
119
|
+
"{right_name} of type {right_type}.",
|
|
119
120
|
# Conditional errors
|
|
120
121
|
"1-1-9-1": "At op {op}: The evaluation condition must result in a Boolean "
|
|
121
|
-
|
|
122
|
+
"expression, found '{type}'.",
|
|
122
123
|
"1-1-9-3": "At op {op}: Then clause {then_name} and else clause {else_name}, both must be "
|
|
123
|
-
|
|
124
|
+
"Scalars.",
|
|
124
125
|
"1-1-9-4": "At op {op}: The condition dataset {name} must contain an unique measure.",
|
|
125
126
|
"1-1-9-5": "At op {op}: The condition dataset Measure must be a Boolean, found '{type}'.",
|
|
126
127
|
"1-1-9-6": "At op {op}: Then-else datasets have different number of identifiers compared "
|
|
127
|
-
|
|
128
|
+
"with condition dataset.",
|
|
128
129
|
"1-1-9-9": "At op {op}: {clause} component {clause_name} role must be {role_1}, found "
|
|
129
|
-
|
|
130
|
+
"{role_2}.",
|
|
130
131
|
"1-1-9-10": "At op {op}: {clause} dataset have different number of identifiers compared with "
|
|
131
|
-
|
|
132
|
+
"condition dataset.",
|
|
132
133
|
"1-1-9-11": "At op {op}: Condition component {name} must be Boolean, found {type}.",
|
|
133
134
|
"1-1-9-12": "At op {op}: then clause {then_symbol} and else clause {else_symbol}, both must "
|
|
134
|
-
|
|
135
|
+
"be Datasets or at least one of them a Scalar.",
|
|
135
136
|
"1-1-9-13": "At op {op}: then {then} and else {else_clause} datasets must contain the same "
|
|
136
|
-
|
|
137
|
+
"number of components.",
|
|
137
138
|
"2-1-9-1": "At op {op}: Condition operators must have the same operator type.",
|
|
138
139
|
"2-1-9-2": "At op {op}: Condition {name} it's not a boolean.",
|
|
139
140
|
"2-1-9-3": "At op {op}: All then and else operands must be scalars.",
|
|
@@ -141,21 +142,20 @@ centralised_messages = {
|
|
|
141
142
|
"2-1-9-5": "At op {op}: Condition Dataset {name} measure must be Boolean.",
|
|
142
143
|
"2-1-9-6": "At op {op}: At least a then or else operand must be Dataset.",
|
|
143
144
|
"2-1-9-7": "At op {op}: All Dataset operands must have the same components.",
|
|
144
|
-
|
|
145
145
|
# Data Validation errors
|
|
146
146
|
"1-1-10-1": "At op {op}: The {op_type} operand must have exactly one measure of type {me_type}",
|
|
147
147
|
"1-1-10-2": "At op {op}: Number of variable has to be equal between the call and signature.",
|
|
148
148
|
"1-1-10-3": "At op {op}: Name in the call {found} has to be equal to variable rule in "
|
|
149
|
-
|
|
149
|
+
"signature {expected}.",
|
|
150
150
|
"1-1-10-4": "At op {op}: When a hierarchical ruleset is defined for value domain, it is "
|
|
151
|
-
|
|
151
|
+
"necessary to specify the component with the rule clause on call.",
|
|
152
152
|
"1-1-10-5": "No rules to analyze on Hierarchy Roll-up as rules have no = operator.",
|
|
153
153
|
"1-1-10-6": "At op {op}: Name in the call {found} has to be equal to variable condition in "
|
|
154
|
-
|
|
154
|
+
"signature {expected} .",
|
|
155
155
|
"1-1-10-7": "Not found component {comp_name} on signature.",
|
|
156
156
|
"1-1-10-8": "At op {op}: Measures involved have to be numerical, other types found {found}.",
|
|
157
157
|
"1-1-10-9": "Invalid signature for the ruleset {ruleset}. On variables, condComp and "
|
|
158
|
-
|
|
158
|
+
"ruleComp must be the same",
|
|
159
159
|
# General Operators
|
|
160
160
|
# "1-1-12-1": "At op {op}: You could not recalculate the identifier {name} on dataset "
|
|
161
161
|
# "{dataset}.",
|
|
@@ -165,49 +165,49 @@ centralised_messages = {
|
|
|
165
165
|
"1-1-13-1": "At op {op}: Duplicated alias {duplicates}.",
|
|
166
166
|
"1-1-13-2": "At op {op}: Missing mandatory aliasing.",
|
|
167
167
|
"1-1-13-3": "At op {op}: Join conflict with duplicated names for column {name} from original "
|
|
168
|
-
|
|
168
|
+
"datasets.",
|
|
169
169
|
"1-1-13-4": "At op {op}: Using clause, using={using_names}, does not define all the "
|
|
170
|
-
|
|
170
|
+
"identifiers, of non reference dataset {dataset}.",
|
|
171
171
|
"1-1-13-5": "At op {op}: Invalid subcase B1, All the datasets must share as identifiers the "
|
|
172
|
-
|
|
172
|
+
"using ones.",
|
|
173
173
|
# not in use but we keep for later, in use 1-1-13-4
|
|
174
174
|
"1-1-13-6": "At op {op}: Invalid subcase B2, All the declared using components "
|
|
175
|
-
|
|
176
|
-
|
|
175
|
+
"'{using_components}' must be present as components in the reference dataset "
|
|
176
|
+
"'{reference}'.",
|
|
177
177
|
"1-1-13-7": "At op {op}: Invalid subcase B2, All the non reference datasets must share as "
|
|
178
|
-
|
|
178
|
+
"identifiers the using ones.",
|
|
179
179
|
"1-1-13-8": "At op {op}: No available using clause.",
|
|
180
180
|
"1-1-13-9": "Ambiguity for this variable {comp_name} inside a join clause.",
|
|
181
181
|
"1-1-13-10": "The join operator does not perform scalar/component operations.",
|
|
182
182
|
"1-1-13-11": "At op {op}: Invalid subcase A, {dataset_reference} should be a superset but "
|
|
183
|
-
|
|
183
|
+
"{component} not found.",
|
|
184
184
|
# inner_join and left join
|
|
185
185
|
"1-1-13-12": "At op {op}: Invalid subcase A. There are different identifiers for the provided "
|
|
186
|
-
|
|
186
|
+
"datasets",
|
|
187
187
|
# full_join
|
|
188
188
|
"1-1-13-13": "At op {op}: Invalid subcase A. There are not same number of identifiers for the "
|
|
189
|
-
|
|
189
|
+
"provided datasets",
|
|
190
190
|
# full_join
|
|
191
191
|
"1-1-13-14": "Cannot perform a join over a Dataset Without Identifiers: {name}.",
|
|
192
192
|
"1-1-13-15": "At op {op}: {comp_name} has to be a Measure for all the provided datasets inside "
|
|
193
|
-
|
|
193
|
+
"the join",
|
|
194
194
|
"1-1-13-16": "At op {op}: Invalid use, please review : {msg}.",
|
|
195
195
|
"1-1-13-17": "At op {op}: {comp_name} not present in the dataset(result from join VDS) at the "
|
|
196
|
-
|
|
196
|
+
"time it is called",
|
|
197
197
|
# Operators general errors
|
|
198
198
|
"1-1-14-1": "At op {op}: Measure names don't match: {left} - {right}.",
|
|
199
199
|
"1-1-14-3": "At op {op}: Invalid scalar types for identifiers at DataSet {dataset}. One {type} "
|
|
200
|
-
|
|
200
|
+
"identifier expected, {count} found.",
|
|
201
201
|
"1-1-14-5": "At op {op}: {names} with type/s {types} is not compatible with {op}",
|
|
202
202
|
"1-1-14-6": "At op {op}: {comp_name} with type {comp_type} and scalar_set with type "
|
|
203
|
-
|
|
203
|
+
"{scalar_type} is not compatible with {op}",
|
|
204
204
|
# "1-1-14-8": "At op {op}: Operation not allowed for multimeasure datasets.",
|
|
205
205
|
"1-1-14-9": "At op {op}: {names} with type/s {types} is not compatible with {op} on datasets "
|
|
206
|
-
|
|
206
|
+
"{datasets}.",
|
|
207
207
|
# Numeric Operators
|
|
208
208
|
"1-1-15-8": "At op {op}: {op} operator cannot have a {comp_type} as parameter.",
|
|
209
209
|
"2-1-15-1": "At op {op}: Component {comp_name} from dataset {dataset_name} contains negative "
|
|
210
|
-
|
|
210
|
+
"values.",
|
|
211
211
|
"2-1-15-2": "At op {op}: Value {value} could not be negative.",
|
|
212
212
|
"2-1-15-3": "At op {op}: Base value {value} could not be less or equal 0.",
|
|
213
213
|
"2-1-15-4": "At op {op}: Invalid values in Component {name}.",
|
|
@@ -216,7 +216,7 @@ centralised_messages = {
|
|
|
216
216
|
"2-1-15-7": "At op {op}: {op} operator cannot be a dataset.",
|
|
217
217
|
# Set Operators
|
|
218
218
|
"1-1-17-1": "At op {op}: Datasets {dataset_1} and {dataset_2} have different number of "
|
|
219
|
-
|
|
219
|
+
"components",
|
|
220
220
|
# String Operators
|
|
221
221
|
# "1-1-18-1": "At op {op}: Invalid Dataset {name}. Dataset with one measure expected.",
|
|
222
222
|
"1-1-18-2": "At op {op}: Composition of DataSet and Component is not allowed.",
|
|
@@ -230,29 +230,41 @@ centralised_messages = {
|
|
|
230
230
|
"1-1-19-2": "At op {op}: Unknown date type for {op}.",
|
|
231
231
|
"1-1-19-3": "At op {op}: Invalid {param} for {op}.",
|
|
232
232
|
"1-1-19-4": "At op {op}: Invalid values {value_1} and {value_2}, periodIndTo parameter must be "
|
|
233
|
-
|
|
233
|
+
"a larger duration value than periodIndFrom parameter.",
|
|
234
234
|
"1-1-19-5": "At op {op}: periodIndTo parameter must be a larger duration value than the values "
|
|
235
|
-
|
|
235
|
+
"to aggregate.",
|
|
236
236
|
"1-1-19-6": "At op {op}: Time type used in the component {comp} is not supported.",
|
|
237
237
|
"1-1-19-7": "At op {op}: can be applied only on Data Sets (of time series) and returns a Data "
|
|
238
|
-
|
|
238
|
+
"Set (of time series).",
|
|
239
239
|
# flow_to_stock, stock_to_flow
|
|
240
240
|
"1-1-19-8": "At op {op}: {op} can only be applied to a {comp_type}",
|
|
241
241
|
"1-1-19-9": "At op {op}: {op} can only be applied to a {comp_type} with a {param}",
|
|
242
|
+
# New Unary time operators
|
|
243
|
+
"1-1-19-10": "{op} can only be applied to operands with data type as Date or Time Period",
|
|
242
244
|
# Other time operators
|
|
243
245
|
"2-1-19-1": "At op {op}: Invalid values {value_1} and {value_2} for duration, "
|
|
244
|
-
|
|
245
|
-
|
|
246
|
+
"periodIndTo parameter must be a larger duration value than the "
|
|
247
|
+
"values to aggregate.",
|
|
246
248
|
"2-1-19-2": "Invalid period indicator {period}.",
|
|
247
249
|
"2-1-19-3": "Only same period indicator allowed for both parameters ({period1} != {period2}).",
|
|
248
250
|
"2-1-19-4": "Date setter, ({value} > {date}). Cannot set date1 with a value higher than date2.",
|
|
249
251
|
"2-1-19-5": "Date setter, ({value} < {date}). Cannot set date2 with a value lower than date1.",
|
|
250
252
|
"2-1-19-6": "Invalid period format, must be YYYY-(L)NNN: {period_format}",
|
|
251
253
|
"2-1-19-7": "Period Number must be between 1 and {periods} for period indicator "
|
|
252
|
-
|
|
253
|
-
"2-1-19-8": "Invalid date format, must be YYYY-MM-DD: {
|
|
254
|
+
"{period_indicator}.",
|
|
255
|
+
"2-1-19-8": "Invalid date format, must be YYYY-MM-DD: {date}",
|
|
254
256
|
"2-1-19-9": "Invalid day {day} for year {year}.",
|
|
255
257
|
"2-1-19-10": "Invalid year {year}, must be between 1900 and 9999.",
|
|
258
|
+
"2-1-19-11": "{op} operator is not compatible with time values",
|
|
259
|
+
"2-1-19-12": "At op {op}: Invalid param type {type} for param {name}, "
|
|
260
|
+
"expected {expected}.",
|
|
261
|
+
"2-1-19-13": "At op {op}: Invalid param data_type {type} for param {name}, "
|
|
262
|
+
"expected {expected}.",
|
|
263
|
+
"2-1-19-14": "At op {op}: Invalid dataset {name}, requires at least one Date/Time_Period "
|
|
264
|
+
"measure.",
|
|
265
|
+
"2-1-19-15": "{op} can only be applied according to the following mask: PY/YDDD/D",
|
|
266
|
+
"2-1-19-16": "{op} can only be applied according to the following mask: PM/MDD/D",
|
|
267
|
+
"2-1-19-17": "{op} can only be positive numbers",
|
|
256
268
|
# ----------- Interpreter Common ------
|
|
257
269
|
"2-3-1": "{comp_type} {comp_name} not found.",
|
|
258
270
|
"2-3-2": "{op_type} cannot be used with {node_op} operators.",
|
|
@@ -281,13 +293,13 @@ centralised_messages = {
|
|
|
281
293
|
"1-3-22": "Unable to categorize {node_value}.",
|
|
282
294
|
"1-3-23": "Missing value domain '{name}' definition, please provide an structure.",
|
|
283
295
|
"1-3-24": "Internal error on Analytic operators inside a calc, No partition or "
|
|
284
|
-
|
|
296
|
+
"order symbol found.",
|
|
285
297
|
"1-3-26": "Value domain {name} not found.",
|
|
286
298
|
"1-3-27": "Dataset without identifiers are not allowed in {op} operator.",
|
|
287
299
|
"1-3-28": "At op {op}: invalid number of parameters: received {received}, expected at "
|
|
288
|
-
|
|
300
|
+
"least: {expected}",
|
|
289
301
|
"1-3-29": "At op {op}: can not use user defined operator that returns a component outside "
|
|
290
|
-
|
|
302
|
+
"clause operator or rule",
|
|
291
303
|
"1-3-30": "At op {op}: too many parameters: received {received}, expected: {expected}",
|
|
292
304
|
"1-3-31": "Cannot use component {name} outside an aggregate function in a having clause.",
|
|
293
305
|
"1-3-32": "Cannot perform operation {op} inside having clause.",
|
|
@@ -301,23 +313,23 @@ centralised_messages = {
|
|
|
301
313
|
"1-4-1-3": "At op {op}: using variable {value}, not defined as an argument.",
|
|
302
314
|
"1-4-1-4": "Found duplicates at arguments naming, please review {type} " "definition {op}.",
|
|
303
315
|
"1-4-1-5": "Found duplicates at rule naming: {names}. Please review {type} "
|
|
304
|
-
|
|
316
|
+
"{ruleset_name} definition.",
|
|
305
317
|
"1-4-1-6": "At op {op}: Arguments incoherence, {defined} defined {passed} passed.",
|
|
306
318
|
"1-4-1-7": "All rules must be named or not named, but found mixed criteria at {type} "
|
|
307
|
-
|
|
319
|
+
"definition {name}.",
|
|
308
320
|
"1-4-1-8": "All rules must have different code items in the left side of '=' in hierarchy "
|
|
309
|
-
|
|
321
|
+
"operator at hierachical ruleset definition {name}.",
|
|
310
322
|
"1-4-1-9": "At op check_datapoint: {name} has an invalid datatype expected DataSet, found "
|
|
311
|
-
|
|
323
|
+
"Scalar.",
|
|
312
324
|
# AST Creation
|
|
313
325
|
"1-4-2-1": "Eval could not be called without a {option} type definition.",
|
|
314
326
|
"1-4-2-2": "Optional or empty expression node is not allowed in time_agg.",
|
|
315
327
|
"1-4-2-3": "{value} could not be called in the count.",
|
|
316
328
|
"1-4-2-4": "At op {op}: Only one order_by element must be used in Analytic with range "
|
|
317
|
-
|
|
329
|
+
"windowing.",
|
|
318
330
|
"1-4-2-5": "At op {op}: User defined operator without returns is not implemented.",
|
|
319
331
|
"1-4-2-6": "At op {op}: Window must be provided.",
|
|
320
332
|
"1-4-2-7": "At op {op}: Partition by or order by clause must be provided for Analytic "
|
|
321
|
-
|
|
333
|
+
"operators.",
|
|
322
334
|
# Not Implemented Error
|
|
323
335
|
}
|
|
@@ -3,61 +3,35 @@ from dataclasses import dataclass
|
|
|
3
3
|
from pathlib import Path
|
|
4
4
|
from typing import Any, Dict, List, Optional, Union
|
|
5
5
|
|
|
6
|
+
import pandas as pd
|
|
7
|
+
|
|
6
8
|
import vtlengine.AST as AST
|
|
7
9
|
import vtlengine.Exceptions
|
|
8
10
|
import vtlengine.Operators as Operators
|
|
9
|
-
import pandas as pd
|
|
10
|
-
from vtlengine.DataTypes import (
|
|
11
|
-
BASIC_TYPES,
|
|
12
|
-
check_unary_implicit_promotion,
|
|
13
|
-
ScalarType,
|
|
14
|
-
Boolean,
|
|
15
|
-
SCALAR_TYPES_CLASS_REVERSE,
|
|
16
|
-
)
|
|
17
|
-
from vtlengine.Operators.Aggregation import extract_grouping_identifiers
|
|
18
|
-
from vtlengine.Operators.Assignment import Assignment
|
|
19
|
-
from vtlengine.Operators.CastOperator import Cast
|
|
20
|
-
from vtlengine.Operators.Comparison import Between, ExistIn
|
|
21
|
-
from vtlengine.Operators.Conditional import If, Case
|
|
22
|
-
from vtlengine.Operators.General import Eval
|
|
23
|
-
from vtlengine.Operators.HROperators import get_measure_from_dataset, HAAssignment, Hierarchy
|
|
24
|
-
from vtlengine.Operators.Numeric import Round, Trunc
|
|
25
|
-
from vtlengine.Operators.String import Instr, Replace, Substr
|
|
26
|
-
from vtlengine.Operators.Time import Fill_time_series, Time_Aggregation, Current_Date
|
|
27
|
-
from vtlengine.Operators.Validation import Check, Check_Datapoint, Check_Hierarchy
|
|
28
|
-
from vtlengine.Utils import (
|
|
29
|
-
AGGREGATION_MAPPING,
|
|
30
|
-
ANALYTIC_MAPPING,
|
|
31
|
-
BINARY_MAPPING,
|
|
32
|
-
JOIN_MAPPING,
|
|
33
|
-
REGULAR_AGGREGATION_MAPPING,
|
|
34
|
-
ROLE_SETTER_MAPPING,
|
|
35
|
-
SET_MAPPING,
|
|
36
|
-
UNARY_MAPPING,
|
|
37
|
-
THEN_ELSE,
|
|
38
|
-
HR_UNARY_MAPPING,
|
|
39
|
-
HR_COMP_MAPPING,
|
|
40
|
-
HR_NUM_BINARY_MAPPING,
|
|
41
|
-
)
|
|
42
|
-
from vtlengine.files.output import save_datapoints
|
|
43
|
-
from vtlengine.files.output._time_period_representation import TimePeriodRepresentation
|
|
44
|
-
from vtlengine.files.parser import load_datapoints, _fill_dataset_empty_data
|
|
45
|
-
|
|
46
11
|
from vtlengine.AST.ASTTemplate import ASTTemplate
|
|
47
12
|
from vtlengine.AST.DAG import HRDAGAnalyzer
|
|
48
|
-
from vtlengine.AST.DAG._words import
|
|
13
|
+
from vtlengine.AST.DAG._words import DELETE, GLOBAL, INSERT
|
|
49
14
|
from vtlengine.AST.Grammar.tokens import (
|
|
50
15
|
AGGREGATE,
|
|
51
16
|
ALL,
|
|
52
17
|
APPLY,
|
|
53
18
|
AS,
|
|
54
19
|
BETWEEN,
|
|
20
|
+
CALC,
|
|
21
|
+
CAST,
|
|
55
22
|
CHECK_DATAPOINT,
|
|
23
|
+
CHECK_HIERARCHY,
|
|
24
|
+
COUNT,
|
|
25
|
+
CURRENT_DATE,
|
|
26
|
+
DATE_ADD,
|
|
56
27
|
DROP,
|
|
28
|
+
EQ,
|
|
57
29
|
EXISTS_IN,
|
|
58
30
|
EXTERNAL,
|
|
31
|
+
FILL_TIME_SERIES,
|
|
59
32
|
FILTER,
|
|
60
33
|
HAVING,
|
|
34
|
+
HIERARCHY,
|
|
61
35
|
INSTR,
|
|
62
36
|
KEEP,
|
|
63
37
|
MEMBERSHIP,
|
|
@@ -66,26 +40,53 @@ from vtlengine.AST.Grammar.tokens import (
|
|
|
66
40
|
SUBSTR,
|
|
67
41
|
TRUNC,
|
|
68
42
|
WHEN,
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
COUNT,
|
|
43
|
+
)
|
|
44
|
+
from vtlengine.DataTypes import (
|
|
45
|
+
BASIC_TYPES,
|
|
46
|
+
SCALAR_TYPES_CLASS_REVERSE,
|
|
47
|
+
Boolean,
|
|
48
|
+
ScalarType,
|
|
49
|
+
check_unary_implicit_promotion,
|
|
77
50
|
)
|
|
78
51
|
from vtlengine.Exceptions import SemanticError
|
|
52
|
+
from vtlengine.files.output import save_datapoints
|
|
53
|
+
from vtlengine.files.output._time_period_representation import TimePeriodRepresentation
|
|
54
|
+
from vtlengine.files.parser import _fill_dataset_empty_data, load_datapoints
|
|
79
55
|
from vtlengine.Model import (
|
|
56
|
+
Component,
|
|
80
57
|
DataComponent,
|
|
81
58
|
Dataset,
|
|
82
59
|
ExternalRoutine,
|
|
83
60
|
Role,
|
|
84
61
|
Scalar,
|
|
85
62
|
ScalarSet,
|
|
86
|
-
Component,
|
|
87
63
|
ValueDomain,
|
|
88
64
|
)
|
|
65
|
+
from vtlengine.Operators.Aggregation import extract_grouping_identifiers
|
|
66
|
+
from vtlengine.Operators.Assignment import Assignment
|
|
67
|
+
from vtlengine.Operators.CastOperator import Cast
|
|
68
|
+
from vtlengine.Operators.Comparison import Between, ExistIn
|
|
69
|
+
from vtlengine.Operators.Conditional import Case, If
|
|
70
|
+
from vtlengine.Operators.General import Eval
|
|
71
|
+
from vtlengine.Operators.HROperators import HAAssignment, Hierarchy, get_measure_from_dataset
|
|
72
|
+
from vtlengine.Operators.Numeric import Round, Trunc
|
|
73
|
+
from vtlengine.Operators.String import Instr, Replace, Substr
|
|
74
|
+
from vtlengine.Operators.Time import Current_Date, Date_Add, Fill_time_series, Time_Aggregation
|
|
75
|
+
from vtlengine.Operators.Validation import Check, Check_Datapoint, Check_Hierarchy
|
|
76
|
+
from vtlengine.Utils import (
|
|
77
|
+
AGGREGATION_MAPPING,
|
|
78
|
+
ANALYTIC_MAPPING,
|
|
79
|
+
BINARY_MAPPING,
|
|
80
|
+
HR_COMP_MAPPING,
|
|
81
|
+
HR_NUM_BINARY_MAPPING,
|
|
82
|
+
HR_UNARY_MAPPING,
|
|
83
|
+
JOIN_MAPPING,
|
|
84
|
+
REGULAR_AGGREGATION_MAPPING,
|
|
85
|
+
ROLE_SETTER_MAPPING,
|
|
86
|
+
SET_MAPPING,
|
|
87
|
+
THEN_ELSE,
|
|
88
|
+
UNARY_MAPPING,
|
|
89
|
+
)
|
|
89
90
|
|
|
90
91
|
|
|
91
92
|
# noinspection PyTypeChecker
|
|
@@ -200,9 +201,9 @@ class InterpreterAnalyzer(ASTTemplate):
|
|
|
200
201
|
if isinstance(child, (AST.Assignment, AST.PersistentAssignment)):
|
|
201
202
|
vtlengine.Exceptions.dataset_output = child.left.value # type: ignore[attr-defined]
|
|
202
203
|
self._load_datapoints_efficient(statement_num)
|
|
203
|
-
if not isinstance(child, (AST.HRuleset, AST.DPRuleset, AST.Operator))
|
|
204
|
-
|
|
205
|
-
|
|
204
|
+
if (not isinstance(child, (AST.HRuleset, AST.DPRuleset, AST.Operator)) and
|
|
205
|
+
not isinstance(child, (AST.Assignment, AST.PersistentAssignment))):
|
|
206
|
+
raise SemanticError("1-3-17")
|
|
206
207
|
result = self.visit(child)
|
|
207
208
|
|
|
208
209
|
# Reset some handlers (joins and if)
|
|
@@ -368,14 +369,14 @@ class InterpreterAnalyzer(ASTTemplate):
|
|
|
368
369
|
is_from_if = self.is_from_if
|
|
369
370
|
self.is_from_if = False
|
|
370
371
|
|
|
371
|
-
if self.is_from_join and node.op in [MEMBERSHIP, AGGREGATE]
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
372
|
+
if (self.is_from_join and node.op in [MEMBERSHIP, AGGREGATE] and
|
|
373
|
+
hasattr(node.left, "value") and hasattr(node.right, "value")):
|
|
374
|
+
if self.udo_params is not None and node.right.value in self.udo_params[-1]:
|
|
375
|
+
comp_name = f"{node.left.value}#{self.udo_params[-1][node.right.value]}"
|
|
376
|
+
else:
|
|
377
|
+
comp_name = f"{node.left.value}#{node.right.value}"
|
|
378
|
+
ast_var_id = AST.VarID(value=comp_name)
|
|
379
|
+
return self.visit(ast_var_id)
|
|
379
380
|
left_operand = self.visit(node.left)
|
|
380
381
|
right_operand = self.visit(node.right)
|
|
381
382
|
if is_from_if:
|
|
@@ -453,10 +454,7 @@ class InterpreterAnalyzer(ASTTemplate):
|
|
|
453
454
|
grouping_op = node.grouping_op
|
|
454
455
|
if node.grouping is not None:
|
|
455
456
|
if grouping_op == "group all":
|
|
456
|
-
if self.only_semantic
|
|
457
|
-
data = None
|
|
458
|
-
else:
|
|
459
|
-
data = copy(operand.data)
|
|
457
|
+
data = None if self.only_semantic else copy(operand.data)
|
|
460
458
|
self.aggregation_dataset = Dataset(
|
|
461
459
|
name=operand.name, components=operand.components, data=data
|
|
462
460
|
)
|
|
@@ -730,7 +728,7 @@ class InterpreterAnalyzer(ASTTemplate):
|
|
|
730
728
|
nullable=self.aggregation_dataset.components[node.value].nullable,
|
|
731
729
|
)
|
|
732
730
|
if self.is_from_regular_aggregation:
|
|
733
|
-
if self.is_from_join and node.value in self.datasets
|
|
731
|
+
if self.is_from_join and node.value in self.datasets:
|
|
734
732
|
return self.datasets[node.value]
|
|
735
733
|
if self.regular_aggregation_dataset is not None:
|
|
736
734
|
if node.value in self.datasets and isinstance(self.datasets[node.value], Scalar):
|
|
@@ -746,10 +744,8 @@ class InterpreterAnalyzer(ASTTemplate):
|
|
|
746
744
|
is_partial_present = 0
|
|
747
745
|
found_comp = None
|
|
748
746
|
for comp_name in self.regular_aggregation_dataset.get_components_names():
|
|
749
|
-
if "#" in comp_name and comp_name.split("#")[1] == node.value
|
|
750
|
-
|
|
751
|
-
found_comp = comp_name
|
|
752
|
-
elif "#" in node.value and node.value.split("#")[1] == comp_name:
|
|
747
|
+
if ("#" in comp_name and comp_name.split("#")[1] == node.value or "#"
|
|
748
|
+
in node.value and node.value.split("#")[1] == comp_name):
|
|
753
749
|
is_partial_present += 1
|
|
754
750
|
found_comp = comp_name
|
|
755
751
|
if is_partial_present == 0:
|
|
@@ -789,10 +785,7 @@ class InterpreterAnalyzer(ASTTemplate):
|
|
|
789
785
|
raise SemanticError(
|
|
790
786
|
"1-1-1-10", comp_name=node.value, dataset_name=self.ruleset_dataset.name
|
|
791
787
|
)
|
|
792
|
-
if self.rule_data is None
|
|
793
|
-
data = None
|
|
794
|
-
else:
|
|
795
|
-
data = self.rule_data[comp_name]
|
|
788
|
+
data = None if self.rule_data is None else self.rule_data[comp_name]
|
|
796
789
|
return DataComponent(
|
|
797
790
|
name=comp_name,
|
|
798
791
|
data=data,
|
|
@@ -809,10 +802,7 @@ class InterpreterAnalyzer(ASTTemplate):
|
|
|
809
802
|
elements = []
|
|
810
803
|
duplicates = []
|
|
811
804
|
for child in node.children:
|
|
812
|
-
if isinstance(child, AST.ParamOp)
|
|
813
|
-
ref_element = child.children[1]
|
|
814
|
-
else:
|
|
815
|
-
ref_element = child
|
|
805
|
+
ref_element = child.children[1] if isinstance(child, AST.ParamOp) else child
|
|
816
806
|
if ref_element in elements:
|
|
817
807
|
duplicates.append(ref_element)
|
|
818
808
|
elements.append(self.visit(child).value)
|
|
@@ -849,9 +839,8 @@ class InterpreterAnalyzer(ASTTemplate):
|
|
|
849
839
|
self.is_from_regular_aggregation = True
|
|
850
840
|
operands.append(self.visit(child))
|
|
851
841
|
self.is_from_regular_aggregation = False
|
|
852
|
-
if node.op == CALC:
|
|
853
|
-
|
|
854
|
-
raise SemanticError("1-3-35", op=node.op)
|
|
842
|
+
if node.op == CALC and any(isinstance(operand, Dataset) for operand in operands):
|
|
843
|
+
raise SemanticError("1-3-35", op=node.op)
|
|
855
844
|
if node.op == AGGREGATE:
|
|
856
845
|
# Extracting the role encoded inside the children assignments
|
|
857
846
|
role_info = {
|
|
@@ -1056,11 +1045,7 @@ class InterpreterAnalyzer(ASTTemplate):
|
|
|
1056
1045
|
def visit_ParamOp(self, node: AST.ParamOp) -> None: # noqa: C901
|
|
1057
1046
|
if node.op == ROUND:
|
|
1058
1047
|
op_element = self.visit(node.children[0])
|
|
1059
|
-
if len(node.params) != 0
|
|
1060
|
-
param_element = self.visit(node.params[0])
|
|
1061
|
-
else:
|
|
1062
|
-
param_element = None
|
|
1063
|
-
|
|
1048
|
+
param_element = self.visit(node.params[0]) if len(node.params) != 0 else None
|
|
1064
1049
|
return Round.analyze(op_element, param_element)
|
|
1065
1050
|
|
|
1066
1051
|
# Numeric Operator
|
|
@@ -1116,6 +1101,9 @@ class InterpreterAnalyzer(ASTTemplate):
|
|
|
1116
1101
|
elif node.op == FILL_TIME_SERIES:
|
|
1117
1102
|
mode = self.visit(node.params[0]) if len(node.params) == 1 else "all"
|
|
1118
1103
|
return Fill_time_series.analyze(self.visit(node.children[0]), mode)
|
|
1104
|
+
elif node.op == DATE_ADD:
|
|
1105
|
+
params = [self.visit(node.params[0]), self.visit(node.params[1])]
|
|
1106
|
+
return Date_Add.analyze(self.visit(node.children[0]), params)
|
|
1119
1107
|
elif node.op == CAST:
|
|
1120
1108
|
operand = self.visit(node.children[0])
|
|
1121
1109
|
scalar_type = node.children[1]
|
|
@@ -1234,11 +1222,8 @@ class InterpreterAnalyzer(ASTTemplate):
|
|
|
1234
1222
|
if node.op == HIERARCHY:
|
|
1235
1223
|
aux = []
|
|
1236
1224
|
for rule in hr_info["rules"]:
|
|
1237
|
-
if rule.rule.op == EQ:
|
|
1225
|
+
if rule.rule.op == EQ or rule.rule.op == WHEN and rule.rule.right.op == EQ:
|
|
1238
1226
|
aux.append(rule)
|
|
1239
|
-
elif rule.rule.op == WHEN:
|
|
1240
|
-
if rule.rule.right.op == EQ:
|
|
1241
|
-
aux.append(rule)
|
|
1242
1227
|
# Filter only the rules with HRBinOP as =,
|
|
1243
1228
|
# as they are the ones that will be computed
|
|
1244
1229
|
if len(aux) == 0:
|
|
@@ -1411,12 +1396,10 @@ class InterpreterAnalyzer(ASTTemplate):
|
|
|
1411
1396
|
left_operand.data = pd.DataFrame({measure_name: []})
|
|
1412
1397
|
if right_operand.data is None:
|
|
1413
1398
|
right_operand.data = pd.DataFrame({measure_name: []})
|
|
1414
|
-
left_null_indexes = set(
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
list(right_operand.data[right_operand.data[measure_name].isnull()].index)
|
|
1419
|
-
)
|
|
1399
|
+
left_null_indexes = set(left_operand.data[left_operand.data[
|
|
1400
|
+
measure_name].isnull()].index)
|
|
1401
|
+
right_null_indexes = set(right_operand.data[right_operand.data[
|
|
1402
|
+
measure_name].isnull()].index)
|
|
1420
1403
|
# If no indexes are in common, then one datapoint is not null
|
|
1421
1404
|
invalid_indexes = list(left_null_indexes.intersection(right_null_indexes))
|
|
1422
1405
|
if len(invalid_indexes) > 0:
|
|
@@ -1504,10 +1487,7 @@ class InterpreterAnalyzer(ASTTemplate):
|
|
|
1504
1487
|
if condition.data_type != BASIC_TYPES[bool]:
|
|
1505
1488
|
raise ValueError("Only boolean scalars are allowed on data component condition")
|
|
1506
1489
|
name = condition.name
|
|
1507
|
-
if condition.data is None
|
|
1508
|
-
data = None
|
|
1509
|
-
else:
|
|
1510
|
-
data = condition.data
|
|
1490
|
+
data = None if condition.data is None else condition.data
|
|
1511
1491
|
|
|
1512
1492
|
if data is not None:
|
|
1513
1493
|
if self.nested_condition and self.condition_stack is not None:
|
|
@@ -1518,8 +1498,7 @@ class InterpreterAnalyzer(ASTTemplate):
|
|
|
1518
1498
|
)
|
|
1519
1499
|
indexes = merge_df.data[merge_df.data.columns[-1]]
|
|
1520
1500
|
else:
|
|
1521
|
-
indexes = data.index
|
|
1522
|
-
data = data.fillna(False)
|
|
1501
|
+
indexes = data[data.notnull()].index
|
|
1523
1502
|
|
|
1524
1503
|
if isinstance(condition, Dataset):
|
|
1525
1504
|
filtered_data = data.iloc[indexes]
|
|
@@ -1644,8 +1623,7 @@ class InterpreterAnalyzer(ASTTemplate):
|
|
|
1644
1623
|
# Getting Dataset elements
|
|
1645
1624
|
result_components = {
|
|
1646
1625
|
comp_name: copy(comp)
|
|
1647
|
-
for comp_name, comp in
|
|
1648
|
-
self.ruleset_dataset.components.items() # type: ignore[union-attr]
|
|
1626
|
+
for comp_name, comp in self.ruleset_dataset.components.items() # type: ignore[union-attr]
|
|
1649
1627
|
}
|
|
1650
1628
|
if self.ruleset_signature is not None:
|
|
1651
1629
|
hr_component = self.ruleset_signature["RULE_COMPONENT"]
|
|
@@ -1759,8 +1737,9 @@ class InterpreterAnalyzer(ASTTemplate):
|
|
|
1759
1737
|
signature_values[param["name"]] = self.visit(node.params[i])
|
|
1760
1738
|
elif param["type"] in ["Dataset", "Component"]:
|
|
1761
1739
|
if isinstance(node.params[i], AST.VarID):
|
|
1762
|
-
signature_values[param["name"]] =
|
|
1763
|
-
|
|
1740
|
+
signature_values[param["name"]] = node.params[
|
|
1741
|
+
i
|
|
1742
|
+
].value # type: ignore[attr-defined]
|
|
1764
1743
|
else:
|
|
1765
1744
|
param_element = self.visit(node.params[i])
|
|
1766
1745
|
if isinstance(param_element, Dataset):
|