vtlengine 1.0.4__tar.gz → 1.1rc1__tar.gz

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 (59) hide show
  1. {vtlengine-1.0.4 → vtlengine-1.1rc1}/PKG-INFO +16 -17
  2. {vtlengine-1.0.4 → vtlengine-1.1rc1}/pyproject.toml +33 -24
  3. {vtlengine-1.0.4 → vtlengine-1.1rc1}/src/vtlengine/API/_InternalApi.py +9 -38
  4. vtlengine-1.1rc1/src/vtlengine/__extras_check.py +17 -0
  5. {vtlengine-1.0.4 → vtlengine-1.1rc1}/src/vtlengine/files/output/__init__.py +2 -0
  6. {vtlengine-1.0.4 → vtlengine-1.1rc1}/src/vtlengine/files/parser/__init__.py +8 -26
  7. {vtlengine-1.0.4 → vtlengine-1.1rc1}/LICENSE.md +0 -0
  8. {vtlengine-1.0.4 → vtlengine-1.1rc1}/README.md +0 -0
  9. {vtlengine-1.0.4 → vtlengine-1.1rc1}/src/vtlengine/API/__init__.py +0 -0
  10. {vtlengine-1.0.4 → vtlengine-1.1rc1}/src/vtlengine/API/data/schema/json_schema_2.1.json +0 -0
  11. {vtlengine-1.0.4 → vtlengine-1.1rc1}/src/vtlengine/AST/ASTConstructor.py +0 -0
  12. {vtlengine-1.0.4 → vtlengine-1.1rc1}/src/vtlengine/AST/ASTConstructorModules/Expr.py +0 -0
  13. {vtlengine-1.0.4 → vtlengine-1.1rc1}/src/vtlengine/AST/ASTConstructorModules/ExprComponents.py +0 -0
  14. {vtlengine-1.0.4 → vtlengine-1.1rc1}/src/vtlengine/AST/ASTConstructorModules/Terminals.py +0 -0
  15. {vtlengine-1.0.4 → vtlengine-1.1rc1}/src/vtlengine/AST/ASTConstructorModules/__init__.py +0 -0
  16. {vtlengine-1.0.4 → vtlengine-1.1rc1}/src/vtlengine/AST/ASTDataExchange.py +0 -0
  17. {vtlengine-1.0.4 → vtlengine-1.1rc1}/src/vtlengine/AST/ASTEncoders.py +0 -0
  18. {vtlengine-1.0.4 → vtlengine-1.1rc1}/src/vtlengine/AST/ASTTemplate.py +0 -0
  19. {vtlengine-1.0.4 → vtlengine-1.1rc1}/src/vtlengine/AST/ASTVisitor.py +0 -0
  20. {vtlengine-1.0.4 → vtlengine-1.1rc1}/src/vtlengine/AST/DAG/__init__.py +0 -0
  21. {vtlengine-1.0.4 → vtlengine-1.1rc1}/src/vtlengine/AST/DAG/_words.py +0 -0
  22. {vtlengine-1.0.4 → vtlengine-1.1rc1}/src/vtlengine/AST/Grammar/Vtl.g4 +0 -0
  23. {vtlengine-1.0.4 → vtlengine-1.1rc1}/src/vtlengine/AST/Grammar/VtlTokens.g4 +0 -0
  24. {vtlengine-1.0.4 → vtlengine-1.1rc1}/src/vtlengine/AST/Grammar/__init__.py +0 -0
  25. {vtlengine-1.0.4 → vtlengine-1.1rc1}/src/vtlengine/AST/Grammar/lexer.py +0 -0
  26. {vtlengine-1.0.4 → vtlengine-1.1rc1}/src/vtlengine/AST/Grammar/parser.py +0 -0
  27. {vtlengine-1.0.4 → vtlengine-1.1rc1}/src/vtlengine/AST/Grammar/tokens.py +0 -0
  28. {vtlengine-1.0.4 → vtlengine-1.1rc1}/src/vtlengine/AST/VtlVisitor.py +0 -0
  29. {vtlengine-1.0.4 → vtlengine-1.1rc1}/src/vtlengine/AST/__init__.py +0 -0
  30. {vtlengine-1.0.4 → vtlengine-1.1rc1}/src/vtlengine/DataTypes/TimeHandling.py +0 -0
  31. {vtlengine-1.0.4 → vtlengine-1.1rc1}/src/vtlengine/DataTypes/__init__.py +0 -0
  32. {vtlengine-1.0.4 → vtlengine-1.1rc1}/src/vtlengine/Exceptions/__init__.py +0 -0
  33. {vtlengine-1.0.4 → vtlengine-1.1rc1}/src/vtlengine/Exceptions/messages.py +0 -0
  34. {vtlengine-1.0.4 → vtlengine-1.1rc1}/src/vtlengine/Interpreter/__init__.py +0 -0
  35. {vtlengine-1.0.4 → vtlengine-1.1rc1}/src/vtlengine/Model/__init__.py +0 -0
  36. {vtlengine-1.0.4 → vtlengine-1.1rc1}/src/vtlengine/Operators/Aggregation.py +0 -0
  37. {vtlengine-1.0.4 → vtlengine-1.1rc1}/src/vtlengine/Operators/Analytic.py +0 -0
  38. {vtlengine-1.0.4 → vtlengine-1.1rc1}/src/vtlengine/Operators/Assignment.py +0 -0
  39. {vtlengine-1.0.4 → vtlengine-1.1rc1}/src/vtlengine/Operators/Boolean.py +0 -0
  40. {vtlengine-1.0.4 → vtlengine-1.1rc1}/src/vtlengine/Operators/CastOperator.py +0 -0
  41. {vtlengine-1.0.4 → vtlengine-1.1rc1}/src/vtlengine/Operators/Clause.py +0 -0
  42. {vtlengine-1.0.4 → vtlengine-1.1rc1}/src/vtlengine/Operators/Comparison.py +0 -0
  43. {vtlengine-1.0.4 → vtlengine-1.1rc1}/src/vtlengine/Operators/Conditional.py +0 -0
  44. {vtlengine-1.0.4 → vtlengine-1.1rc1}/src/vtlengine/Operators/General.py +0 -0
  45. {vtlengine-1.0.4 → vtlengine-1.1rc1}/src/vtlengine/Operators/HROperators.py +0 -0
  46. {vtlengine-1.0.4 → vtlengine-1.1rc1}/src/vtlengine/Operators/Join.py +0 -0
  47. {vtlengine-1.0.4 → vtlengine-1.1rc1}/src/vtlengine/Operators/Numeric.py +0 -0
  48. {vtlengine-1.0.4 → vtlengine-1.1rc1}/src/vtlengine/Operators/RoleSetter.py +0 -0
  49. {vtlengine-1.0.4 → vtlengine-1.1rc1}/src/vtlengine/Operators/Set.py +0 -0
  50. {vtlengine-1.0.4 → vtlengine-1.1rc1}/src/vtlengine/Operators/String.py +0 -0
  51. {vtlengine-1.0.4 → vtlengine-1.1rc1}/src/vtlengine/Operators/Time.py +0 -0
  52. {vtlengine-1.0.4 → vtlengine-1.1rc1}/src/vtlengine/Operators/Validation.py +0 -0
  53. {vtlengine-1.0.4 → vtlengine-1.1rc1}/src/vtlengine/Operators/__init__.py +0 -0
  54. {vtlengine-1.0.4 → vtlengine-1.1rc1}/src/vtlengine/Utils/__init__.py +0 -0
  55. {vtlengine-1.0.4 → vtlengine-1.1rc1}/src/vtlengine/__init__.py +0 -0
  56. {vtlengine-1.0.4 → vtlengine-1.1rc1}/src/vtlengine/files/__init__.py +0 -0
  57. {vtlengine-1.0.4 → vtlengine-1.1rc1}/src/vtlengine/files/output/_time_period_representation.py +0 -0
  58. {vtlengine-1.0.4 → vtlengine-1.1rc1}/src/vtlengine/files/parser/_rfc_dialect.py +0 -0
  59. {vtlengine-1.0.4 → vtlengine-1.1rc1}/src/vtlengine/files/parser/_time_checking.py +0 -0
@@ -1,32 +1,31 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: vtlengine
3
- Version: 1.0.4
3
+ Version: 1.1rc1
4
4
  Summary: Run and Validate VTL Scripts
5
5
  License: AGPL-3.0
6
6
  Keywords: vtl,sdmx,vtlengine,Validation and Transformation Language
7
7
  Author: MeaningfulData
8
8
  Author-email: info@meaningfuldata.eu
9
- Requires-Python: >=3.9,<4.0
9
+ Maintainer: Francisco Javier Hernandez del Caño
10
+ Maintainer-email: javier.hernandez@meaningfuldata.eu
11
+ Requires-Python: >=3.9,<4
10
12
  Classifier: Development Status :: 5 - Production/Stable
11
13
  Classifier: Intended Audience :: Developers
12
14
  Classifier: Intended Audience :: Information Technology
13
15
  Classifier: Intended Audience :: Science/Research
14
- Classifier: License :: OSI Approved :: GNU Affero General Public License v3
15
- Classifier: Programming Language :: Python :: 3
16
- Classifier: Programming Language :: Python :: 3.9
17
- Classifier: Programming Language :: Python :: 3.10
18
- Classifier: Programming Language :: Python :: 3.11
19
- Classifier: Programming Language :: Python :: 3.12
20
- Classifier: Programming Language :: Python :: 3.13
21
16
  Classifier: Typing :: Typed
22
- Requires-Dist: antlr4-python3-runtime (==4.9.2)
23
- Requires-Dist: duckdb (>=1.1,<2.0)
24
- Requires-Dist: jsonschema (>=4.23.0,<5.0.0)
25
- Requires-Dist: networkx (>=2.8.8,<3.0.0)
26
- Requires-Dist: numexpr (>=2.9.0,<3.0.0)
27
- Requires-Dist: pandas (>=2.1.4,<3.0.0)
28
- Requires-Dist: s3fs (>=2025.2.0,<2026.0.0)
29
- Requires-Dist: sqlglot (>=22.2.0,<23.0.0)
17
+ Provides-Extra: all
18
+ Provides-Extra: s3
19
+ Requires-Dist: antlr4-python3-runtime (>=4.9.2,<4.10)
20
+ Requires-Dist: duckdb (>=1.1,<1.2)
21
+ Requires-Dist: fsspec (>=2022.11.0,<2023.0) ; extra == "all"
22
+ Requires-Dist: fsspec (>=2022.11.0,<2023.0) ; extra == "s3"
23
+ Requires-Dist: jsonschema (>=3.2.0,<5.0)
24
+ Requires-Dist: networkx (>=2.8,<3.0)
25
+ Requires-Dist: pandas (>=2.1,<3.0)
26
+ Requires-Dist: s3fs (>=2022.11.0,<2023.0) ; extra == "all"
27
+ Requires-Dist: s3fs (>=2022.11.0,<2023.0) ; extra == "s3"
28
+ Requires-Dist: sqlglot (>=22.2.0,<23.0)
30
29
  Project-URL: Authors, https://github.com/Meaningful-Data/vtlengine/graphs/contributors
31
30
  Project-URL: Documentation, https://docs.vtlengine.meaningfuldata.eu
32
31
  Project-URL: IssueTracker, https://github.com/Meaningful-Data/vtlengine/issues
@@ -1,11 +1,18 @@
1
- [tool.poetry]
1
+ [project]
2
2
  name = "vtlengine"
3
- version = "1.0.4"
3
+ version = "1.1rc1"
4
4
  description = "Run and Validate VTL Scripts"
5
- authors = ["MeaningfulData <info@meaningfuldata.eu>"]
6
5
  license = "AGPL-3.0"
7
6
  readme = "README.md"
8
-
7
+ requires-python = ">=3.9,<4"
8
+ authors = [
9
+ {name = "MeaningfulData", email = "info@meaningfuldata.eu"},
10
+ ]
11
+ maintainers = [
12
+ {name = "Francisco Javier Hernandez del Caño", email = "javier.hernandez@meaningfuldata.eu"},
13
+ {name = "Alberto Hernandez del Caño", email = "alberto.hernandez@meaningfuldata.eu"},
14
+ {name = "Mateo de Lorenzo Argeles", email = "mateo.delorenzo@meaningfuldata.eu"}
15
+ ]
9
16
  classifiers = [
10
17
  "Development Status :: 5 - Production/Stable",
11
18
  "Intended Audience :: Developers",
@@ -13,43 +20,45 @@ classifiers = [
13
20
  "Intended Audience :: Science/Research",
14
21
  "Typing :: Typed"
15
22
  ]
16
-
17
23
  keywords = ['vtl', 'sdmx', 'vtlengine', 'Validation and Transformation Language']
18
24
 
19
- [tool.poetry.urls]
25
+ dependencies = [
26
+ # PyPi dependencies
27
+ "duckdb>=1.1,<1.2",
28
+
29
+ # APT-supported dependencies
30
+ "jsonschema>=3.2.0,<5.0",
31
+ "sqlglot>=22.2.0,<23.0",
32
+ "antlr4-python3-runtime>=4.9.2,<4.10",
33
+ "pandas>=2.1,<3.0",
34
+ "networkx>=2.8,<3.0",
35
+ ]
36
+
37
+ [project.optional-dependencies]
38
+ s3 = ["s3fs>=2022.11.0,<2023.0", "fsspec>=2022.11.0,<2023.0"]
39
+ all = ["s3fs>=2022.11.0,<2023.0", "fsspec>=2022.11.0,<2023.0"]
40
+
41
+ [project.urls]
20
42
  Repository = 'https://github.com/Meaningful-Data/vtlengine'
21
43
  Documentation = 'https://docs.vtlengine.meaningfuldata.eu'
22
44
  MeaningfulData = 'https://www.meaningfuldata.eu/'
23
45
  IssueTracker = 'https://github.com/Meaningful-Data/vtlengine/issues'
24
46
  Authors = 'https://github.com/Meaningful-Data/vtlengine/graphs/contributors'
25
47
 
26
- [tool.poetry.dependencies]
27
- python = "^3.9"
28
- # PyPi dependencies
29
- duckdb = "^1.1"
30
- #numba = "^0.60.0"
31
- s3fs = "^2025.2.0"
32
- jsonschema = "^4.23.0"
33
-
34
- # APT dependencies
35
- antlr4-python3-runtime = "4.9.2"
36
- networkx = "^2.8.8"
37
- numexpr = "^2.9.0"
38
- pandas = "^2.1.4"
39
- sqlglot = "^22.2.0"
40
-
41
48
  [tool.poetry.group.dev.dependencies]
42
49
  pytest = "^8.3"
43
50
  pytest-cov = "^6.0.0"
44
51
  line-profiler-pycharm = "^1.2.0"
45
- sphinx = "^7.4.7"
46
- sphinx-rtd-theme = "^3.0.2"
47
52
  mypy = "1.14.1"
48
53
  pandas-stubs = "^2.1.4.231227"
49
- toml = "^0.10.2"
50
54
  ruff = "^0.9.4"
51
55
  types-jsonschema = "4.23.0.20241208"
52
56
 
57
+ [tool.poetry.group.docs.dependencies]
58
+ sphinx = "^7.4.7"
59
+ sphinx-rtd-theme = "^3.0.2"
60
+ toml = "^0.10.2"
61
+
53
62
  [tool.ruff]
54
63
  line-length = 100
55
64
  lint.mccabe.max-complexity = 20
@@ -5,8 +5,8 @@ from typing import Any, Dict, List, Optional, Union
5
5
 
6
6
  import jsonschema
7
7
  import pandas as pd
8
- from s3fs import S3FileSystem # type: ignore[import-untyped]
9
8
 
9
+ from vtlengine.__extras_check import __check_s3_extra
10
10
  from vtlengine.AST import PersistentAssignment, Start
11
11
  from vtlengine.DataTypes import SCALAR_TYPES
12
12
  from vtlengine.Exceptions import InputValidationException, check_key
@@ -105,38 +105,16 @@ def _load_single_datapoint(datapoint: Union[str, Path]) -> Dict[str, Any]:
105
105
  raise Exception("Invalid datapoint. Input must be a Path or an S3 URI")
106
106
  if isinstance(datapoint, str):
107
107
  if "s3://" in datapoint:
108
- # Handling S3 URI
109
- s3fs_obj = S3FileSystem()
110
-
111
- # Check if the S3 URI is valid
112
- if not s3fs_obj.exists(datapoint):
113
- raise Exception(
114
- f"Invalid datapoint. S3 URI does not exist or it is not accessible: {datapoint}"
115
- )
116
-
117
- # Check if the S3 URI is a directory
118
- if s3fs_obj.isdir(datapoint):
119
- datapoints: Dict[str, Any] = {}
120
- for f in s3fs_obj.ls(datapoint):
121
- if f.endswith(".csv"):
122
- dataset_name = f.split("/")[-1].removesuffix(".csv")
123
- dict_data = {dataset_name: f"s3://{f}"}
124
- datapoints = {**datapoints, **dict_data}
125
- return datapoints
126
-
127
- # Check if the S3 URI is a csv file
128
- if s3fs_obj.isfile(datapoint) and not datapoint.endswith(".csv"):
129
- raise Exception(f"Invalid datapoint. S3 URI must refer to a csv file: {datapoint}")
108
+ __check_s3_extra()
130
109
  dataset_name = datapoint.split("/")[-1].removesuffix(".csv")
131
110
  dict_data = {dataset_name: datapoint}
132
111
  return dict_data
133
-
134
112
  try:
135
113
  datapoint = Path(datapoint)
136
114
  except Exception:
137
115
  raise Exception("Invalid datapoint. Input must refer to a Path or an S3 URI")
138
116
  if datapoint.is_dir():
139
- datapoints = {}
117
+ datapoints: Dict[str, Any] = {}
140
118
  for f in datapoint.iterdir():
141
119
  if f.suffix != ".csv":
142
120
  continue
@@ -400,25 +378,18 @@ def _check_output_folder(output_folder: Union[str, Path]) -> None:
400
378
  """
401
379
  if isinstance(output_folder, str):
402
380
  if "s3://" in output_folder:
403
- s3fs_obj = S3FileSystem()
404
- # Check if the S3 URI is valid
405
- if not s3fs_obj.exists(output_folder):
406
- try:
407
- s3fs_obj.mkdir(output_folder)
408
- except Exception:
409
- raise Exception(
410
- f"Invalid output folder. S3 URI is invalid or "
411
- f"it is not accessible: {output_folder}"
412
- )
381
+ __check_s3_extra()
382
+ if not output_folder.endswith("/"):
383
+ raise ValueError("Output folder must be a Path or S3 URI to a directory")
413
384
  return
414
385
  try:
415
386
  output_folder = Path(output_folder)
416
387
  except Exception:
417
- raise Exception("Output folder must be a Path or S3 URI to a directory")
388
+ raise ValueError("Output folder must be a Path or S3 URI to a directory")
418
389
 
419
390
  if not isinstance(output_folder, Path):
420
- raise Exception("Output folder must be a Path or S3 URI to a directory")
391
+ raise ValueError("Output folder must be a Path or S3 URI to a directory")
421
392
  if not output_folder.exists():
422
393
  if output_folder.suffix != "":
423
- raise Exception("Output folder must be a Path or S3 URI to a directory")
394
+ raise ValueError("Output folder must be a Path or S3 URI to a directory")
424
395
  os.mkdir(output_folder)
@@ -0,0 +1,17 @@
1
+ import importlib.util
2
+
3
+ EXTRAS_DOCS = "https://docs.vtlengine.meaningfuldata.eu/#installation"
4
+ ERROR_MESSAGE = (
5
+ "The '{extra_name}' extra is required to run {extra_desc}. "
6
+ "Please install it using 'pip install vtlengine[{extra_name}]' or "
7
+ "install all extras with 'pip install vtlengine[all]'. "
8
+ f"Check the documentation at: {EXTRAS_DOCS}"
9
+ )
10
+
11
+
12
+ def __check_s3_extra() -> None:
13
+ package_loc = importlib.util.find_spec("s3fs")
14
+ if package_loc is None:
15
+ raise ImportError(
16
+ ERROR_MESSAGE.format(extra_name="s3", extra_desc="over csv files using S3 URIs")
17
+ ) from None
@@ -3,6 +3,7 @@ from typing import Optional, Union
3
3
 
4
4
  import pandas as pd
5
5
 
6
+ from vtlengine.__extras_check import __check_s3_extra
6
7
  from vtlengine.files.output._time_period_representation import (
7
8
  TimePeriodRepresentation,
8
9
  format_time_period_external_representation,
@@ -20,6 +21,7 @@ def save_datapoints(
20
21
  if time_period_representation is not None:
21
22
  format_time_period_external_representation(dataset, time_period_representation)
22
23
  if isinstance(output_path, str):
24
+ __check_s3_extra()
23
25
  if output_path.endswith("/"):
24
26
  s3_file_output = output_path + f"{dataset.name}.csv"
25
27
  else:
@@ -109,7 +109,7 @@ def _sanitize_pandas_columns(
109
109
  return data
110
110
 
111
111
 
112
- def _pandas_load_csv(components: Dict[str, Component], csv_path: Path) -> pd.DataFrame:
112
+ def _pandas_load_csv(components: Dict[str, Component], csv_path: Union[str, Path]) -> pd.DataFrame:
113
113
  obj_dtypes = {comp_name: np.object_ for comp_name, comp in components.items()}
114
114
 
115
115
  try:
@@ -121,31 +121,14 @@ def _pandas_load_csv(components: Dict[str, Component], csv_path: Path) -> pd.Dat
121
121
  na_values=[""],
122
122
  )
123
123
  except UnicodeDecodeError:
124
- raise InputValidationException(code="0-1-2-5", file=csv_path.name)
124
+ if isinstance(csv_path, Path):
125
+ raise InputValidationException(code="0-1-2-5", file=csv_path.name)
126
+ else:
127
+ raise InputValidationException(code="0-1-2-5", file=csv_path)
125
128
 
126
129
  return _sanitize_pandas_columns(components, csv_path, data)
127
130
 
128
131
 
129
- def _pandas_load_s3_csv(components: Dict[str, Component], csv_path: str) -> pd.DataFrame:
130
- obj_dtypes = {comp_name: np.object_ for comp_name, comp in components.items()}
131
-
132
- # start = time()
133
- try:
134
- data = pd.read_csv(
135
- csv_path,
136
- dtype=obj_dtypes,
137
- engine="c",
138
- keep_default_na=False,
139
- na_values=[""],
140
- )
141
-
142
- except UnicodeDecodeError:
143
- raise InputValidationException(code="0-1-2-5", file=csv_path)
144
- except Exception as e:
145
- raise InputValidationException(f"ERROR: {str(e)}, review file {str(csv_path)}")
146
- return _sanitize_pandas_columns(components, csv_path, data)
147
-
148
-
149
132
  def _parse_boolean(value: str) -> bool:
150
133
  if isinstance(value, bool):
151
134
  return value
@@ -240,10 +223,9 @@ def load_datapoints(
240
223
  ) -> pd.DataFrame:
241
224
  if csv_path is None or (isinstance(csv_path, Path) and not csv_path.exists()):
242
225
  return pd.DataFrame(columns=list(components.keys()))
243
- elif isinstance(csv_path, str):
244
- data = _pandas_load_s3_csv(components, csv_path)
245
- elif isinstance(csv_path, Path):
246
- _validate_csv_path(components, csv_path)
226
+ elif isinstance(csv_path, (str, Path)):
227
+ if isinstance(csv_path, Path):
228
+ _validate_csv_path(components, csv_path)
247
229
  data = _pandas_load_csv(components, csv_path)
248
230
  else:
249
231
  raise Exception("Invalid csv_path type")
File without changes
File without changes