digitalhub 0.9.1__py3-none-any.whl → 0.10.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 (121) hide show
  1. digitalhub/__init__.py +2 -3
  2. digitalhub/client/_base/api_builder.py +1 -1
  3. digitalhub/client/_base/client.py +25 -2
  4. digitalhub/client/_base/params_builder.py +16 -0
  5. digitalhub/client/dhcore/api_builder.py +10 -4
  6. digitalhub/client/dhcore/client.py +30 -398
  7. digitalhub/client/dhcore/configurator.py +361 -0
  8. digitalhub/client/dhcore/error_parser.py +107 -0
  9. digitalhub/client/dhcore/models.py +13 -23
  10. digitalhub/client/dhcore/params_builder.py +178 -0
  11. digitalhub/client/dhcore/utils.py +4 -44
  12. digitalhub/client/local/api_builder.py +13 -18
  13. digitalhub/client/local/client.py +18 -2
  14. digitalhub/client/local/enums.py +11 -0
  15. digitalhub/client/local/params_builder.py +116 -0
  16. digitalhub/configurator/api.py +31 -0
  17. digitalhub/configurator/configurator.py +195 -0
  18. digitalhub/configurator/credentials_store.py +65 -0
  19. digitalhub/configurator/ini_module.py +74 -0
  20. digitalhub/entities/_base/_base/entity.py +2 -2
  21. digitalhub/entities/_base/context/entity.py +4 -4
  22. digitalhub/entities/_base/entity/builder.py +5 -5
  23. digitalhub/entities/_base/executable/entity.py +2 -2
  24. digitalhub/entities/_base/material/entity.py +12 -12
  25. digitalhub/entities/_base/material/status.py +1 -1
  26. digitalhub/entities/_base/material/utils.py +2 -2
  27. digitalhub/entities/_base/unversioned/entity.py +2 -2
  28. digitalhub/entities/_base/versioned/entity.py +2 -2
  29. digitalhub/entities/_commons/enums.py +2 -0
  30. digitalhub/entities/_commons/metrics.py +164 -0
  31. digitalhub/entities/_commons/types.py +5 -0
  32. digitalhub/entities/_commons/utils.py +2 -2
  33. digitalhub/entities/_processors/base.py +527 -0
  34. digitalhub/entities/{_operations/processor.py → _processors/context.py} +212 -837
  35. digitalhub/entities/_processors/utils.py +158 -0
  36. digitalhub/entities/artifact/artifact/spec.py +3 -1
  37. digitalhub/entities/artifact/crud.py +13 -12
  38. digitalhub/entities/artifact/utils.py +1 -1
  39. digitalhub/entities/builders.py +6 -18
  40. digitalhub/entities/dataitem/_base/entity.py +0 -41
  41. digitalhub/entities/dataitem/crud.py +27 -15
  42. digitalhub/entities/dataitem/table/entity.py +49 -35
  43. digitalhub/entities/dataitem/table/models.py +4 -3
  44. digitalhub/{utils/data_utils.py → entities/dataitem/table/utils.py} +46 -54
  45. digitalhub/entities/dataitem/utils.py +58 -10
  46. digitalhub/entities/function/crud.py +9 -9
  47. digitalhub/entities/model/_base/entity.py +120 -0
  48. digitalhub/entities/model/_base/spec.py +6 -17
  49. digitalhub/entities/model/_base/status.py +10 -0
  50. digitalhub/entities/model/crud.py +13 -12
  51. digitalhub/entities/model/huggingface/spec.py +9 -4
  52. digitalhub/entities/model/mlflow/models.py +2 -2
  53. digitalhub/entities/model/mlflow/spec.py +7 -7
  54. digitalhub/entities/model/mlflow/utils.py +44 -5
  55. digitalhub/entities/project/_base/entity.py +317 -9
  56. digitalhub/entities/project/_base/spec.py +8 -6
  57. digitalhub/entities/project/crud.py +12 -11
  58. digitalhub/entities/run/_base/entity.py +103 -6
  59. digitalhub/entities/run/_base/spec.py +4 -2
  60. digitalhub/entities/run/_base/status.py +12 -0
  61. digitalhub/entities/run/crud.py +8 -8
  62. digitalhub/entities/secret/_base/entity.py +3 -3
  63. digitalhub/entities/secret/_base/spec.py +4 -2
  64. digitalhub/entities/secret/crud.py +11 -9
  65. digitalhub/entities/task/_base/entity.py +4 -4
  66. digitalhub/entities/task/_base/models.py +51 -40
  67. digitalhub/entities/task/_base/spec.py +2 -0
  68. digitalhub/entities/task/_base/utils.py +2 -2
  69. digitalhub/entities/task/crud.py +12 -8
  70. digitalhub/entities/workflow/crud.py +9 -9
  71. digitalhub/factory/utils.py +9 -9
  72. digitalhub/readers/{_base → data/_base}/builder.py +1 -1
  73. digitalhub/readers/{_base → data/_base}/reader.py +16 -4
  74. digitalhub/readers/{api.py → data/api.py} +2 -2
  75. digitalhub/readers/{factory.py → data/factory.py} +3 -3
  76. digitalhub/readers/{pandas → data/pandas}/builder.py +2 -2
  77. digitalhub/readers/{pandas → data/pandas}/reader.py +110 -30
  78. digitalhub/readers/query/__init__.py +0 -0
  79. digitalhub/stores/_base/store.py +59 -69
  80. digitalhub/stores/api.py +8 -33
  81. digitalhub/stores/builder.py +44 -161
  82. digitalhub/stores/local/store.py +106 -89
  83. digitalhub/stores/remote/store.py +86 -11
  84. digitalhub/stores/s3/configurator.py +108 -0
  85. digitalhub/stores/s3/enums.py +17 -0
  86. digitalhub/stores/s3/models.py +21 -0
  87. digitalhub/stores/s3/store.py +154 -70
  88. digitalhub/{utils/s3_utils.py → stores/s3/utils.py} +7 -3
  89. digitalhub/stores/sql/configurator.py +88 -0
  90. digitalhub/stores/sql/enums.py +16 -0
  91. digitalhub/stores/sql/models.py +24 -0
  92. digitalhub/stores/sql/store.py +106 -85
  93. digitalhub/{readers/_commons → utils}/enums.py +5 -1
  94. digitalhub/utils/exceptions.py +6 -0
  95. digitalhub/utils/file_utils.py +8 -7
  96. digitalhub/utils/generic_utils.py +28 -15
  97. digitalhub/utils/git_utils.py +16 -9
  98. digitalhub/utils/types.py +5 -0
  99. digitalhub/utils/uri_utils.py +2 -2
  100. {digitalhub-0.9.1.dist-info → digitalhub-0.10.0.dist-info}/METADATA +25 -31
  101. {digitalhub-0.9.1.dist-info → digitalhub-0.10.0.dist-info}/RECORD +108 -99
  102. {digitalhub-0.9.1.dist-info → digitalhub-0.10.0.dist-info}/WHEEL +1 -2
  103. digitalhub/client/dhcore/env.py +0 -23
  104. digitalhub/entities/_base/project/entity.py +0 -341
  105. digitalhub-0.9.1.dist-info/top_level.txt +0 -2
  106. test/local/CRUD/test_artifacts.py +0 -96
  107. test/local/CRUD/test_dataitems.py +0 -96
  108. test/local/CRUD/test_models.py +0 -95
  109. test/local/imports/test_imports.py +0 -66
  110. test/local/instances/test_validate.py +0 -55
  111. test/test_crud_functions.py +0 -109
  112. test/test_crud_runs.py +0 -86
  113. test/test_crud_tasks.py +0 -81
  114. test/testkfp.py +0 -37
  115. test/testkfp_pipeline.py +0 -22
  116. /digitalhub/{entities/_base/project → configurator}/__init__.py +0 -0
  117. /digitalhub/entities/{_operations → _processors}/__init__.py +0 -0
  118. /digitalhub/readers/{_base → data}/__init__.py +0 -0
  119. /digitalhub/readers/{_commons → data/_base}/__init__.py +0 -0
  120. /digitalhub/readers/{pandas → data/pandas}/__init__.py +0 -0
  121. {digitalhub-0.9.1.dist-info → digitalhub-0.10.0.dist-info/licenses}/LICENSE.txt +0 -0
