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.

Files changed (44) hide show
  1. vtlengine/API/_InternalApi.py +288 -29
  2. vtlengine/API/__init__.py +277 -70
  3. vtlengine/AST/ASTComment.py +56 -0
  4. vtlengine/AST/ASTConstructor.py +71 -18
  5. vtlengine/AST/ASTConstructorModules/Expr.py +197 -75
  6. vtlengine/AST/ASTConstructorModules/ExprComponents.py +81 -38
  7. vtlengine/AST/ASTConstructorModules/Terminals.py +76 -31
  8. vtlengine/AST/ASTConstructorModules/__init__.py +50 -0
  9. vtlengine/AST/ASTEncoders.py +4 -0
  10. vtlengine/AST/ASTString.py +622 -0
  11. vtlengine/AST/ASTTemplate.py +28 -2
  12. vtlengine/AST/DAG/__init__.py +44 -6
  13. vtlengine/AST/DAG/_words.py +1 -0
  14. vtlengine/AST/Grammar/Vtl.g4 +7 -7
  15. vtlengine/AST/Grammar/lexer.py +19759 -1112
  16. vtlengine/AST/Grammar/parser.py +17996 -3199
  17. vtlengine/AST/__init__.py +127 -14
  18. vtlengine/Exceptions/messages.py +14 -2
  19. vtlengine/Interpreter/__init__.py +90 -11
  20. vtlengine/Model/__init__.py +9 -4
  21. vtlengine/Operators/Aggregation.py +13 -6
  22. vtlengine/Operators/Analytic.py +19 -13
  23. vtlengine/Operators/CastOperator.py +5 -2
  24. vtlengine/Operators/Clause.py +26 -18
  25. vtlengine/Operators/Comparison.py +3 -1
  26. vtlengine/Operators/Conditional.py +40 -18
  27. vtlengine/Operators/General.py +3 -1
  28. vtlengine/Operators/HROperators.py +3 -1
  29. vtlengine/Operators/Join.py +4 -2
  30. vtlengine/Operators/Time.py +22 -15
  31. vtlengine/Operators/Validation.py +5 -2
  32. vtlengine/Operators/__init__.py +15 -8
  33. vtlengine/Utils/__Virtual_Assets.py +34 -0
  34. vtlengine/Utils/__init__.py +49 -0
  35. vtlengine/__init__.py +4 -2
  36. vtlengine/files/parser/__init__.py +16 -26
  37. vtlengine/files/parser/_rfc_dialect.py +1 -1
  38. vtlengine/py.typed +0 -0
  39. vtlengine-1.2.0.dist-info/METADATA +92 -0
  40. vtlengine-1.2.0.dist-info/RECORD +63 -0
  41. {vtlengine-1.1rc2.dist-info → vtlengine-1.2.0.dist-info}/WHEEL +1 -1
  42. vtlengine-1.1rc2.dist-info/METADATA +0 -248
  43. vtlengine-1.1rc2.dist-info/RECORD +0 -59
  44. {vtlengine-1.1rc2.dist-info → vtlengine-1.2.0.dist-info}/LICENSE.md +0 -0
@@ -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
+ """
@@ -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: 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:
@@ -7,3 +7,4 @@ INPUTS = "inputs"
7
7
  OUTPUTS = "outputs"
8
8
  PERSISTENT = "persistent"
9
9
  STATEMENT_ = "statement"
10
+ UNKNOWN = "unknown_variables"
@@ -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 # datOfYearAtom
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 # yearTodayAtom
226
- | MONTHTODAY LPAREN expr RPAREN # monthTodayAtom
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 # datOfYearAtomComponent
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 # yearTodayAtomComponent
245
- | MONTHTODAY LPAREN exprComponent RPAREN # monthTodayAtomComponent
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: