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
@@ -17,7 +17,7 @@ class ProjectSpec(Spec):
17
17
 
18
18
  def __init__(
19
19
  self,
20
- context: str | None = None,
20
+ source: str | None = None,
21
21
  functions: list | None = None,
22
22
  artifacts: list | None = None,
23
23
  workflows: list | None = None,
@@ -26,7 +26,7 @@ class ProjectSpec(Spec):
26
26
  config: dict | None = None,
27
27
  **kwargs,
28
28
  ) -> None:
29
- self.context = context if context is not None else "./"
29
+ self.source = source if source is not None else "./"
30
30
  self.functions = functions if functions is not None else []
31
31
  self.artifacts = artifacts if artifacts is not None else []
32
32
  self.workflows = workflows if workflows is not None else []
@@ -40,8 +40,8 @@ class ProjectValidator(SpecValidator):
40
40
  ProjectValidator validator.
41
41
  """
42
42
 
43
- context: Optional[str] = None
44
- """The project's context."""
43
+ source: Optional[str] = None
44
+ """The project's source."""
45
45
 
46
46
  functions: Optional[list] = None
47
47
  """List of project's functions."""
@@ -6,9 +6,8 @@ from __future__ import annotations
6
6
 
7
7
  import typing
8
8
 
9
- from digitalhub.entities._commons.enums import EntityTypes
10
- from digitalhub.entities._processors.base import base_processor
11
- from digitalhub.entities._processors.context import context_processor
9
+ from digitalhub.entities._commons.enums import EntityKinds, EntityTypes
10
+ from digitalhub.entities._processors.processors import base_processor, context_processor
12
11
  from digitalhub.entities.project.utils import setup_project
13
12
  from digitalhub.utils.exceptions import BackendError
14
13
 
@@ -24,11 +23,9 @@ def new_project(
24
23
  name: str,
25
24
  description: str | None = None,
26
25
  labels: list[str] | None = None,
27
- local: bool = False,
28
26
  config: dict | None = None,
29
- context: str | None = None,
27
+ source: str | None = None,
30
28
  setup_kwargs: dict | None = None,
31
- **kwargs,
32
29
  ) -> Project:
33
30
  """
34
31
  Create a new object.
@@ -41,16 +38,12 @@ def new_project(
41
38
  Description of the object (human readable).
42
39
  labels : list[str]
43
40
  List of labels.
44
- local : bool
45
- If True, use local backend, if False use DHCore backend. Default to False.
46
41
  config : dict
47
42
  DHCore environment configuration.
48
- context : str
43
+ source : str
49
44
  The context local folder of the project.
50
45
  setup_kwargs : dict
51
46
  Setup keyword arguments passed to setup_project() function.
52
- **kwargs : dict
53
- Keyword arguments.
54
47
 
55
48
  Returns
56
49
  -------
@@ -61,26 +54,22 @@ def new_project(
61
54
  --------
62
55
  >>> obj = new_project("my-project")
63
56
  """
64
- if context is None:
65
- context = "./"
57
+ if source is None:
58
+ source = "./"
66
59
  obj = base_processor.create_project_entity(
67
60
  name=name,
68
- kind="project",
61
+ kind=EntityKinds.PROJECT_PROJECT.value,
69
62
  description=description,
70
63
  labels=labels,
71
- local=local,
72
64
  config=config,
73
- context=context,
74
- **kwargs,
65
+ source=source,
75
66
  )
76
67
  return setup_project(obj, setup_kwargs)
77
68
 
78
69
 
79
70
  def get_project(
80
71
  name: str,
81
- local: bool = False,
82
72
  setup_kwargs: dict | None = None,
83
- **kwargs,
84
73
  ) -> Project:
85
74
  """
86
75
  Retrieves project details from backend.
@@ -89,12 +78,8 @@ def get_project(
89
78
  ----------
90
79
  name : str
91
80
  The Project name.
92
- local : bool
93
- Flag to determine if backend is local.
94
81
  setup_kwargs : dict
95
82
  Setup keyword arguments passed to setup_project() function.
96
- **kwargs : dict
97
- Parameters to pass to the API call.
98
83
 
99
84
  Returns
100
85
  -------
@@ -108,16 +93,14 @@ def get_project(
108
93
  obj = base_processor.read_project_entity(
109
94
  entity_type=ENTITY_TYPE,
110
95
  entity_name=name,
111
- local=local,
112
- **kwargs,
113
96
  )
114
97
  return setup_project(obj, setup_kwargs)
115
98
 
116
99
 
117
100
  def import_project(
118
101
  file: str,
119
- local: bool = False,
120
102
  setup_kwargs: dict | None = None,
103
+ reset_id: bool = False,
121
104
  ) -> Project:
122
105
  """
