digitalhub 0.8.0b15__py3-none-any.whl → 0.9.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 (135) hide show
  1. digitalhub/__init__.py +19 -2
  2. digitalhub/client/_base/api_builder.py +16 -0
  3. digitalhub/client/_base/client.py +67 -0
  4. digitalhub/client/_base/key_builder.py +52 -0
  5. digitalhub/client/api.py +2 -38
  6. digitalhub/client/dhcore/api_builder.py +100 -0
  7. digitalhub/client/dhcore/client.py +100 -48
  8. digitalhub/client/dhcore/enums.py +27 -0
  9. digitalhub/client/dhcore/env.py +4 -2
  10. digitalhub/client/dhcore/key_builder.py +58 -0
  11. digitalhub/client/dhcore/utils.py +17 -17
  12. digitalhub/client/local/api_builder.py +100 -0
  13. digitalhub/client/local/client.py +22 -0
  14. digitalhub/client/local/key_builder.py +58 -0
  15. digitalhub/context/api.py +3 -38
  16. digitalhub/context/builder.py +10 -23
  17. digitalhub/context/context.py +20 -92
  18. digitalhub/entities/_base/context/entity.py +30 -22
  19. digitalhub/entities/_base/entity/_constructors/metadata.py +12 -1
  20. digitalhub/entities/_base/entity/_constructors/name.py +1 -1
  21. digitalhub/entities/_base/entity/_constructors/spec.py +1 -1
  22. digitalhub/entities/_base/entity/_constructors/status.py +3 -2
  23. digitalhub/entities/_base/entity/_constructors/uuid.py +1 -1
  24. digitalhub/entities/_base/entity/builder.py +6 -1
  25. digitalhub/entities/_base/entity/entity.py +32 -10
  26. digitalhub/entities/_base/entity/metadata.py +22 -0
  27. digitalhub/entities/_base/entity/spec.py +7 -2
  28. digitalhub/entities/_base/executable/entity.py +8 -8
  29. digitalhub/entities/_base/material/entity.py +49 -17
  30. digitalhub/entities/_base/material/status.py +0 -31
  31. digitalhub/entities/_base/material/utils.py +106 -0
  32. digitalhub/entities/_base/project/entity.py +341 -0
  33. digitalhub/entities/_base/unversioned/entity.py +3 -24
  34. digitalhub/entities/_base/versioned/entity.py +2 -26
  35. digitalhub/entities/_commons/enums.py +103 -0
  36. digitalhub/entities/_commons/utils.py +83 -0
  37. digitalhub/entities/_operations/processor.py +1873 -0
  38. digitalhub/entities/artifact/_base/builder.py +1 -1
  39. digitalhub/entities/artifact/_base/entity.py +1 -1
  40. digitalhub/entities/artifact/artifact/builder.py +2 -1
  41. digitalhub/entities/artifact/crud.py +46 -29
  42. digitalhub/entities/artifact/utils.py +62 -0
  43. digitalhub/entities/dataitem/_base/builder.py +1 -1
  44. digitalhub/entities/dataitem/_base/entity.py +6 -6
  45. digitalhub/entities/dataitem/crud.py +50 -66
  46. digitalhub/entities/dataitem/dataitem/builder.py +2 -1
  47. digitalhub/entities/dataitem/iceberg/builder.py +2 -1
  48. digitalhub/entities/dataitem/table/builder.py +2 -1
  49. digitalhub/entities/dataitem/table/entity.py +5 -10
  50. digitalhub/entities/dataitem/table/models.py +4 -5
  51. digitalhub/entities/dataitem/utils.py +137 -0
  52. digitalhub/entities/function/_base/builder.py +1 -1
  53. digitalhub/entities/function/_base/entity.py +6 -2
  54. digitalhub/entities/function/crud.py +36 -17
  55. digitalhub/entities/model/_base/builder.py +1 -1
  56. digitalhub/entities/model/_base/entity.py +1 -1
  57. digitalhub/entities/model/crud.py +46 -29
  58. digitalhub/entities/model/huggingface/builder.py +2 -1
  59. digitalhub/entities/model/huggingface/spec.py +4 -2
  60. digitalhub/entities/model/mlflow/builder.py +2 -1
  61. digitalhub/entities/model/mlflow/models.py +17 -9
  62. digitalhub/entities/model/mlflow/spec.py +6 -1
  63. digitalhub/entities/model/mlflow/utils.py +4 -2
  64. digitalhub/entities/model/model/builder.py +2 -1
  65. digitalhub/entities/model/sklearn/builder.py +2 -1
  66. digitalhub/entities/model/utils.py +62 -0
  67. digitalhub/entities/project/_base/builder.py +2 -2
  68. digitalhub/entities/project/_base/entity.py +82 -272
  69. digitalhub/entities/project/crud.py +110 -89
  70. digitalhub/entities/project/utils.py +35 -0
  71. digitalhub/entities/run/_base/builder.py +3 -1
  72. digitalhub/entities/run/_base/entity.py +52 -54
  73. digitalhub/entities/run/_base/spec.py +15 -7
  74. digitalhub/entities/run/crud.py +35 -17
  75. digitalhub/entities/secret/_base/builder.py +2 -2
  76. digitalhub/entities/secret/_base/entity.py +4 -10
  77. digitalhub/entities/secret/crud.py +36 -21
  78. digitalhub/entities/task/_base/builder.py +14 -14
  79. digitalhub/entities/task/_base/entity.py +21 -14
  80. digitalhub/entities/task/_base/models.py +35 -6
  81. digitalhub/entities/task/_base/spec.py +50 -13
  82. digitalhub/entities/task/_base/utils.py +18 -0
  83. digitalhub/entities/task/crud.py +35 -15
  84. digitalhub/entities/workflow/_base/builder.py +1 -1
  85. digitalhub/entities/workflow/_base/entity.py +22 -6
  86. digitalhub/entities/workflow/crud.py +36 -17
  87. digitalhub/factory/utils.py +1 -1
  88. digitalhub/readers/_base/reader.py +2 -2
  89. digitalhub/readers/_commons/enums.py +13 -0
  90. digitalhub/readers/api.py +3 -2
  91. digitalhub/readers/factory.py +12 -6
  92. digitalhub/readers/pandas/reader.py +20 -8
  93. digitalhub/runtimes/_base.py +0 -7
  94. digitalhub/runtimes/enums.py +12 -0
  95. digitalhub/stores/_base/store.py +59 -11
  96. digitalhub/stores/builder.py +5 -5
  97. digitalhub/stores/local/store.py +43 -4
  98. digitalhub/stores/remote/store.py +31 -5
  99. digitalhub/stores/s3/store.py +136 -57
  100. digitalhub/stores/sql/store.py +122 -47
  101. digitalhub/utils/exceptions.py +6 -0
  102. digitalhub/utils/file_utils.py +60 -2
  103. digitalhub/utils/generic_utils.py +45 -4
  104. digitalhub/utils/io_utils.py +18 -0
  105. digitalhub/utils/s3_utils.py +17 -0
  106. digitalhub/utils/uri_utils.py +153 -15
  107. {digitalhub-0.8.0b15.dist-info → digitalhub-0.9.0.dist-info}/LICENSE.txt +1 -1
  108. {digitalhub-0.8.0b15.dist-info → digitalhub-0.9.0.dist-info}/METADATA +11 -11
  109. {digitalhub-0.8.0b15.dist-info → digitalhub-0.9.0.dist-info}/RECORD +117 -115
  110. {digitalhub-0.8.0b15.dist-info → digitalhub-0.9.0.dist-info}/WHEEL +1 -1
  111. test/local/instances/test_validate.py +55 -0
  112. test/testkfp.py +4 -1
  113. digitalhub/datastores/_base/datastore.py +0 -85
  114. digitalhub/datastores/api.py +0 -37
  115. digitalhub/datastores/builder.py +0 -110
  116. digitalhub/datastores/local/datastore.py +0 -50
  117. digitalhub/datastores/remote/__init__.py +0 -0
  118. digitalhub/datastores/remote/datastore.py +0 -31
  119. digitalhub/datastores/s3/__init__.py +0 -0
  120. digitalhub/datastores/s3/datastore.py +0 -46
  121. digitalhub/datastores/sql/__init__.py +0 -0
  122. digitalhub/datastores/sql/datastore.py +0 -68
  123. digitalhub/entities/_base/api_utils.py +0 -620
  124. digitalhub/entities/_base/crud.py +0 -468
  125. digitalhub/entities/function/_base/models.py +0 -118
  126. digitalhub/entities/utils/__init__.py +0 -0
  127. digitalhub/entities/utils/api.py +0 -346
  128. digitalhub/entities/utils/entity_types.py +0 -19
  129. digitalhub/entities/utils/state.py +0 -31
  130. digitalhub/entities/utils/utils.py +0 -202
  131. /digitalhub/{context → entities/_base/project}/__init__.py +0 -0
  132. /digitalhub/{datastores → entities/_commons}/__init__.py +0 -0
  133. /digitalhub/{datastores/_base → entities/_operations}/__init__.py +0 -0
  134. /digitalhub/{datastores/local → readers/_commons}/__init__.py +0 -0
  135. {digitalhub-0.8.0b15.dist-info → digitalhub-0.9.0.dist-info}/top_level.txt +0 -0
