vtlengine 1.0.1__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 +9 -5
- vtlengine/API/__init__.py +1 -1
- vtlengine/AST/ASTConstructorModules/Expr.py +96 -5
- vtlengine/AST/ASTConstructorModules/ExprComponents.py +76 -2
- vtlengine/AST/ASTTemplate.py +16 -0
- vtlengine/AST/Grammar/Vtl.g4 +49 -20
- vtlengine/AST/Grammar/VtlTokens.g4 +13 -1
- vtlengine/AST/Grammar/lexer.py +1293 -1183
- vtlengine/AST/Grammar/parser.py +5758 -3939
- vtlengine/AST/Grammar/tokens.py +12 -0
- vtlengine/AST/VtlVisitor.py +9 -1
- vtlengine/AST/__init__.py +19 -0
- vtlengine/DataTypes/TimeHandling.py +2 -0
- vtlengine/Exceptions/__init__.py +44 -0
- vtlengine/Exceptions/messages.py +16 -8
- vtlengine/Interpreter/__init__.py +52 -26
- vtlengine/Model/__init__.py +7 -0
- vtlengine/Operators/Analytic.py +53 -21
- vtlengine/Operators/Boolean.py +1 -1
- vtlengine/Operators/Conditional.py +143 -2
- vtlengine/Operators/Numeric.py +40 -2
- vtlengine/Operators/Time.py +134 -0
- vtlengine/Utils/__init__.py +37 -1
- vtlengine/files/parser/__init__.py +2 -0
- vtlengine/files/parser/_time_checking.py +2 -0
- {vtlengine-1.0.1.dist-info → vtlengine-1.0.2.dist-info}/METADATA +14 -5
- {vtlengine-1.0.1.dist-info → vtlengine-1.0.2.dist-info}/RECORD +29 -29
- {vtlengine-1.0.1.dist-info → vtlengine-1.0.2.dist-info}/LICENSE.md +0 -0
- {vtlengine-1.0.1.dist-info → vtlengine-1.0.2.dist-info}/WHEEL +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from copy import copy
|
|
2
|
-
from typing import Union, Any
|
|
2
|
+
from typing import Union, Any, List
|
|
3
3
|
|
|
4
4
|
import numpy as np
|
|
5
5
|
|
|
@@ -287,4 +287,145 @@ class Nvl(Binary):
|
|
|
287
287
|
}
|
|
288
288
|
for comp in result_components.values():
|
|
289
289
|
comp.nullable = False
|
|
290
|
-
return Dataset(
|
|
290
|
+
return Dataset(
|
|
291
|
+
name="result",
|
|
292
|
+
components=result_components,
|
|
293
|
+
data=None
|
|
294
|
+
)
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
class Case(Operator):
|
|
298
|
+
|
|
299
|
+
@classmethod
|
|
300
|
+
def evaluate(cls,
|
|
301
|
+
conditions: List[Any],
|
|
302
|
+
thenOps: List[Any],
|
|
303
|
+
elseOp: Any
|
|
304
|
+
) -> Union[Scalar, DataComponent, Dataset]:
|
|
305
|
+
|
|
306
|
+
result = cls.validate(conditions, thenOps, elseOp)
|
|
307
|
+
|
|
308
|
+
if isinstance(result, Scalar):
|
|
309
|
+
result.value = elseOp.value
|
|
310
|
+
for i in range(len(conditions)):
|
|
311
|
+
if conditions[i].value:
|
|
312
|
+
result.value = thenOps[i].value
|
|
313
|
+
|
|
314
|
+
if isinstance(result, DataComponent):
|
|
315
|
+
result.data = pd.Series(None, index=conditions[0].data.index)
|
|
316
|
+
|
|
317
|
+
for i, condition in enumerate(conditions):
|
|
318
|
+
value = thenOps[i].value if isinstance(thenOps[i], Scalar) else thenOps[i].data
|
|
319
|
+
result.data = np.where(condition.data, value, # type: ignore[call-overload]
|
|
320
|
+
result.data)
|
|
321
|
+
|
|
322
|
+
condition_mask_else = ~np.any([condition.data for condition in conditions], axis=0)
|
|
323
|
+
else_value = elseOp.value if isinstance(elseOp, Scalar) else elseOp.data
|
|
324
|
+
result.data = pd.Series(np.where(condition_mask_else, else_value, result.data),
|
|
325
|
+
index=conditions[0].data.index)
|
|
326
|
+
|
|
327
|
+
if isinstance(result, Dataset):
|
|
328
|
+
identifiers = result.get_identifiers_names()
|
|
329
|
+
columns = [col for col in result.get_components_names() if col not in identifiers]
|
|
330
|
+
result.data = (conditions[0].data[identifiers] if conditions[0].data is not None
|
|
331
|
+
else pd.DataFrame(columns=identifiers))
|
|
332
|
+
|
|
333
|
+
for i in range(len(conditions)):
|
|
334
|
+
condition = conditions[i]
|
|
335
|
+
bool_col = next(x.name for x in condition.get_measures() if x.data_type == Boolean)
|
|
336
|
+
condition_mask = condition.data[bool_col]
|
|
337
|
+
|
|
338
|
+
result.data.loc[condition_mask, columns] = (
|
|
339
|
+
thenOps[i].value if isinstance(thenOps[i], Scalar)
|
|
340
|
+
else thenOps[i].data.loc[condition_mask, columns]
|
|
341
|
+
)
|
|
342
|
+
|
|
343
|
+
condition_mask_else = ~np.logical_or.reduce([
|
|
344
|
+
condition.data[next(x.name for x in condition.get_measures() if
|
|
345
|
+
x.data_type == Boolean)].astype(bool) for
|
|
346
|
+
condition in conditions])
|
|
347
|
+
|
|
348
|
+
result.data.loc[condition_mask_else, columns] = (
|
|
349
|
+
elseOp.value if isinstance(elseOp, Scalar)
|
|
350
|
+
else elseOp.data.loc[condition_mask_else, columns]
|
|
351
|
+
)
|
|
352
|
+
|
|
353
|
+
return result
|
|
354
|
+
|
|
355
|
+
@classmethod
|
|
356
|
+
def validate(cls,
|
|
357
|
+
conditions: List[Any],
|
|
358
|
+
thenOps: List[Any],
|
|
359
|
+
elseOp: Any
|
|
360
|
+
) -> Union[Scalar, DataComponent, Dataset]:
|
|
361
|
+
|
|
362
|
+
if len(set(map(type, conditions))) > 1:
|
|
363
|
+
raise SemanticError("2-1-9-1", op=cls.op)
|
|
364
|
+
|
|
365
|
+
ops = thenOps + [elseOp]
|
|
366
|
+
then_else_types = set(map(type, ops))
|
|
367
|
+
condition_type = type(conditions[0])
|
|
368
|
+
|
|
369
|
+
if condition_type is Scalar:
|
|
370
|
+
for condition in conditions:
|
|
371
|
+
if condition.data_type != Boolean:
|
|
372
|
+
raise SemanticError("2-1-9-2", op=cls.op, name=condition.name)
|
|
373
|
+
if list(then_else_types) != [Scalar]:
|
|
374
|
+
raise SemanticError("2-1-9-3", op=cls.op)
|
|
375
|
+
|
|
376
|
+
# The output data type is the data type of the last then operation that has a true
|
|
377
|
+
# condition, defaulting to the data type of the else operation if no condition is true
|
|
378
|
+
output_data_type = elseOp.data_type
|
|
379
|
+
for i in range(len(conditions)):
|
|
380
|
+
if conditions[i].value:
|
|
381
|
+
output_data_type = thenOps[i].data_type
|
|
382
|
+
|
|
383
|
+
return Scalar(
|
|
384
|
+
name="result",
|
|
385
|
+
value=None,
|
|
386
|
+
data_type=output_data_type,
|
|
387
|
+
)
|
|
388
|
+
|
|
389
|
+
elif condition_type is DataComponent:
|
|
390
|
+
for condition in conditions:
|
|
391
|
+
if not condition.data_type == Boolean:
|
|
392
|
+
raise SemanticError("2-1-9-4", op=cls.op, name=condition.name)
|
|
393
|
+
|
|
394
|
+
nullable = any(
|
|
395
|
+
thenOp.nullable if isinstance(thenOp, DataComponent) else thenOp.data_type == Null
|
|
396
|
+
for thenOp in ops
|
|
397
|
+
)
|
|
398
|
+
|
|
399
|
+
data_type = ops[0].data_type
|
|
400
|
+
for op in ops[1:]:
|
|
401
|
+
data_type = binary_implicit_promotion(data_type, op.data_type)
|
|
402
|
+
|
|
403
|
+
return DataComponent(
|
|
404
|
+
name="result",
|
|
405
|
+
data=None,
|
|
406
|
+
data_type=data_type,
|
|
407
|
+
role=Role.MEASURE,
|
|
408
|
+
nullable=nullable,
|
|
409
|
+
)
|
|
410
|
+
|
|
411
|
+
# Dataset
|
|
412
|
+
for condition in conditions:
|
|
413
|
+
if len(condition.get_measures_names()) != 1:
|
|
414
|
+
raise SemanticError("1-1-1-4", op=cls.op)
|
|
415
|
+
if condition.get_measures()[0].data_type != Boolean:
|
|
416
|
+
raise SemanticError("2-1-9-5", op=cls.op, name=condition.name)
|
|
417
|
+
|
|
418
|
+
if Dataset not in then_else_types:
|
|
419
|
+
raise SemanticError("2-1-9-6", op=cls.op)
|
|
420
|
+
|
|
421
|
+
components = next(op for op in ops if isinstance(op, Dataset)).components
|
|
422
|
+
comp_names = [comp.name for comp in components.values()]
|
|
423
|
+
for op in ops:
|
|
424
|
+
if isinstance(op, Dataset) and op.get_components_names() != comp_names:
|
|
425
|
+
raise SemanticError("2-1-9-7", op=cls.op)
|
|
426
|
+
|
|
427
|
+
return Dataset(
|
|
428
|
+
name="result",
|
|
429
|
+
components=components,
|
|
430
|
+
data=None
|
|
431
|
+
)
|
vtlengine/Operators/Numeric.py
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
|
+
import _random
|
|
1
2
|
import math
|
|
2
3
|
import operator
|
|
4
|
+
import warnings
|
|
3
5
|
from decimal import getcontext, Decimal
|
|
4
6
|
from typing import Any, Optional, Union
|
|
5
7
|
|
|
6
8
|
import vtlengine.Operators as Operator
|
|
7
9
|
import pandas as pd
|
|
8
|
-
from vtlengine.DataTypes import Integer, Number
|
|
10
|
+
from vtlengine.DataTypes import Integer, Number, binary_implicit_promotion
|
|
9
11
|
from vtlengine.Operators import ALL_MODEL_DATA_TYPES
|
|
10
12
|
|
|
11
13
|
from vtlengine.AST.Grammar.tokens import (
|
|
@@ -24,6 +26,7 @@ from vtlengine.AST.Grammar.tokens import (
|
|
|
24
26
|
ROUND,
|
|
25
27
|
SQRT,
|
|
26
28
|
TRUNC,
|
|
29
|
+
RANDOM,
|
|
27
30
|
)
|
|
28
31
|
from vtlengine.Exceptions import SemanticError
|
|
29
32
|
from vtlengine.Model import DataComponent, Dataset, Scalar
|
|
@@ -51,7 +54,8 @@ class Binary(Operator.Binary):
|
|
|
51
54
|
if isinstance(x, int) and isinstance(y, int):
|
|
52
55
|
if cls.op == DIV and y == 0:
|
|
53
56
|
raise SemanticError("2-1-15-6", op=cls.op, value=y)
|
|
54
|
-
|
|
57
|
+
if cls.op == RANDOM:
|
|
58
|
+
return cls.py_op(x, y)
|
|
55
59
|
x = float(x)
|
|
56
60
|
y = float(y)
|
|
57
61
|
# Handles precision to avoid floating point errors
|
|
@@ -377,3 +381,37 @@ class Trunc(Parameterized):
|
|
|
377
381
|
return truncated_value
|
|
378
382
|
|
|
379
383
|
return int(truncated_value)
|
|
384
|
+
|
|
385
|
+
|
|
386
|
+
class PseudoRandom(_random.Random):
|
|
387
|
+
|
|
388
|
+
def __init__(self, seed: Union[int, float]) -> None:
|
|
389
|
+
super().__init__()
|
|
390
|
+
self.seed(seed)
|
|
391
|
+
|
|
392
|
+
|
|
393
|
+
class Random(Parameterized):
|
|
394
|
+
|
|
395
|
+
op = RANDOM
|
|
396
|
+
return_type = Number
|
|
397
|
+
|
|
398
|
+
@classmethod
|
|
399
|
+
def validate(cls, seed: Any, index: Any = None) -> Any:
|
|
400
|
+
if index.data_type != Integer:
|
|
401
|
+
index.data_type = binary_implicit_promotion(index.data_type, Integer)
|
|
402
|
+
if index.value < 0:
|
|
403
|
+
raise SemanticError("2-1-15-2", op=cls.op, value=index)
|
|
404
|
+
if index.value > 10000:
|
|
405
|
+
warnings.warn("Random: The value of 'index' is very big. This can affect "
|
|
406
|
+
"performance.", UserWarning)
|
|
407
|
+
return super().validate(seed, index)
|
|
408
|
+
|
|
409
|
+
@classmethod
|
|
410
|
+
def py_op(cls,
|
|
411
|
+
seed: Union[int, float],
|
|
412
|
+
index: int
|
|
413
|
+
) -> float:
|
|
414
|
+
instance: PseudoRandom = PseudoRandom(seed)
|
|
415
|
+
for _ in range(index):
|
|
416
|
+
instance.random()
|
|
417
|
+
return instance.random().__round__(6)
|
vtlengine/Operators/Time.py
CHANGED
|
@@ -148,6 +148,10 @@ class Binary(Time):
|
|
|
148
148
|
pass
|
|
149
149
|
|
|
150
150
|
|
|
151
|
+
class Parameterized(Time):
|
|
152
|
+
pass
|
|
153
|
+
|
|
154
|
+
|
|
151
155
|
class Period_indicator(Unary):
|
|
152
156
|
op = PERIOD_INDICATOR
|
|
153
157
|
|
|
@@ -198,6 +202,17 @@ class Period_indicator(Unary):
|
|
|
198
202
|
return result
|
|
199
203
|
|
|
200
204
|
|
|
205
|
+
class Parametrized(Time):
|
|
206
|
+
|
|
207
|
+
@classmethod
|
|
208
|
+
def validate(cls, operand: Any, param: Any) -> Any:
|
|
209
|
+
pass
|
|
210
|
+
|
|
211
|
+
@classmethod
|
|
212
|
+
def evaluate(cls, operand: Any, param: Any) -> Any:
|
|
213
|
+
pass
|
|
214
|
+
|
|
215
|
+
|
|
201
216
|
class Flow_to_stock(Unary):
|
|
202
217
|
|
|
203
218
|
@classmethod
|
|
@@ -784,3 +799,122 @@ class Current_Date(Time):
|
|
|
784
799
|
result = cls.validate()
|
|
785
800
|
result.value = date.today().isoformat()
|
|
786
801
|
return result
|
|
802
|
+
|
|
803
|
+
|
|
804
|
+
class Date_Diff(Binary):
|
|
805
|
+
|
|
806
|
+
@classmethod
|
|
807
|
+
def evaluate(cls, Date1: Any, Date2: Any) -> Any:
|
|
808
|
+
# TODO: Implement this method (or adapt Binary's validate method to work with this operator)
|
|
809
|
+
pass
|
|
810
|
+
|
|
811
|
+
@classmethod
|
|
812
|
+
def validate(cls, Date1: Any, Date2: Any) -> Any:
|
|
813
|
+
pass
|
|
814
|
+
|
|
815
|
+
|
|
816
|
+
class Date_Add(Parametrized):
|
|
817
|
+
@classmethod
|
|
818
|
+
def evaluate(cls, operand: Any, param_list: List[Any]) -> Any:
|
|
819
|
+
# TODO: Implement this method (or adapt Binary's validate method to work with this operator)
|
|
820
|
+
pass
|
|
821
|
+
|
|
822
|
+
@classmethod
|
|
823
|
+
def validate(cls, operand: Any, param_list: List[Any]) -> Any:
|
|
824
|
+
pass
|
|
825
|
+
|
|
826
|
+
|
|
827
|
+
class Year(Unary):
|
|
828
|
+
|
|
829
|
+
@classmethod
|
|
830
|
+
def validate(cls, operand: Any) -> Any:
|
|
831
|
+
# TODO: Implement this method (or adapt Unary's validate method to work with this operator)
|
|
832
|
+
pass
|
|
833
|
+
|
|
834
|
+
@classmethod
|
|
835
|
+
def py_op(cls, x: Any) -> Any:
|
|
836
|
+
pass
|
|
837
|
+
|
|
838
|
+
|
|
839
|
+
class Month(Unary):
|
|
840
|
+
|
|
841
|
+
@classmethod
|
|
842
|
+
def validate(cls, operand: Any) -> Any:
|
|
843
|
+
# TODO: Implement this method (or adapt Unary's validate method to work with this operator)
|
|
844
|
+
pass
|
|
845
|
+
|
|
846
|
+
@classmethod
|
|
847
|
+
def py_op(cls, x: Any) -> Any:
|
|
848
|
+
pass
|
|
849
|
+
|
|
850
|
+
|
|
851
|
+
class Day_of_Month(Unary):
|
|
852
|
+
|
|
853
|
+
@classmethod
|
|
854
|
+
def validate(cls, operand: Any) -> Any:
|
|
855
|
+
# TODO: Implement this method (or adapt Unary's validate method to work with this operator)
|
|
856
|
+
pass
|
|
857
|
+
|
|
858
|
+
@classmethod
|
|
859
|
+
def py_op(cls, x: Any) -> Any:
|
|
860
|
+
pass
|
|
861
|
+
|
|
862
|
+
|
|
863
|
+
class Day_of_Year(Unary):
|
|
864
|
+
|
|
865
|
+
@classmethod
|
|
866
|
+
def validate(cls, operand: Any) -> Any:
|
|
867
|
+
# TODO: Implement this method (or adapt Unary's validate method to work with this operator)
|
|
868
|
+
pass
|
|
869
|
+
|
|
870
|
+
@classmethod
|
|
871
|
+
def py_op(cls, x: Any) -> Any:
|
|
872
|
+
pass
|
|
873
|
+
|
|
874
|
+
|
|
875
|
+
class Day_to_Year(Unary):
|
|
876
|
+
|
|
877
|
+
@classmethod
|
|
878
|
+
def validate(cls, operand: Any) -> Any:
|
|
879
|
+
# TODO: Implement this method (or adapt Unary's validate method to work with this operator)
|
|
880
|
+
pass
|
|
881
|
+
|
|
882
|
+
@classmethod
|
|
883
|
+
def py_op(cls, x: Any) -> Any:
|
|
884
|
+
pass
|
|
885
|
+
|
|
886
|
+
|
|
887
|
+
class Day_to_Month(Unary):
|
|
888
|
+
|
|
889
|
+
@classmethod
|
|
890
|
+
def validate(cls, operand: Any) -> Any:
|
|
891
|
+
# TODO: Implement this method (or adapt Unary's validate method to work with this operator)
|
|
892
|
+
pass
|
|
893
|
+
|
|
894
|
+
@classmethod
|
|
895
|
+
def py_op(cls, x: Any) -> Any:
|
|
896
|
+
pass
|
|
897
|
+
|
|
898
|
+
|
|
899
|
+
class Year_to_Day(Unary):
|
|
900
|
+
|
|
901
|
+
@classmethod
|
|
902
|
+
def validate(cls, operand: Any) -> Any:
|
|
903
|
+
# TODO: Implement this method (or adapt Unary's validate method to work with this operator)
|
|
904
|
+
pass
|
|
905
|
+
|
|
906
|
+
@classmethod
|
|
907
|
+
def py_op(cls, x: Any) -> Any:
|
|
908
|
+
pass
|
|
909
|
+
|
|
910
|
+
|
|
911
|
+
class Month_to_Day(Unary):
|
|
912
|
+
|
|
913
|
+
@classmethod
|
|
914
|
+
def validate(cls, operand: Any) -> Any:
|
|
915
|
+
# TODO: Implement this method (or adapt Unary's validate method to work with this operator)
|
|
916
|
+
pass
|
|
917
|
+
|
|
918
|
+
@classmethod
|
|
919
|
+
def py_op(cls, x: Any) -> Any:
|
|
920
|
+
pass
|
vtlengine/Utils/__init__.py
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from typing import Any, Dict
|
|
2
|
+
|
|
1
3
|
from vtlengine.Operators.Aggregation import (
|
|
2
4
|
Avg,
|
|
3
5
|
Count,
|
|
@@ -84,6 +86,7 @@ from vtlengine.Operators.Numeric import (
|
|
|
84
86
|
Trunc,
|
|
85
87
|
UnMinus,
|
|
86
88
|
UnPlus,
|
|
89
|
+
Random,
|
|
87
90
|
)
|
|
88
91
|
from vtlengine.Operators.RoleSetter import Attribute, Identifier, Measure
|
|
89
92
|
from vtlengine.Operators.Set import Intersection, Setdiff, Symdiff, Union
|
|
@@ -104,6 +107,16 @@ from vtlengine.Operators.Time import (
|
|
|
104
107
|
Stock_to_flow,
|
|
105
108
|
Fill_time_series,
|
|
106
109
|
Time_Shift,
|
|
110
|
+
Year,
|
|
111
|
+
Month,
|
|
112
|
+
Day_of_Month,
|
|
113
|
+
Day_of_Year,
|
|
114
|
+
Day_to_Year,
|
|
115
|
+
Day_to_Month,
|
|
116
|
+
Year_to_Day,
|
|
117
|
+
Month_to_Day,
|
|
118
|
+
Date_Diff,
|
|
119
|
+
Date_Add,
|
|
107
120
|
)
|
|
108
121
|
|
|
109
122
|
from vtlengine.AST.Grammar.tokens import (
|
|
@@ -190,9 +203,20 @@ from vtlengine.AST.Grammar.tokens import (
|
|
|
190
203
|
LEFT_JOIN,
|
|
191
204
|
FULL_JOIN,
|
|
192
205
|
CROSS_JOIN,
|
|
206
|
+
RANDOM,
|
|
207
|
+
DAYOFYEAR,
|
|
208
|
+
DAYOFMONTH,
|
|
209
|
+
MONTH,
|
|
210
|
+
YEAR,
|
|
211
|
+
DAYTOYEAR,
|
|
212
|
+
DAYTOMONTH,
|
|
213
|
+
YEARTODAY,
|
|
214
|
+
MONTHTODAY,
|
|
215
|
+
DATE_DIFF,
|
|
216
|
+
DATE_ADD,
|
|
193
217
|
)
|
|
194
218
|
|
|
195
|
-
BINARY_MAPPING = {
|
|
219
|
+
BINARY_MAPPING: Dict[Any, Any] = {
|
|
196
220
|
# General
|
|
197
221
|
MEMBERSHIP: Membership,
|
|
198
222
|
# Boolean
|
|
@@ -218,6 +242,7 @@ BINARY_MAPPING = {
|
|
|
218
242
|
MOD: Modulo,
|
|
219
243
|
POWER: Power,
|
|
220
244
|
DIV: Div,
|
|
245
|
+
RANDOM: Random,
|
|
221
246
|
# General
|
|
222
247
|
AS: Alias,
|
|
223
248
|
# String
|
|
@@ -225,6 +250,7 @@ BINARY_MAPPING = {
|
|
|
225
250
|
# Time
|
|
226
251
|
TIMESHIFT: Time_Shift,
|
|
227
252
|
CHARSET_MATCH: Match,
|
|
253
|
+
DATE_DIFF: Date_Diff,
|
|
228
254
|
}
|
|
229
255
|
|
|
230
256
|
UNARY_MAPPING = {
|
|
@@ -253,6 +279,14 @@ UNARY_MAPPING = {
|
|
|
253
279
|
PERIOD_INDICATOR: Period_indicator,
|
|
254
280
|
FLOW_TO_STOCK: Flow_to_stock,
|
|
255
281
|
STOCK_TO_FLOW: Stock_to_flow,
|
|
282
|
+
YEAR: Year,
|
|
283
|
+
MONTH: Month,
|
|
284
|
+
DAYOFMONTH: Day_of_Month,
|
|
285
|
+
DAYOFYEAR: Day_of_Year,
|
|
286
|
+
DAYTOYEAR: Day_to_Year,
|
|
287
|
+
DAYTOMONTH: Day_to_Month,
|
|
288
|
+
YEARTODAY: Year_to_Day,
|
|
289
|
+
MONTHTODAY: Month_to_Day,
|
|
256
290
|
}
|
|
257
291
|
|
|
258
292
|
PARAMETRIC_MAPPING = {
|
|
@@ -264,6 +298,7 @@ PARAMETRIC_MAPPING = {
|
|
|
264
298
|
REPLACE: Replace,
|
|
265
299
|
# Time
|
|
266
300
|
FILL_TIME_SERIES: Fill_time_series,
|
|
301
|
+
DATE_ADD: Date_Add,
|
|
267
302
|
}
|
|
268
303
|
|
|
269
304
|
ROLE_SETTER_MAPPING = {
|
|
@@ -320,6 +355,7 @@ ANALYTIC_MAPPING = {
|
|
|
320
355
|
}
|
|
321
356
|
|
|
322
357
|
THEN_ELSE = {"then": "T", "else": "E"}
|
|
358
|
+
|
|
323
359
|
JOIN_MAPPING = {
|
|
324
360
|
INNER_JOIN: InnerJoin,
|
|
325
361
|
LEFT_JOIN: LeftJoin,
|
|
@@ -133,6 +133,8 @@ def _pandas_load_s3_csv(components: Dict[str, Component], csv_path: str) -> pd.D
|
|
|
133
133
|
|
|
134
134
|
|
|
135
135
|
def _parse_boolean(value: str) -> bool:
|
|
136
|
+
if isinstance(value, bool):
|
|
137
|
+
return value
|
|
136
138
|
if value.lower() == "true" or value == "1":
|
|
137
139
|
return True
|
|
138
140
|
return False
|
|
@@ -93,6 +93,8 @@ further_options_period_pattern = (
|
|
|
93
93
|
|
|
94
94
|
|
|
95
95
|
def check_time_period(value: str) -> str:
|
|
96
|
+
if isinstance(value, int):
|
|
97
|
+
value = str(value)
|
|
96
98
|
value = value.replace(" ", "")
|
|
97
99
|
period_result = re.fullmatch(period_pattern, value)
|
|
98
100
|
if period_result is not None:
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: vtlengine
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.2
|
|
4
4
|
Summary: Run and Validate VTL Scripts
|
|
5
|
+
Home-page: https://github.com/Meaningful-Data/vtlengine
|
|
5
6
|
License: AGPL-3.0
|
|
7
|
+
Keywords: vtl,sdmx,vtlengine,Validation and Transformation Language
|
|
6
8
|
Author: MeaningfulData
|
|
7
9
|
Author-email: info@meaningfuldata.eu
|
|
8
10
|
Requires-Python: >=3.10,<4.0
|
|
9
|
-
Classifier: Development Status ::
|
|
11
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
10
12
|
Classifier: Intended Audience :: Developers
|
|
11
13
|
Classifier: Intended Audience :: Information Technology
|
|
12
14
|
Classifier: Intended Audience :: Science/Research
|
|
@@ -16,20 +18,26 @@ Classifier: Programming Language :: Python :: 3.10
|
|
|
16
18
|
Classifier: Programming Language :: Python :: 3.11
|
|
17
19
|
Classifier: Programming Language :: Python :: 3.12
|
|
18
20
|
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Typing :: Typed
|
|
19
22
|
Requires-Dist: antlr4-python3-runtime (==4.9.2)
|
|
20
23
|
Requires-Dist: bottleneck (>=1.3.4,<2.0.0)
|
|
21
24
|
Requires-Dist: duckdb (>=1.1.1,<2.0.0)
|
|
22
25
|
Requires-Dist: networkx (>=2.8.8,<3.0.0)
|
|
23
|
-
Requires-Dist: numba (>=0.60.0,<0.61.0)
|
|
24
26
|
Requires-Dist: numexpr (>=2.9.0,<3.0.0)
|
|
25
27
|
Requires-Dist: pandas (>=2.1.4,<3.0.0)
|
|
26
|
-
Requires-Dist: pyarrow (>=17.0.0,<18.0.0)
|
|
27
28
|
Requires-Dist: s3fs (>=2024.9.0,<2025.0.0)
|
|
28
29
|
Requires-Dist: sqlglot (>=22.2.0,<23.0.0)
|
|
30
|
+
Project-URL: Repository, https://github.com/Meaningful-Data/vtlengine
|
|
29
31
|
Description-Content-Type: text/markdown
|
|
30
32
|
|
|
31
33
|
# VTL Engine
|
|
32
34
|
|
|
35
|
+
| | |
|
|
36
|
+
|---------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|
37
|
+
| Testing | [](https://github.com/Meaningful-Data/vtlengine/actions/workflows/testing.yml) |
|
|
38
|
+
| Package | [](https://pypi.org/project/vtlengine/) |
|
|
39
|
+
| License | [](https://github.com/Meaningful-Data/vtlengine/blob/main/LICENSE.md) |
|
|
40
|
+
|
|
33
41
|
## Introduction
|
|
34
42
|
|
|
35
43
|
The VTL Engine is a Python library for validating and running VTL scripts.
|
|
@@ -67,7 +75,8 @@ Any action with VTL requires the following elements as input:
|
|
|
67
75
|
* **VTL Script**: Is the VTL to be executed, which includes the transformation scheme, as well as de
|
|
68
76
|
User Defined Operators, Hierarchical Rulesets and Datapoint Rulesets. It is provided as a string
|
|
69
77
|
or as a Path object to a vtl file.
|
|
70
|
-
* **Data structures** : Provides the structure of the input artifacts of the VTL script, according
|
|
78
|
+
* **Data structures** : Provides the structure of the input artifacts of the VTL script, according
|
|
79
|
+
to
|
|
71
80
|
the VTL Information model. Given that the current version doesn't prescribe a standard format for
|
|
72
81
|
providing the information, the VTL Engine is implementing a JSON format that can be found here.
|
|
73
82
|
Data Structures can be provided as Dictionaries or as Paths to JSON files. It is possible to have
|
|
@@ -1,58 +1,58 @@
|
|
|
1
|
-
vtlengine/API/_InternalApi.py,sha256=
|
|
2
|
-
vtlengine/API/__init__.py,sha256=
|
|
1
|
+
vtlengine/API/_InternalApi.py,sha256=YO6FrDlIF-OJDjhj5n2Ds7afNvA3x9JwM9J9BJexsmU,14403
|
|
2
|
+
vtlengine/API/__init__.py,sha256=shttqk4kmDbeQasawMuw_qqPN9uS2mzlzKy6QqZfp6o,10987
|
|
3
3
|
vtlengine/AST/ASTConstructor.py,sha256=qmHkfiVmGGAYD7NeNJz_zyGxU3t0hY-kDdkzWjCyuVw,19976
|
|
4
|
-
vtlengine/AST/ASTConstructorModules/Expr.py,sha256=
|
|
5
|
-
vtlengine/AST/ASTConstructorModules/ExprComponents.py,sha256=
|
|
4
|
+
vtlengine/AST/ASTConstructorModules/Expr.py,sha256=6JQ3QynbIqRFrGg8MIJ54VB9Tf2OfxuM2BPwE8xODo0,66589
|
|
5
|
+
vtlengine/AST/ASTConstructorModules/ExprComponents.py,sha256=Ud9s-ff2TUUWqvLbAU8Djj7ApXh9mNUsE-fNhphnZQ4,36903
|
|
6
6
|
vtlengine/AST/ASTConstructorModules/Terminals.py,sha256=hcvgMzhWEAT1AsBZNrx80UYMf0nhcA4mbXDrcXAKQvc,25387
|
|
7
7
|
vtlengine/AST/ASTConstructorModules/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
8
|
vtlengine/AST/ASTDataExchange.py,sha256=kPSz21DGbEv-2bZowObseqf2d2_iQj1VnrqWuD9ZwtA,140
|
|
9
9
|
vtlengine/AST/ASTEncoders.py,sha256=0RxSQ-4SFTOhFtQFntNeo8VT_gq4qCi92ZK7EWWqOCM,758
|
|
10
|
-
vtlengine/AST/ASTTemplate.py,sha256=
|
|
10
|
+
vtlengine/AST/ASTTemplate.py,sha256=uL1wSwSqDwwBFhQEfhIOb8r9xG9uMwUOGBcVKD27bds,12358
|
|
11
11
|
vtlengine/AST/ASTVisitor.py,sha256=3QQTudBpbR4pPQdH7y07EgwuzhoGzNQ59qox8R-E3fM,500
|
|
12
12
|
vtlengine/AST/DAG/__init__.py,sha256=KAE0yz-kB6cBTJVBvOGcVT-fVStofDdCutjMsbITqNw,14714
|
|
13
13
|
vtlengine/AST/DAG/_words.py,sha256=lEuBQ_w-KoKGna-x3gFGfbX1KP4Ez5EgdomH2LOeodk,170
|
|
14
|
-
vtlengine/AST/Grammar/Vtl.g4,sha256=
|
|
15
|
-
vtlengine/AST/Grammar/VtlTokens.g4,sha256=
|
|
14
|
+
vtlengine/AST/Grammar/Vtl.g4,sha256=86bBWjQLCHZSuB5iLIk0JZRgMyMg0n7xbU8qzot2cIE,26313
|
|
15
|
+
vtlengine/AST/Grammar/VtlTokens.g4,sha256=SwDR_59U25APqslczFcvTUiPoH7bC6kGaH2GkJ3kYzA,9972
|
|
16
16
|
vtlengine/AST/Grammar/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
17
|
-
vtlengine/AST/Grammar/lexer.py,sha256=
|
|
18
|
-
vtlengine/AST/Grammar/parser.py,sha256=
|
|
19
|
-
vtlengine/AST/Grammar/tokens.py,sha256=
|
|
20
|
-
vtlengine/AST/VtlVisitor.py,sha256=
|
|
21
|
-
vtlengine/AST/__init__.py,sha256=
|
|
17
|
+
vtlengine/AST/Grammar/lexer.py,sha256=an_9C6ASQ2PN_0tAn41plIYt3gTx2cMrcbtBDXQyI-c,105743
|
|
18
|
+
vtlengine/AST/Grammar/parser.py,sha256=4AA9tdgPuAyXELW5Cr6hZaHq3pdNKp0NeDpp8sPaVb0,635423
|
|
19
|
+
vtlengine/AST/Grammar/tokens.py,sha256=VnNBAtm89AgKIDFPTQL0Jxunv5kUJ_n9D3Aj6Tfs2Do,3142
|
|
20
|
+
vtlengine/AST/VtlVisitor.py,sha256=G9bpyPEvx8hUMzzn1V2RE4O3c59nPUEYrm5bEq8d6kc,35334
|
|
21
|
+
vtlengine/AST/__init__.py,sha256=X5WIN476KnPeFFzHunldVCD1RtaHHUIcxtZONY0jaWk,9824
|
|
22
22
|
vtlengine/DataTypes/NumericTypesHandling.py,sha256=eeSUhnRkAlcYjwbLZcuuUuJUNFWR3tVWQj8DfEHythk,1230
|
|
23
|
-
vtlengine/DataTypes/TimeHandling.py,sha256=
|
|
23
|
+
vtlengine/DataTypes/TimeHandling.py,sha256=HHktFbZTA90bNnLLXc39CrbMsU_5qZW4CQJd44k1IC4,18852
|
|
24
24
|
vtlengine/DataTypes/__init__.py,sha256=tAm7U383MWckZCCqoh2327XaU44qap_l8nGkmmQlh_o,21607
|
|
25
|
-
vtlengine/Exceptions/__init__.py,sha256=
|
|
26
|
-
vtlengine/Exceptions/messages.py,sha256=
|
|
27
|
-
vtlengine/Interpreter/__init__.py,sha256=
|
|
28
|
-
vtlengine/Model/__init__.py,sha256=
|
|
25
|
+
vtlengine/Exceptions/__init__.py,sha256=yEWbYbWZVSyZU4n5fhAbl3bxKo5y88yNHag967zrM7k,4832
|
|
26
|
+
vtlengine/Exceptions/messages.py,sha256=vW03MjerI77YR_RpYg9gK1SXQMisV0jAcq_GYYee-6g,20456
|
|
27
|
+
vtlengine/Interpreter/__init__.py,sha256=IUpPSIWoCln7gWW4c8XL8O52P7yELKKNemnLrHXhfvY,80854
|
|
28
|
+
vtlengine/Model/__init__.py,sha256=_v7Sp5XBu5_qgTFdVSfBfmlGSEQlEj5mh_t_cZC5klY,15554
|
|
29
29
|
vtlengine/Operators/Aggregation.py,sha256=PyJqyOHfZ6o12w5FS-y9-5zfOdNmVjq1cXtn41rtD-E,11629
|
|
30
|
-
vtlengine/Operators/Analytic.py,sha256=
|
|
30
|
+
vtlengine/Operators/Analytic.py,sha256=uU0GrKsipuiOGZxhzb5_AVT5BEPKtJEby1c3c4Lpocs,11429
|
|
31
31
|
vtlengine/Operators/Assignment.py,sha256=xCL9OocHqXvfwMLm33aM8moRoZtgwNxd6OnmVVwbP0Q,795
|
|
32
|
-
vtlengine/Operators/Boolean.py,sha256=
|
|
32
|
+
vtlengine/Operators/Boolean.py,sha256=ZIT60qUNkbcRn7idHVLrViZdx_PxWg2hUNVGuFA7Tf0,2878
|
|
33
33
|
vtlengine/Operators/CastOperator.py,sha256=yPadG3PJ6h3G0TMvt1EOZWjEFilMmkvQsnKZLorzpys,16743
|
|
34
34
|
vtlengine/Operators/Clause.py,sha256=GoE1CgXStq59MxbnIiMJfhPNsWtWZP7R4MTQaVzCPfA,14815
|
|
35
35
|
vtlengine/Operators/Comparison.py,sha256=5Efnl4fCt0hWRn1iukkSOG7s6NWB9u3I5fEsGCVvkYw,16513
|
|
36
|
-
vtlengine/Operators/Conditional.py,sha256=
|
|
36
|
+
vtlengine/Operators/Conditional.py,sha256=SeLWo7cT_Y4RZjKoWOovASGi4DJqHIvBc0ShE4SEXks,18594
|
|
37
37
|
vtlengine/Operators/General.py,sha256=K6fxp-IbFTDGiZrm0A194bnQo7j0IcPyu5Y4Jq-91Hk,6652
|
|
38
38
|
vtlengine/Operators/HROperators.py,sha256=jr6Wz-c9szhZ9luKAj3Bg1CwWbzauwlPOChzknvaBi0,8553
|
|
39
39
|
vtlengine/Operators/Join.py,sha256=VwYCtzqlPT75iVctomp8NPAaKi3HiCQ1Pc_K7IPhZCU,18065
|
|
40
|
-
vtlengine/Operators/Numeric.py,sha256=
|
|
40
|
+
vtlengine/Operators/Numeric.py,sha256=Sc7zPt4HjRH0l8pVnnBF9vkBoQK6zCFBF1Y0kpHiMRM,11928
|
|
41
41
|
vtlengine/Operators/RoleSetter.py,sha256=vjFmZnKPONmR2ztBbi4om7DQZkK6t2joDxMg9v_JPBA,2247
|
|
42
42
|
vtlengine/Operators/Set.py,sha256=7KnHUZaswz3TRcIeE1FwnI_TYR4LP4ZqbMN-bgPQU_g,7041
|
|
43
43
|
vtlengine/Operators/String.py,sha256=hd9bVHqCAQVrXtBNN-oJlWZRONSfeVWRpIL654GvMr8,20315
|
|
44
|
-
vtlengine/Operators/Time.py,sha256=
|
|
44
|
+
vtlengine/Operators/Time.py,sha256=Ng7w8TtFOemmDdDQfms6sUoAz1kUODbI2IybioC4f_0,34823
|
|
45
45
|
vtlengine/Operators/Validation.py,sha256=C7w1bvc8j-dYshPNvtpN_oCGMkbsoGoyv4WBCh9o2pg,10000
|
|
46
46
|
vtlengine/Operators/__init__.py,sha256=CJEwWUlz827yp4lyuXPSsMCMd4IWqCOw0yYvqpB76CI,36993
|
|
47
|
-
vtlengine/Utils/__init__.py,sha256=
|
|
47
|
+
vtlengine/Utils/__init__.py,sha256=pWnyAi5WmoBGiaG00jCBBYHJ1IeSF6k7HpJI-aWbOY4,7105
|
|
48
48
|
vtlengine/__init__.py,sha256=qmLklaVsS-yHG4QeSzGDYln49PLhFaIjBatYNwAm2Ug,89
|
|
49
49
|
vtlengine/files/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
50
50
|
vtlengine/files/output/__init__.py,sha256=X1gmR7Hwp1wKuVTEYPxJRg1cCH-9rYdJk5Ma4_iQc8o,1170
|
|
51
51
|
vtlengine/files/output/_time_period_representation.py,sha256=3uSMK_tHXigsKNFt5-U75ZI9pIRVi6WERFwAG6jEBz0,1580
|
|
52
|
-
vtlengine/files/parser/__init__.py,sha256=
|
|
52
|
+
vtlengine/files/parser/__init__.py,sha256=Dk7BP4f2H-1EIgx8-VyFTqcP_VyfdDj9XzRvAqmr95Q,8807
|
|
53
53
|
vtlengine/files/parser/_rfc_dialect.py,sha256=Y8kAYBxH_t9AieN_tYg7QRh5A4DgvabKarx9Ko3QeCQ,462
|
|
54
|
-
vtlengine/files/parser/_time_checking.py,sha256=
|
|
55
|
-
vtlengine-1.0.
|
|
56
|
-
vtlengine-1.0.
|
|
57
|
-
vtlengine-1.0.
|
|
58
|
-
vtlengine-1.0.
|
|
54
|
+
vtlengine/files/parser/_time_checking.py,sha256=IJLZ6dxCTf6DWPT6TKJ-Hc5nUyRmTgpTq_qfWgeZJ_o,4741
|
|
55
|
+
vtlengine-1.0.2.dist-info/LICENSE.md,sha256=2xqHuoHohba7gpcZZKtOICRjzeKsQANXG8WoV9V35KM,33893
|
|
56
|
+
vtlengine-1.0.2.dist-info/METADATA,sha256=vU4vjEPjnJ15tJC0dboeBP0ZF5IZQne_KrF8GdcDURY,8531
|
|
57
|
+
vtlengine-1.0.2.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
|
|
58
|
+
vtlengine-1.0.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|