digitalhub 0.13.0b3__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 (139) hide show
  1. digitalhub/__init__.py +3 -8
  2. digitalhub/context/api.py +43 -6
  3. digitalhub/context/builder.py +1 -5
  4. digitalhub/context/context.py +28 -13
  5. digitalhub/entities/_base/_base/entity.py +0 -15
  6. digitalhub/entities/_base/context/entity.py +1 -4
  7. digitalhub/entities/_base/entity/builder.py +5 -5
  8. digitalhub/entities/_base/entity/entity.py +0 -8
  9. digitalhub/entities/_base/executable/entity.py +195 -87
  10. digitalhub/entities/_base/material/entity.py +11 -23
  11. digitalhub/entities/_base/material/utils.py +28 -4
  12. digitalhub/entities/_base/runtime_entity/builder.py +53 -18
  13. digitalhub/entities/_base/unversioned/entity.py +1 -1
  14. digitalhub/entities/_base/versioned/entity.py +1 -1
  15. digitalhub/entities/_commons/enums.py +1 -31
  16. digitalhub/entities/_commons/metrics.py +64 -30
  17. digitalhub/entities/_commons/utils.py +119 -30
  18. digitalhub/entities/_constructors/_resources.py +151 -0
  19. digitalhub/entities/{_base/entity/_constructors → _constructors}/name.py +18 -0
  20. digitalhub/entities/_processors/base/crud.py +381 -0
  21. digitalhub/entities/_processors/base/import_export.py +118 -0
  22. digitalhub/entities/_processors/base/processor.py +299 -0
  23. digitalhub/entities/_processors/base/special_ops.py +104 -0
  24. digitalhub/entities/_processors/context/crud.py +652 -0
  25. digitalhub/entities/_processors/context/import_export.py +242 -0
  26. digitalhub/entities/_processors/context/material.py +123 -0
  27. digitalhub/entities/_processors/context/processor.py +400 -0
  28. digitalhub/entities/_processors/context/special_ops.py +476 -0
  29. digitalhub/entities/_processors/processors.py +12 -0
  30. digitalhub/entities/_processors/utils.py +38 -102
  31. digitalhub/entities/artifact/crud.py +58 -22
  32. digitalhub/entities/artifact/utils.py +28 -13
  33. digitalhub/entities/builders.py +2 -0
  34. digitalhub/entities/dataitem/crud.py +63 -20
  35. digitalhub/entities/dataitem/table/entity.py +27 -22
  36. digitalhub/entities/dataitem/utils.py +82 -32
  37. digitalhub/entities/function/_base/entity.py +3 -6
  38. digitalhub/entities/function/crud.py +55 -24
  39. digitalhub/entities/model/_base/entity.py +62 -20
  40. digitalhub/entities/model/crud.py +59 -23
  41. digitalhub/entities/model/mlflow/utils.py +29 -20
  42. digitalhub/entities/model/utils.py +28 -13
  43. digitalhub/entities/project/_base/builder.py +0 -6
  44. digitalhub/entities/project/_base/entity.py +337 -164
  45. digitalhub/entities/project/_base/spec.py +4 -4
  46. digitalhub/entities/project/crud.py +28 -71
  47. digitalhub/entities/project/utils.py +7 -3
  48. digitalhub/entities/run/_base/builder.py +0 -4
  49. digitalhub/entities/run/_base/entity.py +70 -63
  50. digitalhub/entities/run/crud.py +79 -26
  51. digitalhub/entities/secret/_base/entity.py +1 -5
  52. digitalhub/entities/secret/crud.py +31 -28
  53. digitalhub/entities/task/_base/builder.py +0 -4
  54. digitalhub/entities/task/_base/entity.py +5 -5
  55. digitalhub/entities/task/_base/models.py +13 -16
  56. digitalhub/entities/task/crud.py +61 -29
  57. digitalhub/entities/trigger/_base/entity.py +1 -5
  58. digitalhub/entities/trigger/crud.py +89 -30
  59. digitalhub/entities/workflow/_base/entity.py +3 -8
  60. digitalhub/entities/workflow/crud.py +55 -24
  61. digitalhub/factory/entity.py +283 -0
  62. digitalhub/factory/enums.py +18 -0
  63. digitalhub/factory/registry.py +197 -0
  64. digitalhub/factory/runtime.py +44 -0
  65. digitalhub/factory/utils.py +3 -54
  66. digitalhub/runtimes/_base.py +2 -2
  67. digitalhub/stores/client/{dhcore/api_builder.py → api_builder.py} +3 -3
  68. digitalhub/stores/client/builder.py +19 -31
  69. digitalhub/stores/client/client.py +322 -0
  70. digitalhub/stores/client/configurator.py +408 -0
  71. digitalhub/stores/client/enums.py +50 -0
  72. digitalhub/stores/client/{dhcore/error_parser.py → error_parser.py} +0 -4
  73. digitalhub/stores/client/header_manager.py +61 -0
  74. digitalhub/stores/client/http_handler.py +152 -0
  75. digitalhub/stores/client/{_base/key_builder.py → key_builder.py} +14 -14
  76. digitalhub/stores/client/params_builder.py +330 -0
  77. digitalhub/stores/client/response_processor.py +102 -0
  78. digitalhub/stores/client/utils.py +35 -0
  79. digitalhub/stores/{credentials → configurator}/api.py +5 -9
  80. digitalhub/stores/configurator/configurator.py +123 -0
  81. digitalhub/stores/{credentials → configurator}/enums.py +27 -10
  82. digitalhub/stores/configurator/handler.py +213 -0
  83. digitalhub/stores/{credentials → configurator}/ini_module.py +31 -22
  84. digitalhub/stores/data/_base/store.py +0 -20
  85. digitalhub/stores/data/api.py +5 -7
  86. digitalhub/stores/data/builder.py +53 -27
  87. digitalhub/stores/data/local/store.py +0 -103
  88. digitalhub/stores/data/remote/store.py +0 -4
  89. digitalhub/stores/data/s3/configurator.py +39 -77
  90. digitalhub/stores/data/s3/store.py +57 -37
  91. digitalhub/stores/data/sql/configurator.py +66 -46
  92. digitalhub/stores/data/sql/store.py +171 -104
  93. digitalhub/stores/readers/data/factory.py +0 -8
  94. digitalhub/stores/readers/data/pandas/reader.py +9 -19
  95. digitalhub/utils/file_utils.py +0 -17
  96. digitalhub/utils/generic_utils.py +1 -14
  97. digitalhub/utils/git_utils.py +0 -8
  98. digitalhub/utils/io_utils.py +0 -12
  99. digitalhub/utils/store_utils.py +44 -0
  100. {digitalhub-0.13.0b3.dist-info → digitalhub-0.14.9.dist-info}/METADATA +5 -4
  101. {digitalhub-0.13.0b3.dist-info → digitalhub-0.14.9.dist-info}/RECORD +112 -113
  102. {digitalhub-0.13.0b3.dist-info → digitalhub-0.14.9.dist-info}/WHEEL +1 -1
  103. digitalhub/entities/_commons/types.py +0 -9
  104. digitalhub/entities/_processors/base.py +0 -531
  105. digitalhub/entities/_processors/context.py +0 -1299
  106. digitalhub/entities/task/_base/utils.py +0 -22
  107. digitalhub/factory/factory.py +0 -381
  108. digitalhub/stores/client/_base/api_builder.py +0 -34
  109. digitalhub/stores/client/_base/client.py +0 -243
  110. digitalhub/stores/client/_base/params_builder.py +0 -34
  111. digitalhub/stores/client/api.py +0 -36
  112. digitalhub/stores/client/dhcore/client.py +0 -613
  113. digitalhub/stores/client/dhcore/configurator.py +0 -675
  114. digitalhub/stores/client/dhcore/enums.py +0 -34
  115. digitalhub/stores/client/dhcore/key_builder.py +0 -62
  116. digitalhub/stores/client/dhcore/models.py +0 -40
  117. digitalhub/stores/client/dhcore/params_builder.py +0 -278
  118. digitalhub/stores/client/dhcore/utils.py +0 -94
  119. digitalhub/stores/client/local/api_builder.py +0 -116
  120. digitalhub/stores/client/local/client.py +0 -573
  121. digitalhub/stores/client/local/enums.py +0 -15
  122. digitalhub/stores/client/local/key_builder.py +0 -62
  123. digitalhub/stores/client/local/params_builder.py +0 -120
  124. digitalhub/stores/credentials/__init__.py +0 -3
  125. digitalhub/stores/credentials/configurator.py +0 -210
  126. digitalhub/stores/credentials/handler.py +0 -176
  127. digitalhub/stores/credentials/store.py +0 -81
  128. digitalhub/stores/data/enums.py +0 -15
  129. digitalhub/stores/data/s3/utils.py +0 -78
  130. /digitalhub/entities/{_base/entity/_constructors → _constructors}/__init__.py +0 -0
  131. /digitalhub/entities/{_base/entity/_constructors → _constructors}/metadata.py +0 -0
  132. /digitalhub/entities/{_base/entity/_constructors → _constructors}/spec.py +0 -0
  133. /digitalhub/entities/{_base/entity/_constructors → _constructors}/status.py +0 -0
  134. /digitalhub/entities/{_base/entity/_constructors → _constructors}/uuid.py +0 -0
  135. /digitalhub/{stores/client/_base → entities/_processors/base}/__init__.py +0 -0
  136. /digitalhub/{stores/client/dhcore → entities/_processors/context}/__init__.py +0 -0
  137. /digitalhub/stores/{client/local → configurator}/__init__.py +0 -0
  138. {digitalhub-0.13.0b3.dist-info → digitalhub-0.14.9.dist-info}/licenses/AUTHORS +0 -0
  139. {digitalhub-0.13.0b3.dist-info → digitalhub-0.14.9.dist-info}/licenses/LICENSE +0 -0
