digitalhub 0.14.0b5__py3-none-any.whl → 0.14.9__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.
Files changed (93) hide show
  1. digitalhub/__init__.py +2 -2
  2. digitalhub/context/api.py +43 -6
  3. digitalhub/context/builder.py +1 -1
  4. digitalhub/context/context.py +3 -6
  5. digitalhub/entities/_base/context/entity.py +0 -3
  6. digitalhub/entities/_base/executable/entity.py +29 -11
  7. digitalhub/entities/_base/material/entity.py +2 -2
  8. digitalhub/entities/_base/material/utils.py +0 -4
  9. digitalhub/entities/_commons/enums.py +1 -0
  10. digitalhub/entities/_commons/utils.py +19 -0
  11. digitalhub/entities/_processors/base/crud.py +15 -24
  12. digitalhub/entities/_processors/base/import_export.py +3 -7
  13. digitalhub/entities/_processors/base/processor.py +4 -7
  14. digitalhub/entities/_processors/base/special_ops.py +4 -8
  15. digitalhub/entities/_processors/context/crud.py +27 -29
  16. digitalhub/entities/_processors/context/import_export.py +7 -7
  17. digitalhub/entities/_processors/context/material.py +2 -2
  18. digitalhub/entities/_processors/context/special_ops.py +25 -25
  19. digitalhub/entities/_processors/utils.py +7 -116
  20. digitalhub/entities/artifact/crud.py +3 -3
  21. digitalhub/entities/artifact/utils.py +2 -2
  22. digitalhub/entities/builders.py +2 -0
  23. digitalhub/entities/dataitem/crud.py +3 -3
  24. digitalhub/entities/dataitem/utils.py +10 -14
  25. digitalhub/entities/function/_base/entity.py +0 -3
  26. digitalhub/entities/function/crud.py +3 -3
  27. digitalhub/entities/model/crud.py +3 -3
  28. digitalhub/entities/model/mlflow/utils.py +29 -20
  29. digitalhub/entities/model/utils.py +2 -2
  30. digitalhub/entities/project/_base/builder.py +0 -6
  31. digitalhub/entities/project/_base/entity.py +264 -114
  32. digitalhub/entities/project/_base/spec.py +4 -4
  33. digitalhub/entities/project/crud.py +16 -51
  34. digitalhub/entities/project/utils.py +7 -3
  35. digitalhub/entities/secret/crud.py +2 -2
  36. digitalhub/entities/task/_base/models.py +13 -16
  37. digitalhub/entities/trigger/crud.py +28 -9
  38. digitalhub/entities/workflow/_base/entity.py +0 -5
  39. digitalhub/entities/workflow/crud.py +3 -6
  40. digitalhub/stores/client/{dhcore/api_builder.py → api_builder.py} +2 -3
  41. digitalhub/stores/client/builder.py +20 -32
  42. digitalhub/stores/client/client.py +322 -0
  43. digitalhub/stores/client/{dhcore/configurator.py → configurator.py} +148 -195
  44. digitalhub/stores/client/{_base/enums.py → enums.py} +11 -0
  45. digitalhub/stores/client/header_manager.py +61 -0
  46. digitalhub/stores/client/http_handler.py +152 -0
  47. digitalhub/stores/client/{_base/key_builder.py → key_builder.py} +14 -14
  48. digitalhub/stores/client/{dhcore/params_builder.py → params_builder.py} +51 -12
  49. digitalhub/stores/client/response_processor.py +102 -0
  50. digitalhub/stores/client/utils.py +35 -0
  51. digitalhub/stores/{credentials → configurator}/api.py +5 -9
  52. digitalhub/stores/configurator/configurator.py +123 -0
  53. digitalhub/stores/{credentials → configurator}/enums.py +26 -10
  54. digitalhub/stores/configurator/handler.py +213 -0
  55. digitalhub/stores/{credentials → configurator}/ini_module.py +31 -6
  56. digitalhub/stores/data/_base/store.py +0 -4
  57. digitalhub/stores/data/api.py +4 -6
  58. digitalhub/stores/data/builder.py +6 -38
  59. digitalhub/stores/data/s3/configurator.py +30 -114
  60. digitalhub/stores/data/s3/store.py +9 -22
  61. digitalhub/stores/data/sql/configurator.py +49 -71
  62. digitalhub/stores/data/sql/store.py +26 -61
  63. digitalhub/utils/generic_utils.py +0 -12
  64. digitalhub/utils/git_utils.py +0 -8
  65. digitalhub/utils/io_utils.py +0 -8
  66. digitalhub/utils/store_utils.py +1 -1
  67. {digitalhub-0.14.0b5.dist-info → digitalhub-0.14.9.dist-info}/METADATA +3 -3
  68. {digitalhub-0.14.0b5.dist-info → digitalhub-0.14.9.dist-info}/RECORD +73 -86
  69. {digitalhub-0.14.0b5.dist-info → digitalhub-0.14.9.dist-info}/WHEEL +1 -1
  70. digitalhub/stores/client/_base/api_builder.py +0 -34
  71. digitalhub/stores/client/_base/client.py +0 -243
  72. digitalhub/stores/client/_base/params_builder.py +0 -82
  73. digitalhub/stores/client/api.py +0 -32
  74. digitalhub/stores/client/dhcore/__init__.py +0 -3
  75. digitalhub/stores/client/dhcore/client.py +0 -553
  76. digitalhub/stores/client/dhcore/enums.py +0 -18
  77. digitalhub/stores/client/dhcore/key_builder.py +0 -62
  78. digitalhub/stores/client/dhcore/utils.py +0 -86
  79. digitalhub/stores/client/local/__init__.py +0 -3
  80. digitalhub/stores/client/local/api_builder.py +0 -116
  81. digitalhub/stores/client/local/client.py +0 -605
  82. digitalhub/stores/client/local/enums.py +0 -15
  83. digitalhub/stores/client/local/key_builder.py +0 -62
  84. digitalhub/stores/client/local/params_builder.py +0 -97
  85. digitalhub/stores/credentials/__init__.py +0 -3
  86. digitalhub/stores/credentials/configurator.py +0 -185
  87. digitalhub/stores/credentials/handler.py +0 -164
  88. digitalhub/stores/credentials/store.py +0 -77
  89. digitalhub/stores/data/enums.py +0 -15
  90. /digitalhub/stores/client/{dhcore/error_parser.py → error_parser.py} +0 -0
  91. /digitalhub/stores/{client/_base → configurator}/__init__.py +0 -0
  92. {digitalhub-0.14.0b5.dist-info → digitalhub-0.14.9.dist-info}/licenses/AUTHORS +0 -0
  93. {digitalhub-0.14.0b5.dist-info → digitalhub-0.14.9.dist-info}/licenses/LICENSE +0 -0
@@ -4,81 +4,22 @@
4
4
 
5
5
  from __future__ import annotations
6
6
 
7
- from digitalhub.stores.credentials.configurator import Configurator
8
- from digitalhub.stores.credentials.enums import CredsEnvVar
7
+ from digitalhub.stores.configurator.configurator import configurator
8
+ from digitalhub.stores.configurator.enums import ConfigurationVars, CredentialsVars
9
9
 
10
10
 
11
- class SqlStoreConfigurator(Configurator):
11
+ class SqlStoreConfigurator:
12
12
  """
13
- SQL store configuration manager for database connections.
14
-
15
- Handles credential management and configuration for SQL database
16
- connections. Loads credentials from environment variables or
17
- configuration files and provides connection string generation
18
- for database access.
19
-
20
- Attributes
21
- ----------
22
- keys : list[str]
23
- List of all supported credential keys for SQL connections.
24
- required_keys : list[str]
25
- List of mandatory credential keys that must be provided.
13
+ Configurator class for SQL store configuration and credentials management.
26
14
  """
27
15
 
28
- keys = [
29
- CredsEnvVar.DB_USERNAME.value,
30
- CredsEnvVar.DB_PASSWORD.value,
31
- CredsEnvVar.DB_HOST.value,
32
- CredsEnvVar.DB_PORT.value,
33
- CredsEnvVar.DB_DATABASE.value,
34
- CredsEnvVar.DB_PLATFORM.value,
35
- ]
36
- required_keys = [
37
- CredsEnvVar.DB_USERNAME.value,
38
- CredsEnvVar.DB_PASSWORD.value,
39
- CredsEnvVar.DB_HOST.value,
40
- CredsEnvVar.DB_PORT.value,
41
- CredsEnvVar.DB_DATABASE.value,
42
- ]
43
-
44
16
  def __init__(self):
45
- super().__init__()
46
- self.load_configs()
47
-
48
- ##############################
49
- # Configuration methods
50
- ##############################
51
-
52
- def load_env_vars(self) -> None:
53
- """
54
- Load database credentials from environment variables.
55
-
56
- Retrieves SQL database connection credentials from the system
57
- environment variables and stores them in the configurator's
58
- credential handler for use in database connections.
59
- """
60
- env_creds = self._creds_handler.load_from_env(self.keys)
61
- self._creds_handler.set_credentials(self._env, env_creds)
62
-
63
- def load_file_vars(self) -> None:
64
- """
65
- Load database credentials from configuration file.
66
-
67
- Retrieves SQL database connection credentials from a
68
- configuration file and stores them in the configurator's
69
- credential handler for use in database connections.
70
- """
71
- file_creds = self._creds_handler.load_from_file(self.keys)
72
- self._creds_handler.set_credentials(self._file, file_creds)
17
+ self._validate()
73
18
 
74
19
  def get_sql_conn_string(self) -> str:
75
20
  """
76
21
  Generate PostgreSQL connection string from stored credentials.
77
22
 
78
- Constructs a PostgreSQL connection string using the configured
79
- database credentials including username, password, host, port,
80
- and database name.
81
-
82
23
  Returns
83
24
  -------
84
25
  str
@@ -86,11 +27,11 @@ class SqlStoreConfigurator(Configurator):
86
27
  'postgresql://username:password@host:port/database'
87
28
  """
88
29
  creds = self.get_sql_credentials()
89
- user = creds[CredsEnvVar.DB_USERNAME.value]
90
- password = creds[CredsEnvVar.DB_PASSWORD.value]
91
- host = creds[CredsEnvVar.DB_HOST.value]
92
- port = creds[CredsEnvVar.DB_PORT.value]
93
- database = creds[CredsEnvVar.DB_DATABASE.value]
30
+ user = creds[CredentialsVars.DB_USERNAME.value]
31
+ password = creds[CredentialsVars.DB_PASSWORD.value]
32
+ host = creds[ConfigurationVars.DB_HOST.value]
33
+ port = creds[ConfigurationVars.DB_PORT.value]
34
+ database = creds[ConfigurationVars.DB_DATABASE.value]
94
35
  return f"postgresql://{user}:{password}@{host}:{port}/{database}"
95
36
 
96
37
  def get_sql_credentials(self) -> dict:
@@ -108,5 +49,42 @@ class SqlStoreConfigurator(Configurator):
108
49
  Keys correspond to database connection parameters such as
109
50
  username, password, host, port, database, and platform.
110
51
  """
111
- creds = self.get_credentials(self._origin)
112
- return {key: creds.get(key) for key in self.keys}
52
+ keys = [
53
+ CredentialsVars.DB_USERNAME.value,
54
+ CredentialsVars.DB_PASSWORD.value,
55
+ ConfigurationVars.DB_HOST.value,
56
+ ConfigurationVars.DB_PORT.value,
57
+ ConfigurationVars.DB_DATABASE.value,
58
+ ]
59
+ creds = configurator.get_config_creds()
60
+ return {key: creds.get(key) for key in keys}
61
+
62
+ def eval_retry(self) -> bool:
63
+ """
64
+ Evaluate the status of retry lifecycle.
65
+
66
+ Returns
67
+ -------
68
+ bool
69
+ True if a retry should be attempted, False otherwise.
70
+ """
71
+ return configurator.eval_retry()
72
+
73
+ def _validate(self) -> None:
74
+ """
75
+ Validate if all required keys are present in the configuration.
76
+ """
77
+ required_keys = [
78
+ ConfigurationVars.DB_HOST.value,
79
+ ConfigurationVars.DB_PORT.value,
80
+ ConfigurationVars.DB_DATABASE.value,
81
+ CredentialsVars.DB_USERNAME.value,
82
+ CredentialsVars.DB_PASSWORD.value,
83
+ ]
84
+ current_keys = configurator.get_config_creds()
85
+ missing_keys = []
86
+ for key in required_keys:
87
+ if key not in current_keys or current_keys[key] is None:
88
+ missing_keys.append(key)
89
+ if missing_keys:
90
+ raise ValueError(f"Missing required variables for SQL store: {', '.join(missing_keys)}")
@@ -15,6 +15,7 @@ from sqlalchemy.engine import Engine
15
15
  from sqlalchemy.exc import SQLAlchemyError
16
16
 
17
17
  from digitalhub.stores.data._base.store import Store
18
+ from digitalhub.stores.data.sql.configurator import SqlStoreConfigurator
18
19
  from digitalhub.stores.readers.data.api import get_reader_by_object
19
20
  from digitalhub.utils.exceptions import ConfigError, StoreError
20
21
  from digitalhub.utils.types import SourcesOrListOfSources
@@ -22,8 +23,8 @@ from digitalhub.utils.types import SourcesOrListOfSources
22
23
  if typing.TYPE_CHECKING:
23
24
  from sqlalchemy.engine.row import Row
24
25
 
25
- from digitalhub.stores.credentials.configurator import Configurator
26
- from digitalhub.stores.data.sql.configurator import SqlStoreConfigurator
26
+
27
+ ENGINE_CONNECTION_TIMEOUT = 30
27
28
 
28
29
 
29
30
  class SqlStore(Store):
@@ -41,9 +42,9 @@ class SqlStore(Store):
41
42
  and connection parameters.
42
43
  """
43
44
 
44
- def __init__(self, configurator: Configurator | None = None) -> None:
45
- super().__init__(configurator)
46
- self._configurator: SqlStoreConfigurator
45
+ def __init__(self) -> None:
46
+ super().__init__()
47
+ self._configurator: SqlStoreConfigurator = SqlStoreConfigurator()
47
48
 
48
49
  ##############################
49
50
  # I/O methods
@@ -70,7 +71,7 @@ class SqlStore(Store):
70
71
  dst : Path
71
72
  The destination path on the local filesystem where the
72
73
  Parquet file will be saved.
73
- overwrite : bool, default False
74
+ overwrite : bool
74
75
  Whether to overwrite existing files at the destination path.
75
76
 
76
77
  Returns
@@ -159,9 +160,9 @@ class SqlStore(Store):
159
160
  path : SourcesOrListOfSources
160
161
  The SQL URI path to read from in the format
161
162
  'sql://database/schema/table'. Only single paths are supported.
162
- file_format : str, optional
163
+ file_format : str
163
164
  File format specification (not used for SQL operations).
164
- engine : str, optional
165
+ engine : str
165
166
  DataFrame engine to use (e.g., 'pandas', 'polars').
166
167
  If None, uses the default engine.
167
168
  **kwargs : dict
@@ -209,7 +210,7 @@ class SqlStore(Store):
209
210
  path : str
210
211
  The SQL URI path specifying the database connection
211
212
  in the format 'sql://database/schema/table'.
212
- engine : str, optional
213
+ engine : str
213
214
  DataFrame engine to use for result processing
214
215
  (e.g., 'pandas', 'polars'). If None, uses the default.
215
216
 
@@ -238,7 +239,7 @@ class SqlStore(Store):
238
239
  dst : str
239
240
  The destination SQL URI in the format
240
241
  'sql://database/schema/table' or 'sql://database/table'.
241
- extension : str, optional
242
+ extension : str
242
243
  File extension parameter (not used for SQL operations).
243
244
  **kwargs : dict
244
245
  Additional keyword arguments passed to the DataFrame's
@@ -350,22 +351,7 @@ class SqlStore(Store):
350
351
  # Helper methods
351
352
  ##############################
352
353
 
353
- def _get_connection_string(self) -> str:
354
- """
355
- Retrieve the database connection string from the configurator.
356
-
357
- Gets the PostgreSQL connection string using the configured
358
- database credentials (username, password, host, port, database).
359
-
360
- Returns
361
- -------
362
- str
363
- The PostgreSQL connection string in the format
364
- 'postgresql://username:password@host:port/database'.
365
- """
366
- return self._configurator.get_sql_conn_string()
367
-
368
- def _get_engine(self, schema: str | None = None) -> Engine:
354
+ def _get_engine(self, connection_string: str, schema: str | None = None) -> Engine:
369
355
  """
370
356
  Create a SQLAlchemy engine from the connection string.
371
357
 
@@ -374,7 +360,9 @@ class SqlStore(Store):
374
360
 
375
361
  Parameters
376
362
  ----------
377
- schema : str, optional
363
+ connection_string : str
364
+ The database connection string.
365
+ schema : str
378
366
  The database schema to set in the search path.
379
367
  If provided, sets the PostgreSQL search_path option.
380
368
 
@@ -382,57 +370,34 @@ class SqlStore(Store):
382
370
  -------
383
371
  Engine
384
372
  A configured SQLAlchemy engine instance.
385
-
386
- Raises
387
- ------
388
- StoreError
389
- If the connection string is invalid or engine creation fails.
390
373
  """
391
- connection_string = self._get_connection_string()
392
- if not isinstance(connection_string, str):
393
- raise StoreError("Connection string must be a string.")
394
- try:
395
- connect_args = {"connect_timeout": 30}
396
- if schema is not None:
397
- connect_args["options"] = f"-csearch_path={schema}"
398
- return create_engine(connection_string, connect_args=connect_args)
399
- except Exception as ex:
400
- raise StoreError(f"Something wrong with connection string. Arguments: {str(ex.args)}")
401
-
402
- def _check_factory(self, retry: bool = True, schema: str | None = None) -> Engine:
374
+ connect_args = {"connect_timeout": ENGINE_CONNECTION_TIMEOUT}
375
+ if schema is not None:
376
+ connect_args["options"] = f"-csearch_path={schema}"
377
+ return create_engine(connection_string, connect_args=connect_args)
378
+
379
+ def _check_factory(self, schema: str | None = None) -> Engine:
403
380
  """
404
381
  Validate database accessibility and return a working engine.
405
382
 
406
- Creates and tests a database engine, with retry capability if
407
- the initial connection fails. Handles configuration changes
408
- and ensures the database is accessible before returning.
409
-
410
383
  Parameters
411
384
  ----------
412
- retry : bool, default True
413
- Whether to attempt a retry with different configuration
414
- if the initial connection fails.
415
- schema : str, optional
385
+ schema : str
416
386
  The database schema to configure in the engine.
417
387
 
418
388
  Returns
419
389
  -------
420
390
  Engine
421
391
  A validated SQLAlchemy engine with confirmed database access.
422
-
423
- Raises
424
- ------
425
- ConfigError
426
- If database access fails and retry is exhausted or disabled.
427
392
  """
393
+ connection_string = self._configurator.get_sql_conn_string()
394
+ engine = self._get_engine(connection_string, schema)
428
395
  try:
429
- engine = self._get_engine(schema)
430
396
  self._check_access_to_storage(engine)
431
397
  return engine
432
398
  except ConfigError as e:
433
- if retry:
434
- self._configurator.eval_change_origin()
435
- return self._check_factory(retry=False, schema=schema)
399
+ if self._configurator.eval_retry():
400
+ return self._check_factory(schema=schema)
436
401
  raise e
437
402
 
438
403
  @staticmethod
@@ -95,10 +95,6 @@ def requests_chunk_download(source: str, filename: Path) -> None:
95
95
  URL to download the file from.
96
96
  filename : Path
97
97
  Path where to save the downloaded file.
98
-
99
- Returns
100
- -------
101
- None
102
98
  """
103
99
  with requests.get(source, stream=True) as r:
104
100
  r.raise_for_status()
@@ -117,10 +113,6 @@ def extract_archive(path: Path, filename: Path) -> None:
117
113
  Directory where to extract the archive.
118
114
  filename : Path
119
115
  Path to the zip archive file.
120
-
121
- Returns
122
- -------
123
- None
124
116
  """
125
117
  with ZipFile(filename, "r") as zip_file:
126
118
  zip_file.extractall(path)
@@ -256,10 +248,6 @@ def carriage_return_warn(string: str) -> None:
256
248
  ----------
257
249
  string : str
258
250
  The string to check.
259
-
260
- Returns
261
- -------
262
- None
263
251
  """
264
252
  if "\r\n" in string:
265
253
  warn("String contains a carriage return. It may not be parsed correctly from remote runtimes.")
@@ -47,10 +47,6 @@ def clone_repository(path: Path, url: str) -> None:
47
47
  Path where to save the repository.
48
48
  url : str
49
49
  URL of the repository.
50
-
51
- Returns
52
- -------
53
- None
54
50
  """
55
51
  clean_path(path)
56
52
  checkout_object = get_checkout_object(url)
@@ -85,10 +81,6 @@ def clean_path(path: Path) -> None:
85
81
  ----------
86
82
  path : Path
87
83
  Path to clean.
88
-
89
- Returns
90
- -------
91
- None
92
84
  """
93
85
 
94
86
  shutil.rmtree(path, ignore_errors=True)
@@ -23,10 +23,6 @@ def write_yaml(filepath: str | Path, obj: dict | list[dict]) -> None:
23
23
  The YAML file path to write.
24
24
  obj : dict or list of dict
25
25
  The dict or list of dicts to write.
26
-
27
- Returns
28
- -------
29
- None
30
26
  """
31
27
  if isinstance(obj, list):
32
28
  with open(filepath, "w", encoding="utf-8") as out_file:
@@ -46,10 +42,6 @@ def write_text(filepath: Path, text: str) -> None:
46
42
  The file path to write.
47
43
  text : str
48
44
  The text to write.
49
-
50
- Returns
51
- -------
52
- None
53
45
  """
54
46
  filepath.write_text(text, encoding="utf-8")
55
47
 
@@ -32,7 +32,7 @@ def get_sql_engine(schema: str | None = None) -> Engine:
32
32
 
33
33
  Parameters
34
34
  ----------
35
- schema : str, optional
35
+ schema : str
36
36
  The schema to connect to, by default None.
37
37
 
38
38
  Returns
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: digitalhub
3
- Version: 0.14.0b5
3
+ Version: 0.14.9
4
4
  Summary: Python SDK for Digitalhub
5
5
  Project-URL: Homepage, https://github.com/scc-digitalhub/digitalhub-sdk
6
6
  Author-email: Fondazione Bruno Kessler <digitalhub@fbk.eu>, Matteo Martini <mmartini@fbk.eu>
@@ -230,10 +230,10 @@ Requires-Dist: jsonschema; extra == 'dev'
230
230
  Requires-Dist: pytest; extra == 'dev'
231
231
  Requires-Dist: pytest-cov; extra == 'dev'
232
232
  Provides-Extra: full
233
- Requires-Dist: mlflow; extra == 'full'
233
+ Requires-Dist: mlflow==2.19; extra == 'full'
234
234
  Requires-Dist: pandas; extra == 'full'
235
235
  Provides-Extra: mlflow
236
- Requires-Dist: mlflow; extra == 'mlflow'
236
+ Requires-Dist: mlflow==2.19; extra == 'mlflow'
237
237
  Provides-Extra: pandas
238
238
  Requires-Dist: pandas; extra == 'pandas'
239
239
  Description-Content-Type: text/markdown