digitalhub 0.8.0b0__py3-none-any.whl → 0.8.0b1__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 (159) hide show
  1. digitalhub/__init__.py +62 -94
  2. digitalhub/client/__init__.py +0 -0
  3. digitalhub/client/builder.py +105 -0
  4. digitalhub/client/objects/__init__.py +0 -0
  5. digitalhub/client/objects/base.py +56 -0
  6. digitalhub/client/objects/dhcore.py +681 -0
  7. digitalhub/client/objects/local.py +533 -0
  8. digitalhub/context/__init__.py +0 -0
  9. digitalhub/context/builder.py +178 -0
  10. digitalhub/context/context.py +136 -0
  11. digitalhub/datastores/__init__.py +0 -0
  12. digitalhub/datastores/builder.py +134 -0
  13. digitalhub/datastores/objects/__init__.py +0 -0
  14. digitalhub/datastores/objects/base.py +85 -0
  15. digitalhub/datastores/objects/local.py +42 -0
  16. digitalhub/datastores/objects/remote.py +23 -0
  17. digitalhub/datastores/objects/s3.py +38 -0
  18. digitalhub/datastores/objects/sql.py +60 -0
  19. digitalhub/entities/__init__.py +0 -0
  20. digitalhub/entities/_base/__init__.py +0 -0
  21. digitalhub/entities/_base/api.py +346 -0
  22. digitalhub/entities/_base/base.py +82 -0
  23. digitalhub/entities/_base/crud.py +610 -0
  24. digitalhub/entities/_base/entity/__init__.py +0 -0
  25. digitalhub/entities/_base/entity/base.py +132 -0
  26. digitalhub/entities/_base/entity/context.py +118 -0
  27. digitalhub/entities/_base/entity/executable.py +380 -0
  28. digitalhub/entities/_base/entity/material.py +214 -0
  29. digitalhub/entities/_base/entity/unversioned.py +87 -0
  30. digitalhub/entities/_base/entity/versioned.py +94 -0
  31. digitalhub/entities/_base/metadata.py +59 -0
  32. digitalhub/entities/_base/spec/__init__.py +0 -0
  33. digitalhub/entities/_base/spec/base.py +58 -0
  34. digitalhub/entities/_base/spec/material.py +22 -0
  35. digitalhub/entities/_base/state.py +31 -0
  36. digitalhub/entities/_base/status/__init__.py +0 -0
  37. digitalhub/entities/_base/status/base.py +32 -0
  38. digitalhub/entities/_base/status/material.py +49 -0
  39. digitalhub/entities/_builders/__init__.py +0 -0
  40. digitalhub/entities/_builders/metadata.py +60 -0
  41. digitalhub/entities/_builders/name.py +31 -0
  42. digitalhub/entities/_builders/spec.py +43 -0
  43. digitalhub/entities/_builders/status.py +62 -0
  44. digitalhub/entities/_builders/uuid.py +33 -0
  45. digitalhub/entities/artifact/__init__.py +0 -0
  46. digitalhub/entities/artifact/builder.py +133 -0
  47. digitalhub/entities/artifact/crud.py +358 -0
  48. digitalhub/entities/artifact/entity/__init__.py +0 -0
  49. digitalhub/entities/artifact/entity/_base.py +39 -0
  50. digitalhub/entities/artifact/entity/artifact.py +9 -0
  51. digitalhub/entities/artifact/spec.py +39 -0
  52. digitalhub/entities/artifact/status.py +15 -0
  53. digitalhub/entities/dataitem/__init__.py +0 -0
  54. digitalhub/entities/dataitem/builder.py +144 -0
  55. digitalhub/entities/dataitem/crud.py +395 -0
  56. digitalhub/entities/dataitem/entity/__init__.py +0 -0
  57. digitalhub/entities/dataitem/entity/_base.py +75 -0
  58. digitalhub/entities/dataitem/entity/dataitem.py +9 -0
  59. digitalhub/entities/dataitem/entity/iceberg.py +7 -0
  60. digitalhub/entities/dataitem/entity/table.py +125 -0
  61. digitalhub/entities/dataitem/models.py +62 -0
  62. digitalhub/entities/dataitem/spec.py +61 -0
  63. digitalhub/entities/dataitem/status.py +38 -0
  64. digitalhub/entities/entity_types.py +19 -0
  65. digitalhub/entities/function/__init__.py +0 -0
  66. digitalhub/entities/function/builder.py +86 -0
  67. digitalhub/entities/function/crud.py +305 -0
  68. digitalhub/entities/function/entity.py +101 -0
  69. digitalhub/entities/function/models.py +118 -0
  70. digitalhub/entities/function/spec.py +81 -0
  71. digitalhub/entities/function/status.py +9 -0
  72. digitalhub/entities/model/__init__.py +0 -0
  73. digitalhub/entities/model/builder.py +152 -0
  74. digitalhub/entities/model/crud.py +358 -0
  75. digitalhub/entities/model/entity/__init__.py +0 -0
  76. digitalhub/entities/model/entity/_base.py +34 -0
  77. digitalhub/entities/model/entity/huggingface.py +9 -0
  78. digitalhub/entities/model/entity/mlflow.py +90 -0
  79. digitalhub/entities/model/entity/model.py +9 -0
  80. digitalhub/entities/model/entity/sklearn.py +9 -0
  81. digitalhub/entities/model/models.py +26 -0
  82. digitalhub/entities/model/spec.py +146 -0
  83. digitalhub/entities/model/status.py +33 -0
  84. digitalhub/entities/project/__init__.py +0 -0
  85. digitalhub/entities/project/builder.py +82 -0
  86. digitalhub/entities/project/crud.py +350 -0
  87. digitalhub/entities/project/entity.py +2060 -0
  88. digitalhub/entities/project/spec.py +50 -0
  89. digitalhub/entities/project/status.py +9 -0
  90. digitalhub/entities/registries.py +48 -0
  91. digitalhub/entities/run/__init__.py +0 -0
  92. digitalhub/entities/run/builder.py +77 -0
  93. digitalhub/entities/run/crud.py +232 -0
  94. digitalhub/entities/run/entity.py +461 -0
  95. digitalhub/entities/run/spec.py +153 -0
  96. digitalhub/entities/run/status.py +114 -0
  97. digitalhub/entities/secret/__init__.py +0 -0
  98. digitalhub/entities/secret/builder.py +93 -0
  99. digitalhub/entities/secret/crud.py +294 -0
  100. digitalhub/entities/secret/entity.py +73 -0
  101. digitalhub/entities/secret/spec.py +35 -0
  102. digitalhub/entities/secret/status.py +9 -0
  103. digitalhub/entities/task/__init__.py +0 -0
  104. digitalhub/entities/task/builder.py +74 -0
  105. digitalhub/entities/task/crud.py +241 -0
  106. digitalhub/entities/task/entity.py +135 -0
  107. digitalhub/entities/task/models.py +199 -0
  108. digitalhub/entities/task/spec.py +51 -0
  109. digitalhub/entities/task/status.py +9 -0
  110. digitalhub/entities/utils.py +184 -0
  111. digitalhub/entities/workflow/__init__.py +0 -0
  112. digitalhub/entities/workflow/builder.py +91 -0
  113. digitalhub/entities/workflow/crud.py +304 -0
  114. digitalhub/entities/workflow/entity.py +77 -0
  115. digitalhub/entities/workflow/spec.py +15 -0
  116. digitalhub/entities/workflow/status.py +9 -0
  117. digitalhub/readers/__init__.py +0 -0
  118. digitalhub/readers/builder.py +54 -0
  119. digitalhub/readers/objects/__init__.py +0 -0
  120. digitalhub/readers/objects/base.py +70 -0
  121. digitalhub/readers/objects/pandas.py +207 -0
  122. digitalhub/readers/registry.py +15 -0
  123. digitalhub/registry/__init__.py +0 -0
  124. digitalhub/registry/models.py +87 -0
  125. digitalhub/registry/registry.py +74 -0
  126. digitalhub/registry/utils.py +150 -0
  127. digitalhub/runtimes/__init__.py +0 -0
  128. digitalhub/runtimes/base.py +164 -0
  129. digitalhub/runtimes/builder.py +53 -0
  130. digitalhub/runtimes/kind_registry.py +170 -0
  131. digitalhub/stores/__init__.py +0 -0
  132. digitalhub/stores/builder.py +257 -0
  133. digitalhub/stores/objects/__init__.py +0 -0
  134. digitalhub/stores/objects/base.py +189 -0
  135. digitalhub/stores/objects/local.py +230 -0
  136. digitalhub/stores/objects/remote.py +143 -0
  137. digitalhub/stores/objects/s3.py +563 -0
  138. digitalhub/stores/objects/sql.py +328 -0
  139. digitalhub/utils/__init__.py +0 -0
  140. digitalhub/utils/data_utils.py +127 -0
  141. digitalhub/utils/env_utils.py +123 -0
  142. digitalhub/utils/exceptions.py +55 -0
  143. digitalhub/utils/file_utils.py +204 -0
  144. digitalhub/utils/generic_utils.py +207 -0
  145. digitalhub/utils/git_utils.py +148 -0
  146. digitalhub/utils/io_utils.py +79 -0
  147. digitalhub/utils/logger.py +17 -0
  148. digitalhub/utils/uri_utils.py +56 -0
  149. {digitalhub-0.8.0b0.dist-info → digitalhub-0.8.0b1.dist-info}/METADATA +27 -12
  150. digitalhub-0.8.0b1.dist-info/RECORD +161 -0
  151. test/test_crud_artifacts.py +1 -1
  152. test/test_crud_dataitems.py +1 -1
  153. test/test_crud_functions.py +1 -1
  154. test/test_crud_runs.py +1 -1
  155. test/test_crud_tasks.py +1 -1
  156. digitalhub-0.8.0b0.dist-info/RECORD +0 -14
  157. {digitalhub-0.8.0b0.dist-info → digitalhub-0.8.0b1.dist-info}/LICENSE.txt +0 -0
  158. {digitalhub-0.8.0b0.dist-info → digitalhub-0.8.0b1.dist-info}/WHEEL +0 -0
  159. {digitalhub-0.8.0b0.dist-info → digitalhub-0.8.0b1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,54 @@
1
+ from __future__ import annotations
2
+
3
+ import typing
4
+ from typing import Any
5
+
6
+ from digitalhub.readers.registry import REGISTRY_DATAFRAME, REGISTRY_FRAMEWORK
7
+
8
+ if typing.TYPE_CHECKING:
9
+ from digitalhub.readers.objects.base import DataframeReader
10
+
11
+
12
+ def get_reader_by_engine(engine: str) -> DataframeReader:
13
+ """
14
+ Get Dataframe reader.
15
+
16
+ Parameters
17
+ ----------
18
+ engine : str
19
+ Dataframe engine (pandas, polars, etc.).
20
+
21
+ Returns
22
+ -------
23
+ DataframeReader
24
+ Reader object.
25
+ """
26
+ try:
27
+ return REGISTRY_FRAMEWORK[engine]()
28
+ except KeyError:
29
+ engines = list(REGISTRY_FRAMEWORK.keys())
30
+ msg = f"Unsupported dataframe engine: {engine}. Supported engines: {engines}"
31
+ raise ValueError(msg)
32
+
33
+
34
+ def get_reader_by_object(obj: Any) -> DataframeReader:
35
+ """
36
+ Get Dataframe reader by object.
37
+
38
+ Parameters
39
+ ----------
40
+ obj : Any
41
+ Object to get reader from.
42
+
43
+ Returns
44
+ -------
45
+ DataframeReader
46
+ Reader object.
47
+ """
48
+ try:
49
+ obj_name = f"{obj.__class__.__module__}.{obj.__class__.__name__}"
50
+ return REGISTRY_DATAFRAME[obj_name]()
51
+ except KeyError:
52
+ types = list(REGISTRY_DATAFRAME.keys())
53
+ msg = f"Unsupported dataframe type: {obj}. Supported types: {types}"
54
+ raise ValueError(msg)
File without changes
@@ -0,0 +1,70 @@
1
+ from __future__ import annotations
2
+
3
+ from abc import ABCMeta, abstractmethod
4
+ from typing import Any
5
+
6
+
7
+ class DataframeReader(metaclass=ABCMeta):
8
+ """
9
+ Dataframe reader abstract class.
10
+ """
11
+
12
+ ##############################
13
+ # Read methods
14
+ ##############################
15
+
16
+ @staticmethod
17
+ @abstractmethod
18
+ def read_df(path: str | list[str], extension: str, **kwargs) -> Any:
19
+ """
20
+ Read DataFrame from path.
21
+ """
22
+
23
+ ##############################
24
+ # Write methods
25
+ ##############################
26
+
27
+ @abstractmethod
28
+ def write_df(self, df: Any, dst: Any, extension: str | None = None, **kwargs) -> None:
29
+ """
30
+ Method to write a dataframe to a file.
31
+ """
32
+
33
+ @staticmethod
34
+ @abstractmethod
35
+ def write_csv(df: Any, *args, **kwargs) -> str:
36
+ """
37
+ Write DataFrame as csv.
38
+ """
39
+
40
+ @staticmethod
41
+ @abstractmethod
42
+ def write_parquet(df: Any, *args, **kwargs) -> str:
43
+ """
44
+ Write DataFrame as parquet.
45
+ """
46
+
47
+ @staticmethod
48
+ @abstractmethod
49
+ def write_table(df: Any, *args, **kwargs) -> str:
50
+ """
51
+ Write DataFrame as table.
52
+ """
53
+
54
+ ##############################
55
+ # Utils
56
+ ##############################
57
+
58
+ @staticmethod
59
+ @abstractmethod
60
+ def get_schema(df: Any) -> Any:
61
+ """
62
+ Get schema.
63
+ """
64
+
65
+ @staticmethod
66
+ @abstractmethod
67
+ def get_preview(df: Any) -> Any:
68
+ """
69
+ Get preview.
70
+ """
@@ -0,0 +1,207 @@
1
+ from __future__ import annotations
2
+
3
+ from io import BytesIO
4
+ from typing import Any
5
+
6
+ import numpy as np
7
+ import pandas as pd
8
+ from pandas.errors import ParserError
9
+
10
+ from digitalhub.readers.objects.base import DataframeReader
11
+ from digitalhub.utils.data_utils import build_data_preview, get_data_preview
12
+
13
+
14
+ class DataframeReaderPandas(DataframeReader):
15
+ """
16
+ Pandas reader class.
17
+ """
18
+
19
+ ##############################
20
+ # Read methods
21
+ ##############################
22
+
23
+ def read_df(self, path: str | list[str], extension: str, **kwargs) -> pd.DataFrame:
24
+ """
25
+ Read DataFrame from path.
26
+
27
+ Parameters
28
+ ----------
29
+ path : str | list[str]
30
+ Path(s) to read DataFrame from.
31
+ extension : str
32
+ Extension of the file.
33
+ **kwargs : dict
34
+ Keyword arguments.
35
+
36
+ Returns
37
+ -------
38
+ pd.DataFrame
39
+ Pandas DataFrame.
40
+ """
41
+ if extension == "csv":
42
+ method = pd.read_csv
43
+ elif extension == "parquet":
44
+ method = pd.read_parquet
45
+ elif extension == "file":
46
+ try:
47
+ return self.read_df(path, "csv", **kwargs)
48
+ except ParserError:
49
+ raise ValueError(f"Unable to read from {path}.")
50
+
51
+ if isinstance(path, list):
52
+ dfs = [method(p, **kwargs) for p in path]
53
+ return pd.concat(dfs)
54
+ return method(path, **kwargs)
55
+
56
+ ##############################
57
+ # Write methods
58
+ ##############################
59
+
60
+ def write_df(self, df: pd.DataFrame, dst: str | BytesIO, extension: str | None = None, **kwargs) -> None:
61
+ """
62
+ Write DataFrame as parquet.
63
+
64
+ Parameters
65
+ ----------
66
+ df : pd.DataFrame
67
+ The dataframe to write.
68
+ dst : str | BytesIO
69
+ The destination of the dataframe.
70
+ **kwargs : dict
71
+ Keyword arguments.
72
+
73
+ Returns
74
+ -------
75
+ None
76
+ """
77
+ if extension == "csv":
78
+ return self.write_csv(df, dst, **kwargs)
79
+ self.write_parquet(df, dst, **kwargs)
80
+
81
+ @staticmethod
82
+ def write_csv(df: pd.DataFrame, dst: str | BytesIO, **kwargs) -> None:
83
+ """
84
+ Write DataFrame as csv.
85
+
86
+ Parameters
87
+ ----------
88
+ df : pd.DataFrame
89
+ The dataframe to write.
90
+ dst : str | BytesIO
91
+ The destination of the dataframe.
92
+ **kwargs : dict
93
+ Keyword arguments.
94
+
95
+ Returns
96
+ -------
97
+ None
98
+ """
99
+ df.to_csv(dst, index=False, **kwargs)
100
+
101
+ @staticmethod
102
+ def write_parquet(df: pd.DataFrame, dst: str | BytesIO, **kwargs) -> None:
103
+ """
104
+ Write DataFrame as parquet.
105
+
106
+ Parameters
107
+ ----------
108
+ df : pd.DataFrame
109
+ The dataframe to write.
110
+ dst : str | BytesIO
111
+ The destination of the dataframe.
112
+ **kwargs : dict
113
+ Keyword arguments.
114
+
115
+ Returns
116
+ -------
117
+ None
118
+ """
119
+ df.to_parquet(dst, index=False, **kwargs)
120
+
121
+ @staticmethod
122
+ def write_table(df: pd.DataFrame, table: str, engine: Any, schema: str, **kwargs) -> None:
123
+ """
124
+ Write DataFrame as table.
125
+
126
+ Parameters
127
+ ----------
128
+ df : pd.DataFrame
129
+ The dataframe to write.
130
+ table : str
131
+ The destination table.
132
+ engine : Any
133
+ The SQLAlchemy engine.
134
+ schema : str
135
+ The destination schema.
136
+ **kwargs : dict
137
+ Keyword arguments.
138
+
139
+ Returns
140
+ -------
141
+ None
142
+ """
143
+ df.to_sql(table, engine, schema=schema, index=False, **kwargs)
144
+
145
+ ##############################
146
+ # Utils
147
+ ##############################
148
+
149
+ @staticmethod
150
+ def get_schema(df: pd.DataFrame) -> Any:
151
+ """
152
+ Get schema.
153
+
154
+ Parameters
155
+ ----------
156
+ df : pd.DataFrame
157
+ The dataframe.
158
+
159
+ Returns
160
+ -------
161
+ Any
162
+ The schema.
163
+ """
164
+ schema = {"fields": []}
165
+
166
+ for column_name, dtype in df.dtypes.items():
167
+ field = {"name": str(column_name), "type": ""}
168
+
169
+ if pd.api.types.is_integer_dtype(dtype):
170
+ field["type"] = "integer"
171
+ elif pd.api.types.is_float_dtype(dtype):
172
+ field["type"] = "number"
173
+ elif pd.api.types.is_bool_dtype(dtype):
174
+ field["type"] = "boolean"
175
+ elif pd.api.types.is_string_dtype(dtype):
176
+ field["type"] = "string"
177
+ elif pd.api.types.is_datetime64_any_dtype(dtype):
178
+ field["type"] = "datetime"
179
+ else:
180
+ field["type"] = "any"
181
+
182
+ schema["fields"].append(field)
183
+
184
+ return schema
185
+
186
+ @staticmethod
187
+ def get_preview(df: pd.DataFrame) -> Any:
188
+ """
189
+ Get preview.
190
+
191
+ Parameters
192
+ ----------
193
+ df : pd.DataFrame
194
+ The dataframe.
195
+
196
+ Returns
197
+ -------
198
+ Any
199
+ The preview.
200
+ """
201
+ columns = [str(col) for col, _ in df.dtypes.items()]
202
+ head = df.head(10)
203
+ head = head.replace({np.nan: None})
204
+ head = head.values.tolist()
205
+ preview = get_data_preview(columns, head)
206
+ len_df = len(df)
207
+ return build_data_preview(preview, len_df)
@@ -0,0 +1,15 @@
1
+ from __future__ import annotations
2
+
3
+ REGISTRY_FRAMEWORK = {}
4
+ REGISTRY_DATAFRAME = {}
5
+ DATAFRAME_TYPES = []
6
+
7
+ try:
8
+ from digitalhub.readers.objects.pandas import DataframeReaderPandas
9
+
10
+ REGISTRY_FRAMEWORK["pandas"] = DataframeReaderPandas
11
+ REGISTRY_DATAFRAME["pandas.core.frame.DataFrame"] = DataframeReaderPandas
12
+ DATAFRAME_TYPES.append("pandas.core.frame.DataFrame")
13
+
14
+ except ImportError:
15
+ pass
File without changes
@@ -0,0 +1,87 @@
1
+ from __future__ import annotations
2
+
3
+ from pydantic import BaseModel
4
+
5
+
6
+ class RuntimeEntry(BaseModel):
7
+ """
8
+ Model for Runtime entry.
9
+ It specifies the module path and the runtime class name.
10
+ """
11
+
12
+ module: str
13
+ """Module path."""
14
+
15
+ class_name: str
16
+ """Class name."""
17
+
18
+ kind_registry_module: str
19
+ """Kind registry module path."""
20
+
21
+ kind_registry_class_name: str
22
+ """Kind registry class name."""
23
+
24
+
25
+ class SpecEntry(BaseModel):
26
+ """
27
+ Model for Spec entry.
28
+ It specifies the module path, the spec class name
29
+ and the spec pydantic class validator.
30
+ """
31
+
32
+ module: str
33
+ """Module path."""
34
+
35
+ class_name: str
36
+ """Class name."""
37
+
38
+ parameters_validator: str
39
+ """Class name of the parameter validator."""
40
+
41
+
42
+ class StatusEntry(BaseModel):
43
+ """
44
+ Model for Status entry.
45
+ It specifies the module path and the status class name.
46
+ """
47
+
48
+ module: str
49
+ """Module path."""
50
+
51
+ class_name: str
52
+ """Class name."""
53
+
54
+
55
+ class MetadataEntry(BaseModel):
56
+ """
57
+ Model for Metadata entry.
58
+ It specifies the module path and the metadata class name.
59
+ """
60
+
61
+ module: str
62
+ """Module path."""
63
+
64
+ class_name: str
65
+ """Class name."""
66
+
67
+
68
+ class RegistryEntry(BaseModel):
69
+ """
70
+ Basic entry model for every entity.
71
+ Functions, tasks and runs specify also the runtime field.
72
+ """
73
+
74
+ entity_type: str
75
+ """Entity type."""
76
+
77
+ spec: SpecEntry
78
+ """Spec infos."""
79
+
80
+ status: StatusEntry
81
+ """Status infos."""
82
+
83
+ metadata: MetadataEntry
84
+ """Metadata infos."""
85
+
86
+ runtime: RuntimeEntry = None
87
+ """Runtime infos."""
@@ -0,0 +1,74 @@
1
+ from __future__ import annotations
2
+
3
+ from digitalhub.registry.models import RegistryEntry
4
+
5
+
6
+ class GlobalEntityRegistry:
7
+ """
8
+ Global entity registry where all entities classpaths are stored.
9
+ It keeps track of all entities that are registered in the system.
10
+ """
11
+
12
+ def register(self, entity_kind: str, entry: dict) -> None:
13
+ """
14
+ Register an entity kind.
15
+
16
+ Parameters
17
+ ----------
18
+ entity_kind : str
19
+ Entity kind to be registered.
20
+ entry : dict
21
+ Entry to be registered.
22
+
23
+ Returns
24
+ -------
25
+ None
26
+
27
+ """
28
+ if hasattr(self, entity_kind):
29
+ raise ValueError(f"Entity kind {entity_kind} already registered")
30
+ entry = RegistryEntry(**entry)
31
+ setattr(self, entity_kind, entry)
32
+
33
+ def update(self, entity_kind: str, entry: dict) -> None:
34
+ """
35
+ Update an entity kind.
36
+
37
+ Parameters
38
+ ----------
39
+ entity_kind : str
40
+ Entity kind to be updated.
41
+ entry : dict
42
+ Entry to be updated.
43
+
44
+ Returns
45
+ -------
46
+ None
47
+ """
48
+ if hasattr(self, entity_kind):
49
+ entry = RegistryEntry(**entry)
50
+ setattr(self, entity_kind, entry)
51
+ else:
52
+ raise ValueError(f"Entity kind {entity_kind} not registered")
53
+
54
+ def get_entity_type(self, entity_kind: str) -> str:
55
+ """
56
+ Get entity type from kind.
57
+
58
+ Parameters
59
+ ----------
60
+ entity_kind : str
61
+ Entity kind.
62
+
63
+ Returns
64
+ -------
65
+ str
66
+ Entity type.
67
+ """
68
+ if not hasattr(self, entity_kind):
69
+ raise ValueError(f"Entity kind {entity_kind} not registered")
70
+ entry: RegistryEntry = getattr(self, entity_kind)
71
+ return entry.entity_type
72
+
73
+
74
+ registry = GlobalEntityRegistry()
@@ -0,0 +1,150 @@
1
+ from __future__ import annotations
2
+
3
+ import importlib
4
+ import importlib.metadata
5
+ import pkgutil
6
+ import re
7
+ from types import ModuleType
8
+
9
+
10
+ def import_module(package: str) -> ModuleType:
11
+ """
12
+ Import modules from package name.
13
+
14
+ Parameters
15
+ ----------
16
+ package : str
17
+ Package name.
18
+
19
+ Returns
20
+ -------
21
+ ModuleType
22
+ Module.
23
+ """
24
+ try:
25
+ return importlib.import_module(package)
26
+ except ModuleNotFoundError:
27
+ raise ModuleNotFoundError(f"Package {package} not found.")
28
+ except Exception as e:
29
+ raise e
30
+
31
+
32
+ def import_class(module_to_import: str, class_name: str) -> type:
33
+ """
34
+ Import class from implemented module.
35
+
36
+ Parameters
37
+ ----------
38
+ module_to_import : str
39
+ Module name.
40
+ class_name : str
41
+ Class name.
42
+
43
+ Returns
44
+ -------
45
+ type
46
+ Class.
47
+ """
48
+ module = import_module(module_to_import)
49
+ try:
50
+ return getattr(module, class_name)
51
+ except AttributeError:
52
+ raise ModuleNotFoundError(f"Module {module_to_import} has no '{class_name}' class.")
53
+
54
+
55
+ def list_runtimes() -> list[str]:
56
+ """
57
+ List installed runtimes for digitalhub.
58
+
59
+ Returns
60
+ -------
61
+ list
62
+ List of installed runtimes names.
63
+ """
64
+ pattern = r"digitalhub_runtime_.*"
65
+ runtimes = []
66
+ try:
67
+ for _, name, _ in pkgutil.iter_modules():
68
+ if re.match(pattern, name):
69
+ runtimes.append(name)
70
+ return runtimes
71
+ except Exception:
72
+ raise RuntimeError("Error listing installed runtimes.")
73
+
74
+
75
+ def register_runtimes_entities() -> None:
76
+ """
77
+ Register runtimes and related entities into registry.
78
+
79
+ Returns
80
+ -------
81
+ None
82
+ """
83
+ for package in list_runtimes():
84
+ import_module(package)
85
+
86
+
87
+ def register_entities() -> None:
88
+ """
89
+ Register layer and related entities into registry.
90
+
91
+ Returns
92
+ -------
93
+ None
94
+ """
95
+ # Try ot import registry from entities.registries module
96
+ try:
97
+ import_module(f"digitalhub.entities.registries")
98
+ except Exception:
99
+ pass
100
+
101
+
102
+ def create_info(
103
+ root: str,
104
+ entity_type: str,
105
+ prefix: str,
106
+ suffix: str | None = "",
107
+ runtime_info: dict | None = None,
108
+ ) -> dict:
109
+ """
110
+ Create entity info.
111
+
112
+ Parameters
113
+ ----------
114
+ root : str
115
+ Root module.
116
+ entity_type : str
117
+ Entity type.
118
+ prefix : str
119
+ Entity prefix.
120
+ suffix : str
121
+ Entity suffix.
122
+ runtime_info : dict
123
+ Runtime info.
124
+
125
+ Returns
126
+ -------
127
+ dict
128
+ Entity info.
129
+ """
130
+ dict_ = {
131
+ "entity_type": entity_type,
132
+ "spec": {
133
+ "module": f"{root}.{entity_type}.spec",
134
+ "class_name": f"{prefix}Spec{suffix}",
135
+ "parameters_validator": f"{prefix}Params{suffix}",
136
+ },
137
+ "status": {
138
+ "module": f"{root}.{entity_type}.status",
139
+ "class_name": f"{prefix}Status{suffix}",
140
+ },
141
+ "metadata": {
142
+ "module": "digitalhub.entities._base.metadata",
143
+ "class_name": "Metadata",
144
+ },
145
+ }
146
+ # Add runtime only if provided
147
+ # (in functions, tasks, runs and workflows)
148
+ if runtime_info is not None:
149
+ dict_["runtime"] = runtime_info
150
+ return dict_
File without changes