digitalhub 0.7.0b2__py3-none-any.whl → 0.8.0__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 digitalhub might be problematic. Click here for more details.

Files changed (232) hide show
  1. digitalhub/__init__.py +63 -93
  2. digitalhub/client/__init__.py +0 -0
  3. digitalhub/client/_base/__init__.py +0 -0
  4. digitalhub/client/_base/client.py +56 -0
  5. digitalhub/client/api.py +63 -0
  6. digitalhub/client/builder.py +50 -0
  7. digitalhub/client/dhcore/__init__.py +0 -0
  8. digitalhub/client/dhcore/client.py +669 -0
  9. digitalhub/client/dhcore/env.py +21 -0
  10. digitalhub/client/dhcore/models.py +46 -0
  11. digitalhub/client/dhcore/utils.py +111 -0
  12. digitalhub/client/local/__init__.py +0 -0
  13. digitalhub/client/local/client.py +533 -0
  14. digitalhub/context/__init__.py +0 -0
  15. digitalhub/context/api.py +93 -0
  16. digitalhub/context/builder.py +94 -0
  17. digitalhub/context/context.py +136 -0
  18. digitalhub/datastores/__init__.py +0 -0
  19. digitalhub/datastores/_base/__init__.py +0 -0
  20. digitalhub/datastores/_base/datastore.py +85 -0
  21. digitalhub/datastores/api.py +37 -0
  22. digitalhub/datastores/builder.py +110 -0
  23. digitalhub/datastores/local/__init__.py +0 -0
  24. digitalhub/datastores/local/datastore.py +50 -0
  25. digitalhub/datastores/remote/__init__.py +0 -0
  26. digitalhub/datastores/remote/datastore.py +31 -0
  27. digitalhub/datastores/s3/__init__.py +0 -0
  28. digitalhub/datastores/s3/datastore.py +46 -0
  29. digitalhub/datastores/sql/__init__.py +0 -0
  30. digitalhub/datastores/sql/datastore.py +68 -0
  31. digitalhub/entities/__init__.py +0 -0
  32. digitalhub/entities/_base/__init__.py +0 -0
  33. digitalhub/entities/_base/_base/__init__.py +0 -0
  34. digitalhub/entities/_base/_base/entity.py +82 -0
  35. digitalhub/entities/_base/api_utils.py +620 -0
  36. digitalhub/entities/_base/context/__init__.py +0 -0
  37. digitalhub/entities/_base/context/entity.py +118 -0
  38. digitalhub/entities/_base/crud.py +468 -0
  39. digitalhub/entities/_base/entity/__init__.py +0 -0
  40. digitalhub/entities/_base/entity/_constructors/__init__.py +0 -0
  41. digitalhub/entities/_base/entity/_constructors/metadata.py +44 -0
  42. digitalhub/entities/_base/entity/_constructors/name.py +31 -0
  43. digitalhub/entities/_base/entity/_constructors/spec.py +33 -0
  44. digitalhub/entities/_base/entity/_constructors/status.py +52 -0
  45. digitalhub/entities/_base/entity/_constructors/uuid.py +26 -0
  46. digitalhub/entities/_base/entity/builder.py +175 -0
  47. digitalhub/entities/_base/entity/entity.py +106 -0
  48. digitalhub/entities/_base/entity/metadata.py +59 -0
  49. digitalhub/entities/_base/entity/spec.py +58 -0
  50. digitalhub/entities/_base/entity/status.py +43 -0
  51. digitalhub/entities/_base/executable/__init__.py +0 -0
  52. digitalhub/entities/_base/executable/entity.py +405 -0
  53. digitalhub/entities/_base/material/__init__.py +0 -0
  54. digitalhub/entities/_base/material/entity.py +214 -0
  55. digitalhub/entities/_base/material/spec.py +22 -0
  56. digitalhub/entities/_base/material/status.py +49 -0
  57. digitalhub/entities/_base/runtime_entity/__init__.py +0 -0
  58. digitalhub/entities/_base/runtime_entity/builder.py +106 -0
  59. digitalhub/entities/_base/unversioned/__init__.py +0 -0
  60. digitalhub/entities/_base/unversioned/builder.py +66 -0
  61. digitalhub/entities/_base/unversioned/entity.py +49 -0
  62. digitalhub/entities/_base/versioned/__init__.py +0 -0
  63. digitalhub/entities/_base/versioned/builder.py +68 -0
  64. digitalhub/entities/_base/versioned/entity.py +53 -0
  65. digitalhub/entities/artifact/__init__.py +0 -0
  66. digitalhub/entities/artifact/_base/__init__.py +0 -0
  67. digitalhub/entities/artifact/_base/builder.py +86 -0
  68. digitalhub/entities/artifact/_base/entity.py +39 -0
  69. digitalhub/entities/artifact/_base/spec.py +15 -0
  70. digitalhub/entities/artifact/_base/status.py +9 -0
  71. digitalhub/entities/artifact/artifact/__init__.py +0 -0
  72. digitalhub/entities/artifact/artifact/builder.py +18 -0
  73. digitalhub/entities/artifact/artifact/entity.py +32 -0
  74. digitalhub/entities/artifact/artifact/spec.py +27 -0
  75. digitalhub/entities/artifact/artifact/status.py +15 -0
  76. digitalhub/entities/artifact/crud.py +332 -0
  77. digitalhub/entities/builders.py +63 -0
  78. digitalhub/entities/dataitem/__init__.py +0 -0
  79. digitalhub/entities/dataitem/_base/__init__.py +0 -0
  80. digitalhub/entities/dataitem/_base/builder.py +86 -0
  81. digitalhub/entities/dataitem/_base/entity.py +75 -0
  82. digitalhub/entities/dataitem/_base/spec.py +15 -0
  83. digitalhub/entities/dataitem/_base/status.py +20 -0
  84. digitalhub/entities/dataitem/crud.py +372 -0
  85. digitalhub/entities/dataitem/dataitem/__init__.py +0 -0
  86. digitalhub/entities/dataitem/dataitem/builder.py +18 -0
  87. digitalhub/entities/dataitem/dataitem/entity.py +32 -0
  88. digitalhub/entities/dataitem/dataitem/spec.py +15 -0
  89. digitalhub/entities/dataitem/dataitem/status.py +9 -0
  90. digitalhub/entities/dataitem/iceberg/__init__.py +0 -0
  91. digitalhub/entities/dataitem/iceberg/builder.py +18 -0
  92. digitalhub/entities/dataitem/iceberg/entity.py +32 -0
  93. digitalhub/entities/dataitem/iceberg/spec.py +15 -0
  94. digitalhub/entities/dataitem/iceberg/status.py +9 -0
  95. digitalhub/entities/dataitem/table/__init__.py +0 -0
  96. digitalhub/entities/dataitem/table/builder.py +18 -0
  97. digitalhub/entities/dataitem/table/entity.py +146 -0
  98. digitalhub/entities/dataitem/table/models.py +62 -0
  99. digitalhub/entities/dataitem/table/spec.py +25 -0
  100. digitalhub/entities/dataitem/table/status.py +9 -0
  101. digitalhub/entities/function/__init__.py +0 -0
  102. digitalhub/entities/function/_base/__init__.py +0 -0
  103. digitalhub/entities/function/_base/builder.py +79 -0
  104. digitalhub/entities/function/_base/entity.py +98 -0
  105. digitalhub/entities/function/_base/models.py +118 -0
  106. digitalhub/entities/function/_base/spec.py +15 -0
  107. digitalhub/entities/function/_base/status.py +9 -0
  108. digitalhub/entities/function/crud.py +279 -0
  109. digitalhub/entities/model/__init__.py +0 -0
  110. digitalhub/entities/model/_base/__init__.py +0 -0
  111. digitalhub/entities/model/_base/builder.py +86 -0
  112. digitalhub/entities/model/_base/entity.py +34 -0
  113. digitalhub/entities/model/_base/spec.py +49 -0
  114. digitalhub/entities/model/_base/status.py +9 -0
  115. digitalhub/entities/model/crud.py +331 -0
  116. digitalhub/entities/model/huggingface/__init__.py +0 -0
  117. digitalhub/entities/model/huggingface/builder.py +18 -0
  118. digitalhub/entities/model/huggingface/entity.py +32 -0
  119. digitalhub/entities/model/huggingface/spec.py +36 -0
  120. digitalhub/entities/model/huggingface/status.py +9 -0
  121. digitalhub/entities/model/mlflow/__init__.py +0 -0
  122. digitalhub/entities/model/mlflow/builder.py +18 -0
  123. digitalhub/entities/model/mlflow/entity.py +32 -0
  124. digitalhub/entities/model/mlflow/models.py +26 -0
  125. digitalhub/entities/model/mlflow/spec.py +44 -0
  126. digitalhub/entities/model/mlflow/status.py +9 -0
  127. digitalhub/entities/model/mlflow/utils.py +81 -0
  128. digitalhub/entities/model/model/__init__.py +0 -0
  129. digitalhub/entities/model/model/builder.py +18 -0
  130. digitalhub/entities/model/model/entity.py +32 -0
  131. digitalhub/entities/model/model/spec.py +15 -0
  132. digitalhub/entities/model/model/status.py +9 -0
  133. digitalhub/entities/model/sklearn/__init__.py +0 -0
  134. digitalhub/entities/model/sklearn/builder.py +18 -0
  135. digitalhub/entities/model/sklearn/entity.py +32 -0
  136. digitalhub/entities/model/sklearn/spec.py +15 -0
  137. digitalhub/entities/model/sklearn/status.py +9 -0
  138. digitalhub/entities/project/__init__.py +0 -0
  139. digitalhub/entities/project/_base/__init__.py +0 -0
  140. digitalhub/entities/project/_base/builder.py +128 -0
  141. digitalhub/entities/project/_base/entity.py +2078 -0
  142. digitalhub/entities/project/_base/spec.py +50 -0
  143. digitalhub/entities/project/_base/status.py +9 -0
  144. digitalhub/entities/project/crud.py +357 -0
  145. digitalhub/entities/run/__init__.py +0 -0
  146. digitalhub/entities/run/_base/__init__.py +0 -0
  147. digitalhub/entities/run/_base/builder.py +94 -0
  148. digitalhub/entities/run/_base/entity.py +307 -0
  149. digitalhub/entities/run/_base/spec.py +50 -0
  150. digitalhub/entities/run/_base/status.py +9 -0
  151. digitalhub/entities/run/crud.py +219 -0
  152. digitalhub/entities/secret/__init__.py +0 -0
  153. digitalhub/entities/secret/_base/__init__.py +0 -0
  154. digitalhub/entities/secret/_base/builder.py +81 -0
  155. digitalhub/entities/secret/_base/entity.py +74 -0
  156. digitalhub/entities/secret/_base/spec.py +35 -0
  157. digitalhub/entities/secret/_base/status.py +9 -0
  158. digitalhub/entities/secret/crud.py +290 -0
  159. digitalhub/entities/task/__init__.py +0 -0
  160. digitalhub/entities/task/_base/__init__.py +0 -0
  161. digitalhub/entities/task/_base/builder.py +91 -0
  162. digitalhub/entities/task/_base/entity.py +136 -0
  163. digitalhub/entities/task/_base/models.py +208 -0
  164. digitalhub/entities/task/_base/spec.py +53 -0
  165. digitalhub/entities/task/_base/status.py +9 -0
  166. digitalhub/entities/task/crud.py +228 -0
  167. digitalhub/entities/utils/__init__.py +0 -0
  168. digitalhub/entities/utils/api.py +346 -0
  169. digitalhub/entities/utils/entity_types.py +19 -0
  170. digitalhub/entities/utils/state.py +31 -0
  171. digitalhub/entities/utils/utils.py +202 -0
  172. digitalhub/entities/workflow/__init__.py +0 -0
  173. digitalhub/entities/workflow/_base/__init__.py +0 -0
  174. digitalhub/entities/workflow/_base/builder.py +79 -0
  175. digitalhub/entities/workflow/_base/entity.py +74 -0
  176. digitalhub/entities/workflow/_base/spec.py +15 -0
  177. digitalhub/entities/workflow/_base/status.py +9 -0
  178. digitalhub/entities/workflow/crud.py +278 -0
  179. digitalhub/factory/__init__.py +0 -0
  180. digitalhub/factory/api.py +277 -0
  181. digitalhub/factory/factory.py +268 -0
  182. digitalhub/factory/utils.py +90 -0
  183. digitalhub/readers/__init__.py +0 -0
  184. digitalhub/readers/_base/__init__.py +0 -0
  185. digitalhub/readers/_base/builder.py +26 -0
  186. digitalhub/readers/_base/reader.py +70 -0
  187. digitalhub/readers/api.py +80 -0
  188. digitalhub/readers/factory.py +133 -0
  189. digitalhub/readers/pandas/__init__.py +0 -0
  190. digitalhub/readers/pandas/builder.py +29 -0
  191. digitalhub/readers/pandas/reader.py +207 -0
  192. digitalhub/runtimes/__init__.py +0 -0
  193. digitalhub/runtimes/_base.py +102 -0
  194. digitalhub/runtimes/builder.py +32 -0
  195. digitalhub/stores/__init__.py +0 -0
  196. digitalhub/stores/_base/__init__.py +0 -0
  197. digitalhub/stores/_base/store.py +189 -0
  198. digitalhub/stores/api.py +54 -0
  199. digitalhub/stores/builder.py +211 -0
  200. digitalhub/stores/local/__init__.py +0 -0
  201. digitalhub/stores/local/store.py +230 -0
  202. digitalhub/stores/remote/__init__.py +0 -0
  203. digitalhub/stores/remote/store.py +143 -0
  204. digitalhub/stores/s3/__init__.py +0 -0
  205. digitalhub/stores/s3/store.py +563 -0
  206. digitalhub/stores/sql/__init__.py +0 -0
  207. digitalhub/stores/sql/store.py +328 -0
  208. digitalhub/utils/__init__.py +0 -0
  209. digitalhub/utils/data_utils.py +127 -0
  210. digitalhub/utils/exceptions.py +67 -0
  211. digitalhub/utils/file_utils.py +204 -0
  212. digitalhub/utils/generic_utils.py +183 -0
  213. digitalhub/utils/git_utils.py +148 -0
  214. digitalhub/utils/io_utils.py +116 -0
  215. digitalhub/utils/logger.py +17 -0
  216. digitalhub/utils/s3_utils.py +58 -0
  217. digitalhub/utils/uri_utils.py +56 -0
  218. {digitalhub-0.7.0b2.dist-info → digitalhub-0.8.0.dist-info}/METADATA +30 -13
  219. digitalhub-0.8.0.dist-info/RECORD +231 -0
  220. {digitalhub-0.7.0b2.dist-info → digitalhub-0.8.0.dist-info}/WHEEL +1 -1
  221. test/local/CRUD/test_artifacts.py +96 -0
  222. test/local/CRUD/test_dataitems.py +96 -0
  223. test/local/CRUD/test_models.py +95 -0
  224. test/test_crud_functions.py +1 -1
  225. test/test_crud_runs.py +1 -1
  226. test/test_crud_tasks.py +1 -1
  227. digitalhub-0.7.0b2.dist-info/RECORD +0 -14
  228. test/test_crud_artifacts.py +0 -96
  229. test/test_crud_dataitems.py +0 -96
  230. {digitalhub-0.7.0b2.dist-info → digitalhub-0.8.0.dist-info}/LICENSE.txt +0 -0
  231. {digitalhub-0.7.0b2.dist-info → digitalhub-0.8.0.dist-info}/top_level.txt +0 -0
  232. /test/{test_imports.py → local/imports/test_imports.py} +0 -0
