vtlengine 1.0.3rc3__py3-none-any.whl → 1.0.4__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 (47) hide show
  1. vtlengine/API/_InternalApi.py +55 -20
  2. vtlengine/API/__init__.py +11 -2
  3. vtlengine/API/data/schema/json_schema_2.1.json +116 -0
  4. vtlengine/AST/ASTConstructor.py +5 -4
  5. vtlengine/AST/ASTConstructorModules/Expr.py +47 -48
  6. vtlengine/AST/ASTConstructorModules/ExprComponents.py +45 -23
  7. vtlengine/AST/ASTConstructorModules/Terminals.py +21 -11
  8. vtlengine/AST/ASTEncoders.py +1 -1
  9. vtlengine/AST/DAG/__init__.py +0 -3
  10. vtlengine/AST/Grammar/lexer.py +0 -1
  11. vtlengine/AST/Grammar/parser.py +185 -440
  12. vtlengine/AST/VtlVisitor.py +0 -1
  13. vtlengine/DataTypes/TimeHandling.py +50 -15
  14. vtlengine/DataTypes/__init__.py +79 -7
  15. vtlengine/Exceptions/__init__.py +3 -5
  16. vtlengine/Exceptions/messages.py +65 -105
  17. vtlengine/Interpreter/__init__.py +83 -38
  18. vtlengine/Model/__init__.py +7 -9
  19. vtlengine/Operators/Aggregation.py +13 -7
  20. vtlengine/Operators/Analytic.py +48 -9
  21. vtlengine/Operators/Assignment.py +0 -1
  22. vtlengine/Operators/CastOperator.py +44 -44
  23. vtlengine/Operators/Clause.py +16 -10
  24. vtlengine/Operators/Comparison.py +20 -12
  25. vtlengine/Operators/Conditional.py +30 -13
  26. vtlengine/Operators/General.py +9 -4
  27. vtlengine/Operators/HROperators.py +4 -14
  28. vtlengine/Operators/Join.py +15 -14
  29. vtlengine/Operators/Numeric.py +32 -26
  30. vtlengine/Operators/RoleSetter.py +6 -2
  31. vtlengine/Operators/Set.py +12 -8
  32. vtlengine/Operators/String.py +9 -9
  33. vtlengine/Operators/Time.py +136 -116
  34. vtlengine/Operators/Validation.py +10 -4
  35. vtlengine/Operators/__init__.py +56 -69
  36. vtlengine/Utils/__init__.py +6 -1
  37. vtlengine/files/output/__init__.py +0 -1
  38. vtlengine/files/output/_time_period_representation.py +2 -1
  39. vtlengine/files/parser/__init__.py +44 -10
  40. vtlengine/files/parser/_rfc_dialect.py +1 -1
  41. vtlengine/files/parser/_time_checking.py +4 -4
  42. {vtlengine-1.0.3rc3.dist-info → vtlengine-1.0.4.dist-info}/METADATA +7 -6
  43. vtlengine-1.0.4.dist-info/RECORD +58 -0
  44. {vtlengine-1.0.3rc3.dist-info → vtlengine-1.0.4.dist-info}/WHEEL +1 -1
  45. vtlengine/DataTypes/NumericTypesHandling.py +0 -38
  46. vtlengine-1.0.3rc3.dist-info/RECORD +0 -58
  47. {vtlengine-1.0.3rc3.dist-info → vtlengine-1.0.4.dist-info}/LICENSE.md +0 -0
@@ -70,7 +70,9 @@ class Join(Operator):
70
70
  comp.role = (
71
71
  Role.IDENTIFIER
72
72
  if is_identifier
73
- else Role.MEASURE if comp.role == Role.IDENTIFIER else comp.role
73
+ else Role.MEASURE
74
+ if comp.role == Role.IDENTIFIER
75
+ else comp.role
74
76
  )
75
77
  if comp.name not in nullability:
76
78
  nullability[comp.name] = copy(comp.nullable)
@@ -107,7 +109,8 @@ class Join(Operator):
107
109
  else:
108
110
  if component_name in using and component_name in merged_components:
109
111
  data_type = binary_implicit_promotion(
110
- merged_components[component_name].data_type, component.data_type
112
+ merged_components[component_name].data_type,
113
+ component.data_type,
111
114
  )