@@ -32,25 +32,20 @@ class SetCreds(Enum):
32
32
  DH_PROFILE = "DH_NAME"
33
33
 
34
34
 
35
- class CredsEnvVar(Enum):
35
+ class ConfigurationVars(Enum):
36
36
  """
37
- Supported credential environment variables.
37
+ List of supported configuration variables.
38
38
  """
39
+
39
40
  # S3
40
41
  S3_ENDPOINT_URL = "AWS_ENDPOINT_URL"
41
- S3_ACCESS_KEY_ID = "AWS_ACCESS_KEY_ID"
42
- S3_SECRET_ACCESS_KEY = "AWS_SECRET_ACCESS_KEY"
43
- S3_SESSION_TOKEN = "AWS_SESSION_TOKEN"
44
42
  S3_REGION = "AWS_REGION"
45
43
  S3_SIGNATURE_VERSION = "S3_SIGNATURE_VERSION"
46
- S3_CREDENTIALS_EXPIRATION = "AWS_CREDENTIALS_EXPIRATION"
47
44
  S3_PATH_STYLE = "S3_PATH_STYLE"
48
45
 
49
46
  # SQL
50
47
  DB_HOST = "DB_HOST"
51
48
  DB_PORT = "DB_PORT"
52
- DB_USERNAME = "DB_USERNAME"
53
- DB_PASSWORD = "DB_PASSWORD"
54
49
  DB_DATABASE = "DB_DATABASE"