123
106
  Import object from a YAML file and create a new object into the backend.
@@ -126,10 +109,10 @@ def import_project(
126
109
  ----------
127
110
  file : str
128
111
  Path to YAML file.
129
- local : bool
130
- Flag to determine if backend is local.
131
112
  setup_kwargs : dict
132
113
  Setup keyword arguments passed to setup_project() function.
114
+ reset_id : bool
115
+ Flag to determine if the ID of project entities should be reset.
133
116
 
134
117
  Returns
135
118
  -------
@@ -140,13 +123,15 @@ def import_project(
140
123
  --------
141
124
  >>> obj = import_project("my-project.yaml")
142
125
  """
143
- obj = base_processor.import_project_entity(file=file, local=local)
126
+ obj = base_processor.import_project_entity(
127
+ file=file,
128
+ reset_id=reset_id,
129
+ )
144
130
  return setup_project(obj, setup_kwargs)
145
131
 
146
132
 
147
133
  def load_project(
148
134
  file: str,
149
- local: bool = False,
150
135
  setup_kwargs: dict | None = None,
151
136
  ) -> Project:
152
137
  """
@@ -156,8 +141,6 @@ def load_project(
156
141
  ----------
157
142
  file : str
158
143
  Path to YAML file.
159
- local : bool
160
- Flag to determine if backend is local.
161
144
  setup_kwargs : dict
162
145
  Setup keyword arguments passed to setup_project() function.
163
146
 
@@ -170,36 +153,30 @@ def load_project(
170
153
  --------
171
154
  >>> obj = load_project("my-project.yaml")
172
155
  """
173
- obj = base_processor.load_project_entity(file=file, local=local)
156
+ obj = base_processor.load_project_entity(file=file)
174
157
  return setup_project(obj, setup_kwargs)
175
158
 
176
159
 
177
- def list_projects(local: bool = False, **kwargs) -> list[Project]:
160
+ def list_projects() -> list[Project]:
178
161
  """
179
162
  List projects in backend.
180
163
 
181
- Parameters
182
- ----------
183
- local : bool
184
- Flag to determine if backend is local.
185
- **kwargs : dict
186
- Parameters to pass to the API call.
187
164
 
188
165
  Returns
189
166
  -------
190
167
  list
191
168
  List of objects.
192
169
  """
193
- return base_processor.list_project_entities(local=local, **kwargs)
170
+ return base_processor.list_project_entities(ENTITY_TYPE)
194
171
 
195
172
 
196
173
  def get_or_create_project(
197
174
  name: str,
198
- local: bool = False,
175
+ description: str | None = None,
176
+ labels: list[str] | None = None,
199
177
  config: dict | None = None,
200
178
  context: str | None = None,
201
179
  setup_kwargs: dict | None = None,
202
- **kwargs,
203
180
  ) -> Project:
204
181
  """
205
182
  Try to get project. If not exists, create it.
@@ -208,8 +185,6 @@ def get_or_create_project(
208
185
  ----------
209
186
  name : str
210
187
  Project name.
211
- local : bool
212
- Flag to determine if backend is local.
213
188
  config : dict
214
189
  DHCore environment configuration.
215
190
  context : str
@@ -227,22 +202,20 @@ def get_or_create_project(
227
202
  try:
228
203
  return get_project(
229
204
  name,
230
- local=local,
231
205
  setup_kwargs=setup_kwargs,
232
- **kwargs,
233
206
  )
234
207
  except BackendError:
235
208
  return new_project(
236
209
  name,
237
- local=local,
210
+ description=description,
211
+ labels=labels,
238
212
  config=config,
239
213
  setup_kwargs=setup_kwargs,
240
- context=context,
241
- **kwargs,
214
+ source=context,
242
215
  )
243
216
 
244
217
 
245
- def update_project(entity: Project, **kwargs) -> Project:
218
+ def update_project(entity: Project) -> Project:
246
219
  """
247
220
  Update object. Note that object spec are immutable.
248
221
 
@@ -250,8 +223,6 @@ def update_project(entity: Project, **kwargs) -> Project:
250
223
  ----------
251
224
  entity : Project
252
225
  Object to update.
253
- **kwargs : dict
254
- Parameters to pass to the API call.
255
226
 
256
227
  Returns
257
228
  -------
@@ -266,8 +237,6 @@ def update_project(entity: Project, **kwargs) -> Project:
266
237
  entity_type=entity.ENTITY_TYPE,
267
238
  entity_name=entity.name,
268
239
  entity_dict=entity.to_dict(),
269
- local=entity._client.is_local(),
270
- **kwargs,
271
240
  )
272
241
 
273
242
 
@@ -275,8 +244,6 @@ def delete_project(
275
244
  name: str,
276
245
  cascade: bool = True,
277
246
  clean_context: bool = True,
278
- local: bool = False,
279
- **kwargs,
280
247
  ) -> dict:
281
248
  """
282
249
  Delete a project.
@@ -289,10 +256,6 @@ def delete_project(
289
256
  Flag to determine if delete is cascading.
290
257
  clean_context : bool
291
258
  Flag to determine if context will be deleted.
292
- local : bool
293
- Flag to determine if backend is local.
294
- **kwargs : dict
295
- Parameters to pass to the API call.
296
259
 
297
260
  Returns
298
261
  -------
@@ -306,10 +269,8 @@ def delete_project(
306
269
  return base_processor.delete_project_entity(
307
270
  entity_type=ENTITY_TYPE,
308
271
  entity_name=name,
309
- local=local,
310
272
  cascade=cascade,
311
273
  clean_context=clean_context,
312
- **kwargs,
313
274
  )
314
275
 
315
276
 
@@ -323,7 +284,6 @@ def search_entity(
323
284
  updated: str | None = None,
324
285
  description: str | None = None,
325
286
  labels: list[str] | None = None,
326
- **kwargs,
327
287
  ) -> list[ContextEntity]:
328
288
  """
329
289
  Search objects from backend.
@@ -348,13 +308,11 @@ def search_entity(
348
308
  Entity description.
349
309
  labels : list[str]
350
310
  Entity labels.
351
- **kwargs : dict
352
- Parameters to pass to the API call.
353
311
 
354
- Returns
355
- -------
356
- list[ContextEntity]
357
- List of object instances.
312
+ Returns
313
+ -------
314
+ list[ContextEntity]
315
+ List of object instances.
358
316
  """
359
317
  return context_processor.search_entity(
360
318
  project_name,
@@ -366,5 +324,4 @@ def search_entity(
366
324
  updated=updated,
367
325
  description=description,
368
326
  labels=labels,
369
- **kwargs,
370
327
  )
@@ -12,6 +12,10 @@ from digitalhub.utils.generic_utils import import_function
12
12
  if typing.TYPE_CHECKING:
13
13
  from digitalhub.entities.project._base.entity import Project
14
14
 
15
+ CHECK_FILENAME = ".CHECK"
16
+ SETUP_MODULE = "setup_project.py"
17
+ SETUP_FUNCTION = "setup"
18
+
15
19
 
16
20
  def setup_project(project: Project, setup_kwargs: dict | None = None) -> Project:
17
21
  """
@@ -30,10 +34,10 @@ def setup_project(project: Project, setup_kwargs: dict | None = None) -> Project
30
34
  Set up project.
31
35
  """
32
36
  setup_kwargs = setup_kwargs if setup_kwargs is not None else {}
33
- check_pth = Path(project.spec.context, ".CHECK")
34
- setup_pth = Path(project.spec.context, "setup_project.py")
37
+ check_pth = Path(project.spec.source, CHECK_FILENAME)
38
+ setup_pth = Path(project.spec.source, SETUP_MODULE)
35
39
  if setup_pth.exists() and not check_pth.exists():
36
- setup_fnc = import_function(setup_pth, "setup")
40
+ setup_fnc = import_function(setup_pth, SETUP_FUNCTION)
37
41
  project = setup_fnc(project, **setup_kwargs)
38
42
  check_pth.touch()
39
43
  return project
@@ -90,10 +90,6 @@ class RunBuilder(UnversionedBuilder, RuntimeEntityBuilder):
90
90
  ----------
91
91
  task : str
92
92
  Task string.
93
-
94
- Returns
95
- -------
96
- None
97
93
  """
98
94
  task_kind = task.split("://")[0]
99
95
  if task_kind not in self.get_all_kinds():
@@ -10,8 +10,9 @@ import typing
10
10
  from digitalhub.entities._base.unversioned.entity import UnversionedEntity
11
11
  from digitalhub.entities._commons.enums import EntityTypes, State
12
12
  from digitalhub.entities._commons.metrics import MetricType, set_metrics, validate_metric_value
13
- from digitalhub.entities._processors.context import context_processor
14
- from digitalhub.factory.factory import factory
13
+ from digitalhub.entities._processors.processors import context_processor
14
+ from digitalhub.factory.entity import entity_factory
15
+ from digitalhub.factory.runtime import runtime_factory
15
16
  from digitalhub.utils.exceptions import EntityError
16
17
  from digitalhub.utils.logger import LOGGER
17
18
 
@@ -51,15 +52,11 @@ class Run(UnversionedEntity):
51
52
  def build(self) -> None:
52
53
  """
53
54
  Build run.
54
-
55
- Returns
56
- -------
57
- None
58
55
  """
59
56
  executable = self._get_executable()
60
57
  task = self._get_task()
61
58
  new_spec = self._get_runtime().build(executable, task, self.to_dict())
62
- self.spec = factory.build_spec(self.kind, **new_spec)
59
+ self.spec = entity_factory.build_spec(self.kind, **new_spec)
63
60
  self._set_state(State.BUILT.value)
64
61
  self.save(update=True)
65
62
 
@@ -141,10 +138,6 @@ class Run(UnversionedEntity):
141
138
  def stop(self) -> None:
142
139
  """
143
140
  Stop run.
144
-
145
- Returns
146
- -------
147
- None
148
141
  """
149
142
  if not self.spec.local_execution:
150
143
  return context_processor.stop_entity(self.project, self.ENTITY_TYPE, self.id)
@@ -152,10 +145,6 @@ class Run(UnversionedEntity):
152
145
  def resume(self) -> None:
153
146
  """
154
147
  Resume run.
155
-
156
- Returns
157
- -------
158
- None
159
148
  """
160
149
  if not self.spec.local_execution:
161
150
  return context_processor.resume_entity(self.project, self.ENTITY_TYPE, self.id)
@@ -184,10 +173,6 @@ class Run(UnversionedEntity):
184
173
  single_value : bool
185
174
  If True, value is a single value.
186
175
 
187
- Returns
188
- -------
189
- None
190
-
191
176
  Examples
192
177
  --------
193
178
  Log a new value in a list
@@ -197,13 +182,27 @@ class Run(UnversionedEntity):
197
182
  >>> entity.log_metric("loss", 0.0019)
198
183
 
199
184
  Log a list of values and append them to existing metric:
200
- >>> entity.log_metric("loss", [0.0018, 0.0015])
185
+ >>> entity.log_metric(
186
+ ... "loss",
187
+ ... [
188
+ ... 0.0018,
189
+ ... 0.0015,
190
+ ... ],
191
+ ... )
201
192
 
202
193
  Log a single value (not represented as list):
203
- >>> entity.log_metric("accuracy", 0.9, single_value=True)
194
+ >>> entity.log_metric(
195
+ ... "accuracy",
196
+ ... 0.9,
197
+ ... single_value=True,
198
+ ... )
204
199
 
205
200
  Log a list of values and overwrite existing metric:
206
- >>> entity.log_metric("accuracy", [0.8, 0.9], overwrite=True)
201
+ >>> entity.log_metric(
202
+ ... "accuracy",
203
+ ... [0.8, 0.9],
204
+ ... overwrite=True,
205
+ ... )
207
206
  """
208
207
  self._set_metrics(key, value, overwrite, single_value)
209
208
  context_processor.update_metric(self.project, self.ENTITY_TYPE, self.id, key, self.status.metrics[key])
@@ -224,19 +223,59 @@ class Run(UnversionedEntity):
224
223
  overwrite : bool
225
224
  If True, overwrite existing metrics.
226
225
 
227
- Returns
228
- -------
229
- None
226
+ Examples
227
+ --------
228
+ Log multiple metrics at once
229
+ >>> entity.log_metrics(
230
+ ... {
231
+ ... "loss": 0.002,
232
+ ... "accuracy": 0.95,
233
+ ... }
234
+ ... )
235
+
236
+ Log metrics with lists and single values
237
+ >>> entity.log_metrics(
238
+ ... {
239
+ ... "loss": [
240
+ ... 0.1,
241
+ ... 0.05,
242
+ ... ],
243
+ ... "epoch": 10,
244
+ ... }
245
+ ... )
246
+
247
+ Append to existing metrics (default behavior)
248
+ >>> entity.log_metrics(
249
+ ... {
250
+ ... "loss": 0.001,
251
+ ... "accuracy": 0.96,
252
+ ... }
253
+ ... ) # Appends to existing
254
+
255
+ Overwrite existing metrics
256
+ >>> entity.log_metrics(
257
+ ... {
258
+ ... "loss": 0.0005,
259
+ ... "accuracy": 0.98,
260
+ ... },
261
+ ... overwrite=True,
262
+ ... )
230
263
 
231
264
  See also
232
265
  --------
233
266
  log_metric
234
267
  """
235
268
  for key, value in metrics.items():
269
+ # For lists, use log_metric which handles appending correctly
236
270
  if isinstance(value, list):
237
271
  self.log_metric(key, value, overwrite)
272
+
273
+ # For single values, check if we should append or create new
238
274
  else:
239
- self.log_metric(key, value, overwrite, single_value=True)
275
+ if not overwrite and key in self.status.metrics:
276
+ self.log_metric(key, value)
277
+ else:
278
+ self.log_metric(key, value, overwrite, single_value=True)
240
279
 
241
280
  ##############################
242
281
  # Helpers
@@ -245,19 +284,11 @@ class Run(UnversionedEntity):
245
284
  def _setup_execution(self) -> None:
246
285
  """
247
286
  Setup run execution.
248
-
249
- Returns
250
- -------
251
- None
252
287
  """
253
288
 
254
289
  def _start_execution(self) -> None:
255
290
  """
256
291
  Start run execution.
257
-
258
- Returns
259
- -------
260
- None
261
292
  """
262
293
  self._context().set_run(f"{self.key}:{self.id}")
263
294
  if self.spec.local_execution:
@@ -269,10 +300,6 @@ class Run(UnversionedEntity):
269
300
  def _finish_execution(self) -> None:
270
301
  """
271
302
  Finish run execution.
272
-
273
- Returns
274
- -------
275
- None
276
303
  """
277
304
  self._context().unset_run()
278
305
 
@@ -285,7 +312,7 @@ class Run(UnversionedEntity):
285
312
  bool
286
313
  True if run is in runnable state, False otherwise.
287
314
  """
288
- return (self.status.state == State.BUILT.value) or (self.status.state == State.STOPPED.value)
315
+ return self.status.state in (State.BUILT.value, State.STOPPED.value)
289
316
 
290
317
  def _set_status(self, status: dict) -> None:
291
318
  """
@@ -295,12 +322,8 @@ class Run(UnversionedEntity):
295
322
  ----------
296
323
  status : dict
297
324
  Status to set.
298
-
299
- Returns
300
- -------
301
- None
302
325
  """
303
- self.status: RunStatus = factory.build_status(self.kind, **status)
326
+ self.status: RunStatus = entity_factory.build_status(self.kind, **status)
304
327
 
305
328
  def _set_state(self, state: str) -> None:
306
329
  """
@@ -310,10 +333,6 @@ class Run(UnversionedEntity):
310
333
  ----------
311
334
  state : str
312
335
  State to set.
313
-
314
- Returns
315
- -------
316
- None
317
336
  """
318
337
  self.status.state = state
319
338
 
@@ -325,10 +344,6 @@ class Run(UnversionedEntity):
325
344
  ----------
326
345
  message : str
327
346
  Message to set.
328
-
329
- Returns
330
- -------
331
- None
332
347
  """
333
348
  self.status.message = message
334
349
 
@@ -341,7 +356,7 @@ class Run(UnversionedEntity):
341
356
  Runtime
342
357
  Runtime object.
343
358
  """
344
- return factory.build_runtime(self.kind, self.project)
359
+ return runtime_factory.build_runtime(self.kind, self.project)
345
360
 
346
361
  def _get_executable(self) -> dict:
347
362
  """
@@ -353,8 +368,8 @@ class Run(UnversionedEntity):
353
368
  dict
354
369
  Executable (function or workflow) from backend.
355
370
  """
356
- exec_kind = factory.get_executable_kind(self.kind)
357
- exec_type = factory.get_entity_type_from_kind(exec_kind)
371
+ exec_kind = entity_factory.get_executable_kind(self.kind)
372
+ exec_type = entity_factory.get_entity_type_from_kind(exec_kind)
358
373
  string_to_split = getattr(self.spec, exec_type)
359
374
  exec_name, exec_id = string_to_split.split("://")[-1].split("/")[-1].split(":")
360
375
  return context_processor.read_context_entity(
@@ -384,10 +399,6 @@ class Run(UnversionedEntity):
384
399
  def _get_metrics(self) -> None:
385
400
  """
386
401
  Get model metrics from backend.
387
-
388
- Returns
389
- -------
390
- None
391
402
  """
392
403
  self.status.metrics = context_processor.read_metrics(
393
404
  project=self.project,
@@ -415,10 +426,6 @@ class Run(UnversionedEntity):
415
426
  If True, overwrite existing metric.
416
427
  single_value : bool
417
428
  If True, value is a single value.
418
-
419
- Returns
420
- -------
421
- None
422
429
  """
423
430
  value = validate_metric_value(value)
424
431
  self.status.metrics = set_metrics(