zenml-nightly 0.75.0.dev20250312__py3-none-any.whl → 0.75.0.dev20250314__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 (191) hide show
  1. zenml/VERSION +1 -1
  2. zenml/__init__.py +2 -0
  3. zenml/analytics/context.py +7 -0
  4. zenml/analytics/enums.py +2 -2
  5. zenml/artifacts/utils.py +2 -4
  6. zenml/cli/__init__.py +8 -9
  7. zenml/cli/base.py +2 -2
  8. zenml/cli/code_repository.py +1 -1
  9. zenml/cli/login.py +6 -0
  10. zenml/cli/model.py +7 -15
  11. zenml/cli/pipeline.py +3 -3
  12. zenml/cli/project.py +172 -0
  13. zenml/cli/secret.py +47 -44
  14. zenml/cli/service_accounts.py +0 -1
  15. zenml/cli/service_connectors.py +15 -17
  16. zenml/cli/stack.py +0 -3
  17. zenml/cli/stack_components.py +2 -2
  18. zenml/cli/tag.py +3 -5
  19. zenml/cli/utils.py +25 -23
  20. zenml/client.py +749 -475
  21. zenml/config/global_config.py +48 -37
  22. zenml/config/pipeline_configurations.py +3 -2
  23. zenml/config/pipeline_run_configuration.py +2 -1
  24. zenml/config/secret_reference_mixin.py +1 -1
  25. zenml/constants.py +6 -6
  26. zenml/enums.py +0 -7
  27. zenml/event_hub/event_hub.py +3 -1
  28. zenml/exceptions.py +0 -24
  29. zenml/integrations/aws/orchestrators/sagemaker_orchestrator.py +5 -3
  30. zenml/integrations/bitbucket/plugins/event_sources/bitbucket_webhook_event_source.py +1 -4
  31. zenml/integrations/gcp/service_connectors/gcp_service_connector.py +7 -6
  32. zenml/integrations/github/plugins/event_sources/github_webhook_event_source.py +1 -4
  33. zenml/integrations/mlflow/steps/mlflow_registry.py +3 -3
  34. zenml/integrations/seldon/model_deployers/seldon_model_deployer.py +1 -1
  35. zenml/integrations/wandb/__init__.py +1 -1
  36. zenml/integrations/wandb/experiment_trackers/wandb_experiment_tracker.py +29 -9
  37. zenml/integrations/wandb/flavors/wandb_experiment_tracker_flavor.py +5 -3
  38. zenml/model/model.py +10 -10
  39. zenml/model_registries/base_model_registry.py +1 -1
  40. zenml/models/__init__.py +45 -28
  41. zenml/models/v2/base/base.py +0 -5
  42. zenml/models/v2/base/filter.py +2 -2
  43. zenml/models/v2/base/scoped.py +135 -156
  44. zenml/models/v2/core/action.py +12 -12
  45. zenml/models/v2/core/api_key.py +1 -1
  46. zenml/models/v2/core/artifact.py +31 -18
  47. zenml/models/v2/core/artifact_version.py +57 -40
  48. zenml/models/v2/core/code_repository.py +12 -12
  49. zenml/models/v2/core/component.py +22 -33
  50. zenml/models/v2/core/device.py +3 -2
  51. zenml/models/v2/core/event_source.py +14 -14
  52. zenml/models/v2/core/flavor.py +19 -47
  53. zenml/models/v2/core/logs.py +1 -2
  54. zenml/models/v2/core/model.py +23 -20
  55. zenml/models/v2/core/model_version.py +51 -42
  56. zenml/models/v2/core/pipeline.py +16 -16
  57. zenml/models/v2/core/pipeline_build.py +14 -14
  58. zenml/models/v2/core/pipeline_deployment.py +12 -14
  59. zenml/models/v2/core/pipeline_run.py +21 -29
  60. zenml/models/v2/core/project.py +203 -0
  61. zenml/models/v2/core/run_metadata.py +2 -2
  62. zenml/models/v2/core/run_template.py +16 -17
  63. zenml/models/v2/core/schedule.py +12 -21
  64. zenml/models/v2/core/secret.py +94 -128
  65. zenml/models/v2/core/server_settings.py +2 -2
  66. zenml/models/v2/core/service.py +57 -26
  67. zenml/models/v2/core/service_connector.py +14 -16
  68. zenml/models/v2/core/stack.py +24 -26
  69. zenml/models/v2/core/step_run.py +16 -28
  70. zenml/models/v2/core/tag.py +41 -15
  71. zenml/models/v2/core/trigger.py +13 -13
  72. zenml/models/v2/core/trigger_execution.py +2 -2
  73. zenml/models/v2/core/user.py +2 -2
  74. zenml/models/v2/misc/statistics.py +45 -0
  75. zenml/models/v2/misc/tag.py +27 -0
  76. zenml/orchestrators/cache_utils.py +7 -7
  77. zenml/orchestrators/input_utils.py +1 -0
  78. zenml/orchestrators/step_launcher.py +1 -2
  79. zenml/orchestrators/step_run_utils.py +2 -4
  80. zenml/orchestrators/step_runner.py +10 -1
  81. zenml/orchestrators/utils.py +4 -4
  82. zenml/pipelines/build_utils.py +2 -4
  83. zenml/pipelines/pipeline_decorator.py +3 -2
  84. zenml/pipelines/pipeline_definition.py +8 -9
  85. zenml/pipelines/run_utils.py +4 -4
  86. zenml/service_connectors/service_connector.py +0 -10
  87. zenml/service_connectors/service_connector_utils.py +0 -2
  88. zenml/stack/authentication_mixin.py +1 -1
  89. zenml/stack/flavor.py +3 -14
  90. zenml/stack/stack.py +0 -1
  91. zenml/stack/stack_component.py +1 -5
  92. zenml/steps/base_step.py +10 -2
  93. zenml/steps/step_context.py +19 -0
  94. zenml/utils/string_utils.py +1 -1
  95. zenml/utils/tag_utils.py +642 -0
  96. zenml/zen_server/cloud_utils.py +21 -0
  97. zenml/zen_server/exceptions.py +0 -6
  98. zenml/zen_server/rbac/endpoint_utils.py +134 -46
  99. zenml/zen_server/rbac/models.py +65 -3
  100. zenml/zen_server/rbac/rbac_interface.py +9 -0
  101. zenml/zen_server/rbac/rbac_sql_zen_store.py +15 -7
  102. zenml/zen_server/rbac/utils.py +155 -30
  103. zenml/zen_server/rbac/zenml_cloud_rbac.py +39 -11
  104. zenml/zen_server/routers/actions_endpoints.py +3 -5
  105. zenml/zen_server/routers/artifact_endpoint.py +0 -5
  106. zenml/zen_server/routers/artifact_version_endpoints.py +15 -9
  107. zenml/zen_server/routers/auth_endpoints.py +22 -7
  108. zenml/zen_server/routers/code_repositories_endpoints.py +54 -3
  109. zenml/zen_server/routers/devices_endpoints.py +0 -4
  110. zenml/zen_server/routers/event_source_endpoints.py +0 -5
  111. zenml/zen_server/routers/flavors_endpoints.py +0 -5
  112. zenml/zen_server/routers/logs_endpoints.py +0 -1
  113. zenml/zen_server/routers/model_versions_endpoints.py +100 -23
  114. zenml/zen_server/routers/models_endpoints.py +50 -69
  115. zenml/zen_server/routers/pipeline_builds_endpoints.py +55 -3
  116. zenml/zen_server/routers/pipeline_deployments_endpoints.py +56 -4
  117. zenml/zen_server/routers/pipelines_endpoints.py +70 -3
  118. zenml/zen_server/routers/plugin_endpoints.py +0 -1
  119. zenml/zen_server/routers/projects_endpoints.py +283 -0
  120. zenml/zen_server/routers/run_metadata_endpoints.py +97 -0
  121. zenml/zen_server/routers/run_templates_endpoints.py +64 -3
  122. zenml/zen_server/routers/runs_endpoints.py +58 -8
  123. zenml/zen_server/routers/schedule_endpoints.py +67 -6
  124. zenml/zen_server/routers/secrets_endpoints.py +38 -4
  125. zenml/zen_server/routers/server_endpoints.py +53 -1
  126. zenml/zen_server/routers/service_accounts_endpoints.py +14 -15
  127. zenml/zen_server/routers/service_connectors_endpoints.py +94 -14
  128. zenml/zen_server/routers/service_endpoints.py +18 -7
  129. zenml/zen_server/routers/stack_components_endpoints.py +66 -7
  130. zenml/zen_server/routers/stacks_endpoints.py +95 -6
  131. zenml/zen_server/routers/steps_endpoints.py +17 -11
  132. zenml/zen_server/routers/tag_resource_endpoints.py +115 -0
  133. zenml/zen_server/routers/tags_endpoints.py +6 -17
  134. zenml/zen_server/routers/triggers_endpoints.py +5 -8
  135. zenml/zen_server/routers/users_endpoints.py +9 -12
  136. zenml/zen_server/template_execution/utils.py +8 -7
  137. zenml/zen_server/utils.py +21 -0
  138. zenml/zen_server/zen_server_api.py +7 -2
  139. zenml/zen_stores/base_zen_store.py +50 -69
  140. zenml/zen_stores/migrations/versions/12eff0206201_rename_workspace_to_project.py +768 -0
  141. zenml/zen_stores/migrations/versions/1cb6477f72d6_move_artifact_save_type.py +20 -10
  142. zenml/zen_stores/migrations/versions/1f9d1cd00b90_add_unique_name_constraints.py +231 -0
  143. zenml/zen_stores/migrations/versions/288f4fb6e112_make_tags_user_scoped.py +74 -0
  144. zenml/zen_stores/migrations/versions/2e695a26fe7a_add_user_default_workspace.py +45 -0
  145. zenml/zen_stores/migrations/versions/3b1776345020_remove_workspace_from_globals.py +81 -0
  146. zenml/zen_stores/migrations/versions/41b28cae31ce_make_artifacts_workspace_scoped.py +136 -0
  147. zenml/zen_stores/migrations/versions/9e7bf0970266_adding_exclusive_attribute_to_tags.py +47 -0
  148. zenml/zen_stores/migrations/versions/b557b2871693_update_step_run_input_types.py +8 -4
  149. zenml/zen_stores/migrations/versions/cbc6acd71f92_add_workspace_display_name.py +58 -0
  150. zenml/zen_stores/migrations/versions/cc269488e5a9_separate_run_metadata.py +12 -6
  151. zenml/zen_stores/migrations/versions/f1d723fd723b_add_secret_private_attr.py +61 -0
  152. zenml/zen_stores/migrations/versions/f76a368a25a5_add_stack_description.py +35 -0
  153. zenml/zen_stores/rest_zen_store.py +223 -230
  154. zenml/zen_stores/schemas/__init__.py +2 -2
  155. zenml/zen_stores/schemas/action_schemas.py +15 -8
  156. zenml/zen_stores/schemas/api_key_schemas.py +8 -1
  157. zenml/zen_stores/schemas/artifact_schemas.py +35 -10
  158. zenml/zen_stores/schemas/code_repository_schemas.py +22 -17
  159. zenml/zen_stores/schemas/component_schemas.py +9 -14
  160. zenml/zen_stores/schemas/event_source_schemas.py +15 -8
  161. zenml/zen_stores/schemas/flavor_schemas.py +14 -20
  162. zenml/zen_stores/schemas/model_schemas.py +18 -17
  163. zenml/zen_stores/schemas/pipeline_build_schemas.py +7 -7
  164. zenml/zen_stores/schemas/pipeline_deployment_schemas.py +10 -8
  165. zenml/zen_stores/schemas/pipeline_run_schemas.py +9 -12
  166. zenml/zen_stores/schemas/pipeline_schemas.py +9 -9
  167. zenml/zen_stores/schemas/{workspace_schemas.py → project_schemas.py} +53 -65
  168. zenml/zen_stores/schemas/run_metadata_schemas.py +5 -5
  169. zenml/zen_stores/schemas/run_template_schemas.py +17 -13
  170. zenml/zen_stores/schemas/schedule_schema.py +16 -21
  171. zenml/zen_stores/schemas/secret_schemas.py +15 -25
  172. zenml/zen_stores/schemas/service_connector_schemas.py +8 -17
  173. zenml/zen_stores/schemas/service_schemas.py +7 -8
  174. zenml/zen_stores/schemas/stack_schemas.py +12 -15
  175. zenml/zen_stores/schemas/step_run_schemas.py +14 -15
  176. zenml/zen_stores/schemas/tag_schemas.py +30 -2
  177. zenml/zen_stores/schemas/trigger_schemas.py +15 -8
  178. zenml/zen_stores/schemas/user_schemas.py +12 -2
  179. zenml/zen_stores/schemas/utils.py +16 -0
  180. zenml/zen_stores/secrets_stores/service_connector_secrets_store.py +0 -3
  181. zenml/zen_stores/sql_zen_store.py +2984 -2369
  182. zenml/zen_stores/template_utils.py +1 -1
  183. zenml/zen_stores/zen_store_interface.py +136 -126
  184. {zenml_nightly-0.75.0.dev20250312.dist-info → zenml_nightly-0.75.0.dev20250314.dist-info}/METADATA +1 -1
  185. {zenml_nightly-0.75.0.dev20250312.dist-info → zenml_nightly-0.75.0.dev20250314.dist-info}/RECORD +188 -173
  186. zenml/cli/workspace.py +0 -86
  187. zenml/models/v2/core/workspace.py +0 -131
  188. zenml/zen_server/routers/workspaces_endpoints.py +0 -1469
  189. {zenml_nightly-0.75.0.dev20250312.dist-info → zenml_nightly-0.75.0.dev20250314.dist-info}/LICENSE +0 -0
  190. {zenml_nightly-0.75.0.dev20250312.dist-info → zenml_nightly-0.75.0.dev20250314.dist-info}/WHEEL +0 -0
  191. {zenml_nightly-0.75.0.dev20250312.dist-info → zenml_nightly-0.75.0.dev20250314.dist-info}/entry_points.txt +0 -0
zenml/client.py CHANGED
@@ -46,8 +46,8 @@ from zenml.config.global_config import GlobalConfiguration
46
46
  from zenml.config.pipeline_run_configuration import PipelineRunConfiguration
47
47
  from zenml.config.source import Source