@@ -1,6 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from enum import Enum
4
+ from typing import Optional
4
5
 
5
6
  from pydantic import BaseModel, ConfigDict, Field
6
7
 
@@ -40,16 +41,16 @@ class TableSchemaFieldEntry(BaseModel):
40
41
  type_: FieldType = Field(alias="type")
41
42
  """Field type."""
42
43
 
43
- title: str = None
44
+ title: Optional[str] = None
44
45
  """Field title."""
45
46
 
46
47
  format_: str = Field(default=None, alias="format")
47
48
  """Field format."""
48
49
 
49
- example: str = None
50
+ example: Optional[str] = None
50
51
  """Field example."""
51
52
 
52
- description: str = None
53
+ description: Optional[str] = None
53
54
  """Field description."""
54
55
 
55
56
 
@@ -1,49 +1,23 @@
1
1
  from __future__ import annotations
2
2
 
3
- import json
3
+ from digitalhub.utils.generic_utils import dump_json
4
4
 
5
5
 
6
- def build_data_preview(preview: list[dict] | None = None, rows_count: int | None = None) -> dict:
6
+ def prepare_data(data: list[list], columnar: bool = False) -> list[list]:
7
7
  """
8
- Build data preview.
8
+ Prepare data.
9
9
 
10
10
  Parameters
11
11
  ----------
12
- preview : list[dict] | None
13
- Preview.
14
- rows_count : int | None
15
- Row count.
16
-
17
- Returns
18
- -------
19
- dict
20
- Data preview.
21
- """
22
- dict_ = {}
23
- if preview is not None:
24
- dict_["cols"] = preview
25
- if rows_count is not None:
26
- dict_["rows"] = rows_count
27
- return dict_
28
-
29
-
30
- def get_data_preview(columns: list, data: list[list], columnar: bool = False) -> list[dict]:
31
- """
32
- Prepare preview.
33
-
34
- Parameters
35
- ----------
36
- columns : list
37
- Columns names.
38
- data : list[list]
39
- Data to preview.
40
- columnar : bool
12
+ data : list
13
+ Data.
14
+ columnar : bool | None
41
15
  If data are arranged in columns. If False, data are arranged in rows.
42
16
 
43
17
  Returns
44
18
  -------
45
- list[dict]
46
- Data preview.
19
+ list[list]
20
+ Prepared data.
47
21
  """
