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
@@ -38,7 +38,7 @@ from zenml.zen_stores.schemas.pipeline_deployment_schemas import (
38
38
  )
39
39
  from zenml.zen_stores.schemas.pipeline_run_schemas import PipelineRunSchema
40
40
  from zenml.zen_stores.schemas.pipeline_schemas import PipelineSchema
41
- from zenml.zen_stores.schemas.workspace_schemas import WorkspaceSchema
41
+ from zenml.zen_stores.schemas.project_schemas import ProjectSchema
42
42
  from zenml.zen_stores.schemas.run_metadata_schemas import (
43
43
  RunMetadataResourceSchema,
44
44
  RunMetadataSchema,
@@ -118,5 +118,5 @@ __all__ = [
118
118
  "ModelVersionSchema",
119
119
  "ModelVersionArtifactSchema",
120
120
  "ModelVersionPipelineRunSchema",
121
- "WorkspaceSchema",
121
+ "ProjectSchema",
122
122
  ]
@@ -19,7 +19,7 @@ from typing import TYPE_CHECKING, Any, List, Optional
19
19
  from uuid import UUID
20
20
 
21
21
  from pydantic.json import pydantic_encoder
22
- from sqlalchemy import TEXT, Column
22
+ from sqlalchemy import TEXT, Column, UniqueConstraint
23
23
  from sqlmodel import Field, Relationship
24
24
 
25
25
  from zenml.models import (
@@ -32,9 +32,9 @@ from zenml.models import (
32
32
  )
33
33
  from zenml.utils.time_utils import utc_now
34
34
  from zenml.zen_stores.schemas.base_schemas import NamedSchema
35
+ from zenml.zen_stores.schemas.project_schemas import ProjectSchema
35
36
  from zenml.zen_stores.schemas.schema_utils import build_foreign_key_field
36
37
  from zenml.zen_stores.schemas.user_schemas import UserSchema
37
- from zenml.zen_stores.schemas.workspace_schemas import WorkspaceSchema
38
38
 
39
39
  if TYPE_CHECKING:
40
40
  from zenml.zen_stores.schemas import TriggerSchema
@@ -44,16 +44,23 @@ class ActionSchema(NamedSchema, table=True):
44
44
  """SQL Model for actions."""
45
45
 
46
46
  __tablename__ = "action"
47
+ __table_args__ = (
48
+ UniqueConstraint(
49
+ "name",
50
+ "project_id",
51
+ name="unique_action_name_in_project",
52
+ ),
53
+ )
47
54
 
48
- workspace_id: UUID = build_foreign_key_field(
55
+ project_id: UUID = build_foreign_key_field(
49
56
  source=__tablename__,
50
- target=WorkspaceSchema.__tablename__,
51
- source_column="workspace_id",
57
+ target=ProjectSchema.__tablename__,
58
+ source_column="project_id",
52
59
  target_column="id",
53
60
  ondelete="CASCADE",
54
61
  nullable=False,
55
62
  )
56
- workspace: "WorkspaceSchema" = Relationship(back_populates="actions")
63
+ project: "ProjectSchema" = Relationship(back_populates="actions")
57
64
 
58
65
  user_id: Optional[UUID] = build_foreign_key_field(
59
66
  source=__tablename__,
@@ -104,7 +111,7 @@ class ActionSchema(NamedSchema, table=True):
104
111
  """
105
112
  return cls(
106
113
  name=request.name,
107
- workspace_id=request.workspace,
114
+ project_id=request.project,
108
115
  user_id=request.user,
109
116
  configuration=base64.b64encode(
110
117
  json.dumps(
@@ -171,7 +178,7 @@ class ActionSchema(NamedSchema, table=True):
171
178
  metadata = None
172
179
  if include_metadata:
173
180
  metadata = ActionResponseMetadata(
174
- workspace=self.workspace.to_model(),
181
+ project=self.project.to_model(),
175
182
  configuration=json.loads(
176
183
  base64.b64decode(self.configuration).decode()
177
184
  ),
@@ -19,7 +19,7 @@ from typing import Any, Optional, Tuple
19
19
  from uuid import UUID
20
20
 
21
21
  from passlib.context import CryptContext
22
- from sqlalchemy import TEXT, Column
22
+ from sqlalchemy import TEXT, Column, UniqueConstraint
23
23
  from sqlmodel import Field, Relationship
24
24
 
25
25
  from zenml.models import (
@@ -42,6 +42,13 @@ class APIKeySchema(NamedSchema, table=True):
42
42
  """SQL Model for API keys."""
43
43
 
44
44
  __tablename__ = "api_key"
45
+ __table_args__ = (
46
+ UniqueConstraint(
47
+ "name",
48
+ "service_account_id",
49
+ name="unique_api_key_name_in_service_account",
50
+ ),
51
+ )
45
52
 
46
53
  description: str = Field(sa_column=Column(TEXT))
47
54
  key: str
@@ -44,6 +44,7 @@ from zenml.models.v2.core.artifact import ArtifactRequest
44
44
  from zenml.utils.time_utils import utc_now
45
45
  from zenml.zen_stores.schemas.base_schemas import BaseSchema, NamedSchema
46
46
  from zenml.zen_stores.schemas.component_schemas import StackComponentSchema
47
+ from zenml.zen_stores.schemas.project_schemas import ProjectSchema
47
48
  from zenml.zen_stores.schemas.schema_utils import build_foreign_key_field
48
49
  from zenml.zen_stores.schemas.step_run_schemas import (
49
50
  StepRunInputArtifactSchema,
@@ -51,7 +52,6 @@ from zenml.zen_stores.schemas.step_run_schemas import (
51
52
  )
52
53
  from zenml.zen_stores.schemas.user_schemas import UserSchema
53
54
  from zenml.zen_stores.schemas.utils import RunMetadataInterface
54
- from zenml.zen_stores.schemas.workspace_schemas import WorkspaceSchema
55
55
 
56
56
  if TYPE_CHECKING:
57
57
  from zenml.zen_stores.schemas.artifact_visualization_schemas import (
@@ -71,7 +71,8 @@ class ArtifactSchema(NamedSchema, table=True):
71
71
  __table_args__ = (
72
72
  UniqueConstraint(
73
73
  "name",
74
- name="unique_artifact_name",
74
+ "project_id",
75
+ name="unique_artifact_name_in_project",
75
76
  ),
76
77
  )
77
78
 
@@ -91,6 +92,28 @@ class ArtifactSchema(NamedSchema, table=True):
91
92
  ),
92
93
  )
93
94
 
95
+ project_id: UUID = build_foreign_key_field(
96
+ source=__tablename__,
97
+ target=ProjectSchema.__tablename__,
98
+ source_column="project_id",
99
+ target_column="id",
100
+ ondelete="CASCADE",
101
+ nullable=False,
102
+ )
103
+ project: "ProjectSchema" = Relationship()
104
+
105
+ user_id: Optional[UUID] = build_foreign_key_field(
106
+ source=__tablename__,
107
+ target=UserSchema.__tablename__,
108
+ source_column="user_id",
109
+ target_column="id",
110
+ ondelete="SET NULL",
111
+ nullable=True,
112
+ )
113
+ user: Optional["UserSchema"] = Relationship(
114
+ back_populates="artifacts",
115
+ )
116
+
94
117
  @property
95
118
  def latest_version(self) -> Optional["ArtifactVersionSchema"]:
96
119
  """Fetch the latest version for this artifact.
@@ -133,6 +156,8 @@ class ArtifactSchema(NamedSchema, table=True):
133
156
  return cls(
134
157
  name=artifact_request.name,
135
158
  has_custom_name=artifact_request.has_custom_name,
159
+ project_id=artifact_request.project,
160
+ user_id=artifact_request.user,
136
161
  )
137
162
 
138
163
  def to_model(
@@ -165,6 +190,7 @@ class ArtifactSchema(NamedSchema, table=True):
165
190
  tags=[tag.to_model() for tag in self.tags],
166
191
  latest_version_name=latest_name,
167
192
  latest_version_id=latest_id,
193
+ user=self.user.to_model() if self.user else None,
168
194
  )
169
195
 
170
196
  # Create the metadata of the model
@@ -172,6 +198,7 @@ class ArtifactSchema(NamedSchema, table=True):
172
198
  if include_metadata:
173
199
  metadata = ArtifactResponseMetadata(
174
200
  has_custom_name=self.has_custom_name,
201
+ project=self.project.to_model(),
175
202
  )
176
203
 
177
204
  return ArtifactResponse(
@@ -254,10 +281,10 @@ class ArtifactVersionSchema(BaseSchema, RunMetadataInterface, table=True):
254
281
  ondelete="SET NULL",
255
282
  nullable=True,
256
283
  )
257
- workspace_id: UUID = build_foreign_key_field(
284
+ project_id: UUID = build_foreign_key_field(
258
285
  source=__tablename__,
259
- target=WorkspaceSchema.__tablename__,
260
- source_column="workspace_id",
286
+ target=ProjectSchema.__tablename__,
287
+ source_column="project_id",
261
288
  target_column="id",
262
289
  ondelete="CASCADE",
263
290
  nullable=False,
@@ -268,9 +295,7 @@ class ArtifactVersionSchema(BaseSchema, RunMetadataInterface, table=True):
268
295
  user: Optional["UserSchema"] = Relationship(
269
296
  back_populates="artifact_versions"
270
297
  )
271
- workspace: "WorkspaceSchema" = Relationship(
272
- back_populates="artifact_versions"
273
- )
298
+ project: "ProjectSchema" = Relationship(back_populates="artifact_versions")
274
299
  run_metadata: List["RunMetadataSchema"] = Relationship(
275
300
  sa_relationship_kwargs=dict(
276
301
  secondary="run_metadata_resource",
@@ -326,7 +351,7 @@ class ArtifactVersionSchema(BaseSchema, RunMetadataInterface, table=True):
326
351
  version=str(artifact_version_request.version),
327
352
  version_number=version_number,
328
353
  artifact_store_id=artifact_version_request.artifact_store_id,
329
- workspace_id=artifact_version_request.workspace,
354
+ project_id=artifact_version_request.project,
330
355
  user_id=artifact_version_request.user,
331
356
  type=artifact_version_request.type.value,
332
357
  uri=artifact_version_request.uri,
@@ -402,7 +427,7 @@ class ArtifactVersionSchema(BaseSchema, RunMetadataInterface, table=True):
402
427
  metadata = None
403
428
  if include_metadata:
404
429
  metadata = ArtifactVersionResponseMetadata(
405
- workspace=self.workspace.to_model(),
430
+ project=self.project.to_model(),
406
431
  producer_step_run_id=producer_step_run_id,
407
432
  visualizations=[v.to_model() for v in self.visualizations],
408
433
  run_metadata=self.fetch_metadata(),
@@ -17,7 +17,7 @@ import json
17
17
  from typing import Any, Optional
18
18
  from uuid import UUID
19
19
 
20
- from sqlalchemy import TEXT, Column
20
+ from sqlalchemy import TEXT, Column, UniqueConstraint
21
21
  from sqlmodel import Field, Relationship
22
22
 
23
23
  from zenml.models import (
@@ -33,27 +33,32 @@ from zenml.models import (
33
33
  )
34
34
  from zenml.utils.time_utils import utc_now
35
35
  from zenml.zen_stores.schemas.base_schemas import BaseSchema, NamedSchema
36
+ from zenml.zen_stores.schemas.project_schemas import ProjectSchema
36
37
  from zenml.zen_stores.schemas.schema_utils import build_foreign_key_field
37
38
  from zenml.zen_stores.schemas.user_schemas import UserSchema
38
- from zenml.zen_stores.schemas.workspace_schemas import WorkspaceSchema
39
39
 
40
40
 
41
41
  class CodeRepositorySchema(NamedSchema, table=True):
42
42
  """SQL Model for code repositories."""
43
43
 
44
44
  __tablename__ = "code_repository"
45
+ __table_args__ = (
46
+ UniqueConstraint(
47
+ "name",
48
+ "project_id",
49
+ name="unique_code_repository_name_in_project",
50
+ ),
51
+ )
45
52
 
46
- workspace_id: UUID = build_foreign_key_field(
53
+ project_id: UUID = build_foreign_key_field(
47
54
  source=__tablename__,
48
- target=WorkspaceSchema.__tablename__,
49
- source_column="workspace_id",
55
+ target=ProjectSchema.__tablename__,
56
+ source_column="project_id",
50
57
  target_column="id",
51
58
  ondelete="CASCADE",
52
59
  nullable=False,
53
60
  )
54
- workspace: "WorkspaceSchema" = Relationship(
55
- back_populates="code_repositories"
56
- )
61
+ project: "ProjectSchema" = Relationship(back_populates="code_repositories")
57
62
 
58
63
  user_id: Optional[UUID] = build_foreign_key_field(
59
64
  source=__tablename__,
@@ -87,7 +92,7 @@ class CodeRepositorySchema(NamedSchema, table=True):
87
92
  """
88
93
  return cls(
89
94
  name=request.name,
90
- workspace_id=request.workspace,
95
+ project_id=request.project,
91
96
  user_id=request.user,
92
97
  config=json.dumps(request.config),
93
98
  source=request.source.model_dump_json(),
@@ -122,7 +127,7 @@ class CodeRepositorySchema(NamedSchema, table=True):
122
127
  metadata = None
123
128
  if include_metadata:
124
129
  metadata = CodeRepositoryResponseMetadata(
125
- workspace=self.workspace.to_model(),
130
+ project=self.project.to_model(),
126
131
  config=json.loads(self.config),
127
132
  description=self.description,
128
133
  )
@@ -163,15 +168,15 @@ class CodeReferenceSchema(BaseSchema, table=True):
163
168
 
164
169
  __tablename__ = "code_reference"
165
170
 
166
- workspace_id: UUID = build_foreign_key_field(
171
+ project_id: UUID = build_foreign_key_field(
167
172
  source=__tablename__,
168
- target=WorkspaceSchema.__tablename__,
169
- source_column="workspace_id",
173
+ target=ProjectSchema.__tablename__,
174
+ source_column="project_id",
170
175
  target_column="id",
171
176
  ondelete="CASCADE",
172
177
  nullable=False,
173
178
  )
174
- workspace: "WorkspaceSchema" = Relationship()
179
+ project: "ProjectSchema" = Relationship()
175
180
 
176
181
  code_repository_id: UUID = build_foreign_key_field(
177
182
  source=__tablename__,
@@ -188,19 +193,19 @@ class CodeReferenceSchema(BaseSchema, table=True):
188
193
 
189
194
  @classmethod
190
195
  def from_request(
191
- cls, request: "CodeReferenceRequest", workspace_id: UUID
196
+ cls, request: "CodeReferenceRequest", project_id: UUID
192
197
  ) -> "CodeReferenceSchema":
193
198
  """Convert a `CodeReferenceRequest` to a `CodeReferenceSchema`.
194
199
 
195
200
  Args:
196
201
  request: The request model to convert.
197
- workspace_id: The workspace ID.
202
+ project_id: The project ID.
198
203
 
199
204
  Returns:
200
205
  The converted schema.
201
206
  """
202
207
  return cls(
203
- workspace_id=workspace_id,
208
+ project_id=project_id,
204
209
  commit=request.commit,
205
210
  subdirectory=request.subdirectory,
206
211
  code_repository_id=request.code_repository,
@@ -18,6 +18,7 @@ import json
18
18
  from typing import TYPE_CHECKING, Any, List, Optional
19
19
  from uuid import UUID
20
20
 
21
+ from sqlalchemy import UniqueConstraint
21
22
  from sqlmodel import Relationship
22
23
 
23
24
  from zenml.enums import StackComponentType
@@ -37,7 +38,6 @@ from zenml.zen_stores.schemas.service_connector_schemas import (
37
38
  )
38
39
  from zenml.zen_stores.schemas.stack_schemas import StackCompositionSchema
39
40
  from zenml.zen_stores.schemas.user_schemas import UserSchema
40
- from zenml.zen_stores.schemas.workspace_schemas import WorkspaceSchema
41
41
 
42
42
  if TYPE_CHECKING:
43
43
  from zenml.zen_stores.schemas.flavor_schemas import FlavorSchema
@@ -51,22 +51,19 @@ class StackComponentSchema(NamedSchema, table=True):
51
51
  """SQL Model for stack components."""
52
52
 
53
53
  __tablename__ = "stack_component"
54
+ __table_args__ = (
55
+ UniqueConstraint(
56
+ "name",
57
+ "type",
58
+ name="unique_component_name_and_type",
59
+ ),
60
+ )
54
61
 
55
62
  type: str
56
63
  flavor: str
57
64
  configuration: bytes
58
65
  labels: Optional[bytes]
59
66
 
60
- workspace_id: UUID = build_foreign_key_field(
61
- source=__tablename__,
62
- target=WorkspaceSchema.__tablename__,
63
- source_column="workspace_id",
64
- target_column="id",
65
- ondelete="CASCADE",
66
- nullable=False,
67
- )
68
- workspace: "WorkspaceSchema" = Relationship(back_populates="components")
69
-
70
67
  user_id: Optional[UUID] = build_foreign_key_field(
71
68
  source=__tablename__,
72
69
  target=UserSchema.__tablename__,
@@ -132,7 +129,6 @@ class StackComponentSchema(NamedSchema, table=True):
132
129
  """
133
130
  return cls(
134
131
  name=request.name,
135
- workspace_id=request.workspace,
136
132
  user_id=request.user,
137
133
  type=request.type,
138
134
  flavor=request.flavor,
@@ -158,7 +154,7 @@ class StackComponentSchema(NamedSchema, table=True):
158
154
  The updated `StackComponentSchema`.
159
155
  """
160
156
  for field, value in component_update.model_dump(
161
- exclude_unset=True, exclude={"workspace", "user", "connector"}
157
+ exclude_unset=True, exclude={"user", "connector"}
162
158
  ).items():
163
159
  if field == "configuration":
164
160
  self.configuration = base64.b64encode(
@@ -209,7 +205,6 @@ class StackComponentSchema(NamedSchema, table=True):
209
205
  metadata = None
210
206
  if include_metadata:
211
207
  metadata = ComponentResponseMetadata(
212
- workspace=self.workspace.to_model(),
213
208
  configuration=json.loads(
214
209
  base64.b64decode(self.configuration).decode()
215
210
  ),
@@ -18,7 +18,7 @@ import json
18
18
  from typing import TYPE_CHECKING, Any, List, Optional, cast
19
19
  from uuid import UUID
20
20
 
21
- from sqlalchemy import TEXT, Column
21
+ from sqlalchemy import TEXT, Column, UniqueConstraint
22
22
  from sqlmodel import Field, Relationship
23
23
 
24
24
  from zenml import EventSourceResponseMetadata
@@ -33,10 +33,10 @@ from zenml.models import (
33
33
  from zenml.utils.json_utils import pydantic_encoder
34
34
  from zenml.utils.time_utils import utc_now
35
35
  from zenml.zen_stores.schemas.base_schemas import NamedSchema
36
+ from zenml.zen_stores.schemas.project_schemas import ProjectSchema
36
37
  from zenml.zen_stores.schemas.schema_utils import build_foreign_key_field
37
38
  from zenml.zen_stores.schemas.user_schemas import UserSchema
38
39
  from zenml.zen_stores.schemas.utils import get_page_from_list
39
- from zenml.zen_stores.schemas.workspace_schemas import WorkspaceSchema
40
40
 
41
41
  if TYPE_CHECKING:
42
42
  from zenml.zen_stores.schemas import TriggerSchema
@@ -46,16 +46,23 @@ class EventSourceSchema(NamedSchema, table=True):
46
46
  """SQL Model for tag."""
47
47
 
48
48
  __tablename__ = "event_source"
49
+ __table_args__ = (
50
+ UniqueConstraint(
51
+ "name",
52
+ "project_id",
53
+ name="unique_event_source_name_in_project",
54
+ ),
55
+ )
49
56
 
50
- workspace_id: UUID = build_foreign_key_field(
57
+ project_id: UUID = build_foreign_key_field(
51
58
  source=__tablename__,
52
- target=WorkspaceSchema.__tablename__,
53
- source_column="workspace_id",
59
+ target=ProjectSchema.__tablename__,
60
+ source_column="project_id",
54
61
  target_column="id",
55
62
  ondelete="CASCADE",
56
63
  nullable=False,
57
64
  )
58
- workspace: "WorkspaceSchema" = Relationship(back_populates="event_sources")
65
+ project: "ProjectSchema" = Relationship(back_populates="event_sources")
59
66
 
60
67
  user_id: Optional[UUID] = build_foreign_key_field(
61
68
  source=__tablename__,
@@ -89,7 +96,7 @@ class EventSourceSchema(NamedSchema, table=True):
89
96
  The converted schema.
90
97
  """
91
98
  return cls(
92
- workspace_id=request.workspace,
99
+ project_id=request.project,
93
100
  user_id=request.user,
94
101
  flavor=request.flavor,
95
102
  plugin_subtype=request.plugin_subtype,
@@ -150,7 +157,7 @@ class EventSourceSchema(NamedSchema, table=True):
150
157
  metadata = None
151
158
  if include_metadata:
152
159
  metadata = EventSourceResponseMetadata(
153
- workspace=self.workspace.to_model(),
160
+ project=self.project.to_model(),
154
161
  description=self.description,
155
162
  configuration=json.loads(
156
163
  base64.b64decode(self.configuration).decode()
@@ -17,7 +17,7 @@ import json
17
17
  from typing import Any, Optional
18
18
  from uuid import UUID
19
19
 
20
- from sqlalchemy import TEXT, Column
20
+ from sqlalchemy import TEXT, Column, UniqueConstraint
21
21
  from sqlmodel import Field, Relationship
22
22
 
23
23
  from zenml.enums import StackComponentType
@@ -31,7 +31,6 @@ from zenml.utils.time_utils import utc_now
31
31
  from zenml.zen_stores.schemas.base_schemas import NamedSchema
32
32
  from zenml.zen_stores.schemas.schema_utils import build_foreign_key_field
33
33
  from zenml.zen_stores.schemas.user_schemas import UserSchema
34
- from zenml.zen_stores.schemas.workspace_schemas import WorkspaceSchema
35
34
 
36
35
 
37
36
  class FlavorSchema(NamedSchema, table=True):
@@ -45,6 +44,13 @@ class FlavorSchema(NamedSchema, table=True):
45
44
  """
46
45
 
47
46
  __tablename__ = "flavor"
47
+ __table_args__ = (
48
+ UniqueConstraint(
49
+ "name",
50
+ "type",
51
+ name="unique_flavor_name_and_type",
52
+ ),
53
+ )
48
54
 
49
55
  type: str
50
56
  source: str
@@ -54,18 +60,6 @@ class FlavorSchema(NamedSchema, table=True):
54
60
  connector_resource_type: Optional[str]
55
61
  connector_resource_id_attr: Optional[str]
56
62
 
57
- workspace_id: Optional[UUID] = build_foreign_key_field(
58
- source=__tablename__,
59
- target=WorkspaceSchema.__tablename__,
60
- source_column="workspace_id",
61
- target_column="id",
62
- ondelete="CASCADE",
63
- nullable=True,
64
- )
65
- workspace: Optional["WorkspaceSchema"] = Relationship(
66
- back_populates="flavors"
67
- )
68
-
69
63
  user_id: Optional[UUID] = build_foreign_key_field(
70
64
  source=__tablename__,
71
65
  target=UserSchema.__tablename__,
@@ -84,7 +78,10 @@ class FlavorSchema(NamedSchema, table=True):
84
78
 
85
79
  is_custom: bool = Field(default=True)
86
80
 
87
- def update(self, flavor_update: "FlavorUpdate") -> "FlavorSchema":
81
+ def update(
82
+ self,
83
+ flavor_update: "FlavorUpdate",
84
+ ) -> "FlavorSchema":
88
85
  """Update a `FlavorSchema` from a `FlavorUpdate`.
89
86
 
90
87
  Args:
@@ -94,7 +91,7 @@ class FlavorSchema(NamedSchema, table=True):
94
91
  The updated `FlavorSchema`.
95
92
  """
96
93
  for field, value in flavor_update.model_dump(
97
- exclude_unset=True, exclude={"workspace", "user"}
94
+ exclude_unset=True, exclude={"user"}
98
95
  ).items():
99
96
  if field == "config_schema":
100
97
  setattr(self, field, json.dumps(value))
@@ -129,22 +126,19 @@ class FlavorSchema(NamedSchema, table=True):
129
126
  integration=self.integration,
130
127
  source=self.source,
131
128
  logo_url=self.logo_url,
129
+ is_custom=self.is_custom,
132
130
  created=self.created,
133
131
  updated=self.updated,
134
132
  )
135
133
  metadata = None
136
134
  if include_metadata:
137
135
  metadata = FlavorResponseMetadata(
138
- workspace=self.workspace.to_model()
139
- if self.workspace
140
- else None,
141
136
  config_schema=json.loads(self.config_schema),
142
137
  connector_type=self.connector_type,
143
138
  connector_resource_type=self.connector_resource_type,
144
139
  connector_resource_id_attr=self.connector_resource_id_attr,
145
140
  docs_url=self.docs_url,
146
141
  sdk_docs_url=self.sdk_docs_url,
147
- is_custom=self.is_custom,
148
142
  )
149
143
  return FlavorResponse(
150
144
  id=self.id,
@@ -57,6 +57,7 @@ from zenml.zen_stores.schemas.artifact_schemas import ArtifactVersionSchema
57
57
  from zenml.zen_stores.schemas.base_schemas import BaseSchema, NamedSchema
58
58
  from zenml.zen_stores.schemas.constants import MODEL_VERSION_TABLENAME
59
59
  from zenml.zen_stores.schemas.pipeline_run_schemas import PipelineRunSchema
60
+ from zenml.zen_stores.schemas.project_schemas import ProjectSchema
60
61
  from zenml.zen_stores.schemas.run_metadata_schemas import RunMetadataSchema
61
62
  from zenml.zen_stores.schemas.schema_utils import build_foreign_key_field
62
63
  from zenml.zen_stores.schemas.tag_schemas import TagSchema
@@ -65,7 +66,6 @@ from zenml.zen_stores.schemas.utils import (
65
66
  RunMetadataInterface,
66
67
  get_page_from_list,
67
68
  )
68
- from zenml.zen_stores.schemas.workspace_schemas import WorkspaceSchema
69
69
 
70
70
  if TYPE_CHECKING:
71
71
  from zenml.zen_stores.schemas import ServiceSchema, StepRunSchema
@@ -78,20 +78,20 @@ class ModelSchema(NamedSchema, table=True):
78
78
  __table_args__ = (
79
79
  UniqueConstraint(
80
80
  "name",
81
- "workspace_id",
82
- name="unique_model_name_in_workspace",
81
+ "project_id",
82
+ name="unique_model_name_in_project",
83
83
  ),
84
84
  )
85
85
 
86
- workspace_id: UUID = build_foreign_key_field(
86
+ project_id: UUID = build_foreign_key_field(
87
87
  source=__tablename__,
88
- target=WorkspaceSchema.__tablename__,
89
- source_column="workspace_id",
88
+ target=ProjectSchema.__tablename__,
89
+ source_column="project_id",
90
90
  target_column="id",
91
91
  ondelete="CASCADE",
92
92
  nullable=False,
93
93
  )
94
- workspace: "WorkspaceSchema" = Relationship(back_populates="models")
94
+ project: "ProjectSchema" = Relationship(back_populates="models")
95
95
 
96
96
  user_id: Optional[UUID] = build_foreign_key_field(
97
97
  source=__tablename__,
@@ -165,7 +165,7 @@ class ModelSchema(NamedSchema, table=True):
165
165
  """
166
166
  return cls(
167
167
  name=model_request.name,
168
- workspace_id=model_request.workspace,
168
+ project_id=model_request.project,
169
169
  user_id=model_request.user,
170
170
  license=model_request.license,
171
171
  description=model_request.description,
@@ -206,7 +206,7 @@ class ModelSchema(NamedSchema, table=True):
206
206
  metadata = None
207
207
  if include_metadata:
208
208
  metadata = ModelResponseMetadata(
209
- workspace=self.workspace.to_model(),
209
+ project=self.project.to_model(),
210
210
  license=self.license,
211
211
  description=self.description,
212
212
  audience=self.audience,
@@ -248,6 +248,9 @@ class ModelSchema(NamedSchema, table=True):
248
248
  for field, value in model_update.model_dump(
249
249
  exclude_unset=True, exclude_none=True
250
250
  ).items():
251
+ if field in ["add_tags", "remove_tags"]:
252
+ # Tags are handled separately
253
+ continue
251
254
  setattr(self, field, value)
252
255
  self.updated = utc_now()
253
256
  return self
@@ -282,17 +285,15 @@ class ModelVersionSchema(NamedSchema, RunMetadataInterface, table=True):
282
285
  ),
283
286
  )
284
287
 
285
- workspace_id: UUID = build_foreign_key_field(
288
+ project_id: UUID = build_foreign_key_field(
286
289
  source=__tablename__,
287
- target=WorkspaceSchema.__tablename__,
288
- source_column="workspace_id",
290
+ target=ProjectSchema.__tablename__,
291
+ source_column="project_id",
289
292
  target_column="id",
290
293
  ondelete="CASCADE",
291
294
  nullable=False,
292
295
  )
293
- workspace: "WorkspaceSchema" = Relationship(
294
- back_populates="model_versions"
295
- )
296
+ project: "ProjectSchema" = Relationship(back_populates="model_versions")
296
297
 
297
298
  user_id: Optional[UUID] = build_foreign_key_field(
298
299
  source=__tablename__,
@@ -397,7 +398,7 @@ class ModelVersionSchema(NamedSchema, RunMetadataInterface, table=True):
397
398
 
398
399
  return cls(
399
400
  id=id_,
400
- workspace_id=model_version_request.workspace,
401
+ project_id=model_version_request.project,
401
402
  user_id=model_version_request.user,
402
403
  model_id=model_version_request.model,
403
404
  name=model_version_request.name,
@@ -465,7 +466,7 @@ class ModelVersionSchema(NamedSchema, RunMetadataInterface, table=True):
465
466
  metadata = None
466
467
  if include_metadata:
467
468
  metadata = ModelVersionResponseMetadata(
468
- workspace=self.workspace.to_model(),
469
+ project=self.project.to_model(),
469
470
  description=self.description,
470
471
  run_metadata=self.fetch_metadata(),
471
472
  )