48
48
  from zenml.constants import (
49
+ ENV_ZENML_ACTIVE_PROJECT_ID,
49
50
  ENV_ZENML_ACTIVE_STACK_ID,
50
- ENV_ZENML_ACTIVE_WORKSPACE_ID,
51
51
  ENV_ZENML_ENABLE_REPO_INIT_WARNINGS,
52
52
  ENV_ZENML_REPOSITORY_PATH,
53
53
  ENV_ZENML_SERVER,
@@ -59,12 +59,12 @@ from zenml.constants import (
59
59
  )
60
60
  from zenml.enums import (
61
61
  ArtifactType,
62
+ ColorVariants,
62
63
  LogicalOperators,
63
64
  ModelStages,
64
65
  OAuthDeviceStatus,
65
66
  PluginSubType,
66
67
  PluginType,
67
- SecretScope,
68
68
  SorterOps,
69
69
  StackComponentType,
70
70
  StoreType,
@@ -134,6 +134,10 @@ from zenml.models import (
134
134
  PipelineResponse,
135
135
  PipelineRunFilter,
136
136
  PipelineRunResponse,
137
+ ProjectFilter,
138
+ ProjectRequest,
139
+ ProjectResponse,
140
+ ProjectUpdate,
137
141
  RunMetadataRequest,
138
142
  RunMetadataResource,
139
143
  RunTemplateFilter,
@@ -170,6 +174,8 @@ from zenml.models import (
170
174
  StepRunResponse,
171
175
  TagFilter,
172
176
  TagRequest,
177
+ TagResource,
178
+ TagResourceRequest,
173
179
  TagResponse,
174
180
  TagUpdate,
175
181
  TriggerExecutionFilter,
@@ -182,10 +188,6 @@ from zenml.models import (
182
188
  UserRequest,
183
189
  UserResponse,
184
190
  UserUpdate,
185
- WorkspaceFilter,
186
- WorkspaceRequest,
187
- WorkspaceResponse,
188
- WorkspaceUpdate,
189
191
  )
190
192
  from zenml.models.v2.core.step_run import StepRunUpdate
191
193
  from zenml.services.service import ServiceConfig
@@ -212,38 +214,38 @@ F = TypeVar("F", bound=Callable[..., Any])
212
214
  class ClientConfiguration(FileSyncModel):
213
215
  """Pydantic object used for serializing client configuration options."""
214
216
 
215
- _active_workspace: Optional["WorkspaceResponse"] = None
216
- active_workspace_id: Optional[UUID] = None
217
+ _active_project: Optional["ProjectResponse"] = None
218
+ active_project_id: Optional[UUID] = None
217
219
  active_stack_id: Optional[UUID] = None
218
220
  _active_stack: Optional["StackResponse"] = None
219
221
 
220
222
  @property
221
- def active_workspace(self) -> "WorkspaceResponse":
222
- """Get the active workspace for the local client.
223
+ def active_project(self) -> "ProjectResponse":
224
+ """Get the active project for the local client.
223
225
 
224
226
  Returns:
225
- The active workspace.
227
+ The active project.
226
228
 
227
229
  Raises:
228
- RuntimeError: If no active workspace is set.
230
+ RuntimeError: If no active project is set.
229
231
  """
230
- if self._active_workspace:
231
- return self._active_workspace
232
+ if self._active_project:
233
+ return self._active_project
232
234
  else:
233
235
  raise RuntimeError(
234
- "No active workspace is configured. Run "
235
- "`zenml workspace set WORKSPACE_NAME` to set the active "
236
- "workspace."
236
+ "No active project is configured. Run "
237
+ "`zenml project set PROJECT_NAME` to set the active "
238
+ "project."
237
239
  )
238
240
 
239
- def set_active_workspace(self, workspace: "WorkspaceResponse") -> None:
240
- """Set the workspace for the local client.
241
+ def set_active_project(self, project: "ProjectResponse") -> None:
242
+ """Set the project for the local client.
241
243
 
242
244
  Args:
243
- workspace: The workspace to set active.
245
+ project: The project to set active.
244
246
  """
245
- self._active_workspace = workspace
246
- self.active_workspace_id = workspace.id
247
+ self._active_project = project
248
+ self.active_project_id = project.id
247
249
 
248
250
  def set_active_stack(self, stack: "StackResponse") -> None:
249
251
  """Set the stack for the local client.
@@ -344,7 +346,7 @@ class Client(metaclass=ClientMetaClass):
344
346
  """
345
347
 
346
348
  _active_user: Optional["UserResponse"] = None
347
- _active_workspace: Optional["WorkspaceResponse"] = None
349
+ _active_project: Optional["ProjectResponse"] = None
348
350
  _active_stack: Optional["StackResponse"] = None
349
351
 
350
352
  def __init__(
@@ -410,7 +412,7 @@ class Client(metaclass=ClientMetaClass):
410
412
  If a client configuration is found at the given path or the
411
413
  path, it is loaded and used to initialize the client.
412
414
  If no client configuration is found, the global configuration is
413
- used instead to manage the active stack, workspace etc.
415
+ used instead to manage the active stack, project etc.
414
416
 
415
417
  Args:
416
418
  root: The path to set as the active repository root. If not set,
@@ -454,18 +456,19 @@ class Client(metaclass=ClientMetaClass):
454
456
 
455
457
  This method is called to ensure that the client configuration
456
458
  doesn't contain outdated information, such as an active stack or
457
- workspace that no longer exists.
459
+ project that no longer exists.
458
460
  """
459
461
  if not self._config:
460
462
  return
461
463
 
462
- active_workspace, active_stack = self.zen_store.validate_active_config(
463
- self._config.active_workspace_id,
464
+ active_project, active_stack = self.zen_store.validate_active_config(
465
+ self._config.active_project_id,
464
466
  self._config.active_stack_id,
465
467
  config_name="repo",
466
468
  )
467
469
  self._config.set_active_stack(active_stack)
468
- self._config.set_active_workspace(active_workspace)
470
+ if active_project:
471
+ self._config.set_active_project(active_project)
469
472
 
470
473
  def _load_config(self) -> Optional[ClientConfiguration]:
471
474
  """Loads the client configuration from disk.
@@ -675,30 +678,30 @@ class Client(metaclass=ClientMetaClass):
675
678
  """
676
679
  self._set_active_root(root)
677
680
 
678
- def set_active_workspace(
679
- self, workspace_name_or_id: Union[str, UUID]
680
- ) -> "WorkspaceResponse":
681
- """Set the workspace for the local client.
681
+ def set_active_project(
682
+ self, project_name_or_id: Union[str, UUID]
683
+ ) -> "ProjectResponse":
684
+ """Set the project for the local client.
682
685
 
683
686
  Args:
684
- workspace_name_or_id: The name or ID of the workspace to set active.
687
+ project_name_or_id: The name or ID of the project to set active.
685
688
 
686
689
  Returns:
687
- The model of the active workspace.
690
+ The model of the active project.
688
691
  """
689
- workspace = self.zen_store.get_workspace(
690
- workspace_name_or_id=workspace_name_or_id
692
+ project = self.zen_store.get_project(
693
+ project_name_or_id=project_name_or_id
691
694
  ) # raises KeyError
692
695
  if self._config:
693
- self._config.set_active_workspace(workspace)
696
+ self._config.set_active_project(project)
694
697
  # Sanitize the client configuration to reflect the current
695
698
  # settings
696
699
  self._sanitize_config()
697
700
  else:
698
- # set the active workspace globally only if the client doesn't use
701
+ # set the active project globally only if the client doesn't use
699
702
  # a local configuration
700
- GlobalConfiguration().set_active_workspace(workspace)
701
- return workspace
703
+ GlobalConfiguration().set_active_project(project)
704
+ return project
702
705
 
703
706
  # ----------------------------- Server Settings ----------------------------
704
707
 
@@ -964,52 +967,60 @@ class Client(metaclass=ClientMetaClass):
964
967
  self._active_user = self.zen_store.get_user(include_private=True)
965
968
  return self._active_user
966
969
 
967
- # -------------------------------- Workspaces ------------------------------
970
+ # -------------------------------- Projects ------------------------------
968
971
 
969
- def create_workspace(
970
- self, name: str, description: str
971
- ) -> WorkspaceResponse:
972
- """Create a new workspace.
972
+ def create_project(
973
+ self,
974
+ name: str,
975
+ description: str,
976
+ display_name: Optional[str] = None,
977
+ ) -> ProjectResponse:
978
+ """Create a new project.
973
979
 
974
980
  Args:
975
- name: Name of the workspace.
976
- description: Description of the workspace.
981
+ name: Name of the project.
982
+ description: Description of the project.
983
+ display_name: Display name of the project.
977
984
 
978
985
  Returns:
979
- The created workspace.
986
+ The created project.
980
987
  """
981
- return self.zen_store.create_workspace(
982
- WorkspaceRequest(name=name, description=description)
988
+ return self.zen_store.create_project(
989
+ ProjectRequest(
990
+ name=name,
991
+ description=description,
992
+ display_name=display_name or "",
993
+ )
983
994
  )
984
995
 
985
- def get_workspace(
996
+ def get_project(
986
997
  self,
987
998
  name_id_or_prefix: Optional[Union[UUID, str]],
988
999
  allow_name_prefix_match: bool = True,
989
1000
  hydrate: bool = True,
990
- ) -> WorkspaceResponse:
991
- """Gets a workspace.
1001
+ ) -> ProjectResponse:
1002
+ """Gets a project.
992
1003
 
993
1004
  Args:
994
- name_id_or_prefix: The name or ID of the workspace.
1005
+ name_id_or_prefix: The name or ID of the project.
995
1006
  allow_name_prefix_match: If True, allow matching by name prefix.
996
1007
  hydrate: Flag deciding whether to hydrate the output model(s)
997
1008
  by including metadata fields in the response.
998
1009
 
999
1010
  Returns:
1000
- The workspace
1011
+ The project
1001
1012
  """
1002
1013
  if not name_id_or_prefix:
1003
- return self.active_workspace
1014
+ return self.active_project
1004
1015
  return self._get_entity_by_id_or_name_or_prefix(
1005
- get_method=self.zen_store.get_workspace,
1006
- list_method=self.list_workspaces,
1016
+ get_method=self.zen_store.get_project,
1017
+ list_method=self.list_projects,
1007
1018
  name_id_or_prefix=name_id_or_prefix,
1008
1019
  allow_name_prefix_match=allow_name_prefix_match,
1009
1020
  hydrate=hydrate,
1010
1021
  )
1011
1022
 
1012
- def list_workspaces(
1023
+ def list_projects(
1013
1024
  self,
1014
1025
  sort_by: str = "created",
1015
1026
  page: int = PAGINATION_STARTING_PAGE,
@@ -1019,27 +1030,29 @@ class Client(metaclass=ClientMetaClass):
1019
1030
  created: Optional[Union[datetime, str]] = None,
1020
1031
  updated: Optional[Union[datetime, str]] = None,
1021
1032
  name: Optional[str] = None,
1033
+ display_name: Optional[str] = None,
1022
1034
  hydrate: bool = False,
1023
- ) -> Page[WorkspaceResponse]:
1024
- """List all workspaces.
1035
+ ) -> Page[ProjectResponse]:
1036
+ """List all projects.
1025
1037
 
1026
1038
  Args:
1027
1039
  sort_by: The column to sort by
1028
1040
  page: The page of items
1029
1041
  size: The maximum size of all pages
1030
1042
  logical_operator: Which logical operator to use [and, or]
1031
- id: Use the workspace ID to filter by.
1043
+ id: Use the project ID to filter by.
1032
1044
  created: Use to filter by time of creation
1033
1045
  updated: Use the last updated date for filtering
1034
- name: Use the workspace name for filtering
1046
+ name: Use the project name for filtering
1047
+ display_name: Use the project display name for filtering
1035
1048
  hydrate: Flag deciding whether to hydrate the output model(s)
1036
1049
  by including metadata fields in the response.
1037
1050
 
1038
1051
  Returns:
1039
- Page of workspaces
1052
+ Page of projects
1040
1053
  """
1041
- return self.zen_store.list_workspaces(
1042
- WorkspaceFilter(
1054
+ return self.zen_store.list_projects(
1055
+ ProjectFilter(
1043
1056
  sort_by=sort_by,
1044
1057
  page=page,
1045
1058
  size=size,
@@ -1048,106 +1061,113 @@ class Client(metaclass=ClientMetaClass):
1048
1061
  created=created,
1049
1062
  updated=updated,
1050
1063
  name=name,
1064
+ display_name=display_name,
1051
1065
  ),
1052
1066
  hydrate=hydrate,
1053
1067
  )
1054
1068
 
1055
- def update_workspace(
1069
+ def update_project(
1056
1070
  self,
1057
1071
  name_id_or_prefix: Optional[Union[UUID, str]],
1058
1072
  new_name: Optional[str] = None,
1073
+ new_display_name: Optional[str] = None,
1059
1074
  new_description: Optional[str] = None,
1060
- ) -> WorkspaceResponse:
1061
- """Update a workspace.
1075
+ ) -> ProjectResponse:
1076
+ """Update a project.
1062
1077
 
1063
1078
  Args:
1064
- name_id_or_prefix: Name, ID or prefix of the workspace to update.
1065
- new_name: New name of the workspace.
1066
- new_description: New description of the workspace.
1079
+ name_id_or_prefix: Name, ID or prefix of the project to update.
1080
+ new_name: New name of the project.
1081
+ new_display_name: New display name of the project.
1082
+ new_description: New description of the project.
1067
1083
 
1068
1084
  Returns:
1069
- The updated workspace.
1085
+ The updated project.
1070
1086
  """
1071
- workspace = self.get_workspace(
1087
+ project = self.get_project(
1072
1088
  name_id_or_prefix=name_id_or_prefix, allow_name_prefix_match=False
1073
1089
  )
1074
- workspace_update = WorkspaceUpdate(name=new_name or workspace.name)
1090
+ project_update = ProjectUpdate(
1091
+ name=new_name or project.name,
1092
+ display_name=new_display_name or project.display_name,
1093
+ )
1075
1094
  if new_description:
1076
- workspace_update.description = new_description
1077
- return self.zen_store.update_workspace(
1078
- workspace_id=workspace.id,
1079
- workspace_update=workspace_update,
1095
+ project_update.description = new_description
1096
+ return self.zen_store.update_project(
1097
+ project_id=project.id,
1098
+ project_update=project_update,
1080
1099
  )
1081
1100
 
1082
- def delete_workspace(self, name_id_or_prefix: str) -> None:
1083
- """Delete a workspace.
1101
+ def delete_project(self, name_id_or_prefix: str) -> None:
1102
+ """Delete a project.
1084
1103
 
1085
1104
  Args:
1086
- name_id_or_prefix: The name or ID of the workspace to delete.
1105
+ name_id_or_prefix: The name or ID of the project to delete.
1087
1106
 
1088
1107
  Raises:
1089
- IllegalOperationError: If the workspace to delete is the active
1090
- workspace.
1108
+ IllegalOperationError: If the project to delete is the active
1109
+ project.
1091
1110
  """
1092
- workspace = self.get_workspace(
1111
+ project = self.get_project(
1093
1112
  name_id_or_prefix, allow_name_prefix_match=False
1094
1113
  )
1095
- if self.active_workspace.id == workspace.id:
1114
+ if self.active_project.id == project.id:
1096
1115
  raise IllegalOperationError(
1097
- f"Workspace '{name_id_or_prefix}' cannot be deleted since "
1098
- "it is currently active. Please set another workspace as "
1116
+ f"Project '{name_id_or_prefix}' cannot be deleted since "
1117
+ "it is currently active. Please set another project as "
1099
1118
  "active first."
1100
1119
  )
1101
- self.zen_store.delete_workspace(workspace_name_or_id=workspace.id)
1120
+ self.zen_store.delete_project(project_name_or_id=project.id)
1102
1121
 
1103
1122
  @property
1104
- def active_workspace(self) -> WorkspaceResponse:
1105
- """Get the currently active workspace of the local client.
1123
+ def active_project(self) -> ProjectResponse:
1124
+ """Get the currently active project of the local client.
1106
1125
 
1107
- If no active workspace is configured locally for the client, the
1108
- active workspace in the global configuration is used instead.
1126
+ If no active project is configured locally for the client, the
1127
+ active project in the global configuration is used instead.
1109
1128
 
1110
1129
  Returns:
1111
- The active workspace.
1130
+ The active project.
1112
1131
 
1113
1132
  Raises:
1114
- RuntimeError: If the active workspace is not set.
1133
+ RuntimeError: If the active project is not set.
1115
1134
  """
1116
- if workspace_id := os.environ.get(ENV_ZENML_ACTIVE_WORKSPACE_ID):
1117
- if not self._active_workspace or self._active_workspace.id != UUID(
1118
- workspace_id
1135
+ if project_id := os.environ.get(ENV_ZENML_ACTIVE_PROJECT_ID):
1136
+ if not self._active_project or self._active_project.id != UUID(
1137
+ project_id
1119
1138
  ):
1120
- self._active_workspace = self.get_workspace(workspace_id)
1139
+ self._active_project = self.get_project(project_id)
1121
1140
 
1122
- return self._active_workspace
1141
+ return self._active_project
1123
1142
 
1124
- from zenml.constants import DEFAULT_WORKSPACE_NAME
1143
+ from zenml.constants import DEFAULT_PROJECT_NAME
1125
1144
 
1126
- # If running in a ZenML server environment, the active workspace is
1145
+ # If running in a ZenML server environment, the active project is
1127
1146
  # not relevant
1128
1147
  if ENV_ZENML_SERVER in os.environ:
1129
- return self.get_workspace(DEFAULT_WORKSPACE_NAME)
1148
+ return self.get_project(DEFAULT_PROJECT_NAME)
1130
1149
 
1131
- workspace = (
1132
- self._config.active_workspace if self._config else None
1133
- ) or GlobalConfiguration().get_active_workspace()
1134
- if not workspace:
1150
+ project = (
1151
+ self._config.active_project if self._config else None
1152
+ ) or GlobalConfiguration().get_active_project()
1153
+ if not project:
1135
1154
  raise RuntimeError(
1136
- "No active workspace is configured. Run "
1137
- "`zenml workspace set WORKSPACE_NAME` to set the active "
1138
- "workspace."
1155
+ "No active project is configured. Run "
1156
+ "`zenml project set PROJECT_NAME` to set the active "
1157
+ "project."
1139
1158
  )
1140
1159
 
1141
- if workspace.name != DEFAULT_WORKSPACE_NAME:
1142
- logger.warning(
1143
- f"You are running with a non-default workspace "
1144
- f"'{workspace.name}'. Any stacks, components, "
1145
- f"pipelines and pipeline runs produced in this "
1146
- f"workspace will currently not be accessible through "
1147
- f"the dashboard. However, this will be possible "
1148
- f"in the near future."
1149
- )
1150
- return workspace
1160
+ if project.name != DEFAULT_PROJECT_NAME:
1161
+ if not self.zen_store.get_store_info().is_pro_server():
1162
+ logger.warning(
1163
+ f"You are running with a non-default project "
1164
+ f"'{project.name}'. The ZenML project feature is "
1165
+ "available only in ZenML Pro. Pipelines, pipeline runs and "
1166
+ "artifacts produced in this project will not be "
1167
+ "accessible through the dashboard. Please visit "
1168
+ "https://zenml.io/pro to learn more."
1169
+ )
1170
+ return project
1151
1171
 
1152
1172
  # --------------------------------- Stacks ---------------------------------
1153
1173
 
@@ -1187,8 +1207,7 @@ class Client(metaclass=ClientMetaClass):
1187
1207
  name=name,
1188
1208
  components=stack_components,
1189
1209
  stack_spec_path=stack_spec_file,
1190
- workspace=self.active_workspace.id,
1191
- user=self.active_user.id,
1210
+ project=self.active_project.id,
1192
1211
  labels=labels,
1193
1212
  )
1194
1213
 
@@ -1237,8 +1256,6 @@ class Client(metaclass=ClientMetaClass):
1237
1256
  updated: Optional[Union[datetime, str]] = None,
1238
1257
  name: Optional[str] = None,
1239
1258
  description: Optional[str] = None,
1240
- workspace_id: Optional[Union[str, UUID]] = None,
1241
- user_id: Optional[Union[str, UUID]] = None,
1242
1259
  component_id: Optional[Union[str, UUID]] = None,
1243
1260
  user: Optional[Union[UUID, str]] = None,
1244
1261
  component: Optional[Union[UUID, str]] = None,
@@ -1255,8 +1272,6 @@ class Client(metaclass=ClientMetaClass):
1255
1272
  created: Use to filter by time of creation
1256
1273
  updated: Use the last updated date for filtering
1257
1274
  description: Use the stack description for filtering
1258
- workspace_id: The id of the workspace to filter by.
1259
- user_id: The id of the user to filter by.
1260
1275
  component_id: The id of the component to filter by.
1261
1276
  user: The name/ID of the user to filter by.
1262
1277
  component: The name/ID of the component to filter by.
@@ -1272,8 +1287,6 @@ class Client(metaclass=ClientMetaClass):
1272
1287
  size=size,
1273
1288
  sort_by=sort_by,
1274
1289
  logical_operator=logical_operator,
1275
- workspace_id=workspace_id,
1276
- user_id=user_id,
1277
1290
  component_id=component_id,
1278
1291
  user=user,
1279
1292
  component=component,
@@ -1283,7 +1296,6 @@ class Client(metaclass=ClientMetaClass):
1283
1296
  created=created,
1284
1297
  updated=updated,
1285
1298
  )
1286
- stack_filter_model.set_scope_workspace(self.active_workspace.id)
1287
1299
  return self.zen_store.list_stacks(stack_filter_model, hydrate=hydrate)
1288
1300
 
1289
1301
  def update_stack(
@@ -1321,8 +1333,7 @@ class Client(metaclass=ClientMetaClass):
1321
1333
 
1322
1334
  # Create the update model
1323
1335
  update_model = StackUpdate(
1324
- workspace=self.active_workspace.id,
1325
- user=self.active_user.id,
1336
+ project=self.active_project.id,
1326
1337
  stack_spec_path=stack_spec_file,
1327
1338
  )
1328
1339
 
@@ -1632,8 +1643,7 @@ class Client(metaclass=ClientMetaClass):
1632
1643
  name=config.service_name,
1633
1644
  service_type=service_type,
1634
1645
  config=config.model_dump(),
1635
- workspace=self.active_workspace.id,
1636
- user=self.active_user.id,
1646
+ project=self.active_project.id,
1637
1647
  model_version_id=model_version_id,
1638
1648
  )
1639
1649
  # Register the service
@@ -1645,6 +1655,7 @@ class Client(metaclass=ClientMetaClass):
1645
1655
  allow_name_prefix_match: bool = True,
1646
1656
  hydrate: bool = True,
1647
1657
  type: Optional[str] = None,
1658
+ project: Optional[Union[str, UUID]] = None,
1648
1659
  ) -> ServiceResponse:
1649
1660
  """Gets a service.
1650
1661
 
@@ -1654,6 +1665,7 @@ class Client(metaclass=ClientMetaClass):
1654
1665
  hydrate: Flag deciding whether to hydrate the output model(s)
1655
1666
  by including metadata fields in the response.
1656
1667
  type: The type of the service.
1668
+ project: The project name/ID to filter by.
1657
1669
 
1658
1670
  Returns:
1659
1671
  The Service
@@ -1676,7 +1688,6 @@ class Client(metaclass=ClientMetaClass):
1676
1688
  service_filter_model = ServiceFilter(**kwargs)
1677
1689
  if type:
1678
1690
  service_filter_model.set_type(type=type)
1679
- service_filter_model.set_scope_workspace(self.active_workspace.id)
1680
1691
  return self.zen_store.list_services(
1681
1692
  filter_model=service_filter_model,
1682
1693
  hydrate=hydrate,
@@ -1687,6 +1698,7 @@ class Client(metaclass=ClientMetaClass):
1687
1698
  list_method=type_scoped_list_method,
1688
1699
  name_id_or_prefix=name_id_or_prefix,
1689
1700
  allow_name_prefix_match=allow_name_prefix_match,
1701
+ project=project,
1690
1702
  hydrate=hydrate,
1691
1703
  )
1692
1704
 
@@ -1702,8 +1714,7 @@ class Client(metaclass=ClientMetaClass):
1702
1714
  type: Optional[str] = None,
1703
1715
  flavor: Optional[str] = None,
1704
1716
  user: Optional[Union[UUID, str]] = None,
1705
- workspace_id: Optional[Union[str, UUID]] = None,
1706
- user_id: Optional[Union[str, UUID]] = None,
1717
+ project: Optional[Union[str, UUID]] = None,
1707
1718
  hydrate: bool = False,
1708
1719
  running: Optional[bool] = None,
1709
1720
  service_name: Optional[str] = None,
@@ -1725,8 +1736,7 @@ class Client(metaclass=ClientMetaClass):
1725
1736
  updated: Use the last updated date for filtering
1726
1737
  type: Use the service type for filtering
1727
1738
  flavor: Use the service flavor for filtering
1728
- workspace_id: The id of the workspace to filter by.
1729
- user_id: The id of the user to filter by.
1739
+ project: The project name/ID to filter by.
1730
1740
  user: Filter by user name/ID.
1731
1741
  hydrate: Flag deciding whether to hydrate the output model(s)
1732
1742
  by including metadata fields in the response.
@@ -1752,8 +1762,7 @@ class Client(metaclass=ClientMetaClass):
1752
1762
  updated=updated,
1753
1763
  type=type,
1754
1764
  flavor=flavor,
1755
- workspace_id=workspace_id,
1756
- user_id=user_id,
1765
+ project=project or self.active_project.id,
1757
1766
  user=user,
1758
1767
  running=running,
1759
1768
  name=service_name,
@@ -1763,7 +1772,6 @@ class Client(metaclass=ClientMetaClass):
1763
1772
  pipeline_run_id=pipeline_run_id,
1764
1773
  config=dict_to_bytes(config) if config else None,
1765
1774
  )
1766
- service_filter_model.set_scope_workspace(self.active_workspace.id)
1767
1775
  return self.zen_store.list_services(
1768
1776
  filter_model=service_filter_model, hydrate=hydrate
1769
1777
  )
@@ -1821,15 +1829,21 @@ class Client(metaclass=ClientMetaClass):
1821
1829
  service_id=id, update=service_update
1822
1830
  )
1823
1831
 
1824
- def delete_service(self, name_id_or_prefix: UUID) -> None:
1832
+ def delete_service(
1833
+ self,
1834
+ name_id_or_prefix: UUID,
1835
+ project: Optional[Union[str, UUID]] = None,
1836
+ ) -> None:
1825
1837
  """Delete a service.
1826
1838
 
1827
1839
  Args:
1828
1840
  name_id_or_prefix: The name or ID of the service to delete.
1841
+ project: The project name/ID to filter by.
1829
1842
  """
1830
1843
  service = self.get_service(
1831
1844
  name_id_or_prefix,
1832
1845
  allow_name_prefix_match=False,
1846
+ project=project,
1833
1847
  )
1834
1848
  self.zen_store.delete_service(service_id=service.id)
1835
1849
 
@@ -1893,9 +1907,6 @@ class Client(metaclass=ClientMetaClass):
1893
1907
  component_filter_model.set_scope_type(
1894
1908
  component_type=component_type
1895
1909
  )
1896
- component_filter_model.set_scope_workspace(
1897
- self.active_workspace.id
1898
- )
1899
1910
  return self.zen_store.list_stack_components(
1900
1911
  component_filter_model=component_filter_model,
1901
1912
  hydrate=hydrate,
@@ -1921,8 +1932,6 @@ class Client(metaclass=ClientMetaClass):
1921
1932
  name: Optional[str] = None,
1922
1933
  flavor: Optional[str] = None,
1923
1934
  type: Optional[str] = None,
1924
- workspace_id: Optional[Union[str, UUID]] = None,
1925
- user_id: Optional[Union[str, UUID]] = None,
1926
1935
  connector_id: Optional[Union[str, UUID]] = None,
1927
1936
  stack_id: Optional[Union[str, UUID]] = None,
1928
1937
  user: Optional[Union[UUID, str]] = None,
@@ -1940,8 +1949,6 @@ class Client(metaclass=ClientMetaClass):
1940
1949
  updated: Use the last updated date for filtering
1941
1950
  flavor: Use the component flavor for filtering
1942
1951
  type: Use the component type for filtering
1943
- workspace_id: The id of the workspace to filter by.
1944
- user_id: The id of the user to filter by.
1945
1952
  connector_id: The id of the connector to filter by.
1946
1953
  stack_id: The id of the stack to filter by.
1947
1954
  name: The name of the component to filter by.
@@ -1957,8 +1964,6 @@ class Client(metaclass=ClientMetaClass):
1957
1964
  size=size,
1958
1965
  sort_by=sort_by,
1959
1966
  logical_operator=logical_operator,
1960
- workspace_id=workspace_id or self.active_workspace.id,
1961
- user_id=user_id,
1962
1967
  connector_id=connector_id,
1963
1968
  stack_id=stack_id,
1964
1969
  name=name,
@@ -1969,7 +1974,6 @@ class Client(metaclass=ClientMetaClass):
1969
1974
  updated=updated,
1970
1975
  user=user,
1971
1976
  )
1972
- component_filter_model.set_scope_workspace(self.active_workspace.id)
1973
1977
 
1974
1978
  return self.zen_store.list_stack_components(
1975
1979
  component_filter_model=component_filter_model, hydrate=hydrate
@@ -2017,8 +2021,7 @@ class Client(metaclass=ClientMetaClass):
2017
2021
  type=component_type,
2018
2022
  flavor=flavor,
2019
2023
  configuration=configuration,
2020
- user=self.active_user.id,
2021
- workspace=self.active_workspace.id,
2024
+ project=self.active_project.id,
2022
2025
  labels=labels,
2023
2026
  )
2024
2027
 
@@ -2067,8 +2070,7 @@ class Client(metaclass=ClientMetaClass):
2067
2070
  )
2068
2071
 
2069
2072
  update_model = ComponentUpdate(
2070
- workspace=self.active_workspace.id,
2071
- user=self.active_user.id,
2073
+ project=self.active_project.id,
2072
2074
  )
2073
2075
 
2074
2076
  if name is not None:
@@ -2241,7 +2243,6 @@ class Client(metaclass=ClientMetaClass):
2241
2243
  name: Optional[str] = None,
2242
2244
  type: Optional[str] = None,
2243
2245
  integration: Optional[str] = None,
2244
- user_id: Optional[Union[str, UUID]] = None,
2245
2246
  user: Optional[Union[UUID, str]] = None,
2246
2247
  hydrate: bool = False,
2247
2248
  ) -> Page[FlavorResponse]:
@@ -2255,7 +2256,6 @@ class Client(metaclass=ClientMetaClass):
2255
2256
  id: Use the id of flavors to filter by.
2256
2257
  created: Use to flavors by time of creation
2257
2258
  updated: Use the last updated date for filtering
2258
- user_id: The id of the user to filter by.
2259
2259
  user: Filter by user name/ID.
2260
2260
  name: The name of the flavor to filter by.
2261
2261
  type: The type of the flavor to filter by.
@@ -2271,7 +2271,6 @@ class Client(metaclass=ClientMetaClass):
2271
2271
  size=size,
2272
2272
  sort_by=sort_by,
2273
2273
  logical_operator=logical_operator,
2274
- user_id=user_id,
2275
2274
  user=user,
2276
2275
  name=name,
2277
2276
  type=type,
@@ -2280,7 +2279,6 @@ class Client(metaclass=ClientMetaClass):
2280
2279
  created=created,
2281
2280
  updated=updated,
2282
2281
  )
2283
- flavor_filter_model.set_scope_workspace(self.active_workspace.id)
2284
2282
  return self.zen_store.list_flavors(
2285
2283
  flavor_filter_model=flavor_filter_model, hydrate=hydrate
2286
2284
  )
@@ -2365,10 +2363,10 @@ class Client(metaclass=ClientMetaClass):
2365
2363
  updated: Optional[Union[datetime, str]] = None,
2366
2364
  name: Optional[str] = None,
2367
2365
  latest_run_status: Optional[str] = None,
2368
- workspace_id: Optional[Union[str, UUID]] = None,
2369
- user_id: Optional[Union[str, UUID]] = None,
2366
+ project: Optional[Union[str, UUID]] = None,
2370
2367
  user: Optional[Union[UUID, str]] = None,
2371
2368
  tag: Optional[str] = None,
2369
+ tags: Optional[List[str]] = None,
2372
2370
  hydrate: bool = False,
2373
2371
  ) -> Page[PipelineResponse]:
2374
2372
  """List all pipelines.
@@ -2384,10 +2382,10 @@ class Client(metaclass=ClientMetaClass):
2384
2382
  name: The name of the pipeline to filter by.
2385
2383
  latest_run_status: Filter by the status of the latest run of a
2386
2384
  pipeline.
2387
- workspace_id: The id of the workspace to filter by.
2388
- user_id: The id of the user to filter by.
2385
+ project: The project name/ID to filter by.
2389
2386
  user: The name/ID of the user to filter by.
2390
2387
  tag: Tag to filter by.
2388
+ tags: Tags to filter by.
2391
2389
  hydrate: Flag deciding whether to hydrate the output model(s)
2392
2390
  by including metadata fields in the response.
2393
2391
 
@@ -2404,12 +2402,11 @@ class Client(metaclass=ClientMetaClass):
2404
2402
  updated=updated,
2405
2403
  name=name,
2406
2404
  latest_run_status=latest_run_status,
2407
- workspace_id=workspace_id,
2408
- user_id=user_id,
2405
+ project=project or self.active_project.id,
2409
2406
  user=user,
2410
2407
  tag=tag,
2408
+ tags=tags,
2411
2409
  )
2412
- pipeline_filter_model.set_scope_workspace(self.active_workspace.id)
2413
2410
  return self.zen_store.list_pipelines(
2414
2411
  pipeline_filter_model=pipeline_filter_model,
2415
2412
  hydrate=hydrate,
@@ -2418,12 +2415,14 @@ class Client(metaclass=ClientMetaClass):
2418
2415
  def get_pipeline(
2419
2416
  self,
2420
2417
  name_id_or_prefix: Union[str, UUID],
2418
+ project: Optional[Union[str, UUID]] = None,
2421
2419
  hydrate: bool = True,
2422
2420
  ) -> PipelineResponse:
2423
2421
  """Get a pipeline by name, id or prefix.
2424
2422
 
2425
2423
  Args:
2426
2424
  name_id_or_prefix: The name, ID or ID prefix of the pipeline.
2425
+ project: The project name/ID to filter by.
2427
2426
  hydrate: Flag deciding whether to hydrate the output model(s)
2428
2427
  by including metadata fields in the response.
2429
2428
 
@@ -2434,19 +2433,24 @@ class Client(metaclass=ClientMetaClass):
2434
2433
  get_method=self.zen_store.get_pipeline,
2435
2434
  list_method=self.list_pipelines,
2436
2435
  name_id_or_prefix=name_id_or_prefix,
2436
+ project=project,
2437
2437
  hydrate=hydrate,
2438
2438
  )
2439
2439
 
2440
2440
  def delete_pipeline(
2441
2441
  self,
2442
2442
  name_id_or_prefix: Union[str, UUID],
2443
+ project: Optional[Union[str, UUID]] = None,
2443
2444
  ) -> None:
2444
2445
  """Delete a pipeline.
2445
2446
 
2446
2447
  Args:
2447
2448
  name_id_or_prefix: The name, ID or ID prefix of the pipeline.
2449
+ project: The project name/ID to filter by.
2448
2450
  """
2449
- pipeline = self.get_pipeline(name_id_or_prefix=name_id_or_prefix)
2451
+ pipeline = self.get_pipeline(
2452
+ name_id_or_prefix=name_id_or_prefix, project=project
2453
+ )
2450
2454
  self.zen_store.delete_pipeline(pipeline_id=pipeline.id)
2451
2455
 
2452
2456
  @_fail_for_sql_zen_store
@@ -2460,6 +2464,7 @@ class Client(metaclass=ClientMetaClass):
2460
2464
  template_id: Optional[UUID] = None,
2461
2465
  stack_name_or_id: Union[str, UUID, None] = None,
2462
2466
  synchronous: bool = False,
2467
+ project: Optional[Union[str, UUID]] = None,
2463
2468
  ) -> PipelineRunResponse:
2464
2469
  """Trigger a pipeline from the server.
2465
2470
 
@@ -2499,6 +2504,7 @@ class Client(metaclass=ClientMetaClass):
2499
2504
  runnable template on any stack.
2500
2505
  synchronous: If `True`, this method will wait until the triggered
2501
2506
  run is finished.
2507
+ project: The project name/ID to filter by.
2502
2508
 
2503
2509
  Raises:
2504
2510
  RuntimeError: If triggering the pipeline failed.
@@ -2562,6 +2568,7 @@ class Client(metaclass=ClientMetaClass):
2562
2568
  self.list_run_templates,
2563
2569
  pipeline_id=pipeline.id,
2564
2570
  stack_id=stack.id if stack else None,
2571
+ project=project or pipeline.project.id,
2565
2572
  )
2566
2573
 
2567
2574
  for template in templates:
@@ -2600,12 +2607,14 @@ class Client(metaclass=ClientMetaClass):
2600
2607
  def get_build(
2601
2608
  self,
2602
2609
  id_or_prefix: Union[str, UUID],
2610
+ project: Optional[Union[str, UUID]] = None,
2603
2611
  hydrate: bool = True,
2604
2612
  ) -> PipelineBuildResponse:
2605
2613
  """Get a build by id or prefix.
2606
2614
 
2607
2615
  Args:
2608
2616
  id_or_prefix: The id or id prefix of the build.
2617
+ project: The project name/ID to filter by.
2609
2618
  hydrate: Flag deciding whether to hydrate the output model(s)
2610
2619
  by including metadata fields in the response.
2611
2620
 
@@ -2629,9 +2638,16 @@ class Client(metaclass=ClientMetaClass):
2629
2638
  hydrate=hydrate,
2630
2639
  )
2631
2640
 
2632
- entity = self.list_builds(
2633
- id=f"startswith:{id_or_prefix}", hydrate=hydrate
2641
+ list_kwargs: Dict[str, Any] = dict(
2642
+ id=f"startswith:{id_or_prefix}",
2643
+ hydrate=hydrate,
2634
2644
  )
2645
+ scope = ""
2646
+ if project:
2647
+ list_kwargs["project"] = project
2648
+ scope = f" in project {project}"
2649
+
2650
+ entity = self.list_builds(**list_kwargs)
2635
2651
 
2636
2652
  # If only a single entity is found, return it.
2637
2653
  if entity.total == 1:
@@ -2641,11 +2657,11 @@ class Client(metaclass=ClientMetaClass):
2641
2657
  if entity.total == 0:
2642
2658
  raise KeyError(
2643
2659
  f"No builds have been found that have either an id or prefix "
2644
- f"that matches the provided string '{id_or_prefix}'."
2660
+ f"that matches the provided string '{id_or_prefix}'{scope}."
2645
2661
  )
2646
2662
 
2647
2663
  raise ZenKeyError(
2648
- f"{entity.total} builds have been found that have "
2664
+ f"{entity.total} builds have been found{scope} that have "
2649
2665
  f"an ID that matches the provided "
2650
2666
  f"string '{id_or_prefix}':\n"
2651
2667
  f"{[entity.items]}.\n"
@@ -2662,8 +2678,7 @@ class Client(metaclass=ClientMetaClass):
2662
2678
  id: Optional[Union[UUID, str]] = None,
2663
2679
  created: Optional[Union[datetime, str]] = None,
2664
2680
  updated: Optional[Union[datetime, str]] = None,
2665
- workspace_id: Optional[Union[str, UUID]] = None,
2666
- user_id: Optional[Union[str, UUID]] = None,
2681
+ project: Optional[Union[str, UUID]] = None,
2667
2682
  user: Optional[Union[UUID, str]] = None,
2668
2683
  pipeline_id: Optional[Union[str, UUID]] = None,
2669
2684
  stack_id: Optional[Union[str, UUID]] = None,
@@ -2687,8 +2702,7 @@ class Client(metaclass=ClientMetaClass):
2687
2702
  id: Use the id of build to filter by.
2688
2703
  created: Use to filter by time of creation
2689
2704
  updated: Use the last updated date for filtering
2690
- workspace_id: The id of the workspace to filter by.
2691
- user_id: The id of the user to filter by.
2705
+ project: The project name/ID to filter by.
2692
2706
  user: Filter by user name/ID.
2693
2707
  pipeline_id: The id of the pipeline to filter by.
2694
2708
  stack_id: The id of the stack to filter by.
@@ -2715,8 +2729,7 @@ class Client(metaclass=ClientMetaClass):
2715
2729
  id=id,
2716
2730
  created=created,
2717
2731
  updated=updated,
2718
- workspace_id=workspace_id,
2719
- user_id=user_id,
2732
+ project=project or self.active_project.id,
2720
2733
  user=user,
2721
2734
  pipeline_id=pipeline_id,
2722
2735
  stack_id=stack_id,
@@ -2729,19 +2742,21 @@ class Client(metaclass=ClientMetaClass):
2729
2742
  stack_checksum=stack_checksum,
2730
2743
  duration=duration,
2731
2744
  )
2732
- build_filter_model.set_scope_workspace(self.active_workspace.id)
2733
2745
  return self.zen_store.list_builds(
2734
2746
  build_filter_model=build_filter_model,
2735
2747
  hydrate=hydrate,
2736
2748
  )
2737
2749
 
2738
- def delete_build(self, id_or_prefix: str) -> None:
2750
+ def delete_build(
2751
+ self, id_or_prefix: str, project: Optional[Union[str, UUID]] = None
2752
+ ) -> None:
2739
2753
  """Delete a build.
2740
2754
 
2741
2755
  Args:
2742
2756
  id_or_prefix: The id or id prefix of the build.
2757
+ project: The project name/ID to filter by.
2743
2758
  """
2744
- build = self.get_build(id_or_prefix=id_or_prefix)
2759
+ build = self.get_build(id_or_prefix=id_or_prefix, project=project)
2745
2760
  self.zen_store.delete_build(build_id=build.id)
2746
2761
 
2747
2762
  # --------------------------------- Event Sources -------------------------
@@ -2774,8 +2789,7 @@ class Client(metaclass=ClientMetaClass):
2774
2789
  flavor=flavor,
2775
2790
  plugin_type=PluginType.EVENT_SOURCE,
2776
2791
  plugin_subtype=event_source_subtype,
2777
- user=self.active_user.id,
2778
- workspace=self.active_workspace.id,
2792
+ project=self.active_project.id,
2779
2793
  )
2780
2794
 
2781
2795
  return self.zen_store.create_event_source(event_source=event_source)
@@ -2785,6 +2799,7 @@ class Client(metaclass=ClientMetaClass):
2785
2799
  self,
2786
2800
  name_id_or_prefix: Union[UUID, str],
2787
2801
  allow_name_prefix_match: bool = True,
2802
+ project: Optional[Union[str, UUID]] = None,
2788
2803
  hydrate: bool = True,
2789
2804
  ) -> EventSourceResponse:
2790
2805
  """Get an event source by name, ID or prefix.
@@ -2792,6 +2807,7 @@ class Client(metaclass=ClientMetaClass):
2792
2807
  Args:
2793
2808
  name_id_or_prefix: The name, ID or prefix of the stack.
2794
2809
  allow_name_prefix_match: If True, allow matching by name prefix.
2810
+ project: The project name/ID to filter by.
2795
2811
  hydrate: Flag deciding whether to hydrate the output model(s)
2796
2812
  by including metadata fields in the response.
2797
2813
 
@@ -2803,6 +2819,7 @@ class Client(metaclass=ClientMetaClass):
2803
2819
  list_method=self.list_event_sources,
2804
2820
  name_id_or_prefix=name_id_or_prefix,
2805
2821
  allow_name_prefix_match=allow_name_prefix_match,
2822
+ project=project,
2806
2823
  hydrate=hydrate,
2807
2824
  )
2808
2825
 
@@ -2818,8 +2835,7 @@ class Client(metaclass=ClientMetaClass):
2818
2835
  name: Optional[str] = None,
2819
2836
  flavor: Optional[str] = None,
2820
2837
  event_source_type: Optional[str] = None,
2821
- workspace_id: Optional[Union[str, UUID]] = None,
2822
- user_id: Optional[Union[str, UUID]] = None,
2838
+ project: Optional[Union[str, UUID]] = None,
2823
2839
  user: Optional[Union[UUID, str]] = None,
2824
2840
  hydrate: bool = False,
2825
2841
  ) -> Page[EventSourceResponse]:
@@ -2833,8 +2849,7 @@ class Client(metaclass=ClientMetaClass):
2833
2849
  id: Use the id of event_sources to filter by.
2834
2850
  created: Use to filter by time of creation
2835
2851
  updated: Use the last updated date for filtering
2836
- workspace_id: The id of the workspace to filter by.
2837
- user_id: The id of the user to filter by.
2852
+ project: The project name/ID to filter by.
2838
2853
  user: Filter by user name/ID.
2839
2854
  name: The name of the event_source to filter by.
2840
2855
  flavor: The flavor of the event_source to filter by.
@@ -2850,8 +2865,7 @@ class Client(metaclass=ClientMetaClass):
2850
2865
  size=size,
2851
2866
  sort_by=sort_by,
2852
2867
  logical_operator=logical_operator,
2853
- workspace_id=workspace_id,
2854
- user_id=user_id,
2868
+ project=project or self.active_project.id,
2855
2869
  user=user,
2856
2870
  name=name,
2857
2871
  flavor=flavor,
@@ -2860,7 +2874,6 @@ class Client(metaclass=ClientMetaClass):
2860
2874
  created=created,
2861
2875
  updated=updated,
2862
2876
  )
2863
- event_source_filter_model.set_scope_workspace(self.active_workspace.id)
2864
2877
  return self.zen_store.list_event_sources(
2865
2878
  event_source_filter_model, hydrate=hydrate
2866
2879
  )
@@ -2874,8 +2887,9 @@ class Client(metaclass=ClientMetaClass):
2874
2887
  configuration: Optional[Dict[str, Any]] = None,
2875
2888
  rotate_secret: Optional[bool] = None,
2876
2889
  is_active: Optional[bool] = None,
2890
+ project: Optional[Union[str, UUID]] = None,
2877
2891
  ) -> EventSourceResponse:
2878
- """Updates a event_source.
2892
+ """Updates an event_source.
2879
2893
 
2880
2894
  Args:
2881
2895
  name_id_or_prefix: The name, id or prefix of the event_source to update.
@@ -2886,6 +2900,7 @@ class Client(metaclass=ClientMetaClass):
2886
2900
  contain the new secret value
2887
2901
  is_active: Optional[bool] = Allows for activation/deactivating the
2888
2902
  event source
2903
+ project: The project name/ID to filter by.
2889
2904
 
2890
2905
  Returns:
2891
2906
  The model of the updated event_source.
@@ -2895,7 +2910,9 @@ class Client(metaclass=ClientMetaClass):
2895
2910
  """
2896
2911
  # First, get the eve
2897
2912
  event_source = self.get_event_source(
2898
- name_id_or_prefix=name_id_or_prefix, allow_name_prefix_match=False
2913
+ name_id_or_prefix=name_id_or_prefix,
2914
+ allow_name_prefix_match=False,
2915
+ project=project,
2899
2916
  )
2900
2917
 
2901
2918
  # Create the update model
@@ -2921,15 +2938,22 @@ class Client(metaclass=ClientMetaClass):
2921
2938
  return updated_event_source
2922
2939
 
2923
2940
  @_fail_for_sql_zen_store
2924
- def delete_event_source(self, name_id_or_prefix: Union[str, UUID]) -> None:
2941
+ def delete_event_source(
2942
+ self,
2943
+ name_id_or_prefix: Union[str, UUID],
2944
+ project: Optional[Union[str, UUID]] = None,
2945
+ ) -> None:
2925
2946
  """Deletes an event_source.
2926
2947
 
2927
2948
  Args:
2928
2949
  name_id_or_prefix: The name, id or prefix id of the event_source
2929
2950
  to deregister.
2951
+ project: The project name/ID to filter by.
2930
2952
  """
2931
2953
  event_source = self.get_event_source(
2932
- name_id_or_prefix=name_id_or_prefix, allow_name_prefix_match=False
2954
+ name_id_or_prefix=name_id_or_prefix,
2955
+ allow_name_prefix_match=False,
2956
+ project=project,
2933
2957
  )
2934
2958
 
2935
2959
  self.zen_store.delete_event_source(event_source_id=event_source.id)
@@ -2973,8 +2997,7 @@ class Client(metaclass=ClientMetaClass):
2973
2997
  configuration=configuration,
2974
2998
  service_account_id=service_account_id,
2975
2999
  auth_window=auth_window,
2976
- user=self.active_user.id,
2977
- workspace=self.active_workspace.id,
3000
+ project=self.active_project.id,
2978
3001
  )
2979
3002
 
2980
3003
  return self.zen_store.create_action(action=action)
@@ -2984,6 +3007,7 @@ class Client(metaclass=ClientMetaClass):
2984
3007
  self,
2985
3008
  name_id_or_prefix: Union[UUID, str],
2986
3009
  allow_name_prefix_match: bool = True,
3010
+ project: Optional[Union[str, UUID]] = None,
2987
3011
  hydrate: bool = True,
2988
3012
  ) -> ActionResponse:
2989
3013
  """Get an action by name, ID or prefix.
@@ -2991,6 +3015,7 @@ class Client(metaclass=ClientMetaClass):
2991
3015
  Args:
2992
3016
  name_id_or_prefix: The name, ID or prefix of the action.
2993
3017
  allow_name_prefix_match: If True, allow matching by name prefix.
3018
+ project: The project name/ID to filter by.
2994
3019
  hydrate: Flag deciding whether to hydrate the output model(s)
2995
3020
  by including metadata fields in the response.
2996
3021
 
@@ -3002,6 +3027,7 @@ class Client(metaclass=ClientMetaClass):
3002
3027
  list_method=self.list_actions,
3003
3028
  name_id_or_prefix=name_id_or_prefix,
3004
3029
  allow_name_prefix_match=allow_name_prefix_match,
3030
+ project=project,
3005
3031
  hydrate=hydrate,
3006
3032
  )
3007
3033
 
@@ -3018,8 +3044,7 @@ class Client(metaclass=ClientMetaClass):
3018
3044
  name: Optional[str] = None,
3019
3045
  flavor: Optional[str] = None,
3020
3046
  action_type: Optional[str] = None,
3021
- workspace_id: Optional[Union[str, UUID]] = None,
3022
- user_id: Optional[Union[str, UUID]] = None,
3047
+ project: Optional[Union[str, UUID]] = None,
3023
3048
  user: Optional[Union[UUID, str]] = None,
3024
3049
  hydrate: bool = False,
3025
3050
  ) -> Page[ActionResponse]:
@@ -3033,8 +3058,7 @@ class Client(metaclass=ClientMetaClass):
3033
3058
  id: Use the id of the action to filter by.
3034
3059
  created: Use to filter by time of creation
3035
3060
  updated: Use the last updated date for filtering
3036
- workspace_id: The id of the workspace to filter by.
3037
- user_id: The id of the user to filter by.
3061
+ project: The project name/ID to filter by.
3038
3062
  user: Filter by user name/ID.
3039
3063
  name: The name of the action to filter by.
3040
3064
  flavor: The flavor of the action to filter by.
@@ -3050,8 +3074,7 @@ class Client(metaclass=ClientMetaClass):
3050
3074
  size=size,
3051
3075
  sort_by=sort_by,
3052
3076
  logical_operator=logical_operator,
