zenml-nightly 0.70.0.dev20241125__py3-none-any.whl → 0.70.0.dev20241201__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 (91) hide show
  1. zenml/VERSION +1 -1
  2. zenml/artifact_stores/base_artifact_store.py +2 -2
  3. zenml/artifacts/artifact_config.py +7 -1
  4. zenml/artifacts/utils.py +56 -31
  5. zenml/cli/__init__.py +18 -0
  6. zenml/cli/base.py +4 -4
  7. zenml/cli/login.py +26 -0
  8. zenml/cli/pipeline.py +80 -0
  9. zenml/cli/server.py +1 -1
  10. zenml/cli/service_connectors.py +3 -3
  11. zenml/cli/stack.py +0 -3
  12. zenml/cli/stack_components.py +0 -1
  13. zenml/cli/utils.py +0 -5
  14. zenml/client.py +8 -18
  15. zenml/config/compiler.py +12 -3
  16. zenml/config/pipeline_configurations.py +20 -0
  17. zenml/config/pipeline_run_configuration.py +1 -0
  18. zenml/config/step_configurations.py +21 -0
  19. zenml/enums.py +1 -0
  20. zenml/image_builders/local_image_builder.py +13 -3
  21. zenml/integrations/__init__.py +1 -0
  22. zenml/integrations/aws/orchestrators/sagemaker_orchestrator.py +14 -6
  23. zenml/integrations/constants.py +1 -0
  24. zenml/integrations/feast/__init__.py +1 -1
  25. zenml/integrations/feast/feature_stores/feast_feature_store.py +13 -9
  26. zenml/integrations/kubernetes/orchestrators/kube_utils.py +46 -2
  27. zenml/integrations/kubernetes/orchestrators/kubernetes_orchestrator.py +13 -2
  28. zenml/integrations/kubernetes/orchestrators/kubernetes_orchestrator_entrypoint.py +3 -1
  29. zenml/integrations/kubernetes/orchestrators/manifest_utils.py +3 -2
  30. zenml/integrations/kubernetes/step_operators/kubernetes_step_operator.py +3 -1
  31. zenml/integrations/modal/__init__.py +46 -0
  32. zenml/integrations/modal/flavors/__init__.py +26 -0
  33. zenml/integrations/modal/flavors/modal_step_operator_flavor.py +125 -0
  34. zenml/integrations/modal/step_operators/__init__.py +22 -0
  35. zenml/integrations/modal/step_operators/modal_step_operator.py +242 -0
  36. zenml/io/filesystem.py +2 -2
  37. zenml/io/local_filesystem.py +3 -3
  38. zenml/materializers/built_in_materializer.py +18 -1
  39. zenml/materializers/structured_string_materializer.py +8 -3
  40. zenml/model/model.py +11 -85
  41. zenml/model/utils.py +18 -16
  42. zenml/models/__init__.py +6 -0
  43. zenml/models/v2/core/artifact_version.py +6 -3
  44. zenml/models/v2/core/component.py +0 -22
  45. zenml/models/v2/core/model_version.py +6 -3
  46. zenml/models/v2/core/pipeline_run.py +19 -3
  47. zenml/models/v2/core/run_metadata.py +30 -9
  48. zenml/models/v2/core/step_run.py +6 -4
  49. zenml/models/v2/misc/run_metadata.py +38 -0
  50. zenml/orchestrators/input_utils.py +19 -6
  51. zenml/orchestrators/publish_utils.py +12 -5
  52. zenml/orchestrators/step_launcher.py +7 -3
  53. zenml/orchestrators/step_run_utils.py +26 -9
  54. zenml/orchestrators/step_runner.py +40 -3
  55. zenml/orchestrators/utils.py +24 -23
  56. zenml/pipelines/pipeline_decorator.py +4 -0
  57. zenml/pipelines/pipeline_definition.py +26 -8
  58. zenml/pipelines/run_utils.py +9 -5
  59. zenml/steps/base_step.py +11 -1
  60. zenml/steps/entrypoint_function_utils.py +7 -3
  61. zenml/steps/step_decorator.py +4 -0
  62. zenml/steps/utils.py +23 -7
  63. zenml/types.py +4 -0
  64. zenml/utils/metadata_utils.py +186 -153
  65. zenml/utils/string_utils.py +41 -16
  66. zenml/utils/visualization_utils.py +4 -1
  67. zenml/zen_server/cloud_utils.py +3 -1
  68. zenml/zen_server/rbac/endpoint_utils.py +6 -4
  69. zenml/zen_server/rbac/models.py +3 -2
  70. zenml/zen_server/rbac/utils.py +4 -7
  71. zenml/zen_server/routers/users_endpoints.py +35 -37
  72. zenml/zen_server/routers/workspaces_endpoints.py +44 -55
  73. zenml/zen_server/template_execution/utils.py +1 -0
  74. zenml/zen_stores/migrations/versions/b73bc71f1106_remove_component_spec_path.py +36 -0
  75. zenml/zen_stores/migrations/versions/cc269488e5a9_separate_run_metadata.py +135 -0
  76. zenml/zen_stores/migrations/versions/ec6307720f92_simplify_model_version_links.py +7 -6
  77. zenml/zen_stores/schemas/__init__.py +5 -1
  78. zenml/zen_stores/schemas/artifact_schemas.py +12 -11
  79. zenml/zen_stores/schemas/component_schemas.py +0 -3
  80. zenml/zen_stores/schemas/model_schemas.py +13 -11
  81. zenml/zen_stores/schemas/pipeline_run_schemas.py +44 -16
  82. zenml/zen_stores/schemas/run_metadata_schemas.py +66 -31
  83. zenml/zen_stores/schemas/step_run_schemas.py +32 -12
  84. zenml/zen_stores/schemas/utils.py +47 -3
  85. zenml/zen_stores/sql_zen_store.py +130 -34
  86. {zenml_nightly-0.70.0.dev20241125.dist-info → zenml_nightly-0.70.0.dev20241201.dist-info}/METADATA +1 -1
  87. {zenml_nightly-0.70.0.dev20241125.dist-info → zenml_nightly-0.70.0.dev20241201.dist-info}/RECORD +90 -83
  88. zenml/utils/cloud_utils.py +0 -40
  89. {zenml_nightly-0.70.0.dev20241125.dist-info → zenml_nightly-0.70.0.dev20241201.dist-info}/LICENSE +0 -0
  90. {zenml_nightly-0.70.0.dev20241125.dist-info → zenml_nightly-0.70.0.dev20241201.dist-info}/WHEEL +0 -0
  91. {zenml_nightly-0.70.0.dev20241125.dist-info → zenml_nightly-0.70.0.dev20241201.dist-info}/entry_points.txt +0 -0