55
50
  DB_PLATFORM = "DB_PLATFORM"
56
51
  DB_PG_SCHEMA = "DB_SCHEMA"
@@ -58,10 +53,32 @@ class CredsEnvVar(Enum):
58
53
  # DHCORE
59
54
  DHCORE_ENDPOINT = "DHCORE_ENDPOINT"
60
55
  DHCORE_ISSUER = "DHCORE_ISSUER"
56
+ DHCORE_WORKFLOW_IMAGE = "DHCORE_WORKFLOW_IMAGE"
57
+ DHCORE_CLIENT_ID = "DHCORE_CLIENT_ID"
58
+ DEFAULT_FILES_STORE = "DHCORE_DEFAULT_FILES_STORE"
59
+
60
+ # OAUTH2
61
+ OAUTH2_TOKEN_ENDPOINT = "OAUTH2_TOKEN_ENDPOINT"
62
+
63
+
64
+ class CredentialsVars(Enum):
65
+ """
66
+ List of supported credential variables.
67
+ """
68
+
69
+ # S3
70
+ S3_ACCESS_KEY_ID = "AWS_ACCESS_KEY_ID"
71
+ S3_SECRET_ACCESS_KEY = "AWS_SECRET_ACCESS_KEY"
72
+ S3_SESSION_TOKEN = "AWS_SESSION_TOKEN"
73
+ S3_CREDENTIALS_EXPIRATION = "AWS_CREDENTIALS_EXPIRATION"
74
+
75
+ # SQL
76
+ DB_USERNAME = "DB_USERNAME"
77
+ DB_PASSWORD = "DB_PASSWORD"
78
+
79
+ # DHCORE
61
80
  DHCORE_USER = "DHCORE_USER"
