zenml-nightly 0.75.0.dev20250313__py3-none-any.whl → 0.75.0.dev20250315__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 (145) hide show
  1. zenml/VERSION +1 -1
  2. zenml/analytics/context.py +4 -4
  3. zenml/analytics/enums.py +2 -2
  4. zenml/artifacts/utils.py +2 -2
  5. zenml/cli/__init__.py +8 -9
  6. zenml/cli/base.py +2 -2
  7. zenml/cli/code_repository.py +1 -1
  8. zenml/cli/login.py +21 -18
  9. zenml/cli/pipeline.py +3 -3
  10. zenml/cli/project.py +172 -0
  11. zenml/cli/server.py +5 -5
  12. zenml/cli/service_accounts.py +0 -1
  13. zenml/cli/service_connectors.py +15 -16
  14. zenml/cli/stack.py +0 -2
  15. zenml/cli/stack_components.py +2 -2
  16. zenml/cli/utils.py +3 -3
  17. zenml/client.py +352 -341
  18. zenml/config/global_config.py +41 -43
  19. zenml/config/server_config.py +9 -9
  20. zenml/constants.py +5 -3
  21. zenml/event_hub/event_hub.py +1 -1
  22. zenml/integrations/gcp/__init__.py +1 -0
  23. zenml/integrations/gcp/flavors/vertex_orchestrator_flavor.py +5 -0
  24. zenml/integrations/gcp/flavors/vertex_step_operator_flavor.py +5 -28
  25. zenml/integrations/gcp/orchestrators/vertex_orchestrator.py +125 -78
  26. zenml/integrations/gcp/service_connectors/gcp_service_connector.py +7 -6
  27. zenml/integrations/gcp/vertex_custom_job_parameters.py +50 -0
  28. zenml/integrations/mlflow/steps/mlflow_registry.py +3 -3
  29. zenml/integrations/wandb/__init__.py +1 -1
  30. zenml/integrations/wandb/experiment_trackers/wandb_experiment_tracker.py +29 -9
  31. zenml/integrations/wandb/flavors/wandb_experiment_tracker_flavor.py +2 -0
  32. zenml/login/credentials.py +26 -27
  33. zenml/login/credentials_store.py +5 -5
  34. zenml/login/pro/client.py +9 -9
  35. zenml/login/pro/utils.py +8 -8
  36. zenml/login/pro/{tenant → workspace}/__init__.py +1 -1
  37. zenml/login/pro/{tenant → workspace}/client.py +25 -25
  38. zenml/login/pro/{tenant → workspace}/models.py +27 -28
  39. zenml/model/model.py +2 -2
  40. zenml/model_registries/base_model_registry.py +1 -1
  41. zenml/models/__init__.py +29 -29
  42. zenml/models/v2/base/filter.py +1 -1
  43. zenml/models/v2/base/scoped.py +49 -53
  44. zenml/models/v2/core/action.py +12 -12
  45. zenml/models/v2/core/artifact.py +15 -15
  46. zenml/models/v2/core/artifact_version.py +15 -15
  47. zenml/models/v2/core/code_repository.py +12 -12
  48. zenml/models/v2/core/event_source.py +12 -12
  49. zenml/models/v2/core/model.py +26 -18
  50. zenml/models/v2/core/model_version.py +15 -15
  51. zenml/models/v2/core/pipeline.py +15 -15
  52. zenml/models/v2/core/pipeline_build.py +14 -14
  53. zenml/models/v2/core/pipeline_deployment.py +12 -14
  54. zenml/models/v2/core/pipeline_run.py +16 -16
  55. zenml/models/v2/core/project.py +203 -0
  56. zenml/models/v2/core/run_metadata.py +2 -2
  57. zenml/models/v2/core/run_template.py +15 -15
  58. zenml/models/v2/core/schedule.py +12 -12
  59. zenml/models/v2/core/secret.py +1 -1
  60. zenml/models/v2/core/service.py +14 -14
  61. zenml/models/v2/core/step_run.py +13 -13
  62. zenml/models/v2/core/tag.py +96 -3
  63. zenml/models/v2/core/trigger.py +13 -13
  64. zenml/models/v2/core/trigger_execution.py +2 -2
  65. zenml/models/v2/core/user.py +0 -17
  66. zenml/models/v2/misc/server_models.py +6 -6
  67. zenml/models/v2/misc/statistics.py +4 -4
  68. zenml/orchestrators/cache_utils.py +7 -7
  69. zenml/orchestrators/input_utils.py +1 -1
  70. zenml/orchestrators/step_launcher.py +1 -1
  71. zenml/orchestrators/step_run_utils.py +3 -3
  72. zenml/orchestrators/utils.py +4 -4
  73. zenml/pipelines/build_utils.py +2 -2
  74. zenml/pipelines/pipeline_definition.py +5 -5
  75. zenml/pipelines/run_utils.py +1 -1
  76. zenml/service_connectors/service_connector.py +0 -3
  77. zenml/service_connectors/service_connector_utils.py +0 -1
  78. zenml/stack/stack.py +0 -1
  79. zenml/steps/base_step.py +10 -2
  80. zenml/utils/dashboard_utils.py +1 -1
  81. zenml/utils/tag_utils.py +0 -12
  82. zenml/zen_server/cloud_utils.py +3 -3
  83. zenml/zen_server/feature_gate/endpoint_utils.py +1 -1
  84. zenml/zen_server/feature_gate/zenml_cloud_feature_gate.py +1 -1
  85. zenml/zen_server/rbac/endpoint_utils.py +17 -17
  86. zenml/zen_server/rbac/models.py +47 -22
  87. zenml/zen_server/rbac/rbac_sql_zen_store.py +3 -3
  88. zenml/zen_server/rbac/utils.py +23 -25
  89. zenml/zen_server/rbac/zenml_cloud_rbac.py +7 -74
  90. zenml/zen_server/routers/artifact_version_endpoints.py +10 -10
  91. zenml/zen_server/routers/auth_endpoints.py +6 -6
  92. zenml/zen_server/routers/code_repositories_endpoints.py +12 -14
  93. zenml/zen_server/routers/model_versions_endpoints.py +13 -15
  94. zenml/zen_server/routers/models_endpoints.py +7 -9
  95. zenml/zen_server/routers/pipeline_builds_endpoints.py +14 -16
  96. zenml/zen_server/routers/pipeline_deployments_endpoints.py +13 -15
  97. zenml/zen_server/routers/pipelines_endpoints.py +16 -18
  98. zenml/zen_server/routers/{workspaces_endpoints.py → projects_endpoints.py} +111 -68
  99. zenml/zen_server/routers/run_metadata_endpoints.py +7 -9
  100. zenml/zen_server/routers/run_templates_endpoints.py +15 -17
  101. zenml/zen_server/routers/runs_endpoints.py +12 -14
  102. zenml/zen_server/routers/schedule_endpoints.py +12 -14
  103. zenml/zen_server/routers/secrets_endpoints.py +1 -3
  104. zenml/zen_server/routers/server_endpoints.py +7 -7
  105. zenml/zen_server/routers/service_connectors_endpoints.py +11 -13
  106. zenml/zen_server/routers/service_endpoints.py +7 -9
  107. zenml/zen_server/routers/stack_components_endpoints.py +9 -11
  108. zenml/zen_server/routers/stacks_endpoints.py +9 -11
  109. zenml/zen_server/routers/steps_endpoints.py +6 -6
  110. zenml/zen_server/routers/users_endpoints.py +5 -43
  111. zenml/zen_server/template_execution/utils.py +4 -4
  112. zenml/zen_server/utils.py +10 -10
  113. zenml/zen_server/zen_server_api.py +6 -5
  114. zenml/zen_stores/base_zen_store.py +38 -42
  115. zenml/zen_stores/migrations/versions/12eff0206201_rename_workspace_to_project.py +768 -0
  116. zenml/zen_stores/migrations/versions/41b28cae31ce_make_artifacts_workspace_scoped.py +3 -3
  117. zenml/zen_stores/migrations/versions/cbc6acd71f92_add_workspace_display_name.py +58 -0
  118. zenml/zen_stores/rest_zen_store.py +55 -63
  119. zenml/zen_stores/schemas/__init__.py +2 -2
  120. zenml/zen_stores/schemas/action_schemas.py +9 -9
  121. zenml/zen_stores/schemas/artifact_schemas.py +15 -17
  122. zenml/zen_stores/schemas/code_repository_schemas.py +16 -18
  123. zenml/zen_stores/schemas/event_source_schemas.py +9 -9
  124. zenml/zen_stores/schemas/model_schemas.py +15 -17
  125. zenml/zen_stores/schemas/pipeline_build_schemas.py +7 -7
  126. zenml/zen_stores/schemas/pipeline_deployment_schemas.py +7 -7
  127. zenml/zen_stores/schemas/pipeline_run_schemas.py +9 -9
  128. zenml/zen_stores/schemas/pipeline_schemas.py +9 -9
  129. zenml/zen_stores/schemas/{workspace_schemas.py → project_schemas.py} +47 -41
  130. zenml/zen_stores/schemas/run_metadata_schemas.py +5 -5
  131. zenml/zen_stores/schemas/run_template_schemas.py +9 -9
  132. zenml/zen_stores/schemas/schedule_schema.py +9 -9
  133. zenml/zen_stores/schemas/service_schemas.py +7 -7
  134. zenml/zen_stores/schemas/step_run_schemas.py +7 -7
  135. zenml/zen_stores/schemas/trigger_schemas.py +9 -9
  136. zenml/zen_stores/schemas/user_schemas.py +0 -12
  137. zenml/zen_stores/sql_zen_store.py +318 -275
  138. zenml/zen_stores/zen_store_interface.py +56 -70
  139. {zenml_nightly-0.75.0.dev20250313.dist-info → zenml_nightly-0.75.0.dev20250315.dist-info}/METADATA +1 -1
  140. {zenml_nightly-0.75.0.dev20250313.dist-info → zenml_nightly-0.75.0.dev20250315.dist-info}/RECORD +143 -140
  141. zenml/cli/workspace.py +0 -160
  142. zenml/models/v2/core/workspace.py +0 -131
  143. {zenml_nightly-0.75.0.dev20250313.dist-info → zenml_nightly-0.75.0.dev20250315.dist-info}/LICENSE +0 -0
  144. {zenml_nightly-0.75.0.dev20250313.dist-info → zenml_nightly-0.75.0.dev20250315.dist-info}/WHEEL +0 -0
  145. {zenml_nightly-0.75.0.dev20250313.dist-info → zenml_nightly-0.75.0.dev20250315.dist-info}/entry_points.txt +0 -0