@@ -1,6 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import os
4
+ from pathlib import Path
4
5
 
5
6
  # Use env user as fallback in the API calls
6
7
  try:
@@ -13,9 +14,10 @@ except Exception:
13
14
  # but refresh token is only available once. Is it's used, we cannot
14
15
  # overwrite it with coder, so we need to store the new one in a file,
15
16
  # preserved for jupyter restart
16
- ENV_FILE = ".dhcore"
17
+ ENV_FILE = Path.home() / ".dhcore"
17
18
 
18
19
 
19
20
  # API levels that are supported
20
21
  MAX_API_LEVEL = 20
21
- MIN_API_LEVEL = 8
22
+ MIN_API_LEVEL = 9
23
+ LIB_VERSION = 9
@@ -0,0 +1,58 @@
1
+ from __future__ import annotations
2
+
3
+ from digitalhub.client._base.key_builder import ClientKeyBuilder
4
+
5
+
6
+ class ClientDHCoreKeyBuilder(ClientKeyBuilder):
7
+ """
8
+ Class that build the key of entities.
9
+ """
10
+
11
+ def base_entity_key(self, entity_id: str) -> str:
12
+ """
13
+ Build for base entity key.
14
+
15
+ Parameters
16
+ ----------
17
+ entity_id : str
18
+ Entity id.
19
+
20
+ Returns
21
+ -------
22
+ str
23
+ Key.
24
+ """
25
+ return f"store://{entity_id}"
26
+
27
+ def context_entity_key(
28
+ self,
29
+ project: str,
30
+ entity_type: str,
31
+ entity_kind: str,
32
+ entity_name: str,
33
+ entity_id: str | None = None,
34
+ ) -> str:
35
+ """
36
+ Build for context entity key.
37
+
38
+ Parameters
39
+ ----------
40
+ project : str
41
+ Project name.
42
+ entity_type : str
43
+ Entity type.
44
+ entity_kind : str
45
+ Entity kind.
46
+ entity_name : str
47
+ Entity name.
48
+ entity_id : str
49
+ Entity ID.
50
+
51
+ Returns
52
+ -------
53
+ str
54
+ Key.
55
+ """
56
+ if entity_id is None:
57
+ return f"store://{project}/{entity_type}/{entity_kind}/{entity_name}"
58
+ return f"store://{project}/{entity_type}/{entity_kind}/{entity_name}:{entity_id}"
@@ -3,7 +3,8 @@ from __future__ import annotations
3
3
  import os