48
22
  # Reduce data to 10 rows
49
23
  if not columnar:
@@ -56,17 +30,10 @@ def get_data_preview(columns: list, data: list[list], columnar: bool = False) ->
56
30
  if not columnar:
57
31
  data = list(map(list, list(zip(*data))))
58
32
 
59
- # Prepare the preview
60
- data_dict = prepare_preview(columns, data)
61
-
62
- # Filter memoryview values
63
- filtered_memview = filter_memoryview(data_dict)
64
-
65
- # Check the size of the preview data
66
- return check_preview_size(filtered_memview)
33
+ return data
67
34
 
68
35
 
69
- def prepare_preview(column_names: list, data: list[list]) -> list[dict]:
36
+ def prepare_preview(columns: list, data: list[list]) -> list[dict]:
70
37
  """
71
38
  Get preview.
72
39
 
@@ -80,9 +47,10 @@ def prepare_preview(column_names: list, data: list[list]) -> list[dict]:
80
47
  list[dict]
81
48
  Preview.
82
49
  """
83
- if len(column_names) != len(data):
50
+ if len(columns) != len(data):
84
51
  raise ValueError("Column names and data must have the same length")
85
- return [{"name": column, "value": values} for column, values in zip(column_names, data)]
52
+ preview = [{"name": column, "value": values} for column, values in zip(columns, data)]
53
+ return filter_memoryview(preview)
86
54
 
87
55
 
88
56
  def filter_memoryview(data: list[dict]) -> list[dict]:
@@ -91,13 +59,13 @@ def filter_memoryview(data: list[dict]) -> list[dict]:
91
59
 
92
60
  Parameters
93
61
  ----------