3053
- workspace_id=workspace_id,
3054
- user_id=user_id,
3077
+ project=project or self.active_project.id,
3055
3078
  user=user,
3056
3079
  name=name,
3057
3080
  id=id,
@@ -3060,7 +3083,6 @@ class Client(metaclass=ClientMetaClass):
3060
3083
  created=created,
3061
3084
  updated=updated,
3062
3085
  )
3063
- filter_model.set_scope_workspace(self.active_workspace.id)
3064
3086
  return self.zen_store.list_actions(filter_model, hydrate=hydrate)
3065
3087
 
3066
3088
  @_fail_for_sql_zen_store
@@ -3072,6 +3094,7 @@ class Client(metaclass=ClientMetaClass):
3072
3094
  configuration: Optional[Dict[str, Any]] = None,
3073
3095
  service_account_id: Optional[UUID] = None,
3074
3096
  auth_window: Optional[int] = None,
3097
+ project: Optional[Union[str, UUID]] = None,
3075
3098
  ) -> ActionResponse:
3076
3099
  """Update an action.
3077
3100
 
@@ -3085,12 +3108,15 @@ class Client(metaclass=ClientMetaClass):
3085
3108
  auth_window: The new time window in minutes for which the service
3086
3109
  account is authorized to execute the action. Set this to 0 to
3087
3110
  authorize the service account indefinitely (not recommended).
3111
+ project: The project name/ID to filter by.
3088
3112
 
3089
3113
  Returns:
3090
3114
  The updated action.
3091
3115
  """
3092
3116
  action = self.get_action(
3093
- name_id_or_prefix=name_id_or_prefix, allow_name_prefix_match=False
3117
+ name_id_or_prefix=name_id_or_prefix,
3118
+ allow_name_prefix_match=False,
3119
+ project=project,
3094
3120
  )
3095
3121
 
3096
3122
  update_model = ActionUpdate(
@@ -3107,15 +3133,22 @@ class Client(metaclass=ClientMetaClass):
3107
3133
  )
3108
3134
 
3109
3135
  @_fail_for_sql_zen_store
3110
- def delete_action(self, name_id_or_prefix: Union[str, UUID]) -> None:
3136
+ def delete_action(
3137
+ self,
3138
+ name_id_or_prefix: Union[str, UUID],
3139
+ project: Optional[Union[str, UUID]] = None,
3140
+ ) -> None:
3111
3141
  """Delete an action.
3112
3142
 
3113
3143
  Args:
3114
3144
  name_id_or_prefix: The name, id or prefix id of the action
3115
3145
  to delete.
3146
+ project: The project name/ID to filter by.
3116
3147
  """
3117
3148
  action = self.get_action(
3118
- name_id_or_prefix=name_id_or_prefix, allow_name_prefix_match=False
3149
+ name_id_or_prefix=name_id_or_prefix,
3150
+ allow_name_prefix_match=False,
3151
+ project=project,
3119
3152
  )
3120
3153
 
3121
3154
  self.zen_store.delete_action(action_id=action.id)
@@ -3150,8 +3183,7 @@ class Client(metaclass=ClientMetaClass):
3150
3183
  event_source_id=event_source_id,
3151
3184
  event_filter=event_filter,
3152
3185
  action_id=action_id,
3153
- user=self.active_user.id,
3154
- workspace=self.active_workspace.id,
3186
+ project=self.active_project.id,
3155
3187
  )
3156
3188
 
3157
3189
  return self.zen_store.create_trigger(trigger=trigger)
@@ -3161,6 +3193,7 @@ class Client(metaclass=ClientMetaClass):
3161
3193
  self,
3162
3194
  name_id_or_prefix: Union[UUID, str],
3163
3195
  allow_name_prefix_match: bool = True,
3196
+ project: Optional[Union[str, UUID]] = None,
3164
3197
  hydrate: bool = True,
3165
3198
  ) -> TriggerResponse:
3166
3199
  """Get a trigger by name, ID or prefix.
@@ -3168,6 +3201,7 @@ class Client(metaclass=ClientMetaClass):
3168
3201
  Args:
3169
3202
  name_id_or_prefix: The name, ID or prefix of the trigger.
3170
3203
  allow_name_prefix_match: If True, allow matching by name prefix.
3204
+ project: The project name/ID to filter by.
3171
3205
  hydrate: Flag deciding whether to hydrate the output model(s)
3172
3206
  by including metadata fields in the response.
3173
3207
 
@@ -3179,6 +3213,7 @@ class Client(metaclass=ClientMetaClass):
3179
3213
  list_method=self.list_triggers,
3180
3214
  name_id_or_prefix=name_id_or_prefix,
3181
3215
  allow_name_prefix_match=allow_name_prefix_match,
3216
+ project=project,
3182
3217
  hydrate=hydrate,
3183
3218
  )
3184
3219
 
@@ -3199,8 +3234,7 @@ class Client(metaclass=ClientMetaClass):
3199
3234
  event_source_subtype: Optional[str] = None,
3200
3235
  action_flavor: Optional[str] = None,
3201
3236
  action_subtype: Optional[str] = None,
3202
- workspace_id: Optional[Union[str, UUID]] = None,
3203
- user_id: Optional[Union[str, UUID]] = None,
3237
+ project: Optional[Union[str, UUID]] = None,
3204
3238
  user: Optional[Union[UUID, str]] = None,
3205
3239
  hydrate: bool = False,
3206
3240
  ) -> Page[TriggerResponse]:
@@ -3214,8 +3248,7 @@ class Client(metaclass=ClientMetaClass):
3214
3248
  id: Use the id of triggers to filter by.
3215
3249
  created: Use to filter by time of creation
3216
3250
  updated: Use the last updated date for filtering
3217
- workspace_id: The id of the workspace to filter by.
3218
- user_id: The id of the user to filter by.
3251
+ project: The project name/ID to filter by.
3219
3252
  user: Filter by user name/ID.
3220
3253
  name: The name of the trigger to filter by.
3221
3254
  event_source_id: The event source associated with the trigger.
@@ -3237,8 +3270,7 @@ class Client(metaclass=ClientMetaClass):
3237
3270
  size=size,
3238
3271
  sort_by=sort_by,
3239
3272
  logical_operator=logical_operator,
3240
- workspace_id=workspace_id,
3241
- user_id=user_id,
3273
+ project=project or self.active_project.id,
3242
3274
  user=user,
3243
3275
  name=name,
3244
3276
  event_source_id=event_source_id,
@@ -3251,7 +3283,6 @@ class Client(metaclass=ClientMetaClass):
3251
3283
  created=created,
3252
3284
  updated=updated,
3253
3285
  )
3254
- trigger_filter_model.set_scope_workspace(self.active_workspace.id)
3255
3286
  return self.zen_store.list_triggers(
3256
3287
  trigger_filter_model, hydrate=hydrate
3257
3288
  )
@@ -3264,6 +3295,7 @@ class Client(metaclass=ClientMetaClass):
3264
3295
  description: Optional[str] = None,
3265
3296
  event_filter: Optional[Dict[str, Any]] = None,
3266
3297
  is_active: Optional[bool] = None,
3298
+ project: Optional[Union[str, UUID]] = None,
3267
3299
  ) -> TriggerResponse:
3268
3300
  """Updates a trigger.
3269
3301
 
@@ -3273,6 +3305,7 @@ class Client(metaclass=ClientMetaClass):
3273
3305
  description: the new description of the trigger.
3274
3306
  event_filter: The event filter configuration.
3275
3307
  is_active: Whether the trigger is active or not.
3308
+ project: The project name/ID to filter by.
3276
3309
 
3277
3310
  Returns:
3278
3311
  The model of the updated trigger.
@@ -3282,7 +3315,9 @@ class Client(metaclass=ClientMetaClass):
3282
3315
  """
3283
3316
  # First, get the eve
3284
3317
  trigger = self.get_trigger(
3285
- name_id_or_prefix=name_id_or_prefix, allow_name_prefix_match=False
3318
+ name_id_or_prefix=name_id_or_prefix,
3319
+ allow_name_prefix_match=False,
3320
+ project=project,
3286
3321
  )
3287
3322
 
3288
3323
  # Create the update model
@@ -3307,15 +3342,22 @@ class Client(metaclass=ClientMetaClass):
3307
3342
  return updated_trigger
3308
3343
 
3309
3344
  @_fail_for_sql_zen_store
3310
- def delete_trigger(self, name_id_or_prefix: Union[str, UUID]) -> None:
3345
+ def delete_trigger(
3346
+ self,
3347
+ name_id_or_prefix: Union[str, UUID],
3348
+ project: Optional[Union[str, UUID]] = None,
3349
+ ) -> None:
3311
3350
  """Deletes an trigger.
3312
3351
 
3313
3352
  Args:
3314
3353
  name_id_or_prefix: The name, id or prefix id of the trigger
3315
3354
  to deregister.
3355
+ project: The project name/ID to filter by.
3316
3356
  """
3317
3357
  trigger = self.get_trigger(
3318
- name_id_or_prefix=name_id_or_prefix, allow_name_prefix_match=False
3358
+ name_id_or_prefix=name_id_or_prefix,
3359
+ allow_name_prefix_match=False,
3360
+ project=project,
3319
3361
  )
3320
3362
 
3321
3363
  self.zen_store.delete_trigger(trigger_id=trigger.id)
@@ -3326,12 +3368,14 @@ class Client(metaclass=ClientMetaClass):
3326
3368
  def get_deployment(
3327
3369
  self,
3328
3370
  id_or_prefix: Union[str, UUID],
3371
+ project: Optional[Union[str, UUID]] = None,
3329
3372
  hydrate: bool = True,
3330
3373
  ) -> PipelineDeploymentResponse:
3331
3374
  """Get a deployment by id or prefix.
3332
3375
 
3333
3376
  Args:
3334
3377
  id_or_prefix: The id or id prefix of the deployment.
3378
+ project: The project name/ID to filter by.
3335
3379
  hydrate: Flag deciding whether to hydrate the output model(s)
3336
3380
  by including metadata fields in the response.
3337
3381
 
@@ -3354,10 +3398,16 @@ class Client(metaclass=ClientMetaClass):
3354
3398
  )
3355
3399
  return self.zen_store.get_deployment(id_, hydrate=hydrate)
3356
3400
 
3357
- entity = self.list_deployments(
3401
+ list_kwargs: Dict[str, Any] = dict(
3358
3402
  id=f"startswith:{id_or_prefix}",
3359
3403
  hydrate=hydrate,
3360
3404
  )
3405
+ scope = ""
3406
+ if project:
3407
+ list_kwargs["project"] = project
3408
+ scope = f" in project {project}"
3409
+
3410
+ entity = self.list_deployments(**list_kwargs)
3361
3411
 
3362
3412
  # If only a single entity is found, return it.
3363
3413
  if entity.total == 1:
@@ -3367,11 +3417,11 @@ class Client(metaclass=ClientMetaClass):
3367
3417
  if entity.total == 0:
3368
3418
  raise KeyError(
3369
3419
  f"No deployment have been found that have either an id or "
3370
- f"prefix that matches the provided string '{id_or_prefix}'."
3420
+ f"prefix that matches the provided string '{id_or_prefix}'{scope}."
3371
3421
  )
3372
3422
 
3373
3423
  raise ZenKeyError(
3374
- f"{entity.total} deployments have been found that have "
3424
+ f"{entity.total} deployments have been found{scope} that have "
3375
3425
  f"an ID that matches the provided "
3376
3426
  f"string '{id_or_prefix}':\n"
3377
3427
  f"{[entity.items]}.\n"
@@ -3388,8 +3438,7 @@ class Client(metaclass=ClientMetaClass):
3388
3438
  id: Optional[Union[UUID, str]] = None,
3389
3439
  created: Optional[Union[datetime, str]] = None,
3390
3440
  updated: Optional[Union[datetime, str]] = None,
3391
- workspace_id: Optional[Union[str, UUID]] = None,
3392
- user_id: Optional[Union[str, UUID]] = None,
3441
+ project: Optional[Union[str, UUID]] = None,
3393
3442
  user: Optional[Union[UUID, str]] = None,
3394
3443
  pipeline_id: Optional[Union[str, UUID]] = None,
3395
3444
  stack_id: Optional[Union[str, UUID]] = None,
@@ -3407,8 +3456,7 @@ class Client(metaclass=ClientMetaClass):
3407
3456
  id: Use the id of build to filter by.
3408
3457
  created: Use to filter by time of creation
3409
3458
  updated: Use the last updated date for filtering
3410
- workspace_id: The id of the workspace to filter by.
3411
- user_id: The id of the user to filter by.
3459
+ project: The project name/ID to filter by.
3412
3460
  user: Filter by user name/ID.
3413
3461
  pipeline_id: The id of the pipeline to filter by.
3414
3462
  stack_id: The id of the stack to filter by.
@@ -3428,28 +3476,33 @@ class Client(metaclass=ClientMetaClass):
3428
3476
  id=id,
3429
3477
  created=created,
3430
3478
  updated=updated,
3431
- workspace_id=workspace_id,
3432
- user_id=user_id,
3479
+ project=project or self.active_project.id,
3433
3480
  user=user,
3434
3481
  pipeline_id=pipeline_id,
3435
3482
  stack_id=stack_id,
3436
3483
  build_id=build_id,
3437
3484
  template_id=template_id,
3438
3485
  )
3439
- deployment_filter_model.set_scope_workspace(self.active_workspace.id)
3440
3486
  return self.zen_store.list_deployments(
3441
3487
  deployment_filter_model=deployment_filter_model,
3442
3488
  hydrate=hydrate,
3443
3489
  )
3444
3490
 
3445
- def delete_deployment(self, id_or_prefix: str) -> None:
3491
+ def delete_deployment(
3492
+ self,
3493
+ id_or_prefix: str,
3494
+ project: Optional[Union[str, UUID]] = None,
3495
+ ) -> None:
3446
3496
  """Delete a deployment.
3447
3497
 
3448
3498
  Args:
3449
3499
  id_or_prefix: The id or id prefix of the deployment.
3500
+ project: The project name/ID to filter by.
3450
3501
  """
3451
3502
  deployment = self.get_deployment(
3452
- id_or_prefix=id_or_prefix, hydrate=False
3503
+ id_or_prefix=id_or_prefix,
3504
+ project=project,
3505
+ hydrate=False,
3453
3506
  )
3454
3507
  self.zen_store.delete_deployment(deployment_id=deployment.id)
3455
3508
 
@@ -3480,20 +3533,21 @@ class Client(metaclass=ClientMetaClass):
3480
3533
  description=description,
3481
3534
  source_deployment_id=deployment_id,
3482
3535
  tags=tags,
3483
- user=self.active_user.id,
3484
- workspace=self.active_workspace.id,
3536
+ project=self.active_project.id,
3485
3537
  )
3486
3538
  )
3487
3539
 
3488
3540
  def get_run_template(
3489
3541
  self,
3490
3542
  name_id_or_prefix: Union[str, UUID],
3543
+ project: Optional[Union[str, UUID]] = None,
3491
3544
  hydrate: bool = True,
3492
3545
  ) -> RunTemplateResponse:
3493
3546
  """Get a run template.
3494
3547
 
3495
3548
  Args:
3496
3549
  name_id_or_prefix: Name/ID/ID prefix of the template to get.
3550
+ project: The project name/ID to filter by.
3497
3551
  hydrate: Flag deciding whether to hydrate the output model(s)
3498
3552
  by including metadata fields in the response.
3499
3553
 
@@ -3505,6 +3559,7 @@ class Client(metaclass=ClientMetaClass):
3505
3559
  list_method=self.list_run_templates,
3506
3560
  name_id_or_prefix=name_id_or_prefix,
3507
3561
  allow_name_prefix_match=False,
3562
+ project=project,
3508
3563
  hydrate=hydrate,
3509
3564
  )
3510
3565
 
@@ -3519,8 +3574,7 @@ class Client(metaclass=ClientMetaClass):
3519
3574
  id: Optional[Union[UUID, str]] = None,
3520
3575
  name: Optional[str] = None,
3521
3576
  tag: Optional[str] = None,
3522
- workspace_id: Optional[Union[str, UUID]] = None,
3523
- user_id: Optional[Union[str, UUID]] = None,
3577
+ project: Optional[Union[str, UUID]] = None,
3524
3578
  pipeline_id: Optional[Union[str, UUID]] = None,
3525
3579
  build_id: Optional[Union[str, UUID]] = None,
3526
3580
  stack_id: Optional[Union[str, UUID]] = None,
@@ -3542,8 +3596,7 @@ class Client(metaclass=ClientMetaClass):
3542
3596
  id: Filter by run template ID.
3543
3597
  name: Filter by run template name.
3544
3598
  tag: Filter by run template tags.
3545
- workspace_id: Filter by workspace ID.
3546
- user_id: Filter by user ID.
3599
+ project: Filter by project name/ID.
3547
3600
  pipeline_id: Filter by pipeline ID.
3548
3601
  build_id: Filter by build ID.
3549
3602
  stack_id: Filter by stack ID.
@@ -3567,8 +3620,7 @@ class Client(metaclass=ClientMetaClass):
3567
3620
  id=id,
3568
3621
  name=name,
3569
3622
  tag=tag,
3570
- workspace_id=workspace_id,
3571
- user_id=user_id,
3623
+ project=project,
3572
3624
  pipeline_id=pipeline_id,
3573
3625
  build_id=build_id,
3574
3626
  stack_id=stack_id,
@@ -3589,6 +3641,7 @@ class Client(metaclass=ClientMetaClass):
3589
3641
  description: Optional[str] = None,
3590
3642
  add_tags: Optional[List[str]] = None,
3591
3643
  remove_tags: Optional[List[str]] = None,
3644
+ project: Optional[Union[str, UUID]] = None,
3592
3645
  ) -> RunTemplateResponse:
3593
3646
  """Update a run template.
3594
3647
 
@@ -3598,6 +3651,7 @@ class Client(metaclass=ClientMetaClass):
3598
3651
  description: The new description of the run template.
3599
3652
  add_tags: Tags to add to the run template.
3600
3653
  remove_tags: Tags to remove from the run template.
3654
+ project: The project name/ID to filter by.
3601
3655
 
3602
3656
  Returns:
3603
3657
  The updated run template.
@@ -3610,7 +3664,9 @@ class Client(metaclass=ClientMetaClass):
3610
3664
  )
3611
3665
  else:
3612
3666
  template_id = self.get_run_template(
3613
- name_id_or_prefix, hydrate=False
3667
+ name_id_or_prefix,
3668
+ project=project,
3669
+ hydrate=False,
3614
3670
  ).id
3615
3671
 
3616
3672
  return self.zen_store.update_run_template(
@@ -3623,11 +3679,16 @@ class Client(metaclass=ClientMetaClass):
3623
3679
  ),
3624
3680
  )
3625
3681
 
3626
- def delete_run_template(self, name_id_or_prefix: Union[str, UUID]) -> None:
3682
+ def delete_run_template(
3683
+ self,
3684
+ name_id_or_prefix: Union[str, UUID],
3685
+ project: Optional[Union[str, UUID]] = None,
3686
+ ) -> None:
3627
3687
  """Delete a run template.
3628
3688
 
3629
3689
  Args:
3630
3690
  name_id_or_prefix: Name/ID/ID prefix of the template to delete.
3691
+ project: The project name/ID to filter by.
3631
3692
  """
3632
3693
  if is_valid_uuid(name_id_or_prefix):
3633
3694
  template_id = (
@@ -3637,7 +3698,9 @@ class Client(metaclass=ClientMetaClass):
3637
3698
  )
3638
3699
  else:
3639
3700
  template_id = self.get_run_template(
3640
- name_id_or_prefix, hydrate=False
3701
+ name_id_or_prefix,
3702
+ project=project,
3703
+ hydrate=False,
3641
3704
  ).id
3642
3705
 
3643
3706
  self.zen_store.delete_run_template(template_id=template_id)
@@ -3648,6 +3711,7 @@ class Client(metaclass=ClientMetaClass):
3648
3711
  self,
3649
3712
  name_id_or_prefix: Union[str, UUID],
3650
3713
  allow_name_prefix_match: bool = True,
3714
+ project: Optional[Union[str, UUID]] = None,
3651
3715
  hydrate: bool = True,
3652
3716
  ) -> ScheduleResponse:
3653
3717
  """Get a schedule by name, id or prefix.
@@ -3655,6 +3719,7 @@ class Client(metaclass=ClientMetaClass):
3655
3719
  Args:
3656
3720
  name_id_or_prefix: The name, id or prefix of the schedule.
3657
3721
  allow_name_prefix_match: If True, allow matching by name prefix.
3722
+ project: The project name/ID to filter by.
3658
3723
  hydrate: Flag deciding whether to hydrate the output model(s)
3659
3724
  by including metadata fields in the response.
3660
3725
 
@@ -3666,6 +3731,7 @@ class Client(metaclass=ClientMetaClass):
3666
3731
  list_method=self.list_schedules,
3667
3732
  name_id_or_prefix=name_id_or_prefix,
3668
3733
  allow_name_prefix_match=allow_name_prefix_match,
3734
+ project=project,
3669
3735
  hydrate=hydrate,
3670
3736
  )
3671
3737
 
@@ -3679,8 +3745,7 @@ class Client(metaclass=ClientMetaClass):
3679
3745
  created: Optional[Union[datetime, str]] = None,
3680
3746
  updated: Optional[Union[datetime, str]] = None,
3681
3747
  name: Optional[str] = None,
3682
- workspace_id: Optional[Union[str, UUID]] = None,
3683
- user_id: Optional[Union[str, UUID]] = None,
3748
+ project: Optional[Union[str, UUID]] = None,
3684
3749
  user: Optional[Union[UUID, str]] = None,
3685
3750
  pipeline_id: Optional[Union[str, UUID]] = None,
3686
3751
  orchestrator_id: Optional[Union[str, UUID]] = None,
@@ -3704,8 +3769,7 @@ class Client(metaclass=ClientMetaClass):
3704
3769
  created: Use to filter by time of creation
3705
3770
  updated: Use the last updated date for filtering
3706
3771
  name: The name of the stack to filter by.
3707
- workspace_id: The id of the workspace to filter by.
3708
- user_id: The id of the user to filter by.
3772
+ project: The project name/ID to filter by.
3709
3773
  user: Filter by user name/ID.
3710
3774
  pipeline_id: The id of the pipeline to filter by.
3711
3775
  orchestrator_id: The id of the orchestrator to filter by.
@@ -3731,8 +3795,7 @@ class Client(metaclass=ClientMetaClass):
3731
3795
  created=created,
3732
3796
  updated=updated,
3733
3797
  name=name,
3734
- workspace_id=workspace_id,
3735
- user_id=user_id,
3798
+ project=project or self.active_project.id,
3736
3799
  user=user,
3737
3800
  pipeline_id=pipeline_id,
3738
3801
  orchestrator_id=orchestrator_id,
@@ -3744,21 +3807,27 @@ class Client(metaclass=ClientMetaClass):
3744
3807
  catchup=catchup,
3745
3808
  run_once_start_time=run_once_start_time,
3746
3809
  )
3747
- schedule_filter_model.set_scope_workspace(self.active_workspace.id)
3748
3810
  return self.zen_store.list_schedules(
3749
3811
  schedule_filter_model=schedule_filter_model,
3750
3812
  hydrate=hydrate,
3751
3813
  )
3752
3814
 
3753
- def delete_schedule(self, name_id_or_prefix: Union[str, UUID]) -> None:
3815
+ def delete_schedule(
3816
+ self,
3817
+ name_id_or_prefix: Union[str, UUID],
3818
+ project: Optional[Union[str, UUID]] = None,
3819
+ ) -> None:
3754
3820
  """Delete a schedule.