4
4
  import typing
5
5
 
6
- from digitalhub.client.api import check_client_exists, get_client
6
+ from digitalhub.client.api import get_client
7
+ from digitalhub.client.dhcore.enums import AuthType, DhcoreEnvVar
7
8
 
8
9
  if typing.TYPE_CHECKING:
9
10
  from digitalhub.client.dhcore.client import ClientDHCore
@@ -43,20 +44,19 @@ def set_dhcore_env(
43
44
  None
44
45
  """
45
46
  if endpoint is not None:
46
- os.environ["DHCORE_ENDPOINT"] = endpoint
47
+ os.environ[DhcoreEnvVar.ENDPOINT.value] = endpoint
47
48
  if user is not None:
48
- os.environ["DHCORE_USER"] = user
49
+ os.environ[DhcoreEnvVar.USER.value] = user
49
50
  if password is not None:
50
- os.environ["DHCORE_PASSWORD"] = password
51
+ os.environ[DhcoreEnvVar.PASSWORD.value] = password
51
52
  if access_token is not None:
52
- os.environ["DHCORE_ACCESS_TOKEN"] = access_token
53
+ os.environ[DhcoreEnvVar.ACCESS_TOKEN.value] = access_token
53
54
  if refresh_token is not None:
54
- os.environ["DHCORE_REFRESH_TOKEN"] = refresh_token
55
+ os.environ[DhcoreEnvVar.REFRESH_TOKEN.value] = refresh_token
55
56
  if client_id is not None:
56
- os.environ["DHCORE_CLIENT_ID"] = client_id
57
+ os.environ[DhcoreEnvVar.CLIENT_ID.value] = client_id
57
58
 
58
- if check_client_exists(local=False):
59
- update_client_from_env()
59
+ update_client_from_env()
60
60
 
61
61
 
62
62
  def update_client_from_env() -> None:
@@ -70,16 +70,16 @@ def update_client_from_env() -> None:
70
70
  client: ClientDHCore = get_client(local=False)
71
71
 
72
72
  # Update endpoint
73
- endpoint = os.getenv("DHCORE_ENDPOINT")
73
+ endpoint = os.getenv(DhcoreEnvVar.ENDPOINT.value)
74
74
  if endpoint is not None:
75
75
  client._endpoint_core = endpoint
76
76
 
77
77
  # Update auth
78
78
 
79
79
  # If token is set, it will override the other auth options
80
- access_token = os.getenv("DHCORE_ACCESS_TOKEN")
81
- refresh_token = os.getenv("DHCORE_REFRESH_TOKEN")
82
- client_id = os.getenv("DHCORE_CLIENT_ID")
80
+ access_token = os.getenv(DhcoreEnvVar.ACCESS_TOKEN.value)
81
+ refresh_token = os.getenv(DhcoreEnvVar.REFRESH_TOKEN.value)
82
+ client_id = os.getenv(DhcoreEnvVar.CLIENT_ID.value)
83
83
 
84
84
  if access_token is not None:
85
85
  if refresh_token is not None:
@@ -87,16 +87,16 @@ def update_client_from_env() -> None:
87
87
  if client_id is not None:
88
88
  client._client_id = client_id
89
89
  client._access_token = access_token
90
- client._auth_type = "oauth2"
90
+ client._auth_type = AuthType.OAUTH2.value
91
91
  return
92
92
 
93
93
  # Otherwise, if user and password are set, basic auth will be used
94
- username = os.getenv("DHCORE_USER")
95
- password = os.getenv("DHCORE_PASSWORD")
94
+ username = os.getenv(DhcoreEnvVar.USER.value)
95
+ password = os.getenv(DhcoreEnvVar.PASSWORD.value)
96
96
  if username is not None and password is not None:
97
97
  client._user = username
98
98
  client._password = password
99
- client._auth_type = "basic"
99
+ client._auth_type = AuthType.BASIC.value
100
100
 
101
101
 
102
102
  def refresh_token() -> None:
@@ -0,0 +1,100 @@
1
+ from __future__ import annotations
2
+
3
+ from digitalhub.client._base.api_builder import ClientApiBuilder
4
+ from digitalhub.entities._commons.enums import ApiCategories, BackendOperations
5
+ from digitalhub.utils.exceptions import BackendError
6
+
7
+ API_BASE = "/api/v1"
8
+ API_CONTEXT = f"{API_BASE}/-"
9
+
10
+
11
+ class ClientLocalApiBuilder(ClientApiBuilder):
12
+ """
13
+ This class is used to build the API for the Local client.
14
+ """
15
+
16
+ def build_api(self, category: str, operation: str, **kwargs) -> str:
17
+ """
18
+ Build the API for the client.
19
+
20
+ Parameters
21
+ ----------
22
+ category : str
23
+ API category.
24
+ operation : str
25
+ API operation.
26
+ **kwargs : dict
27
+ Additional parameters.
28
+
29
+ Returns
30
+ -------
31
+ str
32
+ API formatted.
33
+ """
34
+ if category == ApiCategories.BASE.value:
35
+ return self.build_api_base(operation, **kwargs)
36
+ return self.build_api_context(operation, **kwargs)
37
+
38
+ def build_api_base(self, operation: str, **kwargs) -> str:
39
+ """
40
+ Build the base API for the client.
41
+
42
+ Parameters
43
+ ----------
44
+ operation : str
45
+ API operation.
46
+ **kwargs : dict
47
+ Additional parameters.
48
+
49
+ Returns
50
+ -------
51
+ str
52
+ API formatted.
53
+ """
54
+ entity_type = kwargs["entity_type"] + "s"
55
+ if operation in (
56
+ BackendOperations.CREATE.value,
57
+ BackendOperations.LIST.value,
58
+ ):
59
+ return f"{API_BASE}/{entity_type}"
60
+ elif operation in (
61
+ BackendOperations.READ.value,
62
+ BackendOperations.UPDATE.value,
63
+ BackendOperations.DELETE.value,
64
+ ):
65
+ return f"{API_BASE}/{entity_type}/{kwargs['entity_name']}"
66
+ elif operation == BackendOperations.SHARE.value:
67
+ raise BackendError("Share API not implemented for Local.")
68
+ raise BackendError(f"Invalid operation '{operation}' for entity type '{entity_type}' in Local.")
69
+
70
+ def build_api_context(self, operation: str, **kwargs) -> str:
71
+ """
72
+ Build the context API for the client.
73
+ """
74
+ entity_type = kwargs["entity_type"] + "s"
75
+ project = kwargs["project"]
76
+ if operation in (
77
+ BackendOperations.CREATE.value,
78
+ BackendOperations.LIST.value,
79
+ ):
80
+ return f"{API_CONTEXT}/{project}/{entity_type}"
81
+ elif operation in (
82
+ BackendOperations.READ.value,
83
+ BackendOperations.UPDATE.value,
84
+ BackendOperations.DELETE.value,
85
+ ):
86
+ return f"{API_CONTEXT}/{project}/{entity_type}/{kwargs['entity_id']}"
87
+ elif operation == BackendOperations.LOGS.value:
88
+ raise BackendError("Logs run API not implemented for Local.")
89
+ elif operation == BackendOperations.STOP.value:
90
+ raise BackendError("Stop run API not implemented for Local.")
91
+ elif operation == BackendOperations.RESUME.value:
92
+ raise BackendError("Resume run API not implemented for Local.")
93
+ elif operation == BackendOperations.DATA.value:
94
+ raise BackendError("Secret API (read/set value) not implemented for Local.")
95
+ elif operation == BackendOperations.FILES.value:
96
+ raise BackendError("Files API not implemented for Local.")
97
+ elif operation == BackendOperations.SEARCH.value:
98
+ raise BackendError("Search API not implemented for Local.")
99
+
100
+ raise BackendError(f"Invalid operation '{operation}' for entity type '{entity_type}' in Local.")
@@ -4,6 +4,8 @@ from copy import deepcopy
4
4
  from datetime import datetime, timezone
5
5
 
6
6
  from digitalhub.client._base.client import Client
7
+ from digitalhub.client.local.api_builder import ClientLocalApiBuilder
8
+ from digitalhub.client.local.key_builder import ClientLocalKeyBuilder
7
9
  from digitalhub.utils.exceptions import BackendError
8
10
 
9
11
 
@@ -22,6 +24,8 @@ class ClientLocal(Client):
22
24
 
23
25
  def __init__(self) -> None:
24
26
  super().__init__()
27
+ self._api_builder = ClientLocalApiBuilder()
28
+ self._key_builder = ClientLocalKeyBuilder()
25
29
  self._db: dict[str, dict[str, dict]] = {}
26
30
 
27
31
  ##############################
@@ -349,6 +353,24 @@ class ClientLocal(Client):
349
353
  except IndexError:
350
354
  raise IndexError("No objects found")
351
355
 
356
+ def search_objects(self, api: str, **kwargs) -> dict:
357
+ """
358
+ Search objects from Local.
359
+
360
+ Parameters
361
+ ----------
362
+ api : str
363
+ Search API.
364
+ **kwargs : dict
365
+ Keyword arguments to pass to the request.
366
+
367
+ Returns
368
+ -------
369
+ dict
370
+ Response objects.
371
+ """
372
+ raise NotImplementedError("Local client does not support search_objects.")
373
+
352
374
  ##############################
353
375
  # Helpers
354
376
  ##############################
@@ -0,0 +1,58 @@
1
+ from __future__ import annotations
2
+
3
+ from digitalhub.client._base.key_builder import ClientKeyBuilder
4
+
5
+
6
+ class ClientLocalKeyBuilder(ClientKeyBuilder):
7
+ """
8
+ Class that build the key of entities.
9
+ """
10
+
11
+ def base_entity_key(self, entity_id: str) -> str:
12
+ """
13
+ Build for base entity key.
14
+
15
+ Parameters
16
+ ----------
17
+ entity_id : str
18
+ Entity id.
19
+
20
+ Returns
21
+ -------
22
+ str
23
+ Key.
24
+ """
25
+ return f"store://{entity_id}"
26
+
27
+ def context_entity_key(
28
+ self,
29
+ project: str,
30
+ entity_type: str,
31
+ entity_kind: str,
32
+ entity_name: str,
33
+ entity_id: str | None = None,
34
+ ) -> str:
35
+ """
36
+ Build for context entity key.
37
+
38
+ Parameters
39
+ ----------
40
+ project : str
41
+ Project name.
42
+ entity_type : str
43
+ Entity type.
44
+ entity_kind : str
45
+ Entity kind.
46
+ entity_name : str
47
+ Entity name.
48
+ entity_id : str
49
+ Entity ID.
50
+
51
+ Returns
52
+ -------
53
+ str
54
+ Key.
55
+ """
56
+ if entity_id is None:
57
+ return f"store://{project}/{entity_type}/{entity_kind}/{entity_name}"
58
+ return f"store://{project}/{entity_type}/{entity_kind}/{entity_name}:{entity_id}"
digitalhub/context/api.py CHANGED
@@ -3,45 +3,26 @@ from __future__ import annotations
3
3
  import typing
4
4
 
5
5
  from digitalhub.context.builder import context_builder
6
- from digitalhub.utils.exceptions import ContextError
7
6
 
8
7
  if typing.TYPE_CHECKING:
9
8
  from digitalhub.context.context import Context
10
9
  from digitalhub.entities.project._base.entity import Project
11
10
 
12
11
 
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:
12
+ def build_context(project: Project, overwrite: bool = False) -> None:
32
13
  """
33
14
  Wrapper for ContextBuilder.build().
34
15
 
35
16
  Parameters
36
17
  ----------
37
18
  project : Project
38
- The project object used to set the current context.
19
+ The project object used to build the context.
39
20
 
40
21
  Returns
41
22
  -------
42
23
  None
43
24
  """
44
- context_builder.build(project)
25
+ context_builder.build(project, overwrite)
45
26
 
46
27
 
47
28
  def get_context(project: str) -> Context:
@@ -61,22 +42,6 @@ def get_context(project: str) -> Context:
61
42
  return context_builder.get(project)
62
43
 
63
44
 
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
45
  def delete_context(project: str) -> None:
81
46
  """
82
47
  Wrapper for ContextBuilder.remove().
@@ -3,6 +3,7 @@ from __future__ import annotations
3
3
  import typing
4
4
 
5
5
  from digitalhub.context.context import Context
6
+ from digitalhub.utils.exceptions import ContextError
6
7
 
7
8
  if typing.TYPE_CHECKING:
8
9
  from digitalhub.entities.project._base.entity import Project
@@ -19,7 +20,7 @@ class ContextBuilder:
19
20
  def __init__(self) -> None:
20
21
  self._instances: dict[str, Context] = {}
21
22
 
22
- def build(self, project_object: Project) -> None:
23
+ def build(self, project_object: Project, overwrite: bool = False) -> None:
23
24
  """
24
25
  Add a project as context.
25
26
 
@@ -27,12 +28,15 @@ class ContextBuilder:
27
28
  ----------
28
29
  project_object : Project
29
30
  The project to add.
31
+ overwrite : bool
32
+ If True, the project will be overwritten if it already exists.
30
33
 
31
34
  Returns
32
35
  -------
33
36
  None
34
37
  """
35
- self._instances[project_object.name] = Context(project_object)
38
+ if (project_object.name not in self._instances) or overwrite:
39
+ self._instances[project_object.name] = Context(project_object)
36
40
 
37
41
  def get(self, project: str) -> Context:
38
42
  """
@@ -53,12 +57,10 @@ class ContextBuilder:
53
57
  ValueError
54
58
  If the project is not in the context.
55
59
  """
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
60
+ try:
61
+ return self._instances[project]
62
+ except KeyError:
63
+ raise ContextError(f"Context '{project}' not found. Get or create a project named '{project}'.")
62
64
 
63
65
  def remove(self, project: str) -> None:
64
66
  """
@@ -75,20 +77,5 @@ class ContextBuilder:
75
77
  """
76
78
  self._instances.pop(project, None)
77
79
 
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
80
 
94
81
  context_builder = ContextBuilder()
@@ -13,8 +13,6 @@ class Context:
13
13
  some information about the project, such as the project name,
14
14
  a client instance (local or non-local), the local context
15
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
16
  """
19
17
 
20
18
  def __init__(self, project: Project) -> None:
@@ -22,115 +20,45 @@ class Context:
22
20
  self.client = project._client
23
21
  self.local = project._client.is_local()
24
22
  self.root = Path(project.spec.context)
23
+ self.root.mkdir(parents=True, exist_ok=True)
25
24
 
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)
25
+ self.is_running: bool = False
26
+ self._run_ctx: str = None
83
27
 
84
- def delete_object(self, api: str, **kwargs) -> dict:
28
+ def set_run(self, run_ctx: str) -> None:
85
29
  """
86
- Delete an object.
30
+ Set run identifier.
87
31
 
88
32
  Parameters
89
33
  ----------
90
- api : str
91
- Delete API.
92
- **kwargs : dict
93
- Keyword arguments passed to the request.
34
+ run_ctx : str
35
+ Run key.
94
36
 
95
37
  Returns
96
38
  -------
97
- dict
98
- Response object.
39
+ None
99
40
  """
100
- return self.client.delete_object(api, **kwargs)
41
+ self.is_running = True
42
+ self._run_ctx = run_ctx
101
43
 
102
- def list_objects(self, api: str, **kwargs) -> dict:
44
+ def unset_run(self) -> None:
103
45
  """
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.
46
+ Unset run identifier.
112
47
 
113
48
  Returns
114
49
  -------
115
- dict
116
- The list of objects.
50
+ None
117
51
  """
118
- return self.client.list_objects(api, **kwargs)
52
+ self.is_running = False
53
+ self._run_ctx = None
119
54
 
120
- def list_first_object(self, api: str, **kwargs) -> dict:
55
+ def get_run_ctx(self) -> str:
121
56
  """
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.
57
+ Get run identifier.
130
58
 
131
59
  Returns
132
60
  -------
133
- dict
134
- The list of objects.
61
+ str
62
+ Run key.
135
63
  """
136
- return self.client.list_first_object(api, **kwargs)
64
+ return self._run_ctx