94
- data : pd.DataFrame
62
+ data : list[dict]
95
63
  Data.
96
64
 
97
65
  Returns
98
66
  -------
99
- list[str]
100
- Column to filter out from preview.
67
+ list[dict]
68
+ Preview.
101
69
  """
102
70
  key_to_filter = []
103
71
  for i in data:
@@ -108,20 +76,44 @@ def filter_memoryview(data: list[dict]) -> list[dict]:
108
76
  return data
109
77
 
110
78
 
111
- def check_preview_size(preview: list[dict]) -> list:
79
+ def check_preview_size(preview: dict) -> dict:
112
80
  """
113
- Check preview size. If it's too big, return empty list.
81
+ Check preview size. If it's too big, return empty dict.
114
82
 
115
83
  Parameters
116
84
  ----------
117
- preview : list[dict]
85
+ preview : dict
118
86
  Preview.
119
87
 
120
88
  Returns
121
89
  -------
122
- list
90
+ dict
123
91
  Preview.
124
92
  """
125
- if len(json.dumps(preview).encode("utf-8")) >= 64000:
126
- return []
93
+ if len(dump_json(preview)) >= 64000:
94
+ return {}
127
95
  return preview
96
+
97
+
98
+ def finalize_preview(preview: list[dict] | None = None, rows_count: int | None = None) -> dict:
99
+ """
100
+ Finalize preview.
101
+
102
+ Parameters
103
+ ----------
104
+ preview : list[dict]
105
+ Preview.
106
+ rows_count : int
107
+ Row count.
108
+
109
+ Returns
110
+ -------
111
+ dict
112
+ Data preview.
113
+ """
114
+ data: dict[str, list[dict] | int] = {}
115
+ if preview is not None:
116
+ data["cols"] = preview
117
+ if rows_count is not None:
118
+ data["rows"] = rows_count
119
+ return data
@@ -8,16 +8,21 @@ from digitalhub.context.api import get_context
8
8
  from digitalhub.entities._base.entity._constructors.uuid import build_uuid
9
9
  from digitalhub.entities._base.material.utils import build_log_path_from_source, eval_local_source
10
10
  from digitalhub.entities._commons.enums import EntityKinds, EntityTypes
11
- from digitalhub.readers._commons.enums import Extensions
12
- from digitalhub.readers.api import get_reader_by_object
11
+ from digitalhub.readers.data.api import get_reader_by_object
12
+ from digitalhub.stores.api import get_store
13
+ from digitalhub.utils.enums import FileExtensions
13
14
  from digitalhub.utils.generic_utils import slugify_string
15
+ from digitalhub.utils.types import SourcesOrListOfSources
14
16
 
15
17
  if typing.TYPE_CHECKING:
16
18
  from digitalhub.entities.dataitem._base.entity import Dataitem
17
19
 
18
20
 
21
+ DEFAULT_EXTENSION = FileExtensions.PARQUET.value
22
+
23
+
19
24
  def eval_source(
20
- source: str | list[str] | None = None,
25
+ source: SourcesOrListOfSources | None = None,
21
26
  data: Any | None = None,
22
27
  kind: str | None = None,
23
28
  name: str | None = None,
@@ -28,7 +33,7 @@ def eval_source(
28
33
 
29
34
  Parameters
30
35
  ----------
31
- source : str | list[str]
36
+ source : SourcesOrListOfSources
32
37
  Source(s).
33
38
 
34
39
  Returns
@@ -39,11 +44,12 @@ def eval_source(
39
44
  raise ValueError("You must provide source or data.")
40
45
 
41
46
  if source is not None:
42
- return eval_local_source(source)
47
+ eval_local_source(source)
48
+ return source
43
49
 
44
50
  if kind == EntityKinds.DATAITEM_TABLE.value:
45
51
  ctx = get_context(project)
46
- pth = ctx.root / f"{slugify_string(name)}.{Extensions.PARQUET.value}"
52
+ pth = ctx.root / f"{slugify_string(name)}.{DEFAULT_EXTENSION}"
47
53
  reader = get_reader_by_object(data)
48
54
  reader.write_parquet(data, pth)
49
55
  return str(pth)
@@ -51,11 +57,49 @@ def eval_source(
51
57
  raise NotImplementedError
52
58
 
53
59
 
60
+ def eval_data(
61
+ project: str,
62
+ kind: str,
63
+ source: SourcesOrListOfSources,
64
+ data: Any | None = None,
65
+ file_format: str | None = None,
66
+ engine: str | None = None,
67
+ ) -> Any:
68
+ """
69
+ Evaluate data is loaded.
70
+
71
+ Parameters
72
+ ----------
73
+ project : str
74
+ Project name.
75
+ source : str
76
+ Source(s).
77
+ data : Any
78
+ Dataframe to log. Alternative to source.
79
+ file_format : str
80
+ Extension of the file.
81
+ engine : str
82
+ Engine to use.
83
+
84
+ Returns
85
+ -------
86
+ None
87
+ """
88
+ if kind == EntityKinds.DATAITEM_TABLE.value:
89
+ if data is None:
90
+ return get_store(project, source).read_df(
91
+ source,
92
+ file_format=file_format,
93
+ engine=engine,
94
+ )
95
+ return data
96
+
97
+
54
98
  def process_kwargs(
55
99
  project: str,
56
100
  name: str,
57
101
  kind: str,
58
- source: str | list[str],
102
+ source: SourcesOrListOfSources,
59
103
  data: Any | None = None,
60
104
  path: str | None = None,
61
105
  **kwargs,
@@ -71,7 +115,7 @@ def process_kwargs(
71
115
  Object name.
72
116
  kind : str
73
117
  Kind the object.
74
- source : str
118
+ source : SourcesOrListOfSources
75
119
  Source(s).
76
120
  data : Any
77
121
  Dataframe to log. Alternative to source.
@@ -98,19 +142,23 @@ def process_kwargs(
98
142
  return kwargs
99
143
 
100
144
 
101
- def clean_tmp_path(pth: str) -> None:
145
+ def clean_tmp_path(pth: SourcesOrListOfSources) -> None:
102
146
  """