@@ -0,0 +1,93 @@
1
+ from __future__ import annotations
2
+
3
+ import typing
4
+
5
+ from digitalhub.context.builder import context_builder
6
+ from digitalhub.utils.exceptions import ContextError
7
+
8
+ if typing.TYPE_CHECKING:
9
+ from digitalhub.context.context import Context
10
+ from digitalhub.entities.project._base.entity import Project
11
+
12
+
13
+ def check_context(project: str) -> None:
14
+ """
15
+ Check if the given project is in the context.
16
+
17
+ Parameters
18
+ ----------
19
+ project : str
20
+ Project name.
21
+
22
+ Returns
23
+ -------
24
+ bool
25
+ True if the project is in the context, False otherwise.
26
+ """
27
+ if project not in context_builder._instances:
28
+ raise ContextError
29
+
30
+
31
+ def set_context(project: Project) -> None:
32
+ """
33
+ Wrapper for ContextBuilder.build().
34
+
35
+ Parameters
36
+ ----------
37
+ project : Project
38
+ The project object used to set the current context.
39
+
40
+ Returns
41
+ -------
42
+ None
43
+ """
44
+ context_builder.build(project)
45
+
46
+
47
+ def get_context(project: str) -> Context:
48
+ """
49
+ Wrapper for ContextBuilder.get().
50
+
51
+ Parameters
52
+ ----------
53
+ project : str
54
+ Project name.
55
+
56
+ Returns
57
+ -------
58
+ Context
59
+ The context for the given project name.
60
+ """
61
+ return context_builder.get(project)
62
+
63
+
64
+ def set_context_object(context: Context) -> None:
65
+ """
66
+ Wrapper for ContextBuilder.set().
67
+
68
+ Parameters
69
+ ----------
70
+ context : Context
71
+ The context to set.
72
+
73
+ Returns
74
+ -------
75
+ None
76
+ """
77
+ context_builder.set(context)
78
+
79
+
80
+ def delete_context(project: str) -> None:
81
+ """
82
+ Wrapper for ContextBuilder.remove().
83
+
84
+ Parameters
85
+ ----------
86
+ project : str
87
+ Project name.
88
+
89
+ Returns
90
+ -------
91
+ None
92
+ """
93
+ context_builder.remove(project)
@@ -0,0 +1,94 @@
1
+ from __future__ import annotations
2
+
3
+ import typing
4
+
5
+ from digitalhub.context.context import Context
6
+
7
+ if typing.TYPE_CHECKING:
8
+ from digitalhub.entities.project._base.entity import Project
9
+
10
+
11
+ class ContextBuilder:
12
+ """
13
+ ContextBuilder class.
14
+ It implements the builder pattern to create a context instance.
15
+ It allows to use multiple projects as context at the same time
16
+ by adding them to the _instances registry with their name.
17
+ """
18
+
19
+ def __init__(self) -> None:
20
+ self._instances: dict[str, Context] = {}
21
+
22
+ def build(self, project_object: Project) -> None:
23
+ """
24
+ Add a project as context.
25
+
26
+ Parameters
27
+ ----------
28
+ project_object : Project
29
+ The project to add.
30
+
31
+ Returns
32
+ -------
33
+ None
34
+ """
35
+ self._instances[project_object.name] = Context(project_object)
36
+
37
+ def get(self, project: str) -> Context:
38
+ """
39
+ Get a context from project name if it exists.
40
+
41
+ Parameters
42
+ ----------
43
+ project : str
44
+ The project name.
45
+
46
+ Returns
47
+ -------
48
+ Context
49
+ The project context.
50
+
51
+ Raises
52
+ ------
53
+ ValueError
54
+ If the project is not in the context.
55
+ """
56
+ ctx = self._instances.get(project)
57
+ if ctx is None:
58
+ raise ValueError(
59
+ f"Context '{project}' not found. Please get or create a project named '{project}' to access its objects."
60
+ )
61
+ return ctx
62
+
63
+ def remove(self, project: str) -> None:
64
+ """
65
+ Remove a project from the context.
66
+
67
+ Parameters
68
+ ----------
69
+ project : str
70
+ The project name.
71
+
72
+ Returns
73
+ -------
74
+ None
75
+ """
76
+ self._instances.pop(project, None)
77
+
78
+ def set(self, context: Context) -> None:
79
+ """
80
+ Set the context.
81
+
82
+ Parameters
83
+ ----------
84
+ context : Context
85
+ The context to set.
86
+
87
+ Returns
88
+ -------
89
+ None
90
+ """
91
+ self._instances[context.name] = context
92
+
93
+
94
+ context_builder = ContextBuilder()
@@ -0,0 +1,136 @@
1
+ from __future__ import annotations
2
+
3
+ import typing
4
+ from pathlib import Path
5
+
6
+ if typing.TYPE_CHECKING:
7
+ from digitalhub.entities.project._base.entity import Project
8
+
9
+
10
+ class Context:
11
+ """
12
+ Context class built forom a `Project` instance. It contains
13
+ some information about the project, such as the project name,
14
+ a client instance (local or non-local), the local context
15
+ project path and information about client locality.
16
+ It exposes CRUD operations for the entities and act as a layer
17
+ between the project object and its client.
18
+ """
19
+
20
+ def __init__(self, project: Project) -> None:
21
+ self.name = project.name
22
+ self.client = project._client
23
+ self.local = project._client.is_local()
24
+ self.root = Path(project.spec.context)
25
+
26
+ def create_object(self, api: str, obj: dict, **kwargs) -> dict:
27
+ """
28
+ Create an object.
29
+
30
+ Parameters
31
+ ----------
32
+ api : str
33
+ Create API.
34
+ obj : dict
35
+ Object to create.
36
+ **kwargs : dict
37
+ Keyword arguments passed to the request.
38
+
39
+ Returns
40
+ -------
41
+ dict
42
+ Response object.
43
+ """
44
+ return self.client.create_object(api, obj, **kwargs)
45
+
46
+ def read_object(self, api: str, **kwargs) -> dict:
47
+ """
48
+ Read an object.
49
+
50
+ Parameters
51
+ ----------
52
+ api : str
53
+ Read API.
54
+ **kwargs : dict
55
+ Keyword arguments passed to the request.
56
+
57
+ Returns
58
+ -------
59
+ dict
60
+ Response object.
61
+ """
62
+ return self.client.read_object(api, **kwargs)
63
+
64
+ def update_object(self, api: str, obj: dict, **kwargs) -> dict:
65
+ """
66
+ Update an object.
67
+
68
+ Parameters
69
+ ----------
70
+ api : str
71
+ Update API.
72
+ obj : dict
73
+ Object to update.
74
+ **kwargs : dict
75
+ Keyword arguments passed to the request.
76
+
77
+ Returns
78
+ -------
79
+ dict
80
+ Response object.
81
+ """
82
+ return self.client.update_object(api, obj, **kwargs)
83
+
84
+ def delete_object(self, api: str, **kwargs) -> dict:
85
+ """
86
+ Delete an object.
87
+
88
+ Parameters
89
+ ----------
90
+ api : str
91
+ Delete API.
92
+ **kwargs : dict
93
+ Keyword arguments passed to the request.
94
+
95
+ Returns
96
+ -------
97
+ dict
98
+ Response object.
99
+ """
100
+ return self.client.delete_object(api, **kwargs)
101
+
102
+ def list_objects(self, api: str, **kwargs) -> dict:
103
+ """
104
+ List objects.
105
+
106
+ Parameters
107
+ ----------
108
+ api : str
109
+ The api to list the objects with.
110
+ **kwargs : dict
111
+ Keyword arguments passed to the request.
112
+
113
+ Returns
114
+ -------
115
+ dict
116
+ The list of objects.
117
+ """
118
+ return self.client.list_objects(api, **kwargs)
119
+
120
+ def list_first_object(self, api: str, **kwargs) -> dict:
121
+ """
122
+ List first objects.
123
+
124
+ Parameters
125
+ ----------
126
+ api : str
127
+ The api to list the objects with.
128
+ **kwargs : dict
129
+ Keyword arguments passed to the request.
130
+
131
+ Returns
132
+ -------
133
+ dict
134
+ The list of objects.
135
+ """
136
+ return self.client.list_first_object(api, **kwargs)
File without changes
File without changes
@@ -0,0 +1,85 @@
1
+ from __future__ import annotations
2
+
3
+ import typing
4
+ from abc import ABCMeta, abstractmethod
5
+ from typing import Any
6
+
7
+ from digitalhub.readers.api import get_reader_by_engine
8
+
9
+ if typing.TYPE_CHECKING:
10
+ from digitalhub.stores._base.store import Store
11
+
12
+
13
+ class Datastore(metaclass=ABCMeta):
14
+ """
15
+ Datastore abstract class.
16
+ """
17
+
18
+ def __init__(self, store: Store, **kwargs) -> None:
19
+ self.store = store
20
+
21
+ ##############################
22
+ # IO methods
23
+ ##############################
24
+
25
+ @abstractmethod
26
+ def write_df(self, df: Any, dst: str, extension: str | None = None, **kwargs) -> str:
27
+ """
28
+ Write DataFrame as parquet or csv.
29
+ """
30
+
31
+ def read_df(
32
+ self,
33
+ path: str | list[str],
34
+ extension: str,
35
+ engine: str | None = None,
36
+ **kwargs,
37
+ ) -> Any:
38
+ """
39
+ Read DataFrame from path.
40
+
41
+ Parameters
42
+ ----------
43
+ path : str | list[str]
44
+ Path(s) to read DataFrame from.
45
+ extension : str
46
+ Extension of the file.
47
+ engine : str
48
+ Dataframe engine (pandas, polars, etc.).
49
+ **kwargs : dict
50
+ Keyword arguments.
51
+
52
+ Returns
53
+ -------
54
+ Any
55
+ DataFrame.
56
+ """
57
+ reader = get_reader_by_engine(engine)
58
+ self._validate_extension(extension)
59
+ return reader.read_df(path, extension, **kwargs)
60
+
61
+ ##############################
62
+ # Helper methods
63
+ ##############################
64
+
65
+ @staticmethod
66
+ def _validate_extension(extension: str) -> None:
67
+ """
68
+ Validate extension.
69
+
70
+ Parameters
71
+ ----------
72
+ extension : str
73
+ Extension of the file.
74
+
75
+ Returns
76
+ -------
77
+ None
78
+
79
+ Raises
80
+ ------
81
+ ValueError
82
+ If extension is not supported.
83
+ """
84
+ if extension not in ["csv", "parquet", "file"]:
85
+ raise ValueError(f"Extension {extension} not supported.")
@@ -0,0 +1,37 @@
1
+ from __future__ import annotations
2
+
3
+ import typing
4
+
5
+ from digitalhub.datastores.builder import builder
6
+
7
+ if typing.TYPE_CHECKING:
8
+ from digitalhub.datastores._base.datastore import Datastore
9
+
10
+
11
+ def get_datastore(uri: str) -> Datastore:
12
+ """
13
+ Get a datastore instance by URI.
14
+
15
+ Parameters
16
+ ----------
17
+ uri : str
18
+ URI to parse.
19
+
20
+ Returns
21
+ -------
22
+ Datastore
23
+ The datastore instance.
24
+ """
25
+ return builder.get(uri)
26
+
27
+
28
+ def get_default_datastore() -> Datastore:
29
+ """
30
+ Get the default datastore instance.
31
+
32
+ Returns
33
+ -------
34
+ Datastore
35
+ The default datastore instance.
36
+ """
37
+ return builder.default()
@@ -0,0 +1,110 @@
1
+ from __future__ import annotations
2
+
3
+ import typing
4
+
5
+ from digitalhub.datastores.local.datastore import LocalDatastore
6
+ from digitalhub.datastores.remote.datastore import RemoteDatastore
7
+ from digitalhub.datastores.s3.datastore import S3Datastore
8
+ from digitalhub.datastores.sql.datastore import SqlDatastore
9
+ from digitalhub.stores.api import get_default_store, get_store
10
+ from digitalhub.utils.uri_utils import map_uri_scheme
11
+
12
+ if typing.TYPE_CHECKING:
13
+ from digitalhub.datastores._base.datastore import Datastore
14
+ from digitalhub.stores._base.store import Store
15
+
16
+
17
+ REGISTRY_DATASTORES = {
18
+ "local": LocalDatastore,
19
+ "remote": RemoteDatastore,
20
+ "s3": S3Datastore,
21
+ "sql": SqlDatastore,
22
+ }
23
+
24
+
25
+ class DatastoreBuilder:
26
+ """
27
+ Datastore builder class.
28
+ """
29
+
30
+ def __init__(self) -> None:
31
+ self._instances: dict[str, Datastore] = {}
32
+ self._default: Datastore | None = None
33
+ self._def_scheme = "s3"
34
+
35
+ def build(self, uri: str) -> None:
36
+ """
37
+ Build a datastore instance and register it.
38
+ It overrides any existing instance.
39
+
40
+ Parameters
41
+ ----------
42
+ uri : str
43
+ URI to parse.
44
+
45
+ Returns
46
+ -------
47
+ None
48
+ """
49
+ store = get_store(uri)
50
+ self._instances[store.type] = self.build_datastore(store)
51
+
52
+ def get(self, uri: str) -> Datastore:
53
+ """
54
+ Get a store instance by URI.
55
+
56
+ Parameters
57
+ ----------
58
+ uri : str
59
+ URI to parse.
60
+
61
+ Returns
62
+ -------
63
+ Datastore
64
+ The datastore instance.
65
+ """
66
+ scheme = map_uri_scheme(uri)
67
+ if scheme not in self._instances:
68
+ self.build(uri)
69
+ return self._instances[scheme]
70
+
71
+ def default(self) -> Datastore:
72
+ """
73
+ Get the default store instance.
74
+
75
+ Returns
76
+ -------
77
+ Datastore
78
+ The default datastore instance.
79
+ """
80
+ if self._default is None:
81
+ store = get_default_store()
82
+ self._default = self.build_datastore(store)
83
+ return self._default
84
+
85
+ def build_datastore(self, store: Store) -> Datastore:
86
+ """
87
+ Build a datastore instance.
88
+
89
+ Parameters
90
+ ----------
91
+ store : Store
92
+ Store instance.
93
+
94
+ Returns
95
+ -------
96
+ Datastore
97
+ The datastore instance.
98
+
99
+ Raises
100
+ ------
101
+ NotImplementedError
102
+ If the store type is not implemented.
103
+ """
104
+ try:
105
+ return REGISTRY_DATASTORES[store.type](store)
106
+ except KeyError as e:
107
+ raise NotImplementedError from e
108
+
109
+
110
+ builder = DatastoreBuilder()
File without changes
@@ -0,0 +1,50 @@
1
+ from __future__ import annotations
2
+
3
+ import typing
4
+ from pathlib import Path
5
+ from typing import Any
6
+
7
+ from digitalhub.datastores._base.datastore import Datastore
8
+ from digitalhub.readers.api import get_reader_by_object
9
+
10
+ if typing.TYPE_CHECKING:
11
+ from digitalhub.stores.local.store import LocalStore
12
+
13
+
14
+ class LocalDatastore(Datastore):
15
+ """
16
+ Local Datastore class.
17
+ """
18
+
19
+ def __init__(self, store: LocalStore, **kwargs) -> None:
20
+ super().__init__(store, **kwargs)
21
+ self.store: LocalStore
22
+
23
+ def write_df(self, df: Any, dst: str, extension: str | None = None, **kwargs) -> str:
24
+ """
25
+ Method to write a dataframe to a file. Kwargs are passed to df.to_parquet().
26
+ If destination is not provided, the dataframe is written to the default
27
+ store path with generated name.
28
+
29
+ Parameters
30
+ ----------
31
+ df : Any
32
+ The dataframe to write.
33
+ dst : str
34
+ The destination of the dataframe.
35
+ **kwargs : dict
36
+ Keyword arguments.
37
+
38
+ Returns
39
+ -------
40
+ str
41
+ Path of written dataframe.
42
+ """
43
+ self.store._check_local_dst(dst)
44
+ self._validate_extension(Path(dst).suffix.removeprefix("."))
45
+
46
+ # Write dataframe
47
+ reader = get_reader_by_object(df)
48
+ reader.write_df(df, dst, extension=extension, **kwargs)
49
+
50
+ return dst
File without changes
@@ -0,0 +1,31 @@
1
+ from __future__ import annotations
2
+
3
+ import typing
4
+ from typing import Any
5
+
6
+ from digitalhub.datastores._base.datastore import Datastore
7
+
8
+ if typing.TYPE_CHECKING:
9
+ from digitalhub.stores.remote.store import RemoteStore
10
+
11
+
12
+ class RemoteDatastore(Datastore):
13
+ """
14
+ Remote Datastore class.
15
+ """
16
+
17
+ def __init__(self, store: RemoteStore, **kwargs) -> None:
18
+ super().__init__(store, **kwargs)
19
+ self.store: RemoteStore
20
+
21
+ def write_df(self, df: Any, dst: str, extension: str | None = None, **kwargs) -> str:
22
+ """
23
+ Method to write a dataframe to a file. Note that this method is not implemented
24
+ since the remote store is not meant to write dataframes.
25
+
26
+ Raises
27
+ ------
28
+ NotImplementedError
29
+ This method is not implemented.
30
+ """
31
+ raise NotImplementedError("Remote store does not support write_df.")
File without changes
@@ -0,0 +1,46 @@
1
+ from __future__ import annotations
2
+
3
+ import typing
4
+ from io import BytesIO
5
+ from typing import Any
6
+
7
+ from digitalhub.datastores._base.datastore import Datastore
8
+ from digitalhub.readers.api import get_reader_by_object
9
+
10
+ if typing.TYPE_CHECKING:
11
+ from digitalhub.stores.s3.store import S3Store
12
+
13
+
14
+ class S3Datastore(Datastore):
15
+ """
16
+ S3 Datastore class.
17
+ """
18
+
19
+ def __init__(self, store: S3Store, **kwargs) -> None:
20
+ super().__init__(store, **kwargs)
21
+ self.store: S3Store
22
+
23
+ def write_df(self, df: Any, dst: str, extension: str | None = None, **kwargs) -> str:
24
+ """
25
+ Write a dataframe to S3 based storage. Kwargs are passed to df.to_parquet().
26
+
27
+ Parameters
28
+ ----------
29
+ df : Any
30
+ The dataframe.
31
+ dst : str
32
+ The destination path on S3 based storage.
33
+ **kwargs : dict
34
+ Keyword arguments.
35
+
36
+ Returns
37
+ -------
38
+ str
39
+ The S3 path where the dataframe was saved.
40
+ """
41
+ fileobj = BytesIO()
42
+ reader = get_reader_by_object(df)
43
+ reader.write_df(df, fileobj, extension=extension, **kwargs)
44
+
45
+ key = self.store._get_key(dst)
46
+ return self.store.upload_fileobject(fileobj, key)
File without changes