112
115
  component.data_type = data_type
113
116
  merged_components[component_name] = component
@@ -216,7 +219,6 @@ class Join(Operator):
216
219
 
217
220
  @classmethod
218
221
  def identifiers_validation(cls, operands: List[Dataset], using: Optional[List[str]]) -> None:
219
-
220
222
  # (Case A)
221
223
  info = {op.name: op.get_identifiers_names() for op in operands}
222
224
  for op_name, identifiers in info.items():
@@ -224,11 +226,12 @@ class Join(Operator):
224
226
  raise SemanticError("1-1-13-14", op=cls.op, name=op_name)
225
227
 
226
228
  for op_name, identifiers in info.items():
227
- if (using is None and op_name != cls.reference_dataset.name and not
228
- set(identifiers).issubset(set(info[cls.reference_dataset.name]))):
229
- missing_components = list(
230
- set(identifiers) - set(info[cls.reference_dataset.name])
231
- )
229
+ if (
230
+ using is None
231
+ and op_name != cls.reference_dataset.name
232
+ and not set(identifiers).issubset(set(info[cls.reference_dataset.name]))
233
+ ):
234
+ missing_components = list(set(identifiers) - set(info[cls.reference_dataset.name]))
232
235
  raise SemanticError(
233
236
  "1-1-13-11",
234
237
  op=cls.op,
@@ -277,7 +280,6 @@ class InnerJoin(Join):
277
280
  def generate_result_components(
278
281
  cls, operands: List[Dataset], using: Optional[List[str]] = None
279
282
  ) -> Dict[str, Component]:
280
-
281
283
  if using is None:
282
284
  return super().generate_result_components(operands, using)
283
285
 
@@ -334,7 +336,9 @@ class CrossJoin(Join):
334
336
  else:
335
337
  if result.data is not None:
336
338
  result.data = pd.merge(
337
- result.data, op.data, how=cls.how # type: ignore[arg-type]
339
+ result.data,
340
+ op.data,
341
+ how=cls.how, # type: ignore[arg-type]
338
342
  )
339
343
  if result.data is not None:
340
344
  result.data = result.data.rename(
@@ -357,7 +361,6 @@ class CrossJoin(Join):
357
361
 
358
362
 
359
363
  class Apply(Operator):
360
-
361
364
  @classmethod
362
365
  def evaluate(cls, dataset: Dataset, expression: Any, op_map: Dict[str, Any]) -> Dataset:
363
366
  for child in expression:
@@ -424,9 +427,7 @@ class Apply(Operator):
424
427
  return Dataset(name=name, components=components, data=data)
425
428
 
426
429
  @classmethod
427
- def get_common_components(
428
- cls, left: Dataset, right: Dataset
429
- ) -> (Dataset, Dataset): # type: ignore[syntax]
430
+ def get_common_components(cls, left: Dataset, right: Dataset) -> (Dataset, Dataset): # type: ignore[syntax]
430
431
  common = set(left.get_components_names()) & set(right.get_components_names())
431
432
  left.components = {
432
433
  comp.name: comp for comp in left.components.values() if comp.name in common
@@ -73,7 +73,7 @@ class Binary(Operator.Binary):
73
73
  class UnPlus(Unary):
74
74
  """
75
75
  `Plus <https://sdmx.org/wp-content/uploads/VTL-2.1-Reference-Manual.pdf#page=94&zoom=100,72,142> `_ unary operator
76
- """ # noqa E501
76
+ """ # noqa E501
77
77
 
78
78
  op = PLUS
79
79
  py_op = operator.pos
@@ -86,7 +86,7 @@ class UnPlus(Unary):
86
86
  class UnMinus(Unary):
87
87
  """
88
88
  `Minus <https://sdmx.org/wp-content/uploads/VTL-2.1-Reference-Manual.pdf#page=95&zoom=100,72,414> `_unary operator
89
- """ # noqa E501
89
+ """ # noqa E501
90
90
 
91
91
  op = MINUS
92
92
  py_op = operator.neg
@@ -95,7 +95,7 @@ class UnMinus(Unary):
95
95
  class AbsoluteValue(Unary):
96
96
  """
97
97
  `Absolute <https://sdmx.org/wp-content/uploads/VTL-2.1-Reference-Manual.pdf#page=112&zoom=100,72,801> `_ unary operator
98
- """ # noqa E501
98
+ """ # noqa E501
99
99
 
100
100
  op = ABS
101
101
  py_op = operator.abs
@@ -104,7 +104,7 @@ class AbsoluteValue(Unary):
104
104
  class Exponential(Unary):
105
105
  """
106
106
  `Exponential <https://sdmx.org/wp-content/uploads/VTL-2.1-Reference-Manual.pdf#page=114&zoom=100,72,94>`_ unary operator
107
- """ # noqa E501
107
+ """ # noqa E501
108
108
 
109
109
  op = EXP
110
110
  py_op = math.exp
@@ -115,7 +115,7 @@ class NaturalLogarithm(Unary):
115
115
  """
116
116
  `Natural logarithm <https://sdmx.org/wp-content/uploads/VTL-2.1-Reference-Manual.pdf#page=115&zoom=100,72,394> `_
117
117
  unary operator
118
- """ # noqa E501
118
+ """ # noqa E501
119
119
 
120
120
  op = LN
121
121
  py_op = math.log
@@ -126,7 +126,7 @@ class SquareRoot(Unary):
126
126
  """
127
127
  `Square Root <https://sdmx.org/wp-content/uploads/VTL-2.1-Reference-Manual.pdf#page=119&zoom=100,72,556> '_
128
128
  unary operator
129
- """ # noqa E501
129
+ """ # noqa E501
130
130
 
131
131
  op = SQRT
132
132
  py_op = math.sqrt
@@ -136,7 +136,7 @@ class SquareRoot(Unary):
136
136
  class Ceil(Unary):
137
137
  """
138
138
  `Ceilling <https://sdmx.org/wp-content/uploads/VTL-2.1-Reference-Manual.pdf#page=110&zoom=100,72,94> `_ unary operator
139
- """ # noqa E501
139
+ """ # noqa E501
140
140
 
141
141
  op = CEIL
142
142
  py_op = math.ceil
@@ -146,7 +146,7 @@ class Ceil(Unary):
146
146
  class Floor(Unary):
147
147
  """
148
148
  `Floor <https://sdmx.org/wp-content/uploads/VTL-2.1-Reference-Manual.pdf#page=111&zoom=100,72,442> `_ unary operator
149
- """ # noqa E501
149
+ """ # noqa E501
150
150
 
151
151
  op = FLOOR
152
152
  py_op = math.floor
@@ -156,7 +156,7 @@ class Floor(Unary):
156
156
  class BinPlus(Binary):
157
157
  """
158
158
  `Addition <https://sdmx.org/wp-content/uploads/VTL-2.1-Reference-Manual.pdf#page=96&zoom=100,72,692> `_ binary operator
159
- """ # noqa E501
159
+ """ # noqa E501
160
160
 
161
161
  op = PLUS
162
162
  py_op = operator.add
@@ -166,7 +166,7 @@ class BinPlus(Binary):
166
166
  class BinMinus(Binary):
167
167
  """
168
168
  `Subtraction <https://sdmx.org/wp-content/uploads/VTL-2.1-Reference-Manual.pdf#page=98&zoom=100,72,448> `_ binary operator
169
- """ # noqa E501
169
+ """ # noqa E501
170
170
 
171
171
  op = MINUS
172
172
  py_op = operator.sub
@@ -177,7 +177,7 @@ class Mult(Binary):
177
177
  """
178
178
  `Multiplication <https://sdmx.org/wp-content/uploads/VTL-2.1-Reference-Manual.pdf#page=100&zoom=100,72,254>`_
179
179
  binary operator
180
- """ # noqa E501
180
+ """ # noqa E501
181
181
 
182
182
  op = MULT
183
183
  py_op = operator.mul
@@ -187,7 +187,7 @@ class Div(Binary):
187
187
  """
188
188
  `Division <https://sdmx.org/wp-content/uploads/VTL-2.1-Reference-Manual.pdf#page=102&zoom=100,72,94>`_
189
189
  binary operator
190
- """ # noqa E501
190
+ """ # noqa E501
191
191
 
192
192
  op = DIV
193
193
  py_op = operator.truediv
@@ -197,7 +197,7 @@ class Div(Binary):
197
197
  class Logarithm(Binary):
198
198
  """
199
199
  `Logarithm <https://sdmx.org/wp-content/uploads/VTL-2.1-Reference-Manual.pdf#page=118&zoom=100,72,228>`_ operator
200
- """ # noqa E501
200
+ """ # noqa E501
201
201
 
202
202
  op = LOG
203
203
  return_type = Number
@@ -215,7 +215,7 @@ class Logarithm(Binary):
215
215
  class Modulo(Binary):
216
216
  """
217
217
  `Module <https://sdmx.org/wp-content/uploads/VTL-2.1-Reference-Manual.pdf#page=104&zoom=100,72,94>`_ operator
218
- """ # noqa E501
218
+ """ # noqa E501
219
219
 
220
220
  op = MOD
221
221
  py_op = operator.mod
@@ -224,7 +224,7 @@ class Modulo(Binary):
224
224
  class Power(Binary):
225
225
  """
226
226
  `Power <https://sdmx.org/wp-content/uploads/VTL-2.1-Reference-Manual.pdf#page=116&zoom=100,72,693>`_ operator
227
- """ # noqa E501
227
+ """ # noqa E501
228
228
 
229
229
  op = POWER
230
230
  return_type = Number
@@ -248,14 +248,15 @@ class Parameterized(Unary):
248
248
  operand: Operator.ALL_MODEL_DATA_TYPES,
249
249
  param: Optional[Union[DataComponent, Scalar]] = None,
250
250
  ) -> Any:
251
-
252
251
  if param is not None:
253
252
  if isinstance(param, Dataset):
254
253
  raise SemanticError("1-1-15-8", op=cls.op, comp_type="Dataset")
255
254
  if isinstance(param, DataComponent):
256
255
  if isinstance(operand, Scalar):
257
256
  raise SemanticError(
258
- "1-1-15-8", op=cls.op, comp_type="DataComponent and an Scalar operand"
257
+ "1-1-15-8",
258
+ op=cls.op,
259
+ comp_type="DataComponent and an Scalar operand",
259
260
  )
260
261
  cls.validate_type_compatibility(param.data_type)
261
262
  else:
@@ -298,14 +299,19 @@ class Parameterized(Unary):
298
299
  )
299
300
  except ValueError:
300
301
  raise SemanticError(
301
- "2-1-15-1", op=cls.op, comp_name=measure_name, dataset_name=operand.name
302
+ "2-1-15-1",
303
+ op=cls.op,
304
+ comp_name=measure_name,
305
+ dataset_name=operand.name,
302
306
  ) from None
303
307
  result.data = result.data[result.get_components_names()]
304
308
  return result
305
309
 
306
310
  @classmethod
307
311
  def component_evaluation(
308
- cls, operand: DataComponent, param: Optional[Union[DataComponent, Scalar]] = None
312
+ cls,
313
+ operand: DataComponent,
314
+ param: Optional[Union[DataComponent, Scalar]] = None,
309
315
  ) -> DataComponent:
310
316
  result = cls.validate(operand, param)
311
317
  if operand.data is None:
@@ -327,7 +333,9 @@ class Parameterized(Unary):
327
333
 
328
334
  @classmethod
329
335
  def evaluate(
330
- cls, operand: ALL_MODEL_DATA_TYPES, param: Optional[Union[DataComponent, Scalar]] = None
336
+ cls,
337
+ operand: ALL_MODEL_DATA_TYPES,
338
+ param: Optional[Union[DataComponent, Scalar]] = None,
331
339
  ) -> Union[DataComponent, Dataset, Scalar]:
332
340
  if isinstance(operand, Dataset):
333
341
  return cls.dataset_evaluation(operand, param)
@@ -340,7 +348,7 @@ class Parameterized(Unary):
340
348
  class Round(Parameterized):
341
349
  """
342
350
  `Round <https://sdmx.org/wp-content/uploads/VTL-2.1-Reference-Manual.pdf#page=106&zoom=100,72,94>`_ operator
343
- """ # noqa E501
351
+ """ # noqa E501
344
352
 
345
353
  op = ROUND
346
354
  return_type = Integer
@@ -365,14 +373,14 @@ class Round(Parameterized):
365
373
  class Trunc(Parameterized):
366
374
  """
367
375
  `Trunc <https://sdmx.org/wp-content/uploads/VTL-2.1-Reference-Manual.pdf#page=108&zoom=100,72,94>`_ operator.
368
- """ # noqa E501
376
+ """ # noqa E501
369
377
 
370
378
  op = TRUNC
371
379
 
372
380
  @classmethod
373
381
  def py_op(cls, x: float, param: Optional[float]) -> Any:
374
382
  multiplier = 1.0
375
- if not pd.isnull(param):
383
+ if not pd.isnull(param) and param is not None:
376
384
  multiplier = 10**param
377
385
 
378
386
  truncated_value = int(x * multiplier) / multiplier
@@ -384,14 +392,12 @@ class Trunc(Parameterized):
384
392
 
385
393
 
386
394
  class PseudoRandom(_random.Random):
387
-
388
395
  def __init__(self, seed: Union[int, float]) -> None:
389
396
  super().__init__()
390
397
  self.seed(seed)
391
398
 
392
399
 
393
400
  class Random(Parameterized):
394
-
395
401
  op = RANDOM
396
402
  return_type = Number
397
403
 
@@ -403,7 +409,7 @@ class Random(Parameterized):
403
409
  raise SemanticError("2-1-15-2", op=cls.op, value=index)
404
410
  if index.value > 10000:
405
411
  warnings.warn(
406
- "Random: The value of 'index' is very big. This can affect " "performance.",
412
+ "Random: The value of 'index' is very big. This can affect performance.",
407
413
  UserWarning,
408
414
  )
409
415
  return super().validate(seed, index)
@@ -35,8 +35,12 @@ class RoleSetter(Unary):
35
35
 
36
36
  @classmethod
37
37
  def evaluate(cls, operand: Any, data_size: int = 0) -> DataComponent:
38
- if (isinstance(operand, DataComponent) and operand.data is not None and
39
- not operand.nullable and any(operand.data.isnull())):
38
+ if (
39
+ isinstance(operand, DataComponent)
40
+ and operand.data is not None
41
+ and not operand.nullable
42
+ and any(operand.data.isnull())
43
+ ):
40
44
  raise SemanticError("1-1-1-16")
41
45
  result = cls.validate(operand, data_size)
42
46
  if isinstance(operand, Scalar):
@@ -13,12 +13,14 @@ from vtlengine.Operators import Operator
13
13
 
14
14
 
15
15
  class Set(Operator):
16
-
17
16
  @classmethod
18
17
  def check_same_structure(cls, dataset_1: Dataset, dataset_2: Dataset) -> None:
19
18
  if len(dataset_1.components) != len(dataset_2.components):
20
19
  raise SemanticError(
21
- "1-1-17-1", op=cls.op, dataset_1=dataset_1.name, dataset_2=dataset_2.name
20
+ "1-1-17-1",
21
+ op=cls.op,
22
+ dataset_1=dataset_1.name,
23
+ dataset_2=dataset_2.name,
22
24
  )
23
25
 
24
26
  for comp in dataset_1.components.values():
@@ -26,7 +28,10 @@ class Set(Operator):
26
28
  raise Exception(f"Component {comp.name} not found in dataset {dataset_2.name}")
27
29
  second_comp = dataset_2.components[comp.name]
28
30
  binary_implicit_promotion(
29
- comp.data_type, second_comp.data_type, cls.type_to_check, cls.return_type
31
+ comp.data_type,
32
+ second_comp.data_type,
33
+ cls.type_to_check,
34
+ cls.return_type,
30
35
  )
31
36
  if comp.role != second_comp.role:
32
37
  raise Exception(
@@ -36,7 +41,6 @@ class Set(Operator):
36
41
 
37
42
  @classmethod
38
43
  def validate(cls, operands: List[Dataset]) -> Dataset:
39
-
40
44
  base_operand = operands[0]
41
45
  for operand in operands[1:]:
42
46
  cls.check_same_structure(base_operand, operand)
@@ -70,7 +74,6 @@ class Union(Set):
70
74
 
71
75
 
72
76
  class Intersection(Set):
73
-
74
77
  @classmethod
75
78
  def evaluate(cls, operands: List[Dataset]) -> Dataset:
76
79
  result = cls.validate(operands)
@@ -97,7 +100,6 @@ class Intersection(Set):
97
100
 
98
101
 
99
102
  class Symdiff(Set):
100
-
101
103
  @classmethod
102
104
  def evaluate(cls, operands: List[Dataset]) -> Dataset:
103
105
  result = cls.validate(operands)
@@ -110,7 +112,10 @@ class Symdiff(Set):
110
112
  else:
111
113
  # Realiza la operación equivalente en pyspark.pandas
112
114
  result.data = result.data.merge(
113
- data, how="outer", on=result.get_identifiers_names(), suffixes=("_x", "_y")
115
+ data,
116
+ how="outer",
117
+ on=result.get_identifiers_names(),
118
+ suffixes=("_x", "_y"),
114
119
  )
115
120
 
116
121
  for measure in result.get_measures_names():
@@ -140,7 +145,6 @@ class Symdiff(Set):
140
145
 
141
146
 
142
147
  class Setdiff(Set):
143
-
144
148
  @staticmethod
145
149
  def has_null(row: Any) -> bool:
146
150
  return row.isnull().any()
@@ -31,7 +31,6 @@ class Unary(Operator.Unary):
31
31
 
32
32
  @classmethod
33
33
  def op_func(cls, x: Any) -> Any:
34
-
35
34
  x = "" if pd.isnull(x) else str(x)
36
35
  return cls.py_op(x)
37
36
 
@@ -116,7 +115,6 @@ class Concatenate(Binary):
116
115
 
117
116
 
118
117
  class Parameterized(Unary):
119
-
120
118
  @classmethod
121
119
  def validate(cls, *args: Any) -> Any:
122
120
  operand: Operator.ALL_MODEL_DATA_TYPES
@@ -353,7 +351,6 @@ class Instr(Parameterized):
353
351
  param2: Optional[Operator.ALL_MODEL_DATA_TYPES] = None,
354
352
  param3: Optional[Operator.ALL_MODEL_DATA_TYPES] = None,
355
353
  ) -> Any:
356
-
357
354
  if (
358
355
  isinstance(param1, Dataset)
359
356
  or isinstance(param2, Dataset)
@@ -395,7 +392,10 @@ class Instr(Parameterized):
395
392
  else:
396
393
  if not check_unary_implicit_promotion(data_type, Integer):
397
394
  raise SemanticError(
398
- "1-1-18-4", op=cls.op, param_type="Occurrence", correct_type="Integer"
395
+ "1-1-18-4",
396
+ op=cls.op,
397
+ param_type="Occurrence",
398
+ correct_type="Integer",
399
399
  )
400
400
  if isinstance(param, DataComponent):
401
401
  if param.data is not None:
@@ -408,9 +408,7 @@ class Instr(Parameterized):
408
408
  if position == 2 and not pd.isnull(param) and param < 1:
409
409
  raise SemanticError("1-1-18-4", op=cls.op, param_type="Start", correct_type=">= 1")
410
410
  elif position == 3 and not pd.isnull(param) and param < 1:
411
- raise SemanticError(
412
- "1-1-18-4", op=cls.op, param_type="Occurrence", correct_type=">= 1"
413
- )
411
+ raise SemanticError("1-1-18-4", op=cls.op, param_type="Occurrence", correct_type=">= 1")
414
412
 
415
413
  @classmethod
416
414
  def apply_operation_series_scalar(
@@ -529,7 +527,6 @@ class Instr(Parameterized):
529
527
  param2: Optional[Any],
530
528
  param3: Optional[Any],
531
529
  ) -> Any:
532
-
533
530
  if pd.isnull(x):
534
531
  return None
535
532
  return cls.py_op(x, param1, param2, param3)
@@ -560,7 +557,10 @@ class Instr(Parameterized):
560
557
  else:
561
558
  # OPERATORS_STRINGOPERATORS.93
562
559
  raise SemanticError(
563
- "1-1-18-4", op=cls.op, param_type="Occurrence", correct_type="Integer"
560
+ "1-1-18-4",
561
+ op=cls.op,
562
+ param_type="Occurrence",
563
+ correct_type="Integer",
564
564
  )
565
565
  else:
566
566
  occurrence = 0