62
81
  DHCORE_PASSWORD = "DHCORE_PASSWORD"
63
- DHCORE_CLIENT_ID = "DHCORE_CLIENT_ID"
64
82
  DHCORE_ACCESS_TOKEN = "DHCORE_ACCESS_TOKEN"
65
83
  DHCORE_REFRESH_TOKEN = "DHCORE_REFRESH_TOKEN"
66
84
  DHCORE_PERSONAL_ACCESS_TOKEN = "DHCORE_PERSONAL_ACCESS_TOKEN"
67
- DHCORE_WORKFLOW_IMAGE = "DHCORE_WORKFLOW_IMAGE"
@@ -0,0 +1,213 @@
1
+ # SPDX-FileCopyrightText: © 2025 DSLab - Fondazione Bruno Kessler
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ from __future__ import annotations
6
+
7
+ import os
8
+ from typing import Any
9
+
10
+ from digitalhub.stores.configurator.enums import ConfigurationVars, CredentialsVars, SetCreds
11
+ from digitalhub.stores.configurator.ini_module import (
12
+ load_file,
13
+ load_key,
14
+ load_profile,
15
+ set_current_profile,
16
+ write_file,
17
+ )
18
+ from digitalhub.utils.generic_utils import list_enum
19
+
20
+
21
+ class ConfigurationHandler:
22
+ """
23
+ Handler for loading and writing configuration variables.
24
+ """
25
+
26
+ def __init__(self):
27
+ self._current_profile = self._read_current_profile()
28
+ self._configuration: dict[str, Any] = self.load_configuration()
29
+ self._credentials: dict[str, Any] = self.load_credentials()
30
+
31
+ @staticmethod
32
+ def _read_env(variables: list) -> dict:
33
+ """
34
+ Read configuration variables from the .dhcore file.
35
+
36
+ Parameters
37
+ ----------
38
+ variables : list
39
+ List of environment variable names to read.
40
+
41
+ Returns
42
+ -------
43
+ dict
44
+ Dictionary of environment variables.
45
+ """
46
+ return {var: os.getenv(var) for var in variables}
47
+
48
+ @staticmethod
49
+ def _read_file(variables: list, profile: str) -> dict:
50
+ """
51
+ Read configuration variables from the .dhcore file.
52
+
53
+ Parameters
54
+ ----------
55
+ variables : list
56
+ List of environment variable names to read.
57
+ profile : str
58
+ Profile name to read from.
59
+
60
+ Returns
61
+ -------
62
+ dict
63
+ Dictionary of configuration variables.
64
+ """
65
+ file = load_file()
66
+ return {var: load_key(file, profile, var) for var in variables}
67
+
68
+ ##############################
69
+ # Configuration methods
70
+ ##############################
71
+
72
+ def load_configuration(self) -> dict[str, Any]:
73
+ """
74
+ Load configuration with env > file precedence.
75
+
76
+ Returns
77
+ -------
78
+ dict
79
+ Merged configuration dictionary.
80
+ """
81
+ profile = self.get_current_profile()
82
+ variables = list_enum(ConfigurationVars)
83
+ env_config = self._read_env(variables)
84
+ file_config = self._read_file(variables, profile)
85
+ return {**file_config, **{k: v for k, v in env_config.items() if v is not None}}
86
+
87
+ def reload_configuration(self) -> None:
88
+ """
89
+ Reload configuration from environment and file.
90
+ """
91
+ self._configuration = self.load_configuration()
92
+
93
+ def get_configuration(self) -> dict[str, Any]:
94
+ """
95
+ Get the merged configuration dictionary.
96
+
97
+ Returns
98
+ -------
99
+ dict[str, Any]
100
+ The configuration dictionary.
101
+ """
102
+ return self._configuration
103
+
104
+ ##############################
105
+ # Credentials methods
106
+ ##############################
107
+
108
+ def load_credentials(self) -> dict[str, Any]:
109
+ """
110
+ Load credentials with file > env precedence.
111
+
112
+ Parameters
113
+ ----------
114
+ profile : str
115
+ Profile name to load credentials from.
116
+
117
+ Returns
118
+ -------
119
+ dict
120
+ Merged credentials dictionary.
121
+ """
122
+ variables = list_enum(CredentialsVars)
123
+ env_config = self._read_env(variables)
124
+ file_config = self._read_file(variables, self.get_current_profile())
125
+ return {**env_config, **{k: v for k, v in file_config.items() if v is not None}}
126
+
127
+ def reload_credentials(self) -> None:
128
+ """
129
+ Reload credentials from environment and file.
130
+ """
131
+ self._credentials = self.load_credentials()
132
+
133
+ def reload_credentials_from_env(self) -> None:
134
+ """
135
+ Reload credentials from environment where env > file precedence.
136
+ Its a partial reload only from env variables used as fallback.
137
+ """
138
+ variables = list_enum(CredentialsVars)
139
+ env_config = self._read_env(variables)
140
+ file_config = self._read_file(variables, self.get_current_profile())
141
+ self._credentials = {**file_config, **{k: v for k, v in env_config.items() if v is not None}}
142
+
143
+ def get_credentials(self) -> dict[str, Any]:
144
+ """
145
+ Get the merged credentials dictionary.
146
+
147
+ Returns
148
+ -------
149
+ dict[str, Any]
150
+ The credentials dictionary.
151
+ """
152
+ return self._credentials
153
+
154
+ ##############################
155
+ # Profile Methods
156
+ ##############################
157
+
158
+ @staticmethod
159
+ def _read_current_profile() -> str:
160
+ """
161
+ Read the current credentials profile name.
162
+
163
+ Returns
164
+ -------
165
+ str
166
+ Name of the credentials profile.
167
+ """
168
+ profile = os.getenv(SetCreds.DH_PROFILE.value)
169
+ if profile is not None:
170
+ return profile
171
+ file = load_file()
172
+ profile = load_profile(file)
173
+ if profile is not None:
174
+ return profile
175
+ return SetCreds.DEFAULT.value
176
+
177
+ def set_current_profile(self, profile: str) -> None:
178
+ """
179
+ Set the current credentials profile name.
180
+
181
+ Parameters
182
+ ----------
183
+ profile : str
184
+ Name of the credentials profile to set.
185
+ """
186
+ self._current_profile = profile
187
+ set_current_profile(profile)
188
+ self.reload_configuration()
189
+ self.reload_credentials()
190
+
191
+ def get_current_profile(self) -> str:
192
+ """
193
+ Get the current credentials profile name.
194
+
195
+ Returns
196
+ -------
197
+ str
198
+ Name of the current credentials profile.
199
+ """
200
+ return self._current_profile
201
+
202
+ def write_file(self, variables: dict) -> None:
203
+ """
204
+ Write variables to the .dhcore file for the current profile.
205
+
206
+ Parameters
207
+ ----------
208
+ infos : dict
209
+ Information to write.
210
+ profile : str
211
+ Profile name to write to.
212
+ """
213
+ write_file(variables, self._current_profile)
@@ -92,9 +92,6 @@ def write_config(creds: dict, environment: str) -> None:
92
92
  environment : str