@@ -14,12 +14,12 @@
14
14
  """Models representing tags."""
15
15
 
16
16
  import random
17
- from typing import Optional
17
+ from typing import TYPE_CHECKING, ClassVar, List, Optional, Type, TypeVar
18
18
 
19
- from pydantic import Field
19
+ from pydantic import Field, field_validator
20
20
 
21
21
  from zenml.constants import STR_FIELD_MAX_LENGTH
22
- from zenml.enums import ColorVariants
22
+ from zenml.enums import ColorVariants, TaggableResourceTypes
23
23
  from zenml.models.v2.base.base import BaseUpdate
24
24
  from zenml.models.v2.base.scoped import (
25
25
  UserScopedFilter,
@@ -29,6 +29,14 @@ from zenml.models.v2.base.scoped import (
29
29
  UserScopedResponseMetadata,
30
30
  UserScopedResponseResources,
31
31
  )
32
+ from zenml.utils.uuid_utils import is_valid_uuid
33
+
34
+ if TYPE_CHECKING:
35
+ from sqlalchemy.sql.elements import ColumnElement
36
+
37
+ from zenml.zen_stores.schemas import BaseSchema
38
+
39
+ AnySchema = TypeVar("AnySchema", bound="BaseSchema")
32
40
 
33
41
  # ------------------ Request Model ------------------
34
42
 
@@ -49,6 +57,28 @@ class TagRequest(UserScopedRequest):
49
57
  default_factory=lambda: random.choice(list(ColorVariants)),
50
58
  )
