vtlengine 1.1rc2__py3-none-any.whl → 1.2.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.
Potentially problematic release.
This version of vtlengine might be problematic. Click here for more details.
- vtlengine/API/_InternalApi.py +288 -29
- vtlengine/API/__init__.py +277 -70
- vtlengine/AST/ASTComment.py +56 -0
- vtlengine/AST/ASTConstructor.py +71 -18
- vtlengine/AST/ASTConstructorModules/Expr.py +197 -75
- vtlengine/AST/ASTConstructorModules/ExprComponents.py +81 -38
- vtlengine/AST/ASTConstructorModules/Terminals.py +76 -31
- vtlengine/AST/ASTConstructorModules/__init__.py +50 -0
- vtlengine/AST/ASTEncoders.py +4 -0
- vtlengine/AST/ASTString.py +622 -0
- vtlengine/AST/ASTTemplate.py +28 -2
- vtlengine/AST/DAG/__init__.py +44 -6
- vtlengine/AST/DAG/_words.py +1 -0
- vtlengine/AST/Grammar/Vtl.g4 +7 -7
- vtlengine/AST/Grammar/lexer.py +19759 -1112
- vtlengine/AST/Grammar/parser.py +17996 -3199
- vtlengine/AST/__init__.py +127 -14
- vtlengine/Exceptions/messages.py +14 -2
- vtlengine/Interpreter/__init__.py +90 -11
- vtlengine/Model/__init__.py +9 -4
- vtlengine/Operators/Aggregation.py +13 -6
- vtlengine/Operators/Analytic.py +19 -13
- vtlengine/Operators/CastOperator.py +5 -2
- vtlengine/Operators/Clause.py +26 -18
- vtlengine/Operators/Comparison.py +3 -1
- vtlengine/Operators/Conditional.py +40 -18
- vtlengine/Operators/General.py +3 -1
- vtlengine/Operators/HROperators.py +3 -1
- vtlengine/Operators/Join.py +4 -2
- vtlengine/Operators/Time.py +22 -15
- vtlengine/Operators/Validation.py +5 -2
- vtlengine/Operators/__init__.py +15 -8
- vtlengine/Utils/__Virtual_Assets.py +34 -0
- vtlengine/Utils/__init__.py +49 -0
- vtlengine/__init__.py +4 -2
- vtlengine/files/parser/__init__.py +16 -26
- vtlengine/files/parser/_rfc_dialect.py +1 -1
- vtlengine/py.typed +0 -0
- vtlengine-1.2.0.dist-info/METADATA +92 -0
- vtlengine-1.2.0.dist-info/RECORD +63 -0
- {vtlengine-1.1rc2.dist-info → vtlengine-1.2.0.dist-info}/WHEEL +1 -1
- vtlengine-1.1rc2.dist-info/METADATA +0 -248
- vtlengine-1.1rc2.dist-info/RECORD +0 -59
- {vtlengine-1.1rc2.dist-info → vtlengine-1.2.0.dist-info}/LICENSE.md +0 -0
vtlengine/AST/ASTTemplate.py
CHANGED
|
@@ -186,8 +186,6 @@ class ASTTemplate(NodeVisitor):
|
|
|
186
186
|
|
|
187
187
|
return node.value
|
|
188
188
|
"""
|
|
189
|
-
if node.value in self.datasets:
|
|
190
|
-
return self.datasets[node.value]
|
|
191
189
|
return node.value
|
|
192
190
|
|
|
193
191
|
def visit_Optional(self, node: AST.Optional) -> AST.AST:
|
|
@@ -329,6 +327,18 @@ class ASTTemplate(NodeVisitor):
|
|
|
329
327
|
self.visit(case.thenOp)
|
|
330
328
|
self.visit(node.elseOp)
|
|
331
329
|
|
|
330
|
+
def visit_CaseObj(self, node: AST.CaseObj) -> Any:
|
|
331
|
+
"""
|
|
332
|
+
CaseObj: (condition, thenOp)
|
|
333
|
+
|
|
334
|
+
Basic usage:
|
|
335
|
+
|
|
336
|
+
self.visit(node.condition)
|
|
337
|
+
self.visit(node.thenOp)
|
|
338
|
+
"""
|
|
339
|
+
self.visit(node.condition)
|
|
340
|
+
self.visit(node.thenOp)
|
|
341
|
+
|
|
332
342
|
def visit_Validation(self, node: AST.Validation) -> Any:
|
|
333
343
|
"""
|
|
334
344
|
Validation: (op, validation, params, inbalance, invalid)
|
|
@@ -505,6 +515,12 @@ class ASTTemplate(NodeVisitor):
|
|
|
505
515
|
for child in node.operands:
|
|
506
516
|
self.visit(child)
|
|
507
517
|
|
|
518
|
+
def visit_ParFunction(self, node: AST.ParFunction) -> None:
|
|
519
|
+
"""
|
|
520
|
+
ParFunction: (operand)
|
|
521
|
+
"""
|
|
522
|
+
self.visit(node.operand)
|
|
523
|
+
|
|
508
524
|
def visit_NoOp(self, node: AST.NoOp) -> None: # pylint: disable=unused-argument
|
|
509
525
|
"""
|
|
510
526
|
NoOp: ()
|
|
@@ -526,3 +542,13 @@ class ASTTemplate(NodeVisitor):
|
|
|
526
542
|
"""
|
|
527
543
|
for param in node.params:
|
|
528
544
|
self.visit(param)
|
|
545
|
+
|
|
546
|
+
def visit_Windowing(self, node: AST.Windowing) -> None:
|
|
547
|
+
"""
|
|
548
|
+
Windowing: (type_, start, start_mode, stop, stop_mode)
|
|
549
|
+
"""
|
|
550
|
+
|
|
551
|
+
def visit_Comment(self, node: AST.Comment) -> None:
|
|
552
|
+
"""
|
|
553
|
+
Comment: (value)
|
|
554
|
+
"""
|
vtlengine/AST/DAG/__init__.py
CHANGED
|
@@ -32,8 +32,8 @@ from vtlengine.AST import (
|
|
|
32
32
|
VarID,
|
|
33
33
|
)
|
|
34
34
|
from vtlengine.AST.ASTTemplate import ASTTemplate
|
|
35
|
-
from vtlengine.AST.DAG._words import DELETE, GLOBAL, INPUTS, INSERT, OUTPUTS, PERSISTENT
|
|
36
|
-
from vtlengine.AST.Grammar.tokens import AS, MEMBERSHIP, TO
|
|
35
|
+
from vtlengine.AST.DAG._words import DELETE, GLOBAL, INPUTS, INSERT, OUTPUTS, PERSISTENT, UNKNOWN
|
|
36
|
+
from vtlengine.AST.Grammar.tokens import AS, DROP, KEEP, MEMBERSHIP, RENAME, TO
|
|
37
37
|
from vtlengine.Exceptions import SemanticError
|
|
38
38
|
|
|
39
39
|
|
|
@@ -61,6 +61,8 @@ class DAGAnalyzer(ASTTemplate):
|
|
|
61
61
|
inputs: Optional[list] = None
|
|
62
62
|
outputs: Optional[list] = None
|
|
63
63
|
persistent: Optional[list] = None
|
|
64
|
+
unknown_variables: Optional[list] = None
|
|
65
|
+
unknown_variables_statement: Optional[list] = None
|
|
64
66
|
|
|
65
67
|
def __post_init__(self):
|
|
66
68
|
self.dependencies = {}
|
|
@@ -72,6 +74,8 @@ class DAGAnalyzer(ASTTemplate):
|
|
|
72
74
|
self.outputs = []
|
|
73
75
|
self.persistent = []
|
|
74
76
|
self.alias = []
|
|
77
|
+
self.unknown_variables = []
|
|
78
|
+
self.unknown_variables_statement = []
|
|
75
79
|
|
|
76
80
|
@classmethod
|
|
77
81
|
def ds_structure(cls, ast: AST):
|
|
@@ -85,10 +89,13 @@ class DAGAnalyzer(ASTTemplate):
|
|
|
85
89
|
all_output = []
|
|
86
90
|
global_inputs = []
|
|
87
91
|
inserted = []
|
|
92
|
+
persistent_datasets = []
|
|
88
93
|
for key, statement in self.dependencies.items():
|
|
89
94
|
outputs = statement[OUTPUTS]
|
|
90
95
|
persistent = statement[PERSISTENT]
|
|
91
96
|
reference = outputs + persistent
|
|
97
|
+
if len(persistent) == 1 and persistent[0] not in persistent_datasets:
|
|
98
|
+
persistent_datasets.append(persistent[0])
|
|
92
99
|
deletion_key = key
|
|
93
100
|
all_output.append(reference[0])
|
|
94
101
|
for subKey, subStatement in self.dependencies.items():
|
|
@@ -127,10 +134,11 @@ class DAGAnalyzer(ASTTemplate):
|
|
|
127
134
|
statements[INSERT][key] = [element]
|
|
128
135
|
|
|
129
136
|
statements[GLOBAL] = global_inputs
|
|
137
|
+
statements[PERSISTENT] = persistent_datasets
|
|
130
138
|
return statements
|
|
131
139
|
|
|
132
140
|
@classmethod
|
|
133
|
-
def createDAG(cls, ast:
|
|
141
|
+
def createDAG(cls, ast: Start):
|
|
134
142
|
""" """
|
|
135
143
|
# Visit AST.
|
|
136
144
|
dag = cls()
|
|
@@ -143,6 +151,11 @@ class DAGAnalyzer(ASTTemplate):
|
|
|
143
151
|
# Create output dict.
|
|
144
152
|
if len(dag.edges) != 0:
|
|
145
153
|
dag.sortAST(ast)
|
|
154
|
+
else:
|
|
155
|
+
MLStatements: list = [
|
|
156
|
+
ML for ML in ast.children if not isinstance(ML, (HRuleset, DPRuleset, Operator))
|
|
157
|
+
]
|
|
158
|
+
dag.check_overwriting(MLStatements)
|
|
146
159
|
return dag
|
|
147
160
|
|
|
148
161
|
except nx.NetworkXUnfeasible as error:
|
|
@@ -167,7 +180,7 @@ class DAGAnalyzer(ASTTemplate):
|
|
|
167
180
|
""" """
|
|
168
181
|
# For each vertex
|
|
169
182
|
for key, statement in self.dependencies.items():
|
|
170
|
-
output = statement[OUTPUTS] + statement[PERSISTENT]
|
|
183
|
+
output = statement[OUTPUTS] + statement[PERSISTENT] + statement[UNKNOWN]
|
|
171
184
|
# If the statement has no := or -> symbol there is no vertex to add.
|
|
172
185
|
if len(output) != 0:
|
|
173
186
|
self.vertex[key] = output[0]
|
|
@@ -236,12 +249,15 @@ class DAGAnalyzer(ASTTemplate):
|
|
|
236
249
|
inputs = list(set(self.inputs))
|
|
237
250
|
outputs = list(set(self.outputs))
|
|
238
251
|
persistent = list(set(self.persistent))
|
|
252
|
+
unknown = list(set(self.unknown_variables_statement))
|
|
239
253
|
|
|
240
254
|
# Remove inputs that are outputs of some statement.
|
|
241
255
|
inputsF = [inputf for inputf in inputs if inputf not in outputs]
|
|
242
256
|
|
|
243
|
-
dict_ = {INPUTS: inputsF, OUTPUTS: outputs, PERSISTENT: persistent}
|
|
244
|
-
|
|
257
|
+
dict_ = {INPUTS: inputsF, OUTPUTS: outputs, PERSISTENT: persistent, UNKNOWN: unknown}
|
|
258
|
+
for variable in self.unknown_variables_statement:
|
|
259
|
+
if variable not in self.unknown_variables:
|
|
260
|
+
self.unknown_variables.append(variable)
|
|
245
261
|
return dict_
|
|
246
262
|
|
|
247
263
|
"""______________________________________________________________________________________
|
|
@@ -284,6 +300,19 @@ class DAGAnalyzer(ASTTemplate):
|
|
|
284
300
|
self.inputs = []
|
|
285
301
|
self.outputs = []
|
|
286
302
|
self.persistent = []
|
|
303
|
+
self.unknown_variables_statement = []
|
|
304
|
+
aux = copy.copy(self.unknown_variables)
|
|
305
|
+
for variable in aux:
|
|
306
|
+
for _number_of_statement, dependency in self.dependencies.items():
|
|
307
|
+
if variable in dependency[OUTPUTS]:
|
|
308
|
+
if variable in self.unknown_variables:
|
|
309
|
+
self.unknown_variables.remove(variable)
|
|
310
|
+
for _number_of_statement, dependency in self.dependencies.items():
|
|
311
|
+
if variable in dependency[UNKNOWN]:
|
|
312
|
+
dependency[UNKNOWN].remove(variable)
|
|
313
|
+
dependency[INPUTS].append(variable)
|
|
314
|
+
if variable not in self.inputs:
|
|
315
|
+
self.inputs.append(variable)
|
|
287
316
|
|
|
288
317
|
def visit_Assignment(self, node: Assignment) -> None:
|
|
289
318
|
if self.isFirstAssignment:
|
|
@@ -301,6 +330,8 @@ class DAGAnalyzer(ASTTemplate):
|
|
|
301
330
|
|
|
302
331
|
def visit_RegularAggregation(self, node: RegularAggregation) -> None:
|
|
303
332
|
self.visit(node.dataset)
|
|
333
|
+
if node.op in [KEEP, DROP, RENAME]:
|
|
334
|
+
return
|
|
304
335
|
for child in node.children:
|
|
305
336
|
self.isFromRegularAggregation = True
|
|
306
337
|
self.visit(child)
|
|
@@ -322,6 +353,13 @@ class DAGAnalyzer(ASTTemplate):
|
|
|
322
353
|
def visit_VarID(self, node: VarID) -> None:
|
|
323
354
|
if (not self.isFromRegularAggregation or self.isDataset) and node.value not in self.alias:
|
|
324
355
|
self.inputs.append(node.value)
|
|
356
|
+
elif (
|
|
357
|
+
self.isFromRegularAggregation
|
|
358
|
+
and node.value not in self.alias
|
|
359
|
+
and not self.isDataset
|
|
360
|
+
and node.value not in self.unknown_variables_statement
|
|
361
|
+
):
|
|
362
|
+
self.unknown_variables_statement.append(node.value)
|
|
325
363
|
|
|
326
364
|
def visit_Identifier(self, node: Identifier) -> None:
|
|
327
365
|
if node.kind == "DatasetID" and node.value not in self.alias:
|
vtlengine/AST/DAG/_words.py
CHANGED
vtlengine/AST/Grammar/Vtl.g4
CHANGED
|
@@ -219,11 +219,11 @@ timeOperators:
|
|
|
219
219
|
| YEAR_OP LPAREN expr RPAREN # yearAtom
|
|
220
220
|
| MONTH_OP LPAREN expr RPAREN # monthAtom
|
|
221
221
|
| DAYOFMONTH LPAREN expr RPAREN # dayOfMonthAtom
|
|
222
|
-
| DAYOFYEAR LPAREN expr RPAREN #
|
|
222
|
+
| DAYOFYEAR LPAREN expr RPAREN # dayOfYearAtom
|
|
223
223
|
| DAYTOYEAR LPAREN expr RPAREN # dayToYearAtom
|
|
224
224
|
| DAYTOMONTH LPAREN expr RPAREN # dayToMonthAtom
|
|
225
|
-
| YEARTODAY LPAREN expr RPAREN #
|
|
226
|
-
| MONTHTODAY LPAREN expr RPAREN #
|
|
225
|
+
| YEARTODAY LPAREN expr RPAREN # yearToDayAtom
|
|
226
|
+
| MONTHTODAY LPAREN expr RPAREN # monthToDayAtom
|
|
227
227
|
;
|
|
228
228
|
|
|
229
229
|
timeOperatorsComponent:
|
|
@@ -238,11 +238,11 @@ timeOperatorsComponent:
|
|
|
238
238
|
| YEAR_OP LPAREN exprComponent RPAREN # yearAtomComponent
|
|
239
239
|
| MONTH_OP LPAREN exprComponent RPAREN # monthAtomComponent
|
|
240
240
|
| DAYOFMONTH LPAREN exprComponent RPAREN # dayOfMonthAtomComponent
|
|
241
|
-
| DAYOFYEAR LPAREN exprComponent RPAREN #
|
|
241
|
+
| DAYOFYEAR LPAREN exprComponent RPAREN # dayOfYearAtomComponent
|
|
242
242
|
| DAYTOYEAR LPAREN exprComponent RPAREN # dayToYearAtomComponent
|
|
243
243
|
| DAYTOMONTH LPAREN exprComponent RPAREN # dayToMonthAtomComponent
|
|
244
|
-
| YEARTODAY LPAREN exprComponent RPAREN #
|
|
245
|
-
| MONTHTODAY LPAREN exprComponent RPAREN #
|
|
244
|
+
| YEARTODAY LPAREN exprComponent RPAREN # yearToDayAtomComponent
|
|
245
|
+
| MONTHTODAY LPAREN exprComponent RPAREN # monthToDayAtomComponent
|
|
246
246
|
;
|
|
247
247
|
|
|
248
248
|
setOperators:
|
|
@@ -363,7 +363,7 @@ calcClauseItem:
|
|
|
363
363
|
|
|
364
364
|
/*SUBSPACE CLAUSE*/
|
|
365
365
|
subspaceClauseItem:
|
|
366
|
-
componentID EQ scalarItem
|
|
366
|
+
componentID EQ (scalarItem | varID)
|
|
367
367
|
;
|
|
368
368
|
|
|
369
369
|
scalarItem:
|