93
93
  Name of the credentials profile/environment.
94
94
 
95
- Returns
96
- -------
97
- None
98
95
 
99
96
  Raises
100
97
  ------
@@ -120,6 +117,37 @@ def write_config(creds: dict, environment: str) -> None:
120
117
  raise ClientError(f"Failed to write env file: {e}")
121
118
 
122
119
 
120
+ def write_file(variables: dict, profile: str) -> None:
121
+ """
122
+ Write variables to the .dhcore.ini file for the specified profile.
123
+ Overwrites any existing values for that profile.
124
+
125
+ Parameters
126
+ ----------
127
+ variables : dict
128
+ Dictionary of variables to write.
129
+ profile : str
130
+ Name of the credentials profile to write to.
131
+ """
132
+ try:
133
+ cfg = load_file()
134
+
135
+ sections = cfg.sections()
136
+ if profile not in sections:
137
+ cfg.add_section(profile)
138
+
139
+ cfg["DEFAULT"]["current_environment"] = profile
140
+ for k, v in variables.items():
141
+ cfg[profile][k] = str(v)
142
+
143
+ ENV_FILE.touch(exist_ok=True)
144
+ with open(ENV_FILE, "w") as inifile:
145
+ cfg.write(inifile)
146
+
147
+ except Exception as e:
148
+ raise ClientError(f"Failed to write env file: {e}")
149
+
150
+
123
151
  def set_current_profile(environment: str) -> None:
124
152
  """
125
153
  Set the current credentials profile in the .dhcore.ini file.
@@ -129,9 +157,6 @@ def set_current_profile(environment: str) -> None:
129
157
  environment : str
130
158
  Name of the credentials profile to set as current.
131
159
 
132
- Returns
133
- -------
134
- None
135
160
 
136
161
  Raises
137
162
  ------
@@ -146,19 +171,3 @@ def set_current_profile(environment: str) -> None:
146
171
 
147
172
  except Exception as e:
148
173
  raise ClientError(f"Failed to write env file: {e}")
149
-
150
-
151
- def read_env_from_file() -> str | None:
152
- """
153
- Read the current credentials profile name from the .dhcore.ini file.
154
-
155
- Returns
156
- -------
157
- str or None
158
- Name of the current credentials profile, or None if not found.
159
- """
160
- try:
161
- cfg = load_file()
162
- return cfg["DEFAULT"]["current_environment"]
163
- except Exception:
164
- return None
@@ -16,7 +16,6 @@ from digitalhub.utils.types import SourcesOrListOfSources
16
16
  from digitalhub.utils.uri_utils import has_local_scheme
17
17
 
18
18
  if typing.TYPE_CHECKING:
19
- from digitalhub.stores.credentials.configurator import Configurator
20
19
  from digitalhub.stores.readers.data._base.reader import DataframeReader
21
20
 
22
21
 
@@ -25,9 +24,6 @@ class Store:
25
24
  Store abstract class.
26
25
  """
27
26
 
28
- def __init__(self, configurator: Configurator | None = None) -> None:
29
- self._configurator = configurator
30
-
31
27
  ##############################
32
28
  # I/O methods
33
29
  ##############################
@@ -114,10 +110,6 @@ class Store:
114
110
  src : str
115
111
  The source path.
116
112
 
117
- Returns
118
- -------
119
- None
120
-
121
113
  Raises
122
114
  ------
123
115
  StoreError
@@ -135,10 +127,6 @@ class Store:
135
127
  dst : str
136
128
  The destination path.
137
129
 
138
- Returns
139
- -------
140
- None
141
-
142
130
  Raises
143
131
  ------
144
132
  StoreError
@@ -158,10 +146,6 @@ class Store:
158
146
  overwrite : bool
159
147
  Specify if overwrite an existing file.
160
148
 
161
- Returns
162
- -------
163
- None
164
-
165
149
  Raises
166
150
  ------
167
151
  StoreError
@@ -179,10 +163,6 @@ class Store:
179
163
  ----------
180
164
  path : str | Path
181
165
  The path to build.
182
-
183
- Returns
184
- -------
185
- None
186
166
  """
187
167
  if not isinstance(path, Path):
188
168
  path = Path(path)
@@ -7,9 +7,9 @@ from __future__ import annotations
7
7
  import typing
8
8
 
9
9
  from digitalhub.context.api import get_context
10
- from digitalhub.stores.credentials.handler import creds_handler
10
+ from digitalhub.stores.configurator.configurator import configurator
11
+ from digitalhub.stores.configurator.enums import ConfigurationVars
11
12
  from digitalhub.stores.data.builder import store_builder
12
- from digitalhub.stores.data.enums import StoreEnv
13
13
 
14
14
  if typing.TYPE_CHECKING:
15
15
  from digitalhub.stores.data._base.store import Store
@@ -34,16 +34,14 @@ def get_default_store(project: str) -> str:
34
34
  ValueError
35
35
  If no default store is found.
36
36
  """
37
- var = StoreEnv.DEFAULT_FILES_STORE.value
37
+ var = ConfigurationVars.DEFAULT_FILES_STORE.value
38
38
 
39
39
  context = get_context(project)
40
- store = context.config.get(var.lower())
40
+ store = context.config.get(var.lower().replace("dhcore_", ""))
41
41
  if store is not None:
42
42
  return store
43
43
 
44
- store = creds_handler.load_from_env([var]).get(var)
45
- if store is None:
46
- store = creds_handler.load_from_file([var]).get(var)
44
+ store = configurator.get_configuration().get(var)
47
45
 