51
59
 
60
+ @field_validator("name")
61
+ @classmethod
62
+ def validate_name_not_uuid(cls, value: str) -> str:
63
+ """Validates that the tag name is not a UUID.
64
+
65
+ Args:
66
+ value: The tag name to validate.
67
+
68
+ Returns:
69
+ The validated tag name.
70
+
71
+ Raises:
72
+ ValueError: If the tag name can be converted
73
+ to a UUID.
74
+ """
75
+ if is_valid_uuid(value):
76
+ raise ValueError(
77
+ "Tag names cannot be UUIDs or strings that "
78
+ "can be converted to UUIDs."
79
+ )
80
+ return value
81
+
52
82
 
53
83
  # ------------------ Update Model ------------------
54
84
 
@@ -60,6 +90,27 @@ class TagUpdate(BaseUpdate):
60
90
  exclusive: Optional[bool] = None
61
91
  color: Optional[ColorVariants] = None
62
92
 
93
+ @field_validator("name")
94
+ @classmethod
95
+ def validate_name_not_uuid(cls, value: Optional[str]) -> Optional[str]:
96
+ """Validates that the tag name is not a UUID.
97
+
98
+ Args:
99
+ value: The tag name to validate.
100
+
101
+ Returns:
102
+ The validated tag name.
103
+
104
+ Raises:
105
+ ValueError: If the tag name can be converted to a UUID.
106
+ """
107
+ if value is not None and is_valid_uuid(value):
108
+ raise ValueError(
109
+ "Tag names cannot be UUIDs or strings that "
110
+ "can be converted to UUIDs."
111
+ )
112
+ return value
113
+
63
114
 
64
115
  # ------------------ Response Model ------------------
65
116
 
@@ -143,6 +194,11 @@ class TagResponse(
143
194
  class TagFilter(UserScopedFilter):
144
195
  """Model to enable advanced filtering of all tags."""
145
196
 
197
+ FILTER_EXCLUDE_FIELDS: ClassVar[List[str]] = [
198
+ *UserScopedFilter.FILTER_EXCLUDE_FIELDS,
199
+ "resource_type",
200
+ ]
201
+
146
202
  name: Optional[str] = Field(
147
203
  description="The unique title of the tag.", default=None
148
204
  )
@@ -153,3 +209,40 @@ class TagFilter(UserScopedFilter):
153
209
  description="The flag signifying whether the tag is an exclusive tag.",
154
210
  default=None,
155
211
  )