@@ -413,8 +413,6 @@ def get_resource_type_for_model(
413
413
  TagResponse,
414
414
  TriggerExecutionResponse,
415
415
  TriggerResponse,
416
- UserResponse,
417
- WorkspaceResponse,
418
416
  )
419
417
 
420
418
  mapping: Dict[
@@ -434,8 +432,8 @@ def get_resource_type_for_model(
434
432
  ModelVersionResponse: ResourceType.MODEL_VERSION,
435
433
  ArtifactResponse: ResourceType.ARTIFACT,
436
434
  ArtifactVersionResponse: ResourceType.ARTIFACT_VERSION,
437
- WorkspaceResponse: ResourceType.WORKSPACE,
438
- UserResponse: ResourceType.USER,
435
+ # WorkspaceResponse: ResourceType.WORKSPACE,
436
+ # UserResponse: ResourceType.USER,
439
437
  PipelineDeploymentResponse: ResourceType.PIPELINE_DEPLOYMENT,
440
438
  PipelineBuildResponse: ResourceType.PIPELINE_BUILD,
441
439
  PipelineRunResponse: ResourceType.PIPELINE_RUN,
@@ -570,7 +568,6 @@ def get_schema_for_resource_type(
570
568
  TriggerExecutionSchema,
571
569
  TriggerSchema,
572
570
  UserSchema,
573
- WorkspaceSchema,
574
571
  )
575
572
 
576
573
  mapping: Dict[ResourceType, Type["BaseSchema"]] = {
@@ -588,13 +585,13 @@ def get_schema_for_resource_type(
588
585
  ResourceType.SERVICE: ServiceSchema,
589
586
  ResourceType.TAG: TagSchema,
590
587
  ResourceType.SERVICE_ACCOUNT: UserSchema,
591
- ResourceType.WORKSPACE: WorkspaceSchema,
588
+ # ResourceType.WORKSPACE: WorkspaceSchema,
592
589
  ResourceType.PIPELINE_RUN: PipelineRunSchema,
593
590
  ResourceType.PIPELINE_DEPLOYMENT: PipelineDeploymentSchema,
594
591
  ResourceType.PIPELINE_BUILD: PipelineBuildSchema,
595
592
  ResourceType.RUN_TEMPLATE: RunTemplateSchema,
596
593
  ResourceType.RUN_METADATA: RunMetadataSchema,
597
- ResourceType.USER: UserSchema,
594
+ # ResourceType.USER: UserSchema,
598
595
  ResourceType.ACTION: ActionSchema,
599
596
  ResourceType.EVENT_SOURCE: EventSourceSchema,
600
597
  ResourceType.TRIGGER: TriggerSchema,
@@ -46,14 +46,10 @@ from zenml.zen_server.auth import (
46
46
  )
47
47
  from zenml.zen_server.exceptions import error_response
48
48
  from zenml.zen_server.rate_limit import RequestLimiter
49
- from zenml.zen_server.rbac.endpoint_utils import (
50
- verify_permissions_and_create_entity,
51
- )
52
49
  from zenml.zen_server.rbac.models import Action, Resource, ResourceType
53
50
  from zenml.zen_server.rbac.utils import (
54
51
  dehydrate_page,
55
52
  dehydrate_response_model,
56
- get_allowed_resource_ids,
57
53
  get_schema_for_resource_type,
58
54
  update_resource_membership,
59
55
  verify_permission_for_model,
@@ -112,17 +108,18 @@ def list_users(
112
108
  Returns:
113
109
  A list of all users.
114
110
  """
115
- allowed_ids = get_allowed_resource_ids(resource_type=ResourceType.USER)
116
- if allowed_ids is not None:
117
- # Make sure users can see themselves
118
- allowed_ids.add(auth_context.user.id)
119
- else:
120
- if not auth_context.user.is_admin and not server_config().rbac_enabled:
121
- allowed_ids = {auth_context.user.id}
122
-
123
- user_filter_model.configure_rbac(
124
- authenticated_user_id=auth_context.user.id, id=allowed_ids
125
- )
111
+ # allowed_ids = get_allowed_resource_ids(resource_type=ResourceType.USER)
112
+ # if allowed_ids is not None:
113
+ # # Make sure users can see themselves
114
+ # allowed_ids.add(auth_context.user.id)
115
+ # else:
116
+ # if not auth_context.user.is_admin and not server_config().rbac_enabled:
117
+ # allowed_ids = {auth_context.user.id}
118
+ if not auth_context.user.is_admin and not server_config().rbac_enabled:
119
+ user_filter_model.configure_rbac(
120
+ authenticated_user_id=auth_context.user.id,
121
+ id={auth_context.user.id},
122
+ )
126
123
 
127
124
  page = zen_store().list_users(
128
125
  user_filter_model=user_filter_model, hydrate=hydrate
@@ -175,11 +172,12 @@ if server_config().auth_scheme != AuthScheme.EXTERNAL:
175
172
  auth_context.user.is_admin, "create user"
176
173
  )
177
174
 
178
- new_user = verify_permissions_and_create_entity(
179
- request_model=user,
180
- resource_type=ResourceType.USER,
181
- create_method=zen_store().create_user,
182
- )
175
+ # new_user = verify_permissions_and_create_entity(
176
+ # request_model=user,
177
+ # resource_type=ResourceType.USER,
178
+ # create_method=zen_store().create_user,
179
+ # )
180
+ new_user = zen_store().create_user(user)
183
181
 
184
182
  # add back the original unhashed activation token, if generated, to
185
183
  # send it back to the client
@@ -217,10 +215,10 @@ def get_user(
217
215
  verify_admin_status_if_no_rbac(
218
216
  auth_context.user.is_admin, "get other user"
219
217
  )
220
- verify_permission_for_model(
221
- user,
222
- action=Action.READ,
223
- )
218
+ # verify_permission_for_model(
219
+ # user,
220
+ # action=Action.READ,
221
+ # )
224
222
 
225
223
  return dehydrate_response_model(user)
226
224
 
@@ -304,10 +302,10 @@ if server_config().auth_scheme != AuthScheme.EXTERNAL:
304
302
  verify_admin_status_if_no_rbac(
305
303
  auth_context.user.is_admin, "update other user account"
306
304
  )
307
- verify_permission_for_model(
308
- user,
309
- action=Action.UPDATE,
310
- )
305
+ # verify_permission_for_model(
306
+ # user,
307
+ # action=Action.UPDATE,
308
+ # )
311
309
 
312
310
  # Validate a password change
313
311
  if user_update.password is not None:
@@ -497,10 +495,10 @@ if server_config().auth_scheme != AuthScheme.EXTERNAL:
497
495
  verify_admin_status_if_no_rbac(
498
496
  auth_context.user.is_admin, "deactivate user"
499
497
  )
500
- verify_permission_for_model(
501
- user,
502
- action=Action.UPDATE,
503
- )
498
+ # verify_permission_for_model(
499
+ # user,
500
+ # action=Action.UPDATE,
501
+ # )
504
502
 
505
503
  user_update = UserUpdate(
506
504
  active=False,
@@ -548,10 +546,10 @@ if server_config().auth_scheme != AuthScheme.EXTERNAL:
548
546
  verify_admin_status_if_no_rbac(
549
547
  auth_context.user.is_admin, "delete user"
550
548
  )
551
- verify_permission_for_model(
552
- user,
553
- action=Action.DELETE,
554
- )
549
+ # verify_permission_for_model(
550
+ # user,
551
+ # action=Action.DELETE,
552
+ # )
555
553
 
556
554
  zen_store().delete_user(user_name_or_id=user_name_or_id)
557
555
 
@@ -746,7 +744,7 @@ if server_config().rbac_enabled:
746
744
  KeyError: If no resource with the given type and ID exists.
747
745
  """
748
746
  user = zen_store().get_user(user_name_or_id)
749
- verify_permission_for_model(user, action=Action.READ)
747
+ # verify_permission_for_model(user, action=Action.READ)
750
748
 
751
749
  if user.id == auth_context.user.id:
752
750
  raise ValueError(
@@ -13,7 +13,7 @@
13
13
  # permissions and limitations under the License.
14
14
  """Endpoint definitions for workspaces."""
15
15
 
16
- from typing import Dict, List, Optional, Tuple, Union
16
+ from typing import Any, Dict, List, Optional, Tuple, Union
17
17
  from uuid import UUID
18
18
 
19
19
  from fastapi import APIRouter, Depends, Security
@@ -98,13 +98,13 @@ from zenml.zen_server.feature_gate.endpoint_utils import (
98
98
  )
99
99
  from zenml.zen_server.rbac.endpoint_utils import (
100
100
  verify_permissions_and_create_entity,
101
- verify_permissions_and_delete_entity,
102
- verify_permissions_and_get_entity,
103
101
  verify_permissions_and_list_entities,
104
- verify_permissions_and_update_entity,
105
102
  )
106
103
  from zenml.zen_server.rbac.models import Action, ResourceType
107
104
  from zenml.zen_server.rbac.utils import (
105
+ batch_verify_permissions_for_models,
106
+ dehydrate_page,
107
+ dehydrate_response_model,
108
108
  get_allowed_resource_ids,
109
109
  verify_permission,
110
110
  verify_permission_for_model,
@@ -146,12 +146,10 @@ def list_workspaces(
146
146
  Returns:
147
147
  A list of workspaces.
148
148
  """
149
- return verify_permissions_and_list_entities(
150
- filter_model=workspace_filter_model,
151
- resource_type=ResourceType.WORKSPACE,
152
- list_method=zen_store().list_workspaces,
153
- hydrate=hydrate,
149
+ workspaces = zen_store().list_workspaces(
150
+ workspace_filter_model, hydrate=hydrate
154
151
  )
152
+ return dehydrate_page(workspaces)
155
153
 
156
154
 
157
155
  @router.post(
@@ -160,7 +158,7 @@ def list_workspaces(
160
158
  )
161
159
  @handle_exceptions
162
160
  def create_workspace(
163
- workspace: WorkspaceRequest,
161
+ workspace_request: WorkspaceRequest,
164
162
  _: AuthContext = Security(authorize),
165
163
  ) -> WorkspaceResponse:
166
164
  """Creates a workspace based on the requestBody.
@@ -168,16 +166,13 @@ def create_workspace(
168
166
  # noqa: DAR401
169
167
 
170
168
  Args:
171
- workspace: Workspace to create.
169
+ workspace_request: Workspace to create.
172
170
 
173
171
  Returns:
174
172
  The created workspace.
175
173
  """
176
- return verify_permissions_and_create_entity(
177
- request_model=workspace,
178
- resource_type=ResourceType.WORKSPACE,
179
- create_method=zen_store().create_workspace,
180
- )
174
+ workspace = zen_store().create_workspace(workspace_request)
175
+ return dehydrate_response_model(workspace)
181
176
 
182
177
 
183
178
  @router.get(
@@ -203,11 +198,10 @@ def get_workspace(
203
198
  Returns:
204
199
  The requested workspace.
205
200
  """
206
- return verify_permissions_and_get_entity(
207
- id=workspace_name_or_id,
208
- get_method=zen_store().get_workspace,
209
- hydrate=hydrate,
201
+ workspace = zen_store().get_workspace(
202
+ workspace_name_or_id, hydrate=hydrate
210
203
  )
204
+ return dehydrate_response_model(workspace)
211
205
 
212
206
 
213
207
  @router.put(
@@ -231,12 +225,11 @@ def update_workspace(
231
225
  Returns:
232
226
  The updated workspace.
233
227
  """
234
- return verify_permissions_and_update_entity(
235
- id=workspace_name_or_id,
236
- update_model=workspace_update,
237
- get_method=zen_store().get_workspace,
238
- update_method=zen_store().update_workspace,
228
+ workspace = zen_store().get_workspace(workspace_name_or_id, hydrate=False)
229
+ updated_workspace = zen_store().update_workspace(
230
+ workspace_id=workspace.id, workspace_update=workspace_update
239
231
  )
232
+ return dehydrate_response_model(updated_workspace)
240
233
 
241
234
 
242
235
  @router.delete(
@@ -253,11 +246,7 @@ def delete_workspace(
253
246
  Args:
254
247
  workspace_name_or_id: Name or ID of the workspace.
255
248
  """
256
- verify_permissions_and_delete_entity(
257
- id=workspace_name_or_id,
258
- get_method=zen_store().get_workspace,
259
- delete_method=zen_store().delete_workspace,
260
- )
249
+ zen_store().delete_workspace(workspace_name_or_id)
261
250
 
262
251
 
263
252
  @router.get(
@@ -951,20 +940,21 @@ def get_or_create_pipeline_run(
951
940
  "is not supported."
952
941
  )
953
942
 
954
- verify_permission(
955
- resource_type=ResourceType.PIPELINE_RUN, action=Action.CREATE
956
- )
943
+ def _pre_creation_hook() -> None:
944
+ verify_permission(
945
+ resource_type=ResourceType.PIPELINE_RUN, action=Action.CREATE
946
+ )
947
+ check_entitlement(resource_type=ResourceType.PIPELINE_RUN)
957
948
 
958
949
  run, created = zen_store().get_or_create_run(
959
- pipeline_run=pipeline_run,
960
- pre_creation_hook=lambda: check_entitlement(
961
- resource_type=ResourceType.PIPELINE_RUN
962
- ),
950
+ pipeline_run=pipeline_run, pre_creation_hook=_pre_creation_hook
963
951
  )
964
952
  if created:
965
953
  report_usage(
966
954
  resource_type=ResourceType.PIPELINE_RUN, resource_id=run.id
967
955
  )
956
+ else:
957
+ verify_permission_for_model(run, action=Action.READ)
968
958
 
969
959
  return run, created
970
960
 
@@ -1009,24 +999,23 @@ def create_run_metadata(
1009
999
  "is not supported."
1010
1000
  )
1011
1001
 
1012
- if run_metadata.resource_type == MetadataResourceTypes.PIPELINE_RUN:
1013
- run = zen_store().get_run(run_metadata.resource_id)
1014
- verify_permission_for_model(run, action=Action.UPDATE)
1015
- elif run_metadata.resource_type == MetadataResourceTypes.STEP_RUN:
1016
- step = zen_store().get_run_step(run_metadata.resource_id)
1017
- verify_permission_for_model(step, action=Action.UPDATE)
1018
- elif run_metadata.resource_type == MetadataResourceTypes.ARTIFACT_VERSION:
1019
- artifact_version = zen_store().get_artifact_version(
1020
- run_metadata.resource_id
1021
- )
1022
- verify_permission_for_model(artifact_version, action=Action.UPDATE)
1023
- elif run_metadata.resource_type == MetadataResourceTypes.MODEL_VERSION:
1024
- model_version = zen_store().get_model_version(run_metadata.resource_id)
1025
- verify_permission_for_model(model_version, action=Action.UPDATE)
1026
- else:
1027
- raise RuntimeError(
1028
- f"Unknown resource type: {run_metadata.resource_type}"
1029
- )
1002
+ verify_models: List[Any] = []
1003
+ for resource in run_metadata.resources:
1004
+ if resource.type == MetadataResourceTypes.PIPELINE_RUN:
1005
+ verify_models.append(zen_store().get_run(resource.id))
1006
+ elif resource.type == MetadataResourceTypes.STEP_RUN:
1007
+ verify_models.append(zen_store().get_run_step(resource.id))
1008
+ elif resource.type == MetadataResourceTypes.ARTIFACT_VERSION:
1009
+ verify_models.append(zen_store().get_artifact_version(resource.id))
1010
+ elif resource.type == MetadataResourceTypes.MODEL_VERSION:
1011
+ verify_models.append(zen_store().get_model_version(resource.id))
1012
+ else:
1013
+ raise RuntimeError(f"Unknown resource type: {resource.type}")
1014
+
1015
+ batch_verify_permissions_for_models(
1016
+ models=verify_models,
1017
+ action=Action.UPDATE,
1018
+ )
1030
1019
 
1031
1020
  verify_permission(
1032
1021
  resource_type=ResourceType.RUN_METADATA, action=Action.CREATE
@@ -363,6 +363,7 @@ def deployment_request_from_template(
363
363
  "external_input_artifacts",
364
364
  "model_artifacts_or_metadata",
365
365
  "client_lazy_loaders",
366
+ "substitutions",
366
367
  "outputs",
367
368
  }
368
369
  ),
@@ -0,0 +1,36 @@
1
+ """Remove component spec path [b73bc71f1106].
2
+
3
+ Revision ID: b73bc71f1106
4
+ Revises: ec6307720f92
5
+ Create Date: 2024-11-29 09:36:33.089945
6
+
7
+ """
8
+
9
+ import sqlalchemy as sa
10
+ from alembic import op
11
+
12
+ # revision identifiers, used by Alembic.
13
+ revision = "b73bc71f1106"
14
+ down_revision = "ec6307720f92"
15
+ branch_labels = None
16
+ depends_on = None
17
+
18
+
19
+ def upgrade() -> None:
20
+ """Upgrade database schema and/or data, creating a new revision."""
21
+ # ### commands auto generated by Alembic - please adjust! ###
22
+ with op.batch_alter_table("stack_component", schema=None) as batch_op:
23
+ batch_op.drop_column("component_spec_path")
24
+
25
+ # ### end Alembic commands ###
26
+
27
+
28
+ def downgrade() -> None:
29
+ """Downgrade database schema and/or data back to the previous revision."""
30
+ # ### commands auto generated by Alembic - please adjust! ###
31
+ with op.batch_alter_table("stack_component", schema=None) as batch_op:
32
+ batch_op.add_column(
33
+ sa.Column("component_spec_path", sa.VARCHAR(), nullable=True)
34
+ )
35
+
36
+ # ### end Alembic commands ###
@@ -0,0 +1,135 @@
1
+ """Separate run metadata into resource link table with new UUIDs.
2
+
3
+ Revision ID: cc269488e5a9
4
+ Revises: b73bc71f1106
5
+ Create Date: 2024-11-12 09:46:46.587478
6
+ """
7
+
8
+ import uuid
9
+
10
+ import sqlalchemy as sa
11
+ import sqlmodel
12
+ from alembic import op
13
+
14
+ # revision identifiers, used by Alembic.
15
+ revision = "cc269488e5a9"
16
+ down_revision = "b73bc71f1106"
17
+ branch_labels = None
18
+ depends_on = None
19
+
20
+
21
+ def upgrade() -> None:
22
+ """Creates the 'run_metadata_resource' table and migrates data."""
23
+ op.create_table(
24
+ "run_metadata_resource",
25
+ sa.Column(
26
+ "id",
27
+ sqlmodel.sql.sqltypes.GUID(),
28
+ nullable=False,
29
+ primary_key=True,
30
+ ),
31
+ sa.Column("resource_id", sqlmodel.sql.sqltypes.GUID(), nullable=False),
32
+ sa.Column("resource_type", sa.String(length=255), nullable=False),
33
+ sa.Column(
34
+ "run_metadata_id",
35
+ sqlmodel.sql.sqltypes.GUID(),
36
+ sa.ForeignKey("run_metadata.id", ondelete="CASCADE"),
37
+ nullable=False,
38
+ ),
39
+ )
40
+
41
+ connection = op.get_bind()
42
+
43
+ run_metadata_data = connection.execute(
44
+ sa.text("""
45
+ SELECT id, resource_id, resource_type
46
+ FROM run_metadata
47
+ """)
48
+ ).fetchall()
49
+
50
+ # Prepare data with new UUIDs for bulk insert
51
+ resource_data = [
52
+ {
53
+ "id": str(uuid.uuid4()), # Generate a new UUID for each row
54
+ "resource_id": row.resource_id,
55
+ "resource_type": row.resource_type,
56
+ "run_metadata_id": row.id,
57
+ }
58
+ for row in run_metadata_data
59
+ ]
60
+
61
+ # Perform bulk insert into `run_metadata_resource`
62
+ if resource_data: # Only perform insert if there's data to migrate
63
+ op.bulk_insert(
64
+ sa.table(
65
+ "run_metadata_resource",
66
+ sa.Column("id", sqlmodel.sql.sqltypes.GUID(), nullable=False),
67
+ sa.Column(
68
+ "resource_id", sqlmodel.sql.sqltypes.GUID(), nullable=False
69
+ ),
70
+ sa.Column(
71
+ "resource_type", sa.String(length=255), nullable=False
72
+ ),
73
+ sa.Column(
74
+ "run_metadata_id",
75
+ sqlmodel.sql.sqltypes.GUID(),
76
+ nullable=False,
77
+ ), # Changed to BIGINT
78
+ ),
79
+ resource_data,
80
+ )
81
+
82
+ op.drop_column("run_metadata", "resource_id")
83
+ op.drop_column("run_metadata", "resource_type")
84
+
85
+ op.add_column(
86
+ "run_metadata",
87
+ sa.Column(
88
+ "publisher_step_id", sqlmodel.sql.sqltypes.GUID(), nullable=True
89
+ ),
90
+ )
91
+
92
+
93
+ def downgrade() -> None:
94
+ """Reverts the 'run_metadata_resource' table and migrates data back."""
95
+ # Recreate the `resource_id` and `resource_type` columns in `run_metadata`
96
+ op.add_column(
97
+ "run_metadata",
98
+ sa.Column("resource_id", sqlmodel.sql.sqltypes.GUID(), nullable=True),
99
+ )
100
+ op.add_column(
101
+ "run_metadata",
102
+ sa.Column("resource_type", sa.String(length=255), nullable=True),
103
+ )
104
+
105
+ # Migrate data back from `run_metadata_resource` to `run_metadata`
106
+ connection = op.get_bind()
107
+
108
+ # Fetch data from `run_metadata_resource`
109
+ run_metadata_resource_data = connection.execute(
110
+ sa.text("""
111
+ SELECT resource_id, resource_type, run_metadata_id
112
+ FROM run_metadata_resource
113
+ """)
114
+ ).fetchall()
115
+
116
+ # Update `run_metadata` with the data from `run_metadata_resource`
117
+ for row in run_metadata_resource_data:
118
+ connection.execute(
119
+ sa.text("""
120
+ UPDATE run_metadata
121
+ SET resource_id = :resource_id, resource_type = :resource_type
122
+ WHERE id = :run_metadata_id
123
+ """),
124
+ {
125
+ "resource_id": row.resource_id,
126
+ "resource_type": row.resource_type,
127
+ "run_metadata_id": row.run_metadata_id,
128
+ },
129
+ )
130
+
131
+ # Drop the `run_metadata_resource` table
132
+ op.drop_table("run_metadata_resource")
133
+
134
+ # Drop the cached column
135
+ op.drop_column("run_metadata", "publisher_step_id")
@@ -59,12 +59,13 @@ def _migrate_artifact_type() -> None:
59
59
  {"id_": artifact_version_id, "type": "ServiceArtifact"}
60
60
  )
61
61
 
62
- connection.execute(
63
- sa.update(artifact_version_table).where(
64
- artifact_version_table.c.id == sa.bindparam("id_")
65
- ),
66
- updates,
67
- )
62
+ if updates:
63
+ connection.execute(
64
+ sa.update(artifact_version_table).where(
65
+ artifact_version_table.c.id == sa.bindparam("id_")
66
+ ),
67
+ updates,
68
+ )
68
69
 
69
70
 
70
71
  def upgrade() -> None:
@@ -39,7 +39,10 @@ from zenml.zen_stores.schemas.pipeline_deployment_schemas import (
39
39
  from zenml.zen_stores.schemas.pipeline_run_schemas import PipelineRunSchema
40
40
  from zenml.zen_stores.schemas.pipeline_schemas import PipelineSchema
41
41
  from zenml.zen_stores.schemas.workspace_schemas import WorkspaceSchema
42
- from zenml.zen_stores.schemas.run_metadata_schemas import RunMetadataSchema
42
+ from zenml.zen_stores.schemas.run_metadata_schemas import (
43
+ RunMetadataResourceSchema,
44
+ RunMetadataSchema,
45
+ )
43
46
  from zenml.zen_stores.schemas.schedule_schema import ScheduleSchema
44
47
  from zenml.zen_stores.schemas.secret_schemas import SecretSchema
45
48
  from zenml.zen_stores.schemas.service_schemas import ServiceSchema
@@ -90,6 +93,7 @@ __all__ = [
90
93
  "PipelineDeploymentSchema",
91
94
  "PipelineRunSchema",
92
95
  "PipelineSchema",
96
+ "RunMetadataResourceSchema",
93
97
  "RunMetadataSchema",
94
98
  "ScheduleSchema",
95
99
  "SecretSchema",
@@ -13,7 +13,6 @@
13
13
  # permissions and limitations under the License.
14
14
  """SQLModel implementation of artifact table."""
15
15
 
16
- import json
17
16
  from datetime import datetime
18
17
  from typing import TYPE_CHECKING, Any, List, Optional
19
18
  from uuid import UUID
@@ -50,6 +49,7 @@ from zenml.zen_stores.schemas.step_run_schemas import (
50
49
  StepRunOutputArtifactSchema,
51
50
  )
52
51
  from zenml.zen_stores.schemas.user_schemas import UserSchema
52
+ from zenml.zen_stores.schemas.utils import RunMetadataInterface
53
53
  from zenml.zen_stores.schemas.workspace_schemas import WorkspaceSchema
54
54
 
55
55
  if TYPE_CHECKING:
@@ -59,7 +59,9 @@ if TYPE_CHECKING:
59
59
  from zenml.zen_stores.schemas.model_schemas import (
60
60
  ModelVersionArtifactSchema,
61
61
  )
62
- from zenml.zen_stores.schemas.run_metadata_schemas import RunMetadataSchema
62
+ from zenml.zen_stores.schemas.run_metadata_schemas import (
63
+ RunMetadataResourceSchema,
64
+ )
63
65
  from zenml.zen_stores.schemas.tag_schemas import TagResourceSchema
64
66
 
65
67
 
@@ -171,7 +173,7 @@ class ArtifactSchema(NamedSchema, table=True):
171
173
  return self
172
174
 
173
175
 
174
- class ArtifactVersionSchema(BaseSchema, table=True):
176
+ class ArtifactVersionSchema(BaseSchema, RunMetadataInterface, table=True):
175
177
  """SQL Model for artifact versions."""
176
178
 
177
179
  __tablename__ = "artifact_version"
@@ -242,12 +244,12 @@ class ArtifactVersionSchema(BaseSchema, table=True):
242
244
  workspace: "WorkspaceSchema" = Relationship(
243
245
  back_populates="artifact_versions"
244
246
  )
245
- run_metadata: List["RunMetadataSchema"] = Relationship(
246
- back_populates="artifact_version",
247
+ run_metadata_resources: List["RunMetadataResourceSchema"] = Relationship(
248
+ back_populates="artifact_versions",
247
249
  sa_relationship_kwargs=dict(
248
- primaryjoin=f"and_(RunMetadataSchema.resource_type=='{MetadataResourceTypes.ARTIFACT_VERSION.value}', foreign(RunMetadataSchema.resource_id)==ArtifactVersionSchema.id)",
250
+ primaryjoin=f"and_(RunMetadataResourceSchema.resource_type=='{MetadataResourceTypes.ARTIFACT_VERSION.value}', foreign(RunMetadataResourceSchema.resource_id)==ArtifactVersionSchema.id)",
249
251
  cascade="delete",
250
- overlaps="run_metadata",
252
+ overlaps="run_metadata_resources",
251
253
  ),
252
254
  )
253
255
  output_of_step_runs: List["StepRunOutputArtifactSchema"] = Relationship(
@@ -352,8 +354,9 @@ class ArtifactVersionSchema(BaseSchema, table=True):
352
354
  producer_step_run_id = step_run.original_step_run_id
353
355
 
354
356
  # Create the body of the model
357
+ artifact = self.artifact.to_model()
355
358
  body = ArtifactVersionResponseBody(
356
- artifact=self.artifact.to_model(),
359
+ artifact=artifact,
357
360
  version=self.version or str(self.version_number),
358
361
  user=self.user.to_model() if self.user else None,
359
362
  uri=self.uri,
@@ -375,9 +378,7 @@ class ArtifactVersionSchema(BaseSchema, table=True):
375
378
  workspace=self.workspace.to_model(),
376
379
  producer_step_run_id=producer_step_run_id,
377
380
  visualizations=[v.to_model() for v in self.visualizations],
378
- run_metadata={
379
- m.key: json.loads(m.value) for m in self.run_metadata
380
- },
381
+ run_metadata=self.fetch_metadata(),
381
382
  )
382
383
 
383
384
  resources = None
@@ -56,7 +56,6 @@ class StackComponentSchema(NamedSchema, table=True):
56
56
  flavor: str
57
57
  configuration: bytes
58
58
  labels: Optional[bytes]
59
- component_spec_path: Optional[str]
60
59
 
61
60
  workspace_id: UUID = build_foreign_key_field(
62
61
  source=__tablename__,
@@ -135,7 +134,6 @@ class StackComponentSchema(NamedSchema, table=True):
135
134
  name=request.name,
136
135
  workspace_id=request.workspace,
137
136
  user_id=request.user,
138
- component_spec_path=request.component_spec_path,
139
137
  type=request.type,
140
138
  flavor=request.flavor,
141
139
  configuration=base64.b64encode(
@@ -218,7 +216,6 @@ class StackComponentSchema(NamedSchema, table=True):
218
216
  labels=json.loads(base64.b64decode(self.labels).decode())
219
217
  if self.labels
220
218
  else None,
221
- component_spec_path=self.component_spec_path,
222
219
  connector_resource_id=self.connector_resource_id,
223
220
  connector=self.connector.to_model()
224
221
  if self.connector