3755
3821
 
3756
3822
  Args:
3757
3823
  name_id_or_prefix: The name, id or prefix id of the schedule
3758
3824
  to delete.
3825
+ project: The project name/ID to filter by.
3759
3826
  """
3760
3827
  schedule = self.get_schedule(
3761
- name_id_or_prefix=name_id_or_prefix, allow_name_prefix_match=False
3828
+ name_id_or_prefix=name_id_or_prefix,
3829
+ allow_name_prefix_match=False,
3830
+ project=project,
3762
3831
  )
3763
3832
  logger.warning(
3764
3833
  f"Deleting schedule '{name_id_or_prefix}'... This will only delete "
@@ -3773,6 +3842,7 @@ class Client(metaclass=ClientMetaClass):
3773
3842
  self,
3774
3843
  name_id_or_prefix: Union[str, UUID],
3775
3844
  allow_name_prefix_match: bool = True,
3845
+ project: Optional[Union[str, UUID]] = None,
3776
3846
  hydrate: bool = True,
3777
3847
  ) -> PipelineRunResponse:
3778
3848
  """Gets a pipeline run by name, ID, or prefix.
@@ -3780,6 +3850,7 @@ class Client(metaclass=ClientMetaClass):
3780
3850
  Args:
3781
3851
  name_id_or_prefix: Name, ID, or prefix of the pipeline run.
3782
3852
  allow_name_prefix_match: If True, allow matching by name prefix.
3853
+ project: The project name/ID to filter by.
3783
3854
  hydrate: Flag deciding whether to hydrate the output model(s)
3784
3855
  by including metadata fields in the response.
3785
3856
 
@@ -3791,6 +3862,7 @@ class Client(metaclass=ClientMetaClass):
3791
3862
  list_method=self.list_pipeline_runs,
3792
3863
  name_id_or_prefix=name_id_or_prefix,
3793
3864
  allow_name_prefix_match=allow_name_prefix_match,
3865
+ project=project,
3794
3866
  hydrate=hydrate,
3795
3867
  )
3796
3868
 
@@ -3804,10 +3876,9 @@ class Client(metaclass=ClientMetaClass):
3804
3876
  created: Optional[Union[datetime, str]] = None,
3805
3877
  updated: Optional[Union[datetime, str]] = None,
3806
3878
  name: Optional[str] = None,
3807
- workspace_id: Optional[Union[str, UUID]] = None,
3879
+ project: Optional[Union[str, UUID]] = None,
3808
3880
  pipeline_id: Optional[Union[str, UUID]] = None,
3809
3881
  pipeline_name: Optional[str] = None,
3810
- user_id: Optional[Union[str, UUID]] = None,
3811
3882
  stack_id: Optional[Union[str, UUID]] = None,
3812
3883
  schedule_id: Optional[Union[str, UUID]] = None,
3813
3884
  build_id: Optional[Union[str, UUID]] = None,
@@ -3819,10 +3890,10 @@ class Client(metaclass=ClientMetaClass):
3819
3890
  status: Optional[str] = None,
3820
3891
  start_time: Optional[Union[datetime, str]] = None,
3821
3892
  end_time: Optional[Union[datetime, str]] = None,
3822
- num_steps: Optional[Union[int, str]] = None,
3823
3893
  unlisted: Optional[bool] = None,
3824
3894
  templatable: Optional[bool] = None,
3825
3895
  tag: Optional[str] = None,
3896
+ tags: Optional[List[str]] = None,
3826
3897
  user: Optional[Union[UUID, str]] = None,
3827
3898
  run_metadata: Optional[Dict[str, Any]] = None,
3828
3899
  pipeline: Optional[Union[UUID, str]] = None,
@@ -3842,11 +3913,10 @@ class Client(metaclass=ClientMetaClass):
3842
3913
  id: The id of the runs to filter by.
3843
3914
  created: Use to filter by time of creation
3844
3915
  updated: Use the last updated date for filtering
3845
- workspace_id: The id of the workspace to filter by.
3916
+ project: The project name/ID to filter by.
3846
3917
  pipeline_id: The id of the pipeline to filter by.
3847
3918
  pipeline_name: DEPRECATED. Use `pipeline` instead to filter by
3848
3919
  pipeline name.
3849
- user_id: The id of the user to filter by.
3850
3920
  stack_id: The id of the stack to filter by.
3851
3921
  schedule_id: The id of the schedule to filter by.
3852
3922
  build_id: The id of the build to filter by.
@@ -3859,10 +3929,10 @@ class Client(metaclass=ClientMetaClass):
3859
3929
  status: The status of the pipeline run
3860
3930
  start_time: The start_time for the pipeline run
3861
3931
  end_time: The end_time for the pipeline run
3862
- num_steps: The number of steps for the pipeline run
3863
3932
  unlisted: If the runs should be unlisted or not.
3864
3933
  templatable: If the runs should be templatable or not.
3865
3934
  tag: Tag to filter by.
3935
+ tags: Tags to filter by.
3866
3936
  user: The name/ID of the user to filter by.
3867
3937
  run_metadata: The run_metadata of the run to filter by.
3868
3938
  pipeline: The name/ID of the pipeline to filter by.
@@ -3885,7 +3955,7 @@ class Client(metaclass=ClientMetaClass):
3885
3955
  created=created,
3886
3956
  updated=updated,
3887
3957
  name=name,
3888
- workspace_id=workspace_id,
3958
+ project=project or self.active_project.id,
3889
3959
  pipeline_id=pipeline_id,
3890
3960
  pipeline_name=pipeline_name,
3891
3961
  schedule_id=schedule_id,
@@ -3895,13 +3965,12 @@ class Client(metaclass=ClientMetaClass):
3895
3965
  template_id=template_id,
3896
3966
  model_version_id=model_version_id,
3897
3967
  orchestrator_run_id=orchestrator_run_id,
3898
- user_id=user_id,
3899
3968
  stack_id=stack_id,
3900
3969
  status=status,
3901
3970
  start_time=start_time,
3902
3971
  end_time=end_time,
3903
- num_steps=num_steps,
3904
3972
  tag=tag,
3973
+ tags=tags,
3905
3974
  unlisted=unlisted,
3906
3975
  user=user,
3907
3976
  run_metadata=run_metadata,
@@ -3912,7 +3981,6 @@ class Client(metaclass=ClientMetaClass):
3912
3981
  stack_component=stack_component,
3913
3982
  templatable=templatable,
3914
3983
  )
3915
- runs_filter_model.set_scope_workspace(self.active_workspace.id)
3916
3984
  return self.zen_store.list_runs(
3917
3985
  runs_filter_model=runs_filter_model,
3918
3986
  hydrate=hydrate,
@@ -3921,14 +3989,18 @@ class Client(metaclass=ClientMetaClass):
3921
3989
  def delete_pipeline_run(
3922
3990
  self,
3923
3991
  name_id_or_prefix: Union[str, UUID],
3992
+ project: Optional[Union[str, UUID]] = None,
3924
3993
  ) -> None:
3925
3994
  """Deletes a pipeline run.
3926
3995
 
3927
3996
  Args:
3928
3997
  name_id_or_prefix: Name, ID, or prefix of the pipeline run.
3998
+ project: The project name/ID to filter by.
3929
3999
  """
3930
4000
  run = self.get_pipeline_run(
3931
- name_id_or_prefix=name_id_or_prefix, allow_name_prefix_match=False
4001
+ name_id_or_prefix=name_id_or_prefix,
4002
+ allow_name_prefix_match=False,
4003
+ project=project,
3932
4004
  )
3933
4005
  self.zen_store.delete_run(run_id=run.id)
3934
4006
 
@@ -3972,8 +4044,7 @@ class Client(metaclass=ClientMetaClass):
3972
4044
  pipeline_run_id: Optional[Union[str, UUID]] = None,
3973
4045
  deployment_id: Optional[Union[str, UUID]] = None,
3974
4046
  original_step_run_id: Optional[Union[str, UUID]] = None,
3975
- workspace_id: Optional[Union[str, UUID]] = None,
3976
- user_id: Optional[Union[str, UUID]] = None,
4047
+ project: Optional[Union[str, UUID]] = None,
3977
4048
  user: Optional[Union[UUID, str]] = None,
3978
4049
  model_version_id: Optional[Union[str, UUID]] = None,
3979
4050
  model: Optional[Union[UUID, str]] = None,
@@ -3992,8 +4063,7 @@ class Client(metaclass=ClientMetaClass):
3992
4063
  updated: Use the last updated date for filtering
3993
4064
  start_time: Use to filter by the time when the step started running
3994
4065
  end_time: Use to filter by the time when the step finished running
3995
- workspace_id: The id of the workspace to filter by.
3996
- user_id: The id of the user to filter by.
4066
+ project: The project name/ID to filter by.
3997
4067
  user: Filter by user name/ID.
3998
4068
  pipeline_run_id: The id of the pipeline run to filter by.
3999
4069
  deployment_id: The id of the deployment to filter by.
@@ -4028,14 +4098,12 @@ class Client(metaclass=ClientMetaClass):
4028
4098
  start_time=start_time,
4029
4099
  end_time=end_time,
4030
4100
  name=name,
4031
- workspace_id=workspace_id,
4032
- user_id=user_id,
4101
+ project=project or self.active_project.id,
4033
4102
  user=user,
4034
4103
  model_version_id=model_version_id,
4035
4104
  model=model,
4036
4105
  run_metadata=run_metadata,
4037
4106
  )
4038
- step_run_filter_model.set_scope_workspace(self.active_workspace.id)
4039
4107
  return self.zen_store.list_run_steps(
4040
4108
  step_run_filter_model=step_run_filter_model,
4041
4109
  hydrate=hydrate,
@@ -4046,12 +4114,14 @@ class Client(metaclass=ClientMetaClass):
4046
4114
  def get_artifact(
4047
4115
  self,
4048
4116
  name_id_or_prefix: Union[str, UUID],
4117
+ project: Optional[Union[str, UUID]] = None,
4049
4118
  hydrate: bool = False,
4050
4119
  ) -> ArtifactResponse:
4051
4120
  """Get an artifact by name, id or prefix.
4052
4121
 
4053
4122
  Args:
4054
4123
  name_id_or_prefix: The name, ID or prefix of the artifact to get.
4124
+ project: The project name/ID to filter by.
4055
4125
  hydrate: Flag deciding whether to hydrate the output model(s)
4056
4126
  by including metadata fields in the response.
4057
4127
 
@@ -4062,6 +4132,7 @@ class Client(metaclass=ClientMetaClass):
4062
4132
  get_method=self.zen_store.get_artifact,
4063
4133
  list_method=self.list_artifacts,
4064
4134
  name_id_or_prefix=name_id_or_prefix,
4135
+ project=project,
4065
4136
  hydrate=hydrate,
4066
4137
  )
4067
4138
 
@@ -4076,8 +4147,11 @@ class Client(metaclass=ClientMetaClass):
4076
4147
  updated: Optional[Union[datetime, str]] = None,
4077
4148
  name: Optional[str] = None,
4078
4149
  has_custom_name: Optional[bool] = None,
4150
+ user: Optional[Union[UUID, str]] = None,
4151
+ project: Optional[Union[str, UUID]] = None,
4079
4152
  hydrate: bool = False,
4080
4153
  tag: Optional[str] = None,
4154
+ tags: Optional[List[str]] = None,
4081
4155
  ) -> Page[ArtifactResponse]:
4082
4156
  """Get a list of artifacts.
4083
4157
 
@@ -4091,9 +4165,12 @@ class Client(metaclass=ClientMetaClass):
4091
4165
  updated: Use the last updated date for filtering
4092
4166
  name: The name of the artifact to filter by.
4093
4167
  has_custom_name: Filter artifacts with/without custom names.
4168
+ user: Filter by user name or ID.
4169
+ project: The project name/ID to filter by.
4094
4170
  hydrate: Flag deciding whether to hydrate the output model(s)
4095
4171
  by including metadata fields in the response.
4096
4172
  tag: Filter artifacts by tag.
4173
+ tags: Tags to filter by.
4097
4174
 
4098
4175
  Returns:
4099
4176
  A list of artifacts.
@@ -4109,6 +4186,9 @@ class Client(metaclass=ClientMetaClass):
4109
4186
  name=name,
4110
4187
  has_custom_name=has_custom_name,
4111
4188
  tag=tag,
4189
+ tags=tags,
4190
+ user=user,
4191
+ project=project or self.active_project.id,
4112
4192
  )
4113
4193
  return self.zen_store.list_artifacts(
4114
4194
  artifact_filter_model,
@@ -4122,6 +4202,7 @@ class Client(metaclass=ClientMetaClass):
4122
4202
  add_tags: Optional[List[str]] = None,
4123
4203
  remove_tags: Optional[List[str]] = None,
4124
4204
  has_custom_name: Optional[bool] = None,
4205
+ project: Optional[Union[str, UUID]] = None,
4125
4206
  ) -> ArtifactResponse:
4126
4207
  """Update an artifact.
4127
4208
 
@@ -4131,11 +4212,15 @@ class Client(metaclass=ClientMetaClass):
4131
4212
  add_tags: Tags to add to the artifact.
4132
4213
  remove_tags: Tags to remove from the artifact.
4133
4214
  has_custom_name: Whether the artifact has a custom name.
4215
+ project: The project name/ID to filter by.
4134
4216
 
4135
4217
  Returns:
4136
4218
  The updated artifact.
4137
4219
  """
4138
- artifact = self.get_artifact(name_id_or_prefix=name_id_or_prefix)
4220
+ artifact = self.get_artifact(
4221
+ name_id_or_prefix=name_id_or_prefix,
4222
+ project=project,
4223
+ )
4139
4224
  artifact_update = ArtifactUpdate(
4140
4225
  name=new_name,
4141
4226
  add_tags=add_tags,
@@ -4149,13 +4234,18 @@ class Client(metaclass=ClientMetaClass):
4149
4234
  def delete_artifact(
4150
4235
  self,
4151
4236
  name_id_or_prefix: Union[str, UUID],
4237
+ project: Optional[Union[str, UUID]] = None,
4152
4238
  ) -> None:
4153
4239
  """Delete an artifact.
4154
4240
 
4155
4241
  Args:
4156
4242
  name_id_or_prefix: The name, ID or prefix of the artifact to delete.
4243
+ project: The project name/ID to filter by.
4157
4244
  """
4158
- artifact = self.get_artifact(name_id_or_prefix=name_id_or_prefix)
4245
+ artifact = self.get_artifact(
4246
+ name_id_or_prefix=name_id_or_prefix,
4247
+ project=project,
4248
+ )
4159
4249
  self.zen_store.delete_artifact(artifact_id=artifact.id)
4160
4250
  logger.info(f"Deleted artifact '{artifact.name}'.")
4161
4251
 
@@ -4163,23 +4253,31 @@ class Client(metaclass=ClientMetaClass):
4163
4253
  self,
4164
4254
  only_versions: bool = True,
4165
4255
  delete_from_artifact_store: bool = False,
4256
+ project: Optional[Union[str, UUID]] = None,
4166
4257
  ) -> None:
4167
4258
  """Delete all unused artifacts and artifact versions.
4168
4259
 
4169
4260
  Args:
4170
4261
  only_versions: Only delete artifact versions, keeping artifacts
4171
4262
  delete_from_artifact_store: Delete data from artifact metadata
4263
+ project: The project name/ID to filter by.
4172
4264
  """
4173
4265
  if delete_from_artifact_store:
4174
4266
  unused_artifact_versions = depaginate(
4175
- self.list_artifact_versions, only_unused=True
4267
+ self.list_artifact_versions,
4268
+ only_unused=True,
4269
+ project=project,
4176
4270
  )
4177
4271
  for unused_artifact_version in unused_artifact_versions:
4178
4272
  self._delete_artifact_from_artifact_store(
4179
4273
  unused_artifact_version
4180
4274
  )
4181
4275
 
4182
- self.zen_store.prune_artifact_versions(only_versions)
4276
+ project = project or self.active_project.id
4277
+
4278
+ self.zen_store.prune_artifact_versions(
4279
+ project_name_or_id=project, only_versions=only_versions
4280
+ )
4183
4281
  logger.info("All unused artifacts and artifact versions deleted.")
4184
4282
 
4185
4283
  # --------------------------- Artifact Versions ---------------------------
@@ -4188,6 +4286,7 @@ class Client(metaclass=ClientMetaClass):
4188
4286
  self,
4189
4287
  name_id_or_prefix: Union[str, UUID],
4190
4288
  version: Optional[str] = None,
4289
+ project: Optional[Union[str, UUID]] = None,
4191
4290
  hydrate: bool = True,
4192
4291
  ) -> ArtifactVersionResponse:
4193
4292
  """Get an artifact version by ID or artifact name.
@@ -4198,6 +4297,7 @@ class Client(metaclass=ClientMetaClass):
4198
4297
  version: The version of the artifact to get. Only used if
4199
4298
  `name_id_or_prefix` is the name of the artifact. If not
4200
4299
  specified, the latest version is returned.
4300
+ project: The project name/ID to filter by.
4201
4301
  hydrate: Flag deciding whether to hydrate the output model(s)
4202
4302
  by including metadata fields in the response.
4203
4303
 
@@ -4210,6 +4310,7 @@ class Client(metaclass=ClientMetaClass):
4210
4310
  method_name="get_artifact_version",
4211
4311
  name_id_or_prefix=name_id_or_prefix,
4212
4312
  version=version,
4313
+ project=project,
4213
4314
  hydrate=hydrate,
4214
4315
  ):
4215
4316
  return cll # type: ignore[return-value]
@@ -4219,6 +4320,7 @@ class Client(metaclass=ClientMetaClass):
4219
4320
  list_method=self.list_artifact_versions,
4220
4321
  name_id_or_prefix=name_id_or_prefix,
4221
4322
  version=version,
4323
+ project=project,
4222
4324
  hydrate=hydrate,
4223
4325
  )
4224
4326
  try:
@@ -4243,7 +4345,7 @@ class Client(metaclass=ClientMetaClass):
4243
4345
  id: Optional[Union[UUID, str]] = None,
4244
4346
  created: Optional[Union[datetime, str]] = None,
4245
4347
  updated: Optional[Union[datetime, str]] = None,
4246
- artifact_id: Optional[Union[str, UUID]] = None,
4348
+ artifact: Optional[Union[str, UUID]] = None,
4247
4349
  name: Optional[str] = None,
4248
4350
  version: Optional[Union[str, int]] = None,
4249
4351
  version_number: Optional[int] = None,
@@ -4252,8 +4354,7 @@ class Client(metaclass=ClientMetaClass):
4252
4354
  data_type: Optional[str] = None,
4253
4355
  uri: Optional[str] = None,
4254
4356
  materializer: Optional[str] = None,
4255
- workspace_id: Optional[Union[str, UUID]] = None,
4256
- user_id: Optional[Union[str, UUID]] = None,
4357
+ project: Optional[Union[str, UUID]] = None,
4257
4358
  model_version_id: Optional[Union[str, UUID]] = None,
4258
4359
  only_unused: Optional[bool] = False,
4259
4360
  has_custom_name: Optional[bool] = None,
@@ -4262,6 +4363,7 @@ class Client(metaclass=ClientMetaClass):
4262
4363
  pipeline_run: Optional[Union[UUID, str]] = None,
4263
4364
  run_metadata: Optional[Dict[str, Any]] = None,
4264
4365
  tag: Optional[str] = None,
4366
+ tags: Optional[List[str]] = None,
4265
4367
  hydrate: bool = False,
4266
4368
  ) -> Page[ArtifactVersionResponse]:
4267
4369
  """Get a list of artifact versions.
@@ -4274,7 +4376,7 @@ class Client(metaclass=ClientMetaClass):
4274
4376
  id: Use the id of artifact version to filter by.
4275
4377
  created: Use to filter by time of creation
4276
4378
  updated: Use the last updated date for filtering
4277
- artifact_id: The id of the artifact to filter by.
4379
+ artifact: The name or ID of the artifact to filter by.
4278
4380
  name: The name of the artifact to filter by.
4279
4381
  version: The version of the artifact to filter by.
4280
4382
  version_number: The version number of the artifact to filter by.
@@ -4283,13 +4385,13 @@ class Client(metaclass=ClientMetaClass):
4283
4385
  data_type: The data type of the artifact to filter by.
4284
4386
  uri: The uri of the artifact to filter by.
4285
4387
  materializer: The materializer of the artifact to filter by.
4286
- workspace_id: The id of the workspace to filter by.
4287
- user_id: The id of the user to filter by.
4388
+ project: The project name/ID to filter by.
4288
4389
  model_version_id: Filter by model version ID.
4289
4390
  only_unused: Only return artifact versions that are not used in
4290
4391
  any pipeline runs.
4291
4392
  has_custom_name: Filter artifacts with/without custom names.
4292
4393
  tag: A tag to filter by.
4394
+ tags: Tags to filter by.
4293
4395
  user: Filter by user name or ID.
4294
4396
  model: Filter by model name or ID.
4295
4397
  pipeline_run: Filter by pipeline run name or ID.
@@ -4300,6 +4402,9 @@ class Client(metaclass=ClientMetaClass):
4300
4402
  Returns:
4301
4403
  A list of artifact versions.
4302
4404
  """
4405
+ if name:
4406
+ artifact = name
4407
+
4303
4408
  artifact_version_filter_model = ArtifactVersionFilter(
4304
4409
  sort_by=sort_by,
4305
4410
  page=page,
@@ -4308,8 +4413,7 @@ class Client(metaclass=ClientMetaClass):
4308
4413
  id=id,
4309
4414
  created=created,
4310
4415
  updated=updated,
4311
- artifact_id=artifact_id,
4312
- name=name,
4416
+ artifact=artifact,
4313
4417
  version=str(version) if version else None,
4314
4418
  version_number=version_number,
4315
4419
  artifact_store_id=artifact_store_id,
@@ -4317,20 +4421,17 @@ class Client(metaclass=ClientMetaClass):
4317
4421
  data_type=data_type,
4318
4422
  uri=uri,
4319
4423
  materializer=materializer,
4320
- workspace_id=workspace_id,
4321
- user_id=user_id,
4424
+ project=project or self.active_project.id,
4322
4425
  model_version_id=model_version_id,
4323
4426
  only_unused=only_unused,
4324
4427
  has_custom_name=has_custom_name,
4325
4428
  tag=tag,
4429
+ tags=tags,
4326
4430
  user=user,
4327
4431
  model=model,
4328
4432
  pipeline_run=pipeline_run,
4329
4433
  run_metadata=run_metadata,
4330
4434
  )
4331
- artifact_version_filter_model.set_scope_workspace(
4332
- self.active_workspace.id
4333
- )
4334
4435
  return self.zen_store.list_artifact_versions(
4335
4436
  artifact_version_filter_model,
4336
4437
  hydrate=hydrate,
@@ -4342,6 +4443,7 @@ class Client(metaclass=ClientMetaClass):
4342
4443
  version: Optional[str] = None,
4343
4444
  add_tags: Optional[List[str]] = None,
4344
4445
  remove_tags: Optional[List[str]] = None,
4446
+ project: Optional[Union[str, UUID]] = None,
4345
4447
  ) -> ArtifactVersionResponse:
4346
4448
  """Update an artifact version.
4347
4449
 
@@ -4352,6 +4454,7 @@ class Client(metaclass=ClientMetaClass):
4352
4454
  specified, the latest version is updated.
4353
4455
  add_tags: Tags to add to the artifact version.
4354
4456
  remove_tags: Tags to remove from the artifact version.
4457
+ project: The project name/ID to filter by.
4355
4458
 
4356
4459
  Returns:
4357
4460
  The updated artifact version.
@@ -4359,6 +4462,7 @@ class Client(metaclass=ClientMetaClass):
4359
4462
  artifact_version = self.get_artifact_version(
4360
4463
  name_id_or_prefix=name_id_or_prefix,
4361
4464
  version=version,
4465
+ project=project,
4362
4466
  )
4363
4467
  artifact_version_update = ArtifactVersionUpdate(
4364
4468
  add_tags=add_tags, remove_tags=remove_tags
@@ -4374,6 +4478,7 @@ class Client(metaclass=ClientMetaClass):
4374
4478
  version: Optional[str] = None,
4375
4479
  delete_metadata: bool = True,
4376
4480
  delete_from_artifact_store: bool = False,
4481
+ project: Optional[Union[str, UUID]] = None,
4377
4482
  ) -> None:
4378
4483
  """Delete an artifact version.
4379
4484
 
@@ -4387,10 +4492,13 @@ class Client(metaclass=ClientMetaClass):
4387
4492
  delete_metadata: If True, delete the metadata of the artifact
4388
4493
  version from the database.
4389
4494
  delete_from_artifact_store: If True, delete the artifact object
4390
- itself from the artifact store.
4495
+ itself from the artifact store.
4496
+ project: The project name/ID to filter by.
4391
4497
  """
4392
4498
  artifact_version = self.get_artifact_version(
4393
- name_id_or_prefix=name_id_or_prefix, version=version
4499
+ name_id_or_prefix=name_id_or_prefix,
4500
+ version=version,
4501
+ project=project,
4394
4502
  )
4395
4503
  if delete_from_artifact_store:
4396
4504
  self._delete_artifact_from_artifact_store(
@@ -4513,8 +4621,7 @@ class Client(metaclass=ClientMetaClass):
4513
4621
  types[key] = metadata_type
4514
4622
 
4515
4623
  run_metadata = RunMetadataRequest(
4516
- workspace=self.active_workspace.id,
4517
- user=self.active_user.id,
4624
+ project=self.active_project.id,
4518
4625
  resources=resources,
4519
4626
  stack_component_id=stack_component_id,
4520
4627
  publisher_step_id=publisher_step_id,
@@ -4529,14 +4636,15 @@ class Client(metaclass=ClientMetaClass):
4529
4636
  self,
4530
4637
  name: str,
4531
4638
  values: Dict[str, str],
4532
- scope: SecretScope = SecretScope.WORKSPACE,
4639
+ private: bool = False,
4533
4640
  ) -> SecretResponse:
4534
4641
  """Creates a new secret.
4535
4642
 
4536
4643
  Args:
4537
4644
  name: The name of the secret.
4538
4645
  values: The values of the secret.
4539
- scope: The scope of the secret.
4646
+ private: Whether the secret is private. A private secret is only
4647
+ accessible to the user who created it.
4540
4648
 
4541
4649
  Returns:
4542
4650
  The created secret (in model form).
@@ -4548,9 +4656,7 @@ class Client(metaclass=ClientMetaClass):
4548
4656
  create_secret_request = SecretRequest(
4549
4657
  name=name,
4550
4658
  values=values,
4551
- scope=scope,
4552
- user=self.active_user.id,
4553
- workspace=self.active_workspace.id,
4659
+ private=private,
4554
4660
  )
4555
4661
  try:
4556
4662
  return self.zen_store.create_secret(secret=create_secret_request)
@@ -4563,7 +4669,7 @@ class Client(metaclass=ClientMetaClass):
4563
4669
  def get_secret(
4564
4670
  self,
4565
4671
  name_id_or_prefix: Union[str, UUID],
4566
- scope: Optional[SecretScope] = None,
4672
+ private: Optional[bool] = None,
4567
4673
  allow_partial_name_match: bool = True,
4568
4674
  allow_partial_id_match: bool = True,
4569
4675
  hydrate: bool = True,
@@ -4573,18 +4679,17 @@ class Client(metaclass=ClientMetaClass):
4573
4679
  Get a secret identified by a name, ID or prefix of the name or ID and
4574
4680
  optionally a scope.
4575
4681
 
4576
- If a scope is not provided, the secret will be searched for in all
4577
- scopes starting with the innermost scope (user) to the outermost scope
4578
- (workspace). When a name or prefix is used instead of a UUID value, each
4579
- scope is first searched for an exact match, then for a ID prefix or
4580
- name substring match before moving on to the next scope.
4682
+ If a private status is not provided, privately scoped secrets will be
4683
+ searched for first, followed by publicly scoped secrets. When a name or
4684
+ prefix is used instead of a UUID value, each scope is first searched for
4685
+ an exact match, then for a ID prefix or name substring match before
4686
+ moving on to the next scope.
4581
4687
 
4582
4688
  Args:
4583
4689
  name_id_or_prefix: The name, ID or prefix to the id of the secret
4584
4690
  to get.
4585
- scope: The scope of the secret. If not set, all scopes will be
4586
- searched starting with the innermost scope (user) to the
4587
- outermost scope (global) until a secret is found.
4691
+ private: Whether the secret is private. If not set, all secrets will
4692
+ be searched for, prioritizing privately scoped secrets.
4588
4693
  allow_partial_name_match: If True, allow partial name matches.
4589
4694
  allow_partial_id_match: If True, allow partial ID matches.
4590
4695
  hydrate: Flag deciding whether to hydrate the output model(s)
@@ -4611,7 +4716,7 @@ class Client(metaclass=ClientMetaClass):
4611
4716
  else name_id_or_prefix,
4612
4717
  hydrate=hydrate,
4613
4718
  )
4614
- if scope is not None and secret.scope != scope:
4719
+ if private is not None and secret.private != private:
4615
4720
  raise KeyError(
4616
4721
  f"No secret found with ID {str(name_id_or_prefix)}"
4617
4722
  )
@@ -4626,11 +4731,9 @@ class Client(metaclass=ClientMetaClass):
4626
4731
  # If not a UUID, try to find by name and then by prefix
4627
4732
  assert not isinstance(name_id_or_prefix, UUID)
4628
4733
 
4629
- # Scopes to search in order of priority
4630
- search_scopes = (
4631
- [SecretScope.USER, SecretScope.WORKSPACE]
4632
- if scope is None
4633
- else [scope]
4734
+ # Private statuses to search in order of priority
4735
+ search_private_statuses = (
4736
+ [False, True] if private is None else [private]
4634
4737
  )
4635
4738
 
4636
4739
  secrets = self.list_secrets(
@@ -4644,10 +4747,10 @@ class Client(metaclass=ClientMetaClass):
4644
4747
  hydrate=hydrate,
4645
4748
  )
4646
4749
 
4647
- for search_scope in search_scopes:
4750
+ for search_private_status in search_private_statuses:
4648
4751
  partial_matches: List[SecretResponse] = []
4649
4752
  for secret in secrets.items:
4650
- if secret.scope != search_scope:
4753
+ if secret.private != search_private_status:
4651
4754
  continue
4652
4755
  # Exact match
4653
4756
  if secret.name == name_id_or_prefix:
@@ -4682,10 +4785,13 @@ class Client(metaclass=ClientMetaClass):
4682
4785
  secret_id=partial_matches[0].id,
4683
4786
  hydrate=hydrate,
4684
4787
  )
4685
-
4686
- msg = f"No secret found with name, ID or prefix '{name_id_or_prefix}'"
4687
- if scope is not None:
4688
- msg += f" in scope '{scope}'"
4788
+ private_status = ""
4789
+ if private is not None:
4790
+ private_status = "private " if private else "public "
4791
+ msg = (
4792
+ f"No {private_status}secret found with name, ID or prefix "
4793
+ f"'{name_id_or_prefix}'"
4794
+ )
4689
4795
 
4690
4796
  raise KeyError(msg)
4691
4797
 
@@ -4699,9 +4805,7 @@ class Client(metaclass=ClientMetaClass):
4699
4805
  created: Optional[datetime] = None,
4700
4806
  updated: Optional[datetime] = None,
4701
4807
  name: Optional[str] = None,
4702
- scope: Optional[SecretScope] = None,
4703
- workspace_id: Optional[Union[str, UUID]] = None,
4704
- user_id: Optional[Union[str, UUID]] = None,
4808
+ private: Optional[bool] = None,
4705
4809
  user: Optional[Union[UUID, str]] = None,
4706
4810
  hydrate: bool = False,
4707
4811
  ) -> Page[SecretResponse]:
@@ -4719,9 +4823,7 @@ class Client(metaclass=ClientMetaClass):
4719
4823
  created: Use to secrets by time of creation
4720
4824
  updated: Use the last updated date for filtering
4721
4825
  name: The name of the secret to filter by.
4722
- scope: The scope of the secret to filter by.
4723
- workspace_id: The id of the workspace to filter by.
4724
- user_id: The id of the user to filter by.
4826
+ private: The private status of the secret to filter by.
4725
4827
  user: Filter by user name/ID.
4726
4828
  hydrate: Flag deciding whether to hydrate the output model(s)
4727
4829
  by including metadata fields in the response.
@@ -4738,16 +4840,13 @@ class Client(metaclass=ClientMetaClass):
4738
4840
  size=size,
4739
4841
  sort_by=sort_by,
4740
4842
  logical_operator=logical_operator,
4741
- user_id=user_id,
4742
4843
  user=user,
4743
- workspace_id=workspace_id,
4744
4844
  name=name,
4745
- scope=scope,
4845
+ private=private,
4746
4846
  id=id,
4747
4847
  created=created,
4748
4848
  updated=updated,
4749
4849
  )
4750
- secret_filter_model.set_scope_workspace(self.active_workspace.id)
4751
4850
  try:
4752
4851
  return self.zen_store.list_secrets(
4753
4852
  secret_filter_model=secret_filter_model,
@@ -4762,9 +4861,9 @@ class Client(metaclass=ClientMetaClass):
4762
4861
  def update_secret(
4763
4862
  self,
4764
4863
  name_id_or_prefix: Union[str, UUID],
4765
- scope: Optional[SecretScope] = None,
4864
+ private: Optional[bool] = None,
4766
4865
  new_name: Optional[str] = None,
4767
- new_scope: Optional[SecretScope] = None,
4866
+ update_private: Optional[bool] = None,
4768
4867
  add_or_update_values: Optional[Dict[str, str]] = None,
4769
4868
  remove_values: Optional[List[str]] = None,
4770
4869
  ) -> SecretResponse:
@@ -4773,9 +4872,10 @@ class Client(metaclass=ClientMetaClass):
4773
4872
  Args:
4774
4873
  name_id_or_prefix: The name, id or prefix of the id for the
4775
4874
  secret to update.
4776
- scope: The scope of the secret to update.
4875
+ private: The private status of the secret to update.
4777
4876
  new_name: The new name of the secret.
4778
- new_scope: The new scope of the secret.
4877
+ update_private: New value used to update the private status of the
4878
+ secret.
4779
4879
  add_or_update_values: The values to add or update.
4780
4880
  remove_values: The values to remove.
4781
4881
 
@@ -4789,7 +4889,7 @@ class Client(metaclass=ClientMetaClass):
4789
4889
  """
4790
4890
  secret = self.get_secret(
4791
4891
  name_id_or_prefix=name_id_or_prefix,
4792
- scope=scope,
4892
+ private=private,
4793
4893
  # Don't allow partial name matches, but allow partial ID matches
4794
4894
  allow_partial_name_match=False,
4795
4895
  allow_partial_id_match=True,
@@ -4798,8 +4898,8 @@ class Client(metaclass=ClientMetaClass):
4798
4898
 
4799
4899
  secret_update = SecretUpdate(name=new_name or secret.name)
4800
4900
 
4801
- if new_scope:
4802
- secret_update.scope = new_scope
4901
+ if update_private:
4902
+ secret_update.private = update_private
4803
4903
  values: Dict[str, Optional[SecretStr]] = {}
4804
4904
  if add_or_update_values:
4805
4905
  values.update(
@@ -4829,17 +4929,17 @@ class Client(metaclass=ClientMetaClass):
4829
4929
  )
4830
4930
 
4831
4931
  def delete_secret(
4832
- self, name_id_or_prefix: str, scope: Optional[SecretScope] = None
4932
+ self, name_id_or_prefix: str, private: Optional[bool] = None
4833
4933
  ) -> None:
4834
4934
  """Deletes a secret.
4835
4935
 
4836
4936
  Args:
4837
4937
  name_id_or_prefix: The name or ID of the secret.
4838
- scope: The scope of the secret to delete.
4938
+ private: The private status of the secret to delete.
4839
4939
  """
4840
4940
  secret = self.get_secret(
4841
4941
  name_id_or_prefix=name_id_or_prefix,
4842
- scope=scope,
4942
+ private=private,
4843
4943
  # Don't allow partial name matches, but allow partial ID matches
4844
4944
  allow_partial_name_match=False,
4845
4945
  allow_partial_id_match=True,
@@ -4847,23 +4947,24 @@ class Client(metaclass=ClientMetaClass):
4847
4947
 
4848
4948
  self.zen_store.delete_secret(secret_id=secret.id)
4849
4949
 
4850
- def get_secret_by_name_and_scope(
4950
+ def get_secret_by_name_and_private_status(
4851
4951
  self,
4852
4952
  name: str,
4853
- scope: Optional[SecretScope] = None,
4953
+ private: Optional[bool] = None,
4854
4954
  hydrate: bool = True,
4855
4955
  ) -> SecretResponse:
4856
- """Fetches a registered secret with a given name and optional scope.
4956
+ """Fetches a registered secret with a given name and optional private status.
4857
4957
 
4858
4958
  This is a version of get_secret that restricts the search to a given
4859
- name and an optional scope, without doing any prefix or UUID matching.
4959
+ name and an optional private status, without doing any prefix or UUID
4960
+ matching.
4860
4961
 
4861
- If no scope is provided, the search will be done first in the user
4862
- scope, then in the workspace scope.
4962
+ If no private status is provided, the search will be done first for
4963
+ private secrets, then for public secrets.
4863
4964
 
4864
4965
  Args:
4865
4966
  name: The name of the secret to get.
4866
- scope: The scope of the secret to get.
4967
+ private: The private status of the secret to get.
4867
4968
  hydrate: Flag deciding whether to hydrate the output model(s)
4868
4969
  by including metadata fields in the response.
4869
4970
 
@@ -4874,21 +4975,20 @@ class Client(metaclass=ClientMetaClass):
4874
4975
  KeyError: If no secret exists for the given name in the given scope.
4875
4976
  """
4876
4977
  logger.debug(
4877
- f"Fetching the secret with name '{name}' and scope '{scope}'."
4978
+ f"Fetching the secret with name '{name}' and private status "
4979
+ f"'{private}'."
4878
4980
  )
4879
4981
 
4880
- # Scopes to search in order of priority
4881
- search_scopes = (
4882
- [SecretScope.USER, SecretScope.WORKSPACE]
4883
- if scope is None
4884
- else [scope]
4982
+ # Private statuses to search in order of priority
4983
+ search_private_statuses = (
4984
+ [False, True] if private is None else [private]
4885
4985
  )
4886
4986
 
4887
- for search_scope in search_scopes:
4987
+ for search_private_status in search_private_statuses:
4888
4988
  secrets = self.list_secrets(
4889
4989
  logical_operator=LogicalOperators.AND,
4890
4990
  name=f"equals:{name}",
4891
- scope=search_scope,
4991
+ private=search_private_status,
4892
4992
  hydrate=hydrate,
4893
4993
  )
4894
4994
 
@@ -4898,33 +4998,34 @@ class Client(metaclass=ClientMetaClass):
4898
4998
  secret_id=secrets.items[0].id, hydrate=hydrate
4899
4999
  )
4900
5000
 
4901
- msg = f"No secret with name '{name}' was found"
4902
- if scope is not None:
4903
- msg += f" in scope '{scope.value}'"
5001
+ private_status = ""
5002
+ if private is not None:
5003
+ private_status = "private " if private else "public "
5004
+ msg = f"No {private_status}secret with name '{name}' was found"
4904
5005
 
4905
5006
  raise KeyError(msg)
4906
5007
 
4907
- def list_secrets_in_scope(
5008
+ def list_secrets_by_private_status(
4908
5009
  self,
4909
- scope: SecretScope,
5010
+ private: bool,
4910
5011
  hydrate: bool = False,
4911
5012
  ) -> Page[SecretResponse]:
4912
- """Fetches the list of secret in a given scope.
5013
+ """Fetches the list of secrets with a given private status.
4913
5014
 
4914
5015
  The returned secrets do not contain the secret values. To get the
4915
5016
  secret values, use `get_secret` individually for each secret.
4916
5017
 
4917
5018
  Args:
4918
- scope: The secrets scope to search for.
5019
+ private: The private status of the secrets to search for.
4919
5020
  hydrate: Flag deciding whether to hydrate the output model(s)
4920
5021
  by including metadata fields in the response.
4921
5022
 
4922
5023
  Returns:
4923
5024
  The list of secrets in the given scope without the secret values.
4924
5025
  """
4925
- logger.debug(f"Fetching the secrets in scope {scope.value}.")
5026
+ logger.debug(f"Fetching the secrets with private status '{private}'.")
4926
5027
 
4927
- return self.list_secrets(scope=scope, hydrate=hydrate)
5028
+ return self.list_secrets(private=private, hydrate=hydrate)
4928
5029
 
4929
5030
  def backup_secrets(
4930
5031
  self,
@@ -5015,8 +5116,7 @@ class Client(metaclass=ClientMetaClass):
5015
5116
  """
5016
5117
  self._validate_code_repository_config(source=source, config=config)
5017
5118
  repo_request = CodeRepositoryRequest(
5018
- user=self.active_user.id,
5019
- workspace=self.active_workspace.id,
5119
+ project=self.active_project.id,
5020
5120
  name=name,
5021
5121
  config=config,
5022
5122
  source=source,
@@ -5031,6 +5131,7 @@ class Client(metaclass=ClientMetaClass):
5031
5131
  self,
5032
5132
  name_id_or_prefix: Union[str, UUID],
5033
5133
  allow_name_prefix_match: bool = True,
5134
+ project: Optional[Union[str, UUID]] = None,
5034
5135
  hydrate: bool = True,
5035
5136
  ) -> CodeRepositoryResponse:
5036
5137
  """Get a code repository by name, id or prefix.
@@ -5038,6 +5139,7 @@ class Client(metaclass=ClientMetaClass):
5038
5139
  Args:
5039
5140
  name_id_or_prefix: The name, ID or ID prefix of the code repository.
5040
5141
  allow_name_prefix_match: If True, allow matching by name prefix.
5142
+ project: The project name/ID to filter by.
5041
5143
  hydrate: Flag deciding whether to hydrate the output model(s)
5042
5144
  by including metadata fields in the response.
5043
5145
 
@@ -5050,6 +5152,7 @@ class Client(metaclass=ClientMetaClass):
5050
5152
  name_id_or_prefix=name_id_or_prefix,
5051
5153
  allow_name_prefix_match=allow_name_prefix_match,
5052
5154
  hydrate=hydrate,
5155
+ project=project,
5053
5156
  )
5054
5157
 
5055
5158
  def list_code_repositories(
@@ -5062,8 +5165,7 @@ class Client(metaclass=ClientMetaClass):
5062
5165
  created: Optional[Union[datetime, str]] = None,
5063
5166
  updated: Optional[Union[datetime, str]] = None,
5064
5167
  name: Optional[str] = None,
5065
- workspace_id: Optional[Union[str, UUID]] = None,
5066
- user_id: Optional[Union[str, UUID]] = None,
5168
+ project: Optional[Union[str, UUID]] = None,
5067
5169
  user: Optional[Union[UUID, str]] = None,
5068
5170
  hydrate: bool = False,
5069
5171
  ) -> Page[CodeRepositoryResponse]:
@@ -5078,8 +5180,7 @@ class Client(metaclass=ClientMetaClass):
5078
5180
  created: Use to filter by time of creation.
5079
5181
  updated: Use the last updated date for filtering.
5080
5182
  name: The name of the code repository to filter by.
5081
- workspace_id: The id of the workspace to filter by.
5082
- user_id: The id of the user to filter by.
5183
+ project: The project name/ID to filter by.
5083
5184
  user: Filter by user name/ID.
5084
5185
  hydrate: Flag deciding whether to hydrate the output model(s)
5085
5186
  by including metadata fields in the response.
@@ -5096,11 +5197,9 @@ class Client(metaclass=ClientMetaClass):
5096
5197
  created=created,
5097
5198
  updated=updated,
5098
5199
  name=name,
5099
- workspace_id=workspace_id,
5100
- user_id=user_id,
5200
+ project=project or self.active_project.id,
5101
5201
  user=user,
5102
5202
  )
5103
- filter_model.set_scope_workspace(self.active_workspace.id)
5104
5203
  return self.zen_store.list_code_repositories(
5105
5204
  filter_model=filter_model,
5106
5205
  hydrate=hydrate,
@@ -5113,6 +5212,7 @@ class Client(metaclass=ClientMetaClass):
5113
5212
  description: Optional[str] = None,
5114
5213
  logo_url: Optional[str] = None,
5115
5214
  config: Optional[Dict[str, Any]] = None,
5215
+ project: Optional[Union[str, UUID]] = None,
5116
5216
  ) -> CodeRepositoryResponse:
5117
5217
  """Update a code repository.
5118
5218
 
@@ -5126,12 +5226,15 @@ class Client(metaclass=ClientMetaClass):
5126
5226
  be used to update the existing configuration values. To remove
5127
5227
  values from the existing configuration, set the value for that
5128
5228
  key to `None`.
5229
+ project: The project name/ID to filter by.
5129
5230
 
5130
5231
  Returns:
5131
5232
  The updated code repository.
5132
5233
  """
5133
5234
  repo = self.get_code_repository(
5134
- name_id_or_prefix=name_id_or_prefix, allow_name_prefix_match=False
5235
+ name_id_or_prefix=name_id_or_prefix,
5236
+ allow_name_prefix_match=False,
5237
+ project=project,
5135
5238
  )
5136
5239
  update = CodeRepositoryUpdate(
5137
5240
  name=name, description=description, logo_url=logo_url
@@ -5155,14 +5258,18 @@ class Client(metaclass=ClientMetaClass):
5155
5258
  def delete_code_repository(
5156
5259
  self,
5157
5260
  name_id_or_prefix: Union[str, UUID],
5261
+ project: Optional[Union[str, UUID]] = None,
5158
5262
  ) -> None:
5159
5263
  """Delete a code repository.
5160
5264
 
5161
5265
  Args:
5162
5266
  name_id_or_prefix: The name, ID or prefix of the code repository.
5267
+ project: The project name/ID to filter by.
5163
5268
  """
5164
5269
  repo = self.get_code_repository(
5165
- name_id_or_prefix=name_id_or_prefix, allow_name_prefix_match=False
5270
+ name_id_or_prefix=name_id_or_prefix,
5271
+ allow_name_prefix_match=False,
5272
+ project=project,
5166
5273
  )
5167
5274
  self.zen_store.delete_code_repository(code_repository_id=repo.id)
5168
5275
 
@@ -5279,8 +5386,6 @@ class Client(metaclass=ClientMetaClass):
5279
5386
  assert connector_instance is not None
5280
5387
  connector_request = connector_instance.to_model(
5281
5388
  name=name,
5282
- user=self.active_user.id,
5283
- workspace=self.active_workspace.id,
5284
5389
  description=description or "",
5285
5390
  labels=labels,
5286
5391
  )
@@ -5327,8 +5432,6 @@ class Client(metaclass=ClientMetaClass):
5327
5432
  expiration_seconds=expiration_seconds,
5328
5433
  expires_at=expires_at,
5329
5434
  expires_skew_tolerance=expires_skew_tolerance,
5330
- user=self.active_user.id,
5331
- workspace=self.active_workspace.id,
5332
5435
  labels=labels or {},
5333
5436
  )
5334
5437
  # Validate and configure the resources
@@ -5410,32 +5513,9 @@ class Client(metaclass=ClientMetaClass):
5410
5513
  Returns:
5411
5514
  The registered service connector.
5412
5515
  """
5413
-
5414
- def scoped_list_method(
5415
- hydrate: bool = False,
5416
- **kwargs: Any,
5417
- ) -> Page[ServiceConnectorResponse]:
5418
- """Call `zen_store.list_service_connectors` with workspace scoping.
5419
-
5420
- Args:
5421
- hydrate: Flag deciding whether to hydrate the output model(s)
5422
- by including metadata fields in the response.
5423
- **kwargs: Keyword arguments to pass to
5424
- `ServiceConnectorFilterModel`.
5425
-
5426
- Returns:
5427
- The list of service connectors.
5428
- """
5429
- filter_model = ServiceConnectorFilter(**kwargs)
5430
- filter_model.set_scope_workspace(self.active_workspace.id)
5431
- return self.zen_store.list_service_connectors(
5432
- filter_model=filter_model,
5433
- hydrate=hydrate,
5434
- )
5435
-
5436
5516
  connector = self._get_entity_by_id_or_name_or_prefix(
5437
5517
  get_method=self.zen_store.get_service_connector,
5438
- list_method=scoped_list_method,
5518
+ list_method=self.list_service_connectors,
5439
5519
  name_id_or_prefix=name_id_or_prefix,
5440
5520
  allow_name_prefix_match=allow_name_prefix_match,
5441
5521
  hydrate=hydrate,
@@ -5474,8 +5554,6 @@ class Client(metaclass=ClientMetaClass):
5474
5554
  auth_method: Optional[str] = None,
5475
5555
  resource_type: Optional[str] = None,
5476
5556
  resource_id: Optional[str] = None,
5477
- workspace_id: Optional[Union[str, UUID]] = None,
5478
- user_id: Optional[Union[str, UUID]] = None,
5479
5557
  user: Optional[Union[UUID, str]] = None,
5480
5558
  labels: Optional[Dict[str, Optional[str]]] = None,
5481
5559
  secret_id: Optional[Union[str, UUID]] = None,
@@ -5497,8 +5575,6 @@ class Client(metaclass=ClientMetaClass):
5497
5575
  they can give access to.
5498
5576
  resource_id: Filter service connectors by the resource id that
5499
5577
  they can give access to.
5500
- workspace_id: The id of the workspace to filter by.
5501
- user_id: The id of the user to filter by.
5502
5578
  user: Filter by user name/ID.
5503
5579
  name: The name of the service connector to filter by.
5504
5580
  labels: The labels of the service connector to filter by.
@@ -5515,8 +5591,6 @@ class Client(metaclass=ClientMetaClass):
5515
5591
  size=size,
5516
5592
  sort_by=sort_by,
5517
5593
  logical_operator=logical_operator,
5518
- workspace_id=workspace_id or self.active_workspace.id,
5519
- user_id=user_id,
5520
5594
  user=user,
5521
5595
  name=name,
5522
5596
  connector_type=connector_type,
@@ -5529,7 +5603,6 @@ class Client(metaclass=ClientMetaClass):
5529
5603
  labels=labels,
5530
5604
  secret_id=secret_id,
5531
5605
  )
5532
- connector_filter_model.set_scope_workspace(self.active_workspace.id)
5533
5606
  return self.zen_store.list_service_connectors(
5534
5607
  filter_model=connector_filter_model,
5535
5608
  hydrate=hydrate,
@@ -5707,10 +5780,6 @@ class Client(metaclass=ClientMetaClass):
5707
5780
 
5708
5781
  # Convert the update model to a request model for validation
5709
5782
  connector_request_dict = connector_update.model_dump()
5710
- connector_request_dict.update(
5711
- user=self.active_user.id,
5712
- workspace=self.active_workspace.id,
5713
- )
5714
5783
  connector_request = ServiceConnectorRequest.model_validate(
5715
5784
  connector_request_dict
5716
5785
  )
@@ -5995,10 +6064,11 @@ class Client(metaclass=ClientMetaClass):
5995
6064
  connectors have access to.
5996
6065
  """
5997
6066
  return self.zen_store.list_service_connector_resources(
5998
- workspace_name_or_id=self.active_workspace.id,
5999
- connector_type=connector_type,
6000
- resource_type=resource_type,
6001
- resource_id=resource_id,
6067
+ ServiceConnectorFilter(
6068
+ connector_type=connector_type,
6069
+ resource_type=resource_type,
6070
+ resource_id=resource_id,
6071
+ )
6002
6072
  )
6003
6073
 
6004
6074
  def list_service_connector_types(
@@ -6085,19 +6155,26 @@ class Client(metaclass=ClientMetaClass):
6085
6155
  trade_offs=trade_offs,
6086
6156
  ethics=ethics,
6087
6157
  tags=tags,
6088
- user=self.active_user.id,
6089
- workspace=self.active_workspace.id,
6158
+ project=self.active_project.id,
6090
6159
  save_models_to_registry=save_models_to_registry,
6091
6160
  )
6092
6161
  )
6093
6162
 
6094
- def delete_model(self, model_name_or_id: Union[str, UUID]) -> None:
6163
+ def delete_model(
6164
+ self,
6165
+ model_name_or_id: Union[str, UUID],
6166
+ project: Optional[Union[str, UUID]] = None,
6167
+ ) -> None:
6095
6168
  """Deletes a model from Model Control Plane.
6096
6169
 
6097
6170
  Args:
6098
6171
  model_name_or_id: name or id of the model to be deleted.
6172
+ project: The project name/ID to filter by.
6099
6173
  """
6100
- self.zen_store.delete_model(model_name_or_id=model_name_or_id)
6174
+ model = self.get_model(
6175
+ model_name_or_id=model_name_or_id, project=project
6176
+ )
6177
+ self.zen_store.delete_model(model_id=model.id)
6101
6178
 
6102
6179
  def update_model(
6103
6180
  self,
@@ -6113,6 +6190,7 @@ class Client(metaclass=ClientMetaClass):
6113
6190
  add_tags: Optional[List[str]] = None,
6114
6191
  remove_tags: Optional[List[str]] = None,
6115
6192
  save_models_to_registry: Optional[bool] = None,
6193
+ project: Optional[Union[str, UUID]] = None,
6116
6194
  ) -> ModelResponse:
6117
6195
  """Updates an existing model in Model Control Plane.
6118
6196
 
@@ -6130,14 +6208,16 @@ class Client(metaclass=ClientMetaClass):
6130
6208
  remove_tags: Tags to remove from to the model.
6131
6209
  save_models_to_registry: Whether to save the model to the
6132
6210
  registry.
6211
+ project: The project name/ID to filter by.
6133
6212
 
6134
6213
  Returns:
6135
6214
  The updated model.
6136
6215
  """
6137
- if not is_valid_uuid(model_name_or_id):
6138
- model_name_or_id = self.zen_store.get_model(model_name_or_id).id
6216
+ model = self.get_model(
6217
+ model_name_or_id=model_name_or_id, project=project
6218
+ )
6139
6219
  return self.zen_store.update_model(
6140
- model_id=model_name_or_id, # type:ignore[arg-type]
6220
+ model_id=model.id,
6141
6221
  model_update=ModelUpdate(
6142
6222
  name=name,
6143
6223
  license=license,
@@ -6156,24 +6236,36 @@ class Client(metaclass=ClientMetaClass):
6156
6236
  def get_model(
6157
6237
  self,
6158
6238
  model_name_or_id: Union[str, UUID],
6239
+ project: Optional[Union[str, UUID]] = None,
6159
6240
  hydrate: bool = True,
6241
+ bypass_lazy_loader: bool = False,
6160
6242
  ) -> ModelResponse:
6161
6243
  """Get an existing model from Model Control Plane.
6162
6244
 
6163
6245
  Args:
6164
6246
  model_name_or_id: name or id of the model to be retrieved.
6247
+ project: The project name/ID to filter by.
6165
6248
  hydrate: Flag deciding whether to hydrate the output model(s)
6166
6249
  by including metadata fields in the response.
6250
+ bypass_lazy_loader: Whether to bypass the lazy loader.
6167
6251
 
6168
6252
  Returns:
6169
6253
  The model of interest.
6170
6254
  """
6171
- if cll := client_lazy_loader(
6172
- "get_model", model_name_or_id=model_name_or_id, hydrate=hydrate
6173
- ):
6174
- return cll # type: ignore[return-value]
6175
- return self.zen_store.get_model(
6176
- model_name_or_id=model_name_or_id,
6255
+ if not bypass_lazy_loader:
6256
+ if cll := client_lazy_loader(
6257
+ "get_model",
6258
+ model_name_or_id=model_name_or_id,
6259
+ hydrate=hydrate,
6260
+ project=project,
6261
+ ):
6262
+ return cll # type: ignore[return-value]
6263
+
6264
+ return self._get_entity_by_id_or_name_or_prefix(
6265
+ get_method=self.zen_store.get_model,
6266
+ list_method=self.list_models,
6267
+ name_id_or_prefix=model_name_or_id,
6268
+ project=project,
6177
6269
  hydrate=hydrate,
6178
6270
  )
6179
6271
 
@@ -6186,9 +6278,12 @@ class Client(metaclass=ClientMetaClass):
6186
6278
  created: Optional[Union[datetime, str]] = None,
6187
6279
  updated: Optional[Union[datetime, str]] = None,
6188
6280
  name: Optional[str] = None,
6281
+ id: Optional[Union[UUID, str]] = None,
6189
6282
  user: Optional[Union[UUID, str]] = None,
6283
+ project: Optional[Union[str, UUID]] = None,
6190
6284
  hydrate: bool = False,
6191
6285
  tag: Optional[str] = None,
6286
+ tags: Optional[List[str]] = None,
6192
6287
  ) -> Page[ModelResponse]:
6193
6288
  """Get models by filter from Model Control Plane.
6194
6289
 
@@ -6200,16 +6295,20 @@ class Client(metaclass=ClientMetaClass):
6200
6295
  created: Use to filter by time of creation
6201
6296
  updated: Use the last updated date for filtering
6202
6297
  name: The name of the model to filter by.
6298
+ id: The id of the model to filter by.
6203
6299
  user: Filter by user name/ID.
6300
+ project: The project name/ID to filter by.
6204
6301
  hydrate: Flag deciding whether to hydrate the output model(s)
6205
6302
  by including metadata fields in the response.
6206
6303
  tag: The tag of the model to filter by.
6304
+ tags: Tags to filter by.
6207
6305
 
6208
6306
  Returns:
6209
6307
  A page object with all models.
6210
6308
  """
6211
6309
  filter = ModelFilter(
6212
6310
  name=name,
6311
+ id=id,
6213
6312
  sort_by=sort_by,
6214
6313
  page=page,
6215
6314
  size=size,
@@ -6217,7 +6316,9 @@ class Client(metaclass=ClientMetaClass):
6217
6316
  created=created,
6218
6317
  updated=updated,
6219
6318
  tag=tag,
6319
+ tags=tags,
6220
6320
  user=user,
6321
+ project=project or self.active_project.id,
6221
6322
  )
6222
6323
 
6223
6324
  return self.zen_store.list_models(
@@ -6234,6 +6335,7 @@ class Client(metaclass=ClientMetaClass):
6234
6335
  name: Optional[str] = None,
6235
6336
  description: Optional[str] = None,
6236
6337
  tags: Optional[List[str]] = None,
6338
+ project: Optional[Union[str, UUID]] = None,
6237
6339
  ) -> ModelVersionResponse:
6238
6340
  """Creates a new model version in Model Control Plane.
6239
6341
 
@@ -6243,19 +6345,20 @@ class Client(metaclass=ClientMetaClass):
6243
6345
  name: the name of the Model Version to be created.
6244
6346
  description: the description of the Model Version to be created.
6245
6347
  tags: Tags associated with the model.
6348
+ project: The project name/ID to filter by.
6246
6349
 
6247
6350
  Returns:
6248
6351
  The newly created model version.
6249
6352
  """
6250
- if not is_valid_uuid(model_name_or_id):
6251
- model_name_or_id = self.get_model(model_name_or_id).id
6353
+ model = self.get_model(
6354
+ model_name_or_id=model_name_or_id, project=project
6355
+ )
6252
6356
  return self.zen_store.create_model_version(
6253
6357
  model_version=ModelVersionRequest(
6254
6358
  name=name,
6255
6359
  description=description,
6256
- user=self.active_user.id,
6257
- workspace=self.active_workspace.id,
6258
- model=model_name_or_id,
6360
+ project=model.project.id,
6361
+ model=model.id,
6259
6362
  tags=tags,
6260
6363
  )
6261
6364
  )
@@ -6279,6 +6382,7 @@ class Client(metaclass=ClientMetaClass):
6279
6382
  model_version_name_or_number_or_id: Optional[
6280
6383
  Union[str, int, ModelStages, UUID]
6281
6384
  ] = None,
6385
+ project: Optional[Union[str, UUID]] = None,
6282
6386
  hydrate: bool = True,
6283
6387
  ) -> ModelVersionResponse:
6284
6388
  """Get an existing model version from Model Control Plane.
@@ -6289,6 +6393,7 @@ class Client(metaclass=ClientMetaClass):
6289
6393
  model_version_name_or_number_or_id: name, id, stage or number of
6290
6394
  the model version to be retrieved. If skipped - latest version
6291
6395
  is retrieved.
6396
+ project: The project name/ID to filter by.
6292
6397
  hydrate: Flag deciding whether to hydrate the output model(s)
6293
6398
  by including metadata fields in the response.
6294
6399
 
@@ -6313,6 +6418,7 @@ class Client(metaclass=ClientMetaClass):
6313
6418
  "get_model_version",
6314
6419
  model_name_or_id=model_name_or_id,
6315
6420
  model_version_name_or_number_or_id=model_version_name_or_number_or_id,
6421
+ project=project,
6316
6422
  hydrate=hydrate,
6317
6423
  ):
6318
6424
  return cll # type: ignore[return-value]
@@ -6327,18 +6433,20 @@ class Client(metaclass=ClientMetaClass):
6327
6433
  )
6328
6434
  elif isinstance(model_version_name_or_number_or_id, int):
6329
6435
  model_versions = self.zen_store.list_model_versions(
6330
- model_name_or_id=model_name_or_id,
6331
6436
  model_version_filter_model=ModelVersionFilter(
6437
+ model=model_name_or_id,
6332
6438
  number=model_version_name_or_number_or_id,
6439
+ project=project or self.active_project.id,
6333
6440
  ),
6334
6441
  hydrate=hydrate,
6335
6442
  ).items
6336
6443
  elif isinstance(model_version_name_or_number_or_id, str):
6337
6444
  if model_version_name_or_number_or_id == ModelStages.LATEST:
6338
6445
  model_versions = self.zen_store.list_model_versions(
6339
- model_name_or_id=model_name_or_id,
6340
6446
  model_version_filter_model=ModelVersionFilter(
6341
- sort_by=f"{SorterOps.DESCENDING}:number"
6447
+ model=model_name_or_id,
6448
+ sort_by=f"{SorterOps.DESCENDING}:number",
6449
+ project=project or self.active_project.id,
6342
6450
  ),
6343
6451
  hydrate=hydrate,
6344
6452
  ).items
@@ -6349,17 +6457,19 @@ class Client(metaclass=ClientMetaClass):
6349
6457
  model_versions = []
6350
6458
  elif model_version_name_or_number_or_id in ModelStages.values():
6351
6459
  model_versions = self.zen_store.list_model_versions(
6352
- model_name_or_id=model_name_or_id,
6353
6460
  model_version_filter_model=ModelVersionFilter(
6354
- stage=model_version_name_or_number_or_id
6461
+ model=model_name_or_id,
6462
+ stage=model_version_name_or_number_or_id,
6463
+ project=project or self.active_project.id,
6355
6464
  ),
6356
6465
  hydrate=hydrate,
6357
6466
  ).items
6358
6467
  else:
6359
6468
  model_versions = self.zen_store.list_model_versions(
6360
- model_name_or_id=model_name_or_id,
6361
6469
  model_version_filter_model=ModelVersionFilter(
6362
- name=model_version_name_or_number_or_id
6470
+ model=model_name_or_id,
6471
+ name=model_version_name_or_number_or_id,
6472
+ project=project or self.active_project.id,
6363
6473
  ),
6364
6474
  hydrate=hydrate,
6365
6475
  ).items
@@ -6387,7 +6497,7 @@ class Client(metaclass=ClientMetaClass):
6387
6497
 
6388
6498
  def list_model_versions(
6389
6499
  self,
6390
- model_name_or_id: Optional[Union[str, UUID]] = None,
6500
+ model_name_or_id: Union[str, UUID],
6391
6501
  sort_by: str = "number",
6392
6502
  page: int = PAGINATION_STARTING_PAGE,
6393
6503
  size: int = PAGE_SIZE_DEFAULT,
@@ -6395,11 +6505,15 @@ class Client(metaclass=ClientMetaClass):
6395
6505
  created: Optional[Union[datetime, str]] = None,
6396
6506
  updated: Optional[Union[datetime, str]] = None,
6397
6507
  name: Optional[str] = None,
6508
+ id: Optional[Union[UUID, str]] = None,
6398
6509
  number: Optional[int] = None,
6399
6510
  stage: Optional[Union[str, ModelStages]] = None,
6511
+ run_metadata: Optional[Dict[str, str]] = None,
6400
6512
  user: Optional[Union[UUID, str]] = None,
6401
6513
  hydrate: bool = False,
6402
6514
  tag: Optional[str] = None,
6515
+ tags: Optional[List[str]] = None,
6516
+ project: Optional[Union[str, UUID]] = None,
6403
6517
  ) -> Page[ModelVersionResponse]:
6404
6518
  """Get model versions by filter from Model Control Plane.
6405
6519
 
@@ -6413,12 +6527,16 @@ class Client(metaclass=ClientMetaClass):
6413
6527
  created: Use to filter by time of creation
6414
6528
  updated: Use the last updated date for filtering
6415
6529
  name: name or id of the model version.
6530
+ id: id of the model version.
6416
6531
  number: number of the model version.
6417
6532
  stage: stage of the model version.
6533
+ run_metadata: run metadata of the model version.
6418
6534
  user: Filter by user name/ID.
6419
6535
  hydrate: Flag deciding whether to hydrate the output model(s)
6420
6536
  by including metadata fields in the response.
6421
6537
  tag: The tag to filter by.
6538
+ tags: Tags to filter by.
6539
+ project: The project name/ID to filter by.
6422
6540
 
6423
6541
  Returns:
6424
6542
  A page object with all model versions.
@@ -6431,14 +6549,18 @@ class Client(metaclass=ClientMetaClass):
6431
6549
  created=created,
6432
6550
  updated=updated,
6433
6551
  name=name,
6552
+ id=id,
6434
6553
  number=number,
6435
6554
  stage=stage,
6555
+ run_metadata=run_metadata,
6436
6556
  tag=tag,
6557
+ tags=tags,
6437
6558
  user=user,
6559
+ model=model_name_or_id,
6560
+ project=project or self.active_project.id,
6438
6561
  )
6439
6562
 
6440
6563
  return self.zen_store.list_model_versions(
6441
- model_name_or_id=model_name_or_id,
6442
6564
  model_version_filter_model=model_version_filter_model,
6443
6565
  hydrate=hydrate,
6444
6566
  )
@@ -6453,6 +6575,7 @@ class Client(metaclass=ClientMetaClass):
6453
6575
  description: Optional[str] = None,
6454
6576
  add_tags: Optional[List[str]] = None,
6455
6577
  remove_tags: Optional[List[str]] = None,
6578
+ project: Optional[Union[str, UUID]] = None,
6456
6579
  ) -> ModelVersionResponse:
6457
6580
  """Get all model versions by filter.
6458
6581
 
@@ -6466,21 +6589,23 @@ class Client(metaclass=ClientMetaClass):
6466
6589
  description: Target model version description to be set.
6467
6590
  add_tags: Tags to add to the model version.
6468
6591
  remove_tags: Tags to remove from to the model version.
6592
+ project: The project name/ID to filter by.
6469
6593
 
6470
6594
  Returns:
6471
6595
  An updated model version.
6472
6596
  """
6473
6597
  if not is_valid_uuid(model_name_or_id):
6474
- model_name_or_id = self.get_model(model_name_or_id).id
6598
+ model = self.get_model(model_name_or_id, project=project)
6599
+ model_name_or_id = model.id
6600
+ project = project or model.project.id
6475
6601
  if not is_valid_uuid(version_name_or_id):
6476
6602
  version_name_or_id = self.get_model_version(
6477
- model_name_or_id, version_name_or_id
6603
+ model_name_or_id, version_name_or_id, project=project
6478
6604
  ).id
6479
6605
 
6480
6606
  return self.zen_store.update_model_version(
6481
6607
  model_version_id=version_name_or_id, # type:ignore[arg-type]
6482
6608
  model_version_update_model=ModelVersionUpdate(
6483
- model=model_name_or_id,
6484
6609
  stage=stage,
6485
6610
  force=force,
6486
6611
  name=name,
@@ -6829,6 +6954,7 @@ class Client(metaclass=ClientMetaClass):
6829
6954
  logical_operator: LogicalOperators = LogicalOperators.AND,
6830
6955
  trigger_id: Optional[UUID] = None,
6831
6956
  user: Optional[Union[UUID, str]] = None,
6957
+ project: Optional[Union[UUID, str]] = None,
6832
6958
  hydrate: bool = False,
6833
6959
  ) -> Page[TriggerExecutionResponse]:
6834
6960
  """List all trigger executions matching the given filter criteria.
@@ -6840,6 +6966,7 @@ class Client(metaclass=ClientMetaClass):
6840
6966
  logical_operator: Which logical operator to use [and, or].
6841
6967
  trigger_id: ID of the trigger to filter by.
6842
6968
  user: Filter by user name/ID.
6969
+ project: Filter by project name/ID.
6843
6970
  hydrate: Flag deciding whether to hydrate the output model(s)
6844
6971
  by including metadata fields in the response.
6845
6972
 
@@ -6853,8 +6980,8 @@ class Client(metaclass=ClientMetaClass):
6853
6980
  size=size,
6854
6981
  user=user,
6855
6982
  logical_operator=logical_operator,
6983
+ project=project or self.active_project.id,
6856
6984
  )
6857
- filter_model.set_scope_workspace(self.active_workspace.id)
6858
6985
  return self.zen_store.list_trigger_executions(
6859
6986
  trigger_execution_filter_model=filter_model, hydrate=hydrate
6860
6987
  )
@@ -6877,6 +7004,7 @@ class Client(metaclass=ClientMetaClass):
6877
7004
  list_method: Callable[..., Page[AnyResponse]],
6878
7005
  name_id_or_prefix: Union[str, UUID],
6879
7006
  allow_name_prefix_match: bool = True,
7007
+ project: Optional[Union[str, UUID]] = None,
6880
7008
  hydrate: bool = True,
6881
7009
  ) -> AnyResponse:
6882
7010
  """Fetches an entity using the id, name, or partial id/name.
@@ -6889,6 +7017,7 @@ class Client(metaclass=ClientMetaClass):
6889
7017
  allow_name_prefix_match: If True, allow matching by name prefix.
6890
7018
  hydrate: Flag deciding whether to hydrate the output model(s)
6891
7019
  by including metadata fields in the response.
7020
+ project: The project name/ID to filter by.
6892
7021
 
6893
7022
  Returns:
6894
7023
  The entity with the given name, id or partial id.
@@ -6907,10 +7036,15 @@ class Client(metaclass=ClientMetaClass):
6907
7036
 
6908
7037
  # If not a UUID, try to find by name
6909
7038
  assert not isinstance(name_id_or_prefix, UUID)
6910
- entity = list_method(
7039
+ list_kwargs: Dict[str, Any] = dict(
6911
7040
  name=f"equals:{name_id_or_prefix}",
6912
7041
  hydrate=hydrate,
6913
7042
  )
7043
+ scope = ""
7044
+ if project:
7045
+ scope = f"in project {project} "
7046
+ list_kwargs["project"] = project
7047
+ entity = list_method(**list_kwargs)
6914
7048
 
6915
7049
  # If only a single entity is found, return it
6916
7050
  if entity.total == 1:
@@ -6923,6 +7057,7 @@ class Client(metaclass=ClientMetaClass):
6923
7057
  list_method=list_method,
6924
7058
  partial_id_or_name=name_id_or_prefix,
6925
7059
  allow_name_prefix_match=allow_name_prefix_match,
7060
+ project=project,
6926
7061
  hydrate=hydrate,
6927
7062
  )
6928
7063
 
@@ -6934,7 +7069,7 @@ class Client(metaclass=ClientMetaClass):
6934
7069
  for item in entity.items
6935
7070
  ]
6936
7071
  raise ZenKeyError(
6937
- f"{entity.total} {entity_label} have been found that have "
7072
+ f"{entity.total} {entity_label} have been found {scope}that have "
6938
7073
  f"a name that matches the provided "
6939
7074
  f"string '{name_id_or_prefix}':\n"
6940
7075
  f"{formatted_entity_items}.\n"
@@ -6948,6 +7083,7 @@ class Client(metaclass=ClientMetaClass):
6948
7083
  list_method: Callable[..., Page[AnyResponse]],
6949
7084
  name_id_or_prefix: Union[str, UUID],
6950
7085
  version: Optional[str],
7086
+ project: Optional[Union[str, UUID]] = None,
6951
7087
  hydrate: bool = True,
6952
7088
  ) -> "AnyResponse":
6953
7089
  from zenml.utils.uuid_utils import is_valid_uuid
@@ -6967,13 +7103,18 @@ class Client(metaclass=ClientMetaClass):
6967
7103
  return get_method(name_id_or_prefix, hydrate=hydrate)
6968
7104
 
6969
7105
  assert not isinstance(name_id_or_prefix, UUID)
6970
- exact_name_matches = list_method(
7106
+ list_kwargs: Dict[str, Any] = dict(
6971
7107
  size=1,
6972
7108
  sort_by="desc:created",
6973
7109
  name=name_id_or_prefix,
6974
7110
  version=version,
6975
7111
  hydrate=hydrate,
6976
7112
  )
7113
+ scope = ""
7114
+ if project:
7115
+ scope = f" in project {project}"
7116
+ list_kwargs["project"] = project
7117
+ exact_name_matches = list_method(**list_kwargs)
6977
7118
 
6978
7119
  if len(exact_name_matches) == 1:
6979
7120
  # If the name matches exactly, use the explicitly specified version
@@ -6995,13 +7136,13 @@ class Client(metaclass=ClientMetaClass):
6995
7136
  elif partial_id_matches.total == 0:
6996
7137
  raise KeyError(
6997
7138
  f"No {entity_label} found for name, ID or prefix "
6998
- f"{name_id_or_prefix}."
7139
+ f"{name_id_or_prefix}{scope}."
6999
7140
  )
7000
7141
  else:
7001
7142
  raise ZenKeyError(
7002
- f"{partial_id_matches.total} {entity_label} have been found "
7003
- "that have an id prefix that matches the provided string "
7004
- f"'{name_id_or_prefix}':\n"
7143
+ f"{partial_id_matches.total} {entity_label} have been found"
7144
+ f"{scope} that have an id prefix that matches the provided "
7145
+ f"string '{name_id_or_prefix}':\n"
7005
7146
  f"{partial_id_matches.items}.\n"
7006
7147
  f"Please provide more characters to uniquely identify "
7007
7148
  f"only one of the {entity_label}s."
@@ -7013,6 +7154,7 @@ class Client(metaclass=ClientMetaClass):
7013
7154
  list_method: Callable[..., Page[AnyResponse]],
7014
7155
  partial_id_or_name: str,
7015
7156
  allow_name_prefix_match: bool,
7157
+ project: Optional[Union[str, UUID]] = None,
7016
7158
  hydrate: bool = True,
7017
7159
  ) -> AnyResponse:
7018
7160
  """Fetches an entity using a partial ID or name.
@@ -7024,6 +7166,7 @@ class Client(metaclass=ClientMetaClass):
7024
7166
  allow_name_prefix_match: If True, allow matching by name prefix.
7025
7167
  hydrate: Flag deciding whether to hydrate the output model(s)
7026
7168
  by including metadata fields in the response.
7169
+ project: The project name/ID to filter by.
7027
7170
 
7028
7171
  Returns:
7029
7172
  The entity with the given partial ID or name.
@@ -7040,6 +7183,10 @@ class Client(metaclass=ClientMetaClass):
7040
7183
  }
7041
7184
  if allow_name_prefix_match:
7042
7185
  list_method_args["name"] = f"startswith:{partial_id_or_name}"
7186
+ scope = ""
7187
+ if project:
7188
+ scope = f"in project {project} "
7189
+ list_method_args["project"] = project
7043
7190
 
7044
7191
  entity = list_method(**list_method_args)
7045
7192
 
@@ -7059,7 +7206,7 @@ class Client(metaclass=ClientMetaClass):
7059
7206
  # If no entity is found, raise an error.
7060
7207
  if entity.total == 0:
7061
7208
  raise KeyError(
7062
- f"No {entity_label} have been found that have "
7209
+ f"No {entity_label} have been found{scope} that have "
7063
7210
  f"{prefix_description} that matches the provided string "
7064
7211
  f"'{partial_id_or_name}'."
7065
7212
  )
@@ -7073,7 +7220,7 @@ class Client(metaclass=ClientMetaClass):
7073
7220
  else:
7074
7221
  ambiguous_entities.append(str(model.id))
7075
7222
  raise ZenKeyError(
7076
- f"{entity.total} {entity_label} have been found that have "
7223
+ f"{entity.total} {entity_label} have been found{scope} that have "
7077
7224
  f"{prefix_description} that matches the provided "
7078
7225
  f"string '{partial_id_or_name}':\n"
7079
7226
  f"{ambiguous_entities}.\n"
@@ -7508,57 +7655,97 @@ class Client(metaclass=ClientMetaClass):
7508
7655
  api_key_name_or_id=api_key.id,
7509
7656
  )
7510
7657
 
7511
- #############################################
7512
- # Tags
7513
- #
7514
- # Note: tag<>resource are not exposed and
7515
- # can be accessed via relevant resources
7516
- #############################################
7517
-
7518
- def create_tag(self, tag: TagRequest) -> TagResponse:
7658
+ # ---------------------------------- Tags ----------------------------------
7659
+ def create_tag(
7660
+ self,
7661
+ name: str,
7662
+ exclusive: bool = False,
7663
+ color: Optional[Union[str, ColorVariants]] = None,
7664
+ ) -> TagResponse:
7519
7665
  """Creates a new tag.
7520
7666
 
7521
7667
  Args:
7522
- tag: the Tag to be created.
7668
+ name: the name of the tag.
7669
+ exclusive: the boolean to decide whether the tag is an exclusive tag.
7670
+ An exclusive tag means that the tag can exist only for a single:
7671
+ - pipeline run within the scope of a pipeline
7672
+ - artifact version within the scope of an artifact
7673
+ - run template
7674
+ color: the color of the tag
7523
7675
 
7524
7676
  Returns:
7525
7677
  The newly created tag.
7526
7678
  """
7527
- return self.zen_store.create_tag(tag=tag)
7679
+ request_model = TagRequest(name=name, exclusive=exclusive)
7528
7680
 
7529
- def delete_tag(self, tag_name_or_id: Union[str, UUID]) -> None:
7681
+ if color is not None:
7682
+ request_model.color = ColorVariants(color)
7683
+
7684
+ return self.zen_store.create_tag(tag=request_model)
7685
+
7686
+ def delete_tag(
7687
+ self,
7688
+ tag_name_or_id: Union[str, UUID],
7689
+ ) -> None:
7530
7690
  """Deletes a tag.
7531
7691
 
7532
7692
  Args:
7533
7693
  tag_name_or_id: name or id of the tag to be deleted.
7534
7694
  """
7535
- self.zen_store.delete_tag(tag_name_or_id=tag_name_or_id)
7695
+ self.zen_store.delete_tag(
7696
+ tag_name_or_id=tag_name_or_id,
7697
+ )
7536
7698
 
7537
7699
  def update_tag(
7538
7700
  self,
7539
7701
  tag_name_or_id: Union[str, UUID],
7540
- tag_update_model: TagUpdate,
7702
+ name: Optional[str] = None,
7703
+ exclusive: Optional[bool] = None,
7704
+ color: Optional[Union[str, ColorVariants]] = None,
7541
7705
  ) -> TagResponse:
7542
7706
  """Updates an existing tag.
7543
7707
 
7544
7708
  Args:
7545
7709
  tag_name_or_id: name or UUID of the tag to be updated.
7546
- tag_update_model: the tag to be updated.
7710
+ name: the name of the tag.
7711
+ exclusive: the boolean to decide whether the tag is an exclusive tag.
7712
+ An exclusive tag means that the tag can exist only for a single:
7713
+ - pipeline run within the scope of a pipeline
7714
+ - artifact version within the scope of an artifact
7715
+ - run template
7716
+ color: the color of the tag
7547
7717
 
7548
7718
  Returns:
7549
7719
  The updated tag.
7550
7720
  """
7721
+ update_model = TagUpdate()
7722
+
7723
+ if name is not None:
7724
+ update_model.name = name
7725
+
7726
+ if exclusive is not None:
7727
+ update_model.exclusive = exclusive
7728
+
7729
+ if color is not None:
7730
+ if isinstance(color, str):
7731
+ update_model.color = ColorVariants(color)
7732
+ else:
7733
+ update_model.color = color
7734
+
7551
7735
  return self.zen_store.update_tag(
7552
- tag_name_or_id=tag_name_or_id, tag_update_model=tag_update_model
7736
+ tag_name_or_id=tag_name_or_id,
7737
+ tag_update_model=update_model,
7553
7738
  )
7554
7739
 
7555
7740
  def get_tag(
7556
- self, tag_name_or_id: Union[str, UUID], hydrate: bool = True
7741
+ self,
7742
+ tag_name_or_id: Union[str, UUID],
7743
+ hydrate: bool = True,
7557
7744
  ) -> TagResponse:
7558
7745
  """Get an existing tag.
7559
7746
 
7560
7747
  Args:
7561
- tag_name_or_id: name or id of the model to be retrieved.
7748
+ tag_name_or_id: name or id of the tag to be retrieved.
7562
7749
  hydrate: Flag deciding whether to hydrate the output model(s)
7563
7750
  by including metadata fields in the response.
7564
7751
 
@@ -7566,19 +7753,39 @@ class Client(metaclass=ClientMetaClass):
7566
7753
  The tag of interest.
7567
7754
  """
7568
7755
  return self.zen_store.get_tag(
7569
- tag_name_or_id=tag_name_or_id, hydrate=hydrate
7756
+ tag_name_or_id=tag_name_or_id,
7757
+ hydrate=hydrate,
7570
7758
  )
7571
7759
 
7572
7760
  def list_tags(
7573
7761
  self,
7574
- tag_filter_model: TagFilter,
7762
+ sort_by: str = "created",
7763
+ page: int = PAGINATION_STARTING_PAGE,
7764
+ size: int = PAGE_SIZE_DEFAULT,
7765
+ logical_operator: LogicalOperators = LogicalOperators.AND,
7766
+ id: Optional[Union[UUID, str]] = None,
7767
+ user: Optional[Union[UUID, str]] = None,
7768
+ created: Optional[Union[datetime, str]] = None,
7769
+ updated: Optional[Union[datetime, str]] = None,
7770
+ name: Optional[str] = None,
7771
+ color: Optional[Union[str, ColorVariants]] = None,
7772
+ exclusive: Optional[bool] = None,
7575
7773
  hydrate: bool = False,
7576
7774
  ) -> Page[TagResponse]:
7577
7775
  """Get tags by filter.
7578
7776
 
7579
7777
  Args:
7580
- tag_filter_model: All filter parameters including pagination
7581
- params.
7778
+ sort_by: The column to sort by.
7779
+ page: The page of items.
7780
+ size: The maximum size of all pages.
7781
+ logical_operator: Which logical operator to use [and, or].
7782
+ id: Use the id of stacks to filter by.
7783
+ user: Use the user to filter by.
7784
+ created: Use to filter by time of creation.
7785
+ updated: Use the last updated date for filtering.
7786
+ name: The name of the tag.
7787
+ color: The color of the tag.
7788
+ exclusive: Flag indicating whether the tag is exclusive.
7582
7789
  hydrate: Flag deciding whether to hydrate the output model(s)
7583
7790
  by including metadata fields in the response.
7584
7791
 
@@ -7586,5 +7793,72 @@ class Client(metaclass=ClientMetaClass):
7586
7793
  A page of all tags.
7587
7794
  """
7588
7795
  return self.zen_store.list_tags(
7589
- tag_filter_model=tag_filter_model, hydrate=hydrate
7796
+ tag_filter_model=TagFilter(
7797
+ sort_by=sort_by,
7798
+ page=page,
7799
+ size=size,
7800
+ logical_operator=logical_operator,
7801
+ id=id,
7802
+ user=user,
7803
+ created=created,
7804
+ updated=updated,
7805
+ name=name,
7806
+ color=color,
7807
+ exclusive=exclusive,
7808
+ ),
7809
+ hydrate=hydrate,
7810
+ )
7811
+
7812
+ def attach_tag(
7813
+ self,
7814
+ tag_name_or_id: Union[str, UUID],
7815
+ resources: List[TagResource],
7816
+ ) -> None:
7817
+ """Attach a tag to resources.
7818
+
7819
+ Args:
7820
+ tag_name_or_id: name or id of the tag to be attached.
7821
+ resources: the resources to attach the tag to.
7822
+ """
7823
+ if isinstance(tag_name_or_id, str):
7824
+ try:
7825
+ tag_model = self.create_tag(name=tag_name_or_id)
7826
+ except EntityExistsError:
7827
+ tag_model = self.get_tag(tag_name_or_id)
7828
+ else:
7829
+ tag_model = self.get_tag(tag_name_or_id)
7830
+
7831
+ self.zen_store.batch_create_tag_resource(
7832
+ tag_resources=[
7833
+ TagResourceRequest(
7834
+ tag_id=tag_model.id,
7835
+ resource_id=resource.id,
7836
+ resource_type=resource.type,
7837
+ )
7838
+ for resource in resources
7839
+ ]
7840
+ )
7841
+
7842
+ def detach_tag(
7843
+ self,
7844
+ tag_name_or_id: Union[str, UUID],
7845
+ resources: List[TagResource],
7846
+ ) -> None:
7847
+ """Detach a tag from resources.
7848
+
7849
+ Args:
7850
+ tag_name_or_id: name or id of the tag to be detached.
7851
+ resources: the resources to detach the tag from.
7852
+ """
7853
+ tag_model = self.get_tag(tag_name_or_id)
7854
+
7855
+ self.zen_store.batch_delete_tag_resource(
7856
+ tag_resources=[
7857
+ TagResourceRequest(
7858
+ tag_id=tag_model.id,
7859
+ resource_id=resource.id,
7860
+ resource_type=resource.type,
7861
+ )
7862
+ for resource in resources
7863
+ ]
7590
7864
  )