212
+ resource_type: Optional[TaggableResourceTypes] = Field(
213
+ description="Filter tags associated with a specific resource type.",
214
+ default=None,
215
+ )
216
+
217
+ def get_custom_filters(
218
+ self, table: Type["AnySchema"]
219
+ ) -> List["ColumnElement[bool]"]:
220
+ """Get custom filters.
221
+
222
+ Args:
223
+ table: The query table.
224
+
225
+ Returns:
226
+ A list of custom filters.
227
+ """
228
+ custom_filters = super().get_custom_filters(table)
229
+
230
+ from sqlmodel import exists, select
231
+
232
+ from zenml.zen_stores.schemas import (
233
+ TagResourceSchema,
234
+ TagSchema,
235
+ )
236
+
237
+ if self.resource_type:
238
+ # Filter for tags that have at least one association with the specified resource type
239
+ resource_type_filter = exists(
240
+ select(TagResourceSchema).where(
241
+ TagResourceSchema.tag_id == TagSchema.id,
242
+ TagResourceSchema.resource_type
243
+ == self.resource_type.value,
244
+ )
245
+ )
246
+ custom_filters.append(resource_type_filter)
247
+
248
+ return custom_filters
@@ -33,12 +33,12 @@ from zenml.constants import STR_FIELD_MAX_LENGTH
33
33
  from zenml.models.v2.base.base import BaseUpdate
34
34
  from zenml.models.v2.base.page import Page
35
35
  from zenml.models.v2.base.scoped import (
36
- WorkspaceScopedFilter,
37
- WorkspaceScopedRequest,
38
- WorkspaceScopedResponse,
39
- WorkspaceScopedResponseBody,
40
- WorkspaceScopedResponseMetadata,
41
- WorkspaceScopedResponseResources,
36
+ ProjectScopedFilter,
37
+ ProjectScopedRequest,
38
+ ProjectScopedResponse,
39
+ ProjectScopedResponseBody,
40
+ ProjectScopedResponseMetadata,
41
+ ProjectScopedResponseResources,
42
42
  )
43
43
  from zenml.models.v2.core.trigger_execution import TriggerExecutionResponse
44
44
 
@@ -57,7 +57,7 @@ if TYPE_CHECKING:
57
57
  # ------------------ Request Model ------------------
58
58
 
59
59
 
60
- class TriggerRequest(WorkspaceScopedRequest):
60
+ class TriggerRequest(ProjectScopedRequest):
61
61
  """Model for creating a new trigger."""
62
62
 