48
46
  if store is None or store == "":
49
47
  raise ValueError(
@@ -8,77 +8,103 @@ import typing
8
8
 
9
9
  from digitalhub.stores.data.local.store import LocalStore
10
10
  from digitalhub.stores.data.remote.store import RemoteStore
11
- from digitalhub.stores.data.s3.configurator import S3StoreConfigurator
12
11
  from digitalhub.stores.data.s3.store import S3Store
13
- from digitalhub.stores.data.sql.configurator import SqlStoreConfigurator
14
12
  from digitalhub.stores.data.sql.store import SqlStore
15
13
  from digitalhub.utils.uri_utils import SchemeCategory, map_uri_scheme
16
14
 
17
15
  if typing.TYPE_CHECKING:
18
- from digitalhub.stores.credentials.configurator import Configurator
19
16
  from digitalhub.stores.data._base.store import Store
20
17
  from digitalhub.utils.exceptions import StoreError
21
18
 
22
19
 
23
- class StoreInfo:
24
- def __init__(self, store: Store, configurator: Configurator | None = None) -> None:
25
- self._store = store
26
- self._configurator = configurator
27
-
28
-
29
20
  class StoreBuilder:
30
21
  """
31
- Store builder class.
22
+ Store factory and registry for managing data store instances.
23
+
24
+ Provides registration, instantiation, and caching of data store
25
+ instances based on URI schemes. Supports various store types
26
+ including S3, SQL, local, and remote stores with their respective
27
+ configurators.
28
+
29
+ Attributes
30
+ ----------
31
+ _builders : dict[str, StoreInfo]
32
+ Registry of store types mapped to their StoreInfo instances.
33
+ _instances : dict[str, Store]
34
+ Cache of instantiated store instances by store type.
32
35
  """
33
36
 
34
37
  def __init__(self) -> None:
35
- self._builders: dict[str, StoreInfo] = {}
38
+ self._builders: dict[str, Store] = {}
36
39
  self._instances: dict[str, dict[str, Store]] = {}
37
40
 
38
41
  def register(
39
42
  self,
40
43
  store_type: str,
41
44
  store: Store,
42
- configurator: Configurator | None = None,
43
45
  ) -> None:
46
+ """
47
+ Register a store type with its class and optional configurator.
48
+
49
+ Adds a new store type to the builder registry, associating it
50
+ with a store class and optional configurator for later instantiation.
51
+
52
+ Parameters
53
+ ----------
54
+ store_type : str
55
+ The unique identifier for the store type (e.g., 's3', 'sql').
56
+ store : Store
57
+ The store class to register for this type.
58
+ configurator : Configurator
59
+ The configurator class for store configuration.
60
+ If None, the store will be instantiated without configuration.
61
+
62
+ Raises
63
+ ------
64
+ StoreError
65
+ If the store type is already registered in the builder.
66
+ """
44
67
  if store_type not in self._builders:
45
- self._builders[store_type] = StoreInfo(store, configurator)
68
+ self._builders[store_type] = store
46
69
  else:
47
70
  raise StoreError(f"Store type {store_type} already registered")
48
71
 
49
72
  def get(self, uri: str) -> Store:
50
73
  """
51
- Get a store instance by URI, building it if necessary.
74
+ Get or create a store instance based on URI scheme.
75
+
76
+ Determines the appropriate store type from the URI scheme,
77
+ instantiates the store if not already cached, and returns
78
+ the store instance. Store instances are cached for reuse.
52
79
 
53
80
  Parameters
54
81
  ----------
55
82
  uri : str
56
- URI to parse.
83
+ The URI to parse for determining the store type.
84
+ The scheme (e.g., 's3://', 'sql://') determines which
85
+ store type to instantiate.
57
86
 
58
87
  Returns
59
88
  -------
60
89
  Store
61
- The store instance.
90
+ The store instance appropriate for handling the given URI.
91
+
92
+ Raises
93
+ ------
94
+ KeyError
95
+ If no store is registered for the URI scheme.
62
96
  """
63
97
  store_type = map_uri_scheme(uri)
64
98
 
65
99
  # Build the store instance if not already present
66
100
  if store_type not in self._instances:
67
- store_info = self._builders[store_type]
68
- store_cls = store_info._store
69
- cfgrt_cls = store_info._configurator
70
-
71
- if cfgrt_cls is None:
72
- store = store_cls()
73
- else:
74
- store = store_cls(cfgrt_cls())
75
- self._instances[store_type] = store
101
+ self._instances[store_type] = self._builders[store_type]()
76
102
 
77
103
  return self._instances[store_type]
78
104
 
79
105
 
80
106
  store_builder = StoreBuilder()
81
- store_builder.register(SchemeCategory.S3.value, S3Store, S3StoreConfigurator)
82
- store_builder.register(SchemeCategory.SQL.value, SqlStore, SqlStoreConfigurator)
107
+ store_builder.register(SchemeCategory.S3.value, S3Store)
108
+ store_builder.register(SchemeCategory.SQL.value, SqlStore)
83
109
  store_builder.register(SchemeCategory.LOCAL.value, LocalStore)
84
110
  store_builder.register(SchemeCategory.REMOTE.value, RemoteStore)
@@ -4,7 +4,6 @@
4
4
 
5
5
  from __future__ import annotations
6
6
 
7
- import shutil
8
7
  from pathlib import Path
9
8
  from typing import Any
10
9
 
@@ -180,105 +179,3 @@ class LocalStore(Store):
180
179
  reader = get_reader_by_object(df)
181
180
  reader.write_df(df, dst, extension=extension, **kwargs)
182
181
  return dst
183
-
184
- ##############################
185
- # Private I/O methods
186
- ##############################
187
-
188
- def _get_src_dst_files(self, src: Path, dst: Path) -> list[str]:
189
- """
190
- Copy files from source to destination.
191
-
192
- Parameters
193
- ----------
194
- src : Path
195
- The source path.
196
- dst : Path
197
- The destination path.
198
-
199
- Returns
200
- -------
201
- list[str]
202
- Returns the list of destination and source paths of the
203
- copied files.
204
- """
205
- return [self._get_src_dst_file(i, dst) for i in src.rglob("*") if i.is_file()]
206
-
207
- def _get_src_dst_file(self, src: Path, dst: Path) -> str:
208
- """
209
- Copy file from source to destination.
210
-
211
- Parameters
212
- ----------
213
- src : Path
214
- The source path.
215
- dst : Path
216
- The destination path.
217
-
218
- Returns
219
- -------
220
- str
221
- """
222
- dst_pth = self._copy_file(src, dst, True)
223
- return str(dst_pth), str(src)
224
-
225
- def _copy_dir(self, src: Path, dst: Path, overwrite: bool) -> list[str]:
226
- """
227
- Download file from source to destination.
228
-
229
- Parameters
230
- ----------
231
- src : Path
232
- The source path.
233
- dst : Path
234
- The destination path.
235
-
236
- Returns
237
- -------
238
- list[str]
239
- """
240
- dst = self._rebuild_path(dst, src)
241
- shutil.copytree(src, dst, dirs_exist_ok=overwrite)
242
- return [str(i) for i in dst.rglob("*") if i.is_file()]
243
-
244
- def _copy_file(self, src: Path, dst: Path, overwrite: bool) -> str:
245
- """
246
- Copy file from source to destination.
247
-
248
- Parameters
249
- ----------
250
- src : Path
251
- The source path.
252
- dst : Path
253
- The destination path.
254
-
255
- Returns
256
- -------
257
- str
258
- """
259
- dst = self._rebuild_path(dst, src)
260
- self._check_overwrite(dst, overwrite)
261
- return str(shutil.copy2(src, dst))
262
-
263
- def _rebuild_path(self, dst: Path, src: Path) -> Path:
264
- """
265
- Rebuild path.
266
-
267
- Parameters
268
- ----------
269
- dst : Path
270
- The destination path.
271
- src : Path
272
- The source path.
273
-
274
- Returns
275
- -------
276
- Path
277
- The rebuilt path.
278
- """
279
- if dst.is_dir():
280
- if src.is_absolute():
281
- raise StoreError("Source must be a relative path if the destination is a directory.")
282
- dst = dst / src
283
- self._build_path(dst)
284
- return dst
@@ -174,10 +174,6 @@ class RemoteStore(Store):
174
174
  src : str
175
175
  The source location.
176
176
 
177
- Returns
178
- -------
179
- None
180
-
181
177
  Raises
182
178
  ------
183
179
  HTTPError