103
147
  Clean temporary path.
104
148
 
105
149
  Parameters
106
150
  ----------
107
- pth : str
151
+ pth : SourcesOrListOfSources
108
152
  Path to clean.
109
153
 
110
154
  Returns
111
155
  -------
112
156
  None
113
157
  """
158
+ if isinstance(pth, list):
159
+ for p in pth:
160
+ shutil.rmtree(p, ignore_errors=True)
161
+ return
114
162
  shutil.rmtree(pth, ignore_errors=True)
115
163
 
116
164
 
@@ -3,7 +3,7 @@ from __future__ import annotations
3
3
  import typing
4
4
 
5
5
  from digitalhub.entities._commons.enums import EntityTypes
6
- from digitalhub.entities._operations.processor import processor
6
+ from digitalhub.entities._processors.context import context_processor
7
7
 
8
8
  if typing.TYPE_CHECKING:
9
9
  from digitalhub.entities.function._base.entity import Function
@@ -56,7 +56,7 @@ def new_function(
56
56
  >>> code_src="function.py",
57
57
  >>> handler="function-handler")
58
58
  """
59
- return processor.create_context_entity(
59
+ return context_processor.create_context_entity(
60
60
  project=project,
61
61
  name=name,
62
62
  kind=kind,
@@ -103,7 +103,7 @@ def get_function(
103
103
  >>> project="my-project",
104
104
  >>> entity_id="my-function-id")
105
105
  """
106
- return processor.read_context_entity(
106
+ return context_processor.read_context_entity(
107
107
  identifier,
108
108
  entity_type=ENTITY_TYPE,
109
109
  project=project,
@@ -143,7 +143,7 @@ def get_function_versions(
143
143
  >>> obj = get_function_versions("my-function-name"
144
144
  >>> project="my-project")
145
145
  """
146
- return processor.read_context_entity_versions(
146
+ return context_processor.read_context_entity_versions(
147
147
  identifier,
148
148
  entity_type=ENTITY_TYPE,
149
149
  project=project,
@@ -171,7 +171,7 @@ def list_functions(project: str, **kwargs) -> list[Function]:
171
171
  --------
172
172
  >>> objs = list_functions(project="my-project")
173
173
  """
174
- return processor.list_context_entities(
174
+ return context_processor.list_context_entities(
175
175
  project=project,
176
176
  entity_type=ENTITY_TYPE,
177
177
  **kwargs,
@@ -196,7 +196,7 @@ def import_function(file: str) -> Function:
196
196
  --------
197
197
  >>> obj = import_function("my-function.yaml")
198
198
  """
199
- return processor.import_executable_entity(file)
199
+ return context_processor.import_executable_entity(file)
200
200
 
201
201
 
202
202
  def load_function(file: str) -> Function:
@@ -217,7 +217,7 @@ def load_function(file: str) -> Function:
217
217
  --------
218
218
  >>> obj = load_function("my-function.yaml")
219
219
  """
220
- return processor.load_executable_entity(file)
220
+ return context_processor.load_executable_entity(file)
221
221
 
222
222
 
223
223
  def update_function(entity: Function) -> Function:
@@ -238,7 +238,7 @@ def update_function(entity: Function) -> Function:
238
238
  --------
239
239
  >>> obj = update_function(obj)
240
240
  """
241
- return processor.update_context_entity(
241
+ return context_processor.update_context_entity(
242
242
  project=entity.project,
243
243
  entity_type=entity.ENTITY_TYPE,
244
244
  entity_id=entity.id,
@@ -287,7 +287,7 @@ def delete_function(
287
287
  >>> project="my-project",
288
288
  >>> delete_all_versions=True)
289
289
  """
290
- return processor.delete_context_entity(
290
+ return context_processor.delete_context_entity(
291
291
  identifier=identifier,
292
292
  entity_type=ENTITY_TYPE,
293
293
  project=project,
@@ -4,6 +4,8 @@ import typing
4
4
 
5
5
  from digitalhub.entities._base.material.entity import MaterialEntity
6
6
  from digitalhub.entities._commons.enums import EntityTypes
7
+ from digitalhub.entities._commons.metrics import MetricType, set_metrics, validate_metric_value
8
+ from digitalhub.entities._processors.context import context_processor
7
9
 
8
10
  if typing.TYPE_CHECKING:
9
11
  from digitalhub.entities._base.entity.metadata import Metadata
@@ -32,3 +34,121 @@ class Model(MaterialEntity):
32
34
  super().__init__(project, name, uuid, kind, metadata, spec, status, user)
33
35
  self.spec: ModelSpec
34
36
  self.status: ModelStatus
37
+
38
+ def save(self, update: bool = False) -> Model:
39
+ """
40
+ Save entity into backend.
41
+
42
+ Parameters
43
+ ----------
44
+ update : bool
45
+ Flag to indicate update.
46
+
47
+ Returns
48
+ -------
49
+ Model
50
+ Entity saved.
51
+ """
52
+ obj: Model = super().save(update)
53
+ obj._get_metrics()
54
+ return obj
55
+
56
+ def log_metric(
57
+ self,
58
+ key: str,
59
+ value: MetricType,
60
+ overwrite: bool = False,
61
+ single_value: bool = False,
62
+ ) -> None:
63
+ """
64
+ Log metric into entity status.
65
+ A metric is named by a key and value (single number or list of numbers).
66
+ The metric by default is put in a list or appended to an existing list.
67
+ If single_value is True, the value will be a single number.
68
+
69
+ Parameters
70
+ ----------
71
+ key : str
72
+ Key of the metric.
73
+ value : MetricType
74
+ Value of the metric.
75
+ overwrite : bool
76
+ If True, overwrite existing metric.
77
+ single_value : bool
78
+ If True, value is a single value.
79
+
80
+ Returns
81
+ -------
82
+ None
83
+
84
+ Examples
85
+ --------
86
+ Log a new value in a list
87
+ >>> entity.log_metric("loss", 0.002)
88
+
89
+ Append a new value in a list
90
+ >>> entity.log_metric("loss", 0.0019)
91
+
92
+ Log a list of values and append them to existing metric:
93
+ >>> entity.log_metric("loss", [0.0018, 0.0015])
94
+
95
+ Log a single value (not represented as list):
96
+ >>> entity.log_metric("accuracy", 0.9, single_value=True)
97
+
98
+ Log a list of values and overwrite existing metric:
99
+ >>> entity.log_metric("accuracy", [0.8, 0.9], overwrite=True)
100
+ """
101
+ self._set_metrics(key, value, overwrite, single_value)
102
+ context_processor.update_metric(self.project, self.ENTITY_TYPE, self.id, key, self.status.metrics[key])
103
+
104
+ ##############################
105
+ # Helper methods
106
+ ##############################
107
+
108
+ def _get_metrics(self) -> None:
109
+ """
110
+ Get model metrics from backend.
111
+
112
+ Returns
113
+ -------
114
+ None
115
+ """
116
+ self.status.metrics = context_processor.read_metrics(
117
+ project=self.project,
118
+ entity_type=self.ENTITY_TYPE,
119
+ entity_id=self.id,
120
+ )
121
+
122
+ def _set_metrics(
123
+ self,
124
+ key: str,
125
+ value: MetricType,
126
+ overwrite: bool,
127
+ single_value: bool,
128
+ ) -> None:
129
+ """
130
+ Set model metrics.
131
+
132
+ Parameters
133
+ ----------
134
+ key : str
135
+ Key of the metric.
136
+ value : MetricType
137
+ Value of the metric.
138
+ overwrite : bool
139
+ If True, overwrite existing metric.
140
+ single_value : bool
141
+ If True, value is a single value.
142
+
143
+ Returns
144
+ -------
145
+ None
146
+ """
147
+ value = validate_metric_value(value)
148
+ self.status.metrics = set_metrics(
149
+ self.status.metrics,
150
+ key,
151
+ value,
152
+ overwrite,
153
+ single_value,
154
+ )
@@ -1,5 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
+ from typing import Optional
4
+
3
5
  from digitalhub.entities._base.material.spec import MaterialSpec, MaterialValidator
4
6
 
5
7
 
@@ -13,16 +15,12 @@ class ModelSpec(MaterialSpec):
13
15
  path: str,
14
16
  framework: str | None = None,
15
17
  algorithm: str | None = None,
16
- base_model: str | None = None,
17
18
  parameters: dict | None = None,
18
- metrics: dict | None = None,
19
19
  ) -> None:
20
- self.path = path
20
+ super().__init__(path)
21
21
  self.framework = framework
22
22
  self.algorithm = algorithm
23
- self.base_model = base_model
24
23
  self.parameters = parameters
25
- self.metrics = metrics
26
24
 
27
25
 
28
26
  class ModelValidator(MaterialValidator):
@@ -30,20 +28,11 @@ class ModelValidator(MaterialValidator):
30
28
  ModelValidator validator.
31
29
  """
32
30
 
33
- path: str
34
- """Path to the model."""
35
-
36
- framework: str = None
31
+ framework: Optional[str] = None
37
32
  """Model framework (e.g. 'pytorch')."""
38
33
 
39
- algorithm: str = None
34
+ algorithm: Optional[str] = None
40
35
  """Model algorithm (e.g. 'resnet')."""
41
36
 
42
- base_model: str = None
43
- """Base model."""
44
-
45
- parameters: dict = None
37
+ parameters: Optional[dict] = None
46
38
  """Model validator."""
47
-
48
- metrics: dict = None
49
- """Model metrics."""
@@ -7,3 +7,13 @@ class ModelStatus(MaterialStatus):
7
7
  """
8
8
  ModelStatus status.
9
9
  """
10
+
11
+ def __init__(
12
+ self,
13
+ state: str,
14
+ message: str | None = None,
15
+ files: list[dict] | None = None,
16
+ metrics: dict | None = None,
17
+ ):
18
+ super().__init__(state, message, files)
19
+ self.metrics = metrics if metrics is not None else {}
@@ -3,8 +3,9 @@ from __future__ import annotations
3
3
  import typing
4
4
 
5
5
  from digitalhub.entities._commons.enums import EntityTypes
6
- from digitalhub.entities._operations.processor import processor
6
+ from digitalhub.entities._processors.context import context_processor
7
7
  from digitalhub.entities.artifact.utils import eval_source, process_kwargs
8
+ from digitalhub.utils.types import SourcesOrListOfSources
8
9
 
9
10
  if typing.TYPE_CHECKING:
10
11
  from digitalhub.entities.model._base.entity import Model
@@ -60,7 +61,7 @@ def new_model(
60
61
  >>> kind="model",
61
62
  >>> path="s3://my-bucket/my-key")
62
63
  """
63
- return processor.create_context_entity(
64
+ return context_processor.create_context_entity(
64
65
  project=project,
65
66
  name=name,
66
67
  kind=kind,
@@ -77,7 +78,7 @@ def log_model(
77
78
  project: str,
78
79
  name: str,
79
80
  kind: str,
80
- source: list[str] | str,
81
+ source: SourcesOrListOfSources,
81
82
  path: str | None = None,
82
83
  **kwargs,
83
84
  ) -> Model:
@@ -92,7 +93,7 @@ def log_model(
92
93
  Object name.
93
94
  kind : str
94
95
  Kind the object.
95
- source : str
96
+ source : SourcesOrListOfSources
96
97
  Model location on local path.
97
98
  path : str
98
99
  Destination path of the model. If not provided, it's generated.
@@ -113,7 +114,7 @@ def log_model(
113
114
  """
114
115
  eval_source(source)
115
116
  kwargs = process_kwargs(project, name, source=source, path=path, **kwargs)
116
- return processor.log_material_entity(
117
+ return context_processor.log_material_entity(
117
118
  source=source,
118
119
  project=project,
119
120
  name=name,
@@ -157,7 +158,7 @@ def get_model(
157
158
  >>> project="my-project",
158
159
  >>> entity_id="my-model-id")
159
160
  """
160
- return processor.read_material_entity(
161
+ return context_processor.read_context_entity(
161
162
  identifier=identifier,
162
163
  entity_type=ENTITY_TYPE,
163
164
  project=project,
@@ -197,7 +198,7 @@ def get_model_versions(
197
198
  >>> objs = get_model_versions("my-model-name",
198
199
  >>> project="my-project")
199
200
  """
200
- return processor.read_material_entity_versions(
201
+ return context_processor.read_context_entity_versions(
201
202
  identifier=identifier,
202
203
  entity_type=ENTITY_TYPE,
203
204
  project=project,
@@ -225,7 +226,7 @@ def list_models(project: str, **kwargs) -> list[Model]:
225
226
  --------
226
227
  >>> objs = list_models(project="my-project")
227
228
  """
228
- return processor.list_material_entities(
229
+ return context_processor.list_context_entities(
229
230
  project=project,
230
231
  entity_type=ENTITY_TYPE,
231
232
  **kwargs,
@@ -250,7 +251,7 @@ def import_model(file: str) -> Model:
250
251
  --------
251
252
  >>> obj = import_model("my-model.yaml")
252
253
  """
253
- return processor.import_context_entity(file)
254
+ return context_processor.import_context_entity(file)
254
255
 
255
256
 
256
257
  def load_model(file: str) -> Model:
@@ -271,7 +272,7 @@ def load_model(file: str) -> Model:
271
272
  --------
272
273
  >>> obj = load_model("my-model.yaml")
273
274
  """
274
- return processor.load_context_entity(file)
275
+ return context_processor.load_context_entity(file)
275
276
 
276
277
 
277
278
  def update_model(entity: Model) -> Model:
@@ -292,7 +293,7 @@ def update_model(entity: Model) -> Model:
292
293
  --------
293
294
  >>> obj = get_model("store://my-model-key")
294
295
  """
295
- return processor.update_context_entity(
296
+ return context_processor.update_context_entity(
296
297
  project=entity.project,
297
298
  entity_type=entity.ENTITY_TYPE,
298
299
  entity_id=entity.id,
@@ -338,7 +339,7 @@ def delete_model(
338
339
  >>> project="my-project",
339
340
  >>> delete_all_versions=True)
340
341
  """
341
- return processor.delete_context_entity(
342
+ return context_processor.delete_context_entity(
342
343
  identifier=identifier,
343
344
  entity_type=ENTITY_TYPE,
344
345
  project=project,