63
63
  name: str = Field(
@@ -145,7 +145,7 @@ class TriggerUpdate(BaseUpdate):
145
145
  # ------------------ Response Model ------------------
146
146
 
147
147
 
148
- class TriggerResponseBody(WorkspaceScopedResponseBody):
148
+ class TriggerResponseBody(ProjectScopedResponseBody):
149
149
  """Response body for triggers."""
150
150
 
151
151
  action_flavor: str = Field(
@@ -172,7 +172,7 @@ class TriggerResponseBody(WorkspaceScopedResponseBody):
172
172
  )
173
173
 
174
174
 
175
- class TriggerResponseMetadata(WorkspaceScopedResponseMetadata):
175
+ class TriggerResponseMetadata(ProjectScopedResponseMetadata):
176
176
  """Response metadata for triggers."""
177
177
 
178
178
  description: str = Field(
@@ -192,7 +192,7 @@ class TriggerResponseMetadata(WorkspaceScopedResponseMetadata):
192
192
  )
193
193
 
194
194
 
195
- class TriggerResponseResources(WorkspaceScopedResponseResources):
195
+ class TriggerResponseResources(ProjectScopedResponseResources):
196
196
  """Class for all resource models associated with the trigger entity."""
197
197
 
198
198
  action: "ActionResponse" = Field(
@@ -209,7 +209,7 @@ class TriggerResponseResources(WorkspaceScopedResponseResources):
209
209
 
210
210
 
211
211
  class TriggerResponse(
212
- WorkspaceScopedResponse[
212
+ ProjectScopedResponse[
213
213
  TriggerResponseBody, TriggerResponseMetadata, TriggerResponseResources
214
214
  ]
215
215
  ):
@@ -324,11 +324,11 @@ class TriggerResponse(
324
324
  # ------------------ Filter Model ------------------
325
325
 
326
326
 
327
- class TriggerFilter(WorkspaceScopedFilter):
327
+ class TriggerFilter(ProjectScopedFilter):
328
328
  """Model to enable advanced filtering of all triggers."""
329
329
 
330
330
  FILTER_EXCLUDE_FIELDS: ClassVar[List[str]] = [
331
- *WorkspaceScopedFilter.FILTER_EXCLUDE_FIELDS,
331
+ *ProjectScopedFilter.FILTER_EXCLUDE_FIELDS,
332
332
  "action_flavor",
333
333
  "action_subtype",
334
334
  "event_source_flavor",
@@ -27,7 +27,7 @@ from zenml.models.v2.base.base import (
27
27
  BaseDatedResponseBody,
28
28
  BaseResponseResources,
29
29
  )
30
- from zenml.models.v2.base.scoped import WorkspaceScopedFilter
30
+ from zenml.models.v2.base.scoped import ProjectScopedFilter
31
31
 
32
32
  if TYPE_CHECKING:
33
33
  from zenml.models.v2.core.trigger import TriggerResponse
@@ -109,7 +109,7 @@ class TriggerExecutionResponse(
109
109
  # ------------------ Filter Model ------------------
110
110
 
111
111
 
112
- class TriggerExecutionFilter(WorkspaceScopedFilter):
112
+ class TriggerExecutionFilter(ProjectScopedFilter):
113
113
  """Model to enable advanced filtering of all trigger executions."""
114
114
 
115
115
  trigger_id: Optional[Union[UUID, str]] = Field(
@@ -81,10 +81,6 @@ class UserBase(BaseModel):
81
81
  default=None,
82
82
  title="The metadata associated with the user.",
83
83
  )
84
- default_workspace_id: Optional[UUID] = Field(
85
- default=None,
86
- title="The default workspace ID for the user.",
87
- )
88
84
 
89
85
  @classmethod
90
86
  def _get_crypt_context(cls) -> "CryptContext":
@@ -283,10 +279,6 @@ class UserResponseBody(BaseDatedResponseBody):
283
279
  is_admin: bool = Field(
284
280
  title="Whether the account is an administrator.",
285
281
  )
286
- default_workspace_id: Optional[UUID] = Field(
287
- default=None,
288
- title="The default workspace ID for the user.",
289
- )
290
282
 
291
283
 
292
284
  class UserResponseMetadata(BaseResponseMetadata):
@@ -403,15 +395,6 @@ class UserResponse(
403
395
  """
404
396
  return self.get_body().is_admin
405
397
 
406
- @property
407
- def default_workspace_id(self) -> Optional[UUID]:
408
- """The `default_workspace_id` property.
409
-
410
- Returns:
411
- the value of the property.
412
- """
413
- return self.get_body().default_workspace_id
414
-
415
398
  @property
416
399
  def email(self) -> Optional[str]:
417
400
  """The `email` property.
@@ -131,16 +131,16 @@ class ServerModel(BaseModel):
131
131
  "connected. Only set if the server is a ZenML Pro server.",
132
132
  )
133
133
 
134
- pro_tenant_id: Optional[UUID] = Field(
134
+ pro_workspace_id: Optional[UUID] = Field(
135
135
  None,
136
- title="The ID of the ZenML Pro tenant to which the server is connected. "
137
- "Only set if the server is a ZenML Pro server.",
136
+ title="The ID of the ZenML Pro workspace to which the server is "
137
+ "connected. Only set if the server is a ZenML Pro server.",
138
138
  )
139
139
 
140
- pro_tenant_name: Optional[str] = Field(
140
+ pro_workspace_name: Optional[str] = Field(
141
141
  None,
142
- title="The name of the ZenML Pro tenant to which the server is connected. "
143
- "Only set if the server is a ZenML Pro server.",
142
+ title="The name of the ZenML Pro workspace to which the server is "
143
+ "connected. Only set if the server is a ZenML Pro server.",
144
144
  )
145
145
 
146
146
  def is_local(self) -> bool:
@@ -20,8 +20,8 @@ from zenml.models.v2.base.base import (
20
20
  )
21
21
 
22
22
 
23
- class WorkspaceStatistics(BaseZenModel):
24
- """Workspace statistics."""
23
+ class ProjectStatistics(BaseZenModel):
24
+ """Project statistics."""
25
25
 
26
26
  pipelines: int = Field(
27
27
  title="The number of pipelines.",
@@ -40,6 +40,6 @@ class ServerStatistics(BaseZenModel):
40
40
  components: int = Field(
41
41
  title="The number of components.",
42
42
  )
43
- workspaces: int = Field(
44
- title="The number of workspaces.",
43
+ projects: int = Field(
44
+ title="The number of projects.",
45
45
  )
@@ -34,7 +34,7 @@ def generate_cache_key(
34
34
  step: "Step",
35
35
  input_artifact_ids: Dict[str, "UUID"],
36
36
  artifact_store: "BaseArtifactStore",
37
- workspace_id: "UUID",
37
+ project_id: "UUID",
38
38
  ) -> str:
39
39
  """Generates a cache key for a step run.
40
40
 
@@ -42,7 +42,7 @@ def generate_cache_key(
42
42
  runs are identical and can be cached.
43
43
 
44
44
  The cache key is a MD5 hash of:
45
- - the workspace ID,
45
+ - the project ID,
46
46
  - the artifact store ID and path,
47
47
  - the source code that defines the step,
48
48
  - the parameters of the step,
@@ -55,15 +55,15 @@ def generate_cache_key(
55
55
  step: The step to generate the cache key for.
56
56
  input_artifact_ids: The input artifact IDs for the step.
57
57
  artifact_store: The artifact store of the active stack.
58
- workspace_id: The ID of the active workspace.
58
+ project_id: The ID of the active project.
59
59
 
60
60
  Returns:
61
61
  A cache key.
62
62
  """
63
63
  hash_ = hashlib.md5() # nosec
64
64
 
65
- # Workspace ID
66
- hash_.update(workspace_id.bytes)
65
+ # Project ID
66
+ hash_.update(project_id.bytes)
67
67
 
68
68
  # Artifact store ID and path
69
69
  hash_.update(artifact_store.id.bytes)
@@ -106,7 +106,7 @@ def get_cached_step_run(cache_key: str) -> Optional["StepRunResponse"]:
106
106
  """If a given step can be cached, get the corresponding existing step run.
107
107
 
108
108
  A step run can be cached if there is an existing step run in the same
109
- workspace which has the same cache key and was successfully executed.
109
+ project which has the same cache key and was successfully executed.
110
110
 
111
111
  Args:
112
112
  cache_key: The cache key of the step.
@@ -117,7 +117,7 @@ def get_cached_step_run(cache_key: str) -> Optional["StepRunResponse"]:
117
117
  client = Client()
118
118
 
119
119
  cache_candidates = client.list_run_steps(
120
- workspace=client.active_workspace.id,
120
+ project=client.active_project.id,
121
121
  cache_key=cache_key,
122
122
  status=ExecutionStatus.COMPLETED,
123
123
  sort_by=f"{SorterOps.DESCENDING}:created",
@@ -55,7 +55,7 @@ def resolve_step_inputs(
55
55
  for run_step in pagination_utils.depaginate(
56
56
  Client().list_run_steps,
57
57
  pipeline_run_id=pipeline_run.id,
58
- workspace=pipeline_run.workspace.id,
58
+ project=pipeline_run.project.id,
59
59
  )
60
60
  }
61
61
 
@@ -319,7 +319,7 @@ class StepLauncher:
319
319
  pipeline_run = PipelineRunRequest(
320
320
  name=run_name,
321
321
  orchestrator_run_id=self._orchestrator_run_id,
322
- workspace=client.active_workspace.id,
322
+ project=client.active_project.id,
323
323
  deployment=self._deployment.id,
324
324
  pipeline=(
325
325
  self._deployment.pipeline.id
@@ -75,7 +75,7 @@ class StepRunRequestFactory:
75
75
  pipeline_run_id=self.pipeline_run.id,
76
76
  status=ExecutionStatus.RUNNING,
77
77
  start_time=utc_now(),
78
- workspace=Client().active_workspace.id,
78
+ project=Client().active_project.id,
79
79
  )
80
80
 
81
81
  def populate_request(self, request: StepRunRequest) -> None:
@@ -102,7 +102,7 @@ class StepRunRequestFactory:
102
102
  step=step,
103
103
  input_artifact_ids=input_artifact_ids,
104
104
  artifact_store=self.stack.artifact_store,
105
- workspace_id=Client().active_workspace.id,
105
+ project_id=Client().active_project.id,
106
106
  )
107
107
  request.cache_key = cache_key
108
108
 
@@ -344,7 +344,7 @@ def log_model_version_dashboard_url(
344
344
  ) -> None:
345
345
  """Log the dashboard URL for a model version.
346
346
 
347
- If the current server is not a ZenML Pro tenant, a fallback message is
347
+ If the current server is not a ZenML Pro workspace, a fallback message is
348
348
  logged instead.
349
349
 
350
350
  Args:
@@ -23,8 +23,8 @@ from zenml.config.global_config import (
23
23
  GlobalConfiguration,
24
24
  )
25
25
  from zenml.constants import (
26
+ ENV_ZENML_ACTIVE_PROJECT_ID,
26
27
  ENV_ZENML_ACTIVE_STACK_ID,
27
- ENV_ZENML_ACTIVE_WORKSPACE_ID,
28
28
  ENV_ZENML_DISABLE_CREDENTIALS_DISK_CACHING,
29
29
  ENV_ZENML_PIPELINE_RUN_API_TOKEN_EXPIRATION,
30
30
  ENV_ZENML_SERVER,
@@ -211,13 +211,13 @@ def get_config_environment_vars(
211
211
  # in the pipeline run environment
212
212
  environment_vars[ENV_ZENML_DISABLE_CREDENTIALS_DISK_CACHING] = "true"
213
213
 
214
- # Make sure to use the correct active stack/workspace which might come
214
+ # Make sure to use the correct active stack/project which might come
215
215
  # from a .zen repository and not the global config
216
216
  environment_vars[ENV_ZENML_ACTIVE_STACK_ID] = str(
217
217
  Client().active_stack_model.id
218
218
  )
219
- environment_vars[ENV_ZENML_ACTIVE_WORKSPACE_ID] = str(
220
- Client().active_workspace.id
219
+ environment_vars[ENV_ZENML_ACTIVE_PROJECT_ID] = str(
220
+ Client().active_project.id
221
221
  )
222
222
 
223
223
  return environment_vars
@@ -215,7 +215,7 @@ def reuse_or_create_pipeline_build(
215
215
  build_model = Client().zen_store.get_build(build_id=build)
216
216
  else:
217
217
  build_request = PipelineBuildRequest(
218
- workspace=Client().active_workspace.id,
218
+ project=Client().active_project.id,
219
219
  stack=Client().active_stack_model.id,
220
220
  pipeline=pipeline_id,
221
221
  **build.model_dump(),
@@ -418,7 +418,7 @@ def create_pipeline_build(
418
418
  )
419
419
  stack_checksum = compute_stack_checksum(stack=stack_model)
420
420
  build_request = PipelineBuildRequest(
421
- workspace=client.active_workspace.id,
421
+ project=client.active_project.id,
422
422
  stack=stack_model.id,
423
423
  pipeline=pipeline_id,
424
424
  is_local=is_local,
@@ -684,7 +684,7 @@ To avoid this consider setting pipeline parameters only in one place (config or
684
684
  components = Client().active_stack_model.components
685
685
  orchestrator = components[StackComponentType.ORCHESTRATOR][0]
686
686
  schedule_model = ScheduleRequest(
687
- workspace=Client().active_workspace.id,
687
+ project=Client().active_project.id,
688
688
  pipeline_id=pipeline_id,
689
689
  orchestrator_id=orchestrator.id,
690
690
  name=schedule_name,
@@ -770,7 +770,7 @@ To avoid this consider setting pipeline parameters only in one place (config or
770
770
  code_path = code_utils.upload_code_if_necessary(code_archive)
771
771
 
772
772
  request = PipelineDeploymentRequest(
773
- workspace=Client().active_workspace.id,
773
+ project=Client().active_project.id,
774
774
  stack=stack.id,
775
775
  pipeline=pipeline_id,
776
776
  build=build_id,
@@ -1013,7 +1013,7 @@ To avoid this consider setting pipeline parameters only in one place (config or
1013
1013
  for component_type, component in stack.components.items()
1014
1014
  }
1015
1015
  return {
1016
- "workspace_id": deployment.workspace.id,
1016
+ "project_id": deployment.project.id,
1017
1017
  "store_type": Client().zen_store.type.value,
1018
1018
  **stack_metadata,
1019
1019
  "total_steps": len(self.invocations),
@@ -1094,7 +1094,7 @@ To avoid this consider setting pipeline parameters only in one place (config or
1094
1094
  return _get()
1095
1095
  except RuntimeError:
1096
1096
  request = PipelineRequest(
1097
- workspace=client.active_workspace.id,
1097
+ project=client.active_project.id,
1098
1098
  name=self.name,
1099
1099
  )
1100
1100
 
@@ -1233,7 +1233,7 @@ To avoid this consider setting pipeline parameters only in one place (config or
1233
1233
  return id_
1234
1234
 
1235
1235
  if not allow_suffix:
1236
- raise RuntimeError("Duplicate step ID")
1236
+ raise RuntimeError(f"Duplicate step ID `{id_}`")
1237
1237
 
1238
1238
  for index in range(2, 10000):
1239
1239
  id_ = f"{base_id}_{index}"
@@ -81,7 +81,7 @@ def create_placeholder_run(
81
81
  # running.
82
82
  start_time=start_time,
83
83
  orchestrator_run_id=None,
84
- workspace=deployment.workspace.id,
84
+ project=deployment.project.id,
85
85
  deployment=deployment.id,
86
86
  pipeline=deployment.pipeline.id if deployment.pipeline else None,
87
87
  status=ExecutionStatus.INITIALIZING,
@@ -705,7 +705,6 @@ class ServiceConnector(BaseModel, metaclass=ServiceConnectorMeta):
705
705
 
706
706
  def to_model(
707
707
  self,
708
- workspace: UUID,
709
708
  name: Optional[str] = None,
710
709
  description: str = "",
711
710
  labels: Optional[Dict[str, str]] = None,
@@ -714,7 +713,6 @@ class ServiceConnector(BaseModel, metaclass=ServiceConnectorMeta):
714
713
 
715
714
  Args:
716
715
  name: The name of the connector.
717
- workspace: The ID of the workspace that the connector belongs to.
718
716
  description: The description of the connector.
719
717
  labels: The labels of the connector.
720
718
 
@@ -737,7 +735,6 @@ class ServiceConnector(BaseModel, metaclass=ServiceConnectorMeta):
737
735
  connector_type=spec.connector_type,
738
736
  name=name,
739
737
  description=description,
740
- workspace=workspace,
741
738
  auth_method=self.auth_method,
742
739
  expires_at=self.expires_at,
743
740
  expires_skew_tolerance=self.expires_skew_tolerance,
@@ -184,7 +184,6 @@ def get_resources_options_from_resource_model_for_full_stack(
184
184
  else:
185
185
  resource_model = zen_store.verify_service_connector_config(
186
186
  service_connector=ServiceConnectorRequest(
187
- workspace=client.active_workspace.id,
188
187
  name="fake",
189
188
  connector_type=connector_details.type,
190
189
  auth_method=connector_details.auth_method,
zenml/stack/stack.py CHANGED
@@ -756,7 +756,6 @@ class Stack:
756
756
  type=flavor.type,
757
757
  config=LocalImageBuilderConfig(),
758
758
  user=Client().active_user.id,
759
- workspace=Client().active_workspace.id,
760
759
  created=now,
761
760
  updated=now,
762
761
  )
zenml/steps/base_step.py CHANGED
@@ -432,7 +432,9 @@ class BaseStep:
432
432
  self,
433
433
  *args: Any,
434
434
  id: Optional[str] = None,
435
- after: Union[str, Sequence[str], None] = None,
435
+ after: Union[
436
+ str, StepArtifact, Sequence[Union[str, StepArtifact]], None
437
+ ] = None,
436
438
  **kwargs: Any,
437
439
  ) -> Any:
438
440
  """Handle a call of the step.
@@ -497,8 +499,14 @@ class BaseStep:
497
499
  }
498
500
  if isinstance(after, str):
499
501
  upstream_steps.add(after)
502
+ elif isinstance(after, StepArtifact):
503
+ upstream_steps.add(after.invocation_id)
500
504
  elif isinstance(after, Sequence):
501
- upstream_steps = upstream_steps.union(after)
505
+ for item in after:
506
+ if isinstance(item, str):
507
+ upstream_steps.add(item)
508
+ elif isinstance(item, StepArtifact):
509
+ upstream_steps.add(item.invocation_id)
502
510
 
503
511
  invocation_id = Pipeline.ACTIVE_PIPELINE.add_step_invocation(
504
512
  step=self,
@@ -33,7 +33,7 @@ logger = get_logger(__name__)
33
33
 
34
34
 
35
35
  def get_cloud_dashboard_url() -> Optional[str]:
36
- """Get the base url of the cloud dashboard if the server is a cloud tenant.
36
+ """Get the base url of the cloud dashboard if the server is a ZenML Pro workspace.
37
37
 
38
38
  Returns:
39
39
  The base url of the cloud dashboard.
zenml/utils/tag_utils.py CHANGED
@@ -379,18 +379,6 @@ def add_tags(
379
379
  else:
380
380
  tag_model = client.create_tag(name=tag)
381
381
 
382
- if tag_model.exclusive and resource_type not in [
383
- TaggableResourceTypes.PIPELINE_RUN,
384
- TaggableResourceTypes.ARTIFACT_VERSION,
385
- TaggableResourceTypes.RUN_TEMPLATE,
386
- ]:
387
- logger.warning(
388
- "The tag will be added, however, please keep in mind that "
389
- "the functionality of having exclusive tags is only "
390
- "applicable for pipeline runs, artifact versions and run "
391
- f"templates, not {resource_type.value}s."
392
- )
393
-
394
382
  if resource_id:
395
383
  client.attach_tag(
396
384
  tag_name_or_id=tag_model.name,
@@ -267,6 +267,6 @@ def cloud_connection() -> ZenMLCloudConnection:
267
267
  return _cloud_connection
268
268
 
269
269
 
270
- def send_pro_tenant_status_update() -> None:
271
- """Send a tenant status update to the Cloud API."""
272
- cloud_connection().patch("/tenant_status")
270
+ def send_pro_workspace_status_update() -> None:
271
+ """Send a workspace status update to the Cloud API."""
272
+ cloud_connection().patch("/workspace_status")
@@ -20,7 +20,7 @@ from zenml.zen_server.utils import feature_gate, server_config
20
20
 
21
21
 
22
22
  def check_entitlement(resource_type: ResourceType) -> None:
23
- """Queries the feature gate to see if the operation falls within the tenants entitlements.
23
+ """Queries the feature gate to see if the operation falls within the Pro workspaces entitlements.
24
24
 
25
25
  Raises an exception if the user is not entitled to create an instance of the
26
26
  resource. Otherwise, simply returns.
@@ -110,7 +110,7 @@ class ZenMLCloudFeatureGateInterface(FeatureGateInterface):
110
110
  feature=resource,
111
111
  total=1 if not is_decrement else -1,
112
112
  metadata={
113
- "tenant_id": str(server_config.get_external_server_id()),
113
+ "workspace_id": str(server_config.get_external_server_id()),
114
114
  "resource_id": str(resource_id),
115
115
  },
116
116
  ).model_dump()