zenml-nightly 0.68.1.dev20241111__py3-none-any.whl → 0.70.0.dev20241114__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 (202) hide show
  1. README.md +1 -1
  2. RELEASE_NOTES.md +77 -0
  3. zenml/VERSION +1 -1
  4. zenml/__init__.py +2 -0
  5. zenml/artifacts/utils.py +5 -1
  6. zenml/cli/base.py +1 -1
  7. zenml/client.py +9 -2
  8. zenml/config/server_config.py +17 -1
  9. zenml/constants.py +1 -7
  10. zenml/enums.py +8 -0
  11. zenml/exceptions.py +4 -0
  12. zenml/integrations/aws/orchestrators/sagemaker_orchestrator.py +1 -14
  13. zenml/integrations/lightning/orchestrators/lightning_orchestrator.py +29 -9
  14. zenml/model/model.py +16 -62
  15. zenml/model/utils.py +5 -0
  16. zenml/models/v2/base/filter.py +121 -8
  17. zenml/models/v2/core/artifact_version.py +23 -0
  18. zenml/models/v2/core/model_version.py +23 -0
  19. zenml/models/v2/core/pipeline_run.py +22 -1
  20. zenml/models/v2/core/step_run.py +22 -0
  21. zenml/orchestrators/base_orchestrator.py +12 -1
  22. zenml/orchestrators/step_launcher.py +2 -1
  23. zenml/orchestrators/utils.py +45 -26
  24. zenml/stack_deployments/aws_stack_deployment.py +23 -6
  25. zenml/stack_deployments/azure_stack_deployment.py +28 -5
  26. zenml/stack_deployments/gcp_stack_deployment.py +25 -8
  27. zenml/stack_deployments/stack_deployment.py +3 -5
  28. zenml/steps/utils.py +5 -0
  29. zenml/utils/metadata_utils.py +335 -0
  30. zenml/zen_server/auth.py +221 -3
  31. zenml/zen_server/cache.py +208 -0
  32. zenml/zen_server/dashboard/assets/{404-DT4QRUqN.js → 404-NVXKFp-x.js} +1 -1
  33. zenml/zen_server/dashboard/assets/{@radix-DP6vWzyx.js → @radix-DeK6qiuw.js} +1 -1
  34. zenml/zen_server/dashboard/assets/{@react-router-BMhZulnd.js → @react-router-B3Z5rLr2.js} +1 -1
  35. zenml/zen_server/dashboard/assets/{@reactflow-8U9qNlMR.js → @reactflow-CK0KJUen.js} +2 -2
  36. zenml/zen_server/dashboard/assets/{@tanstack-BUCbhJyH.js → @tanstack-DT5WLu9C.js} +1 -1
  37. zenml/zen_server/dashboard/assets/AlertDialogDropdownItem-DezXKmDf.js +1 -0
  38. zenml/zen_server/dashboard/assets/{CodeSnippet-CqybNv0k.js → CodeSnippet-JzR8CEtw.js} +2 -2
  39. zenml/zen_server/dashboard/assets/{CollapsibleCard-0r_8G2Lj.js → CollapsibleCard-DQW_ktMO.js} +1 -1
  40. zenml/zen_server/dashboard/assets/{Commands-BDjgBQKi.js → Commands-DL2kwkRd.js} +1 -1
  41. zenml/zen_server/dashboard/assets/ComponentBadge-D_g62Wv8.js +1 -0
  42. zenml/zen_server/dashboard/assets/{CopyButton-C745BrKi.js → CopyButton-LNcWaa14.js} +1 -1
  43. zenml/zen_server/dashboard/assets/{CsvVizualization-PpAq0CeZ.js → CsvVizualization-DknpE5ej.js} +5 -5
  44. zenml/zen_server/dashboard/assets/{DialogItem-DcVCZEew.js → DialogItem-Bxf8FuAT.js} +1 -1
  45. zenml/zen_server/dashboard/assets/{DisplayDate-BeXgUG_C.js → DisplayDate-CDMUcQHS.js} +1 -1
  46. zenml/zen_server/dashboard/assets/{EmptyState-DeK7H4pr.js → EmptyState-BzdlCwp3.js} +1 -1
  47. zenml/zen_server/dashboard/assets/{Error-BMlzibXj.js → Error-DYflYyps.js} +1 -1
  48. zenml/zen_server/dashboard/assets/ExecutionStatus-C7zyIQKZ.js +1 -0
  49. zenml/zen_server/dashboard/assets/{Helpbox-BLf40fLV.js → Helpbox-oYSGpLqd.js} +1 -1
  50. zenml/zen_server/dashboard/assets/{Infobox-BwisKifi.js → Infobox-Cx4xGoXR.js} +1 -1
  51. zenml/zen_server/dashboard/assets/{InlineAvatar-jEgodSgX.js → InlineAvatar-DiGOWNKF.js} +1 -1
  52. zenml/zen_server/dashboard/assets/{Lock-3lLt1ih0.js → Lock-CYYy18Mm.js} +1 -1
  53. zenml/zen_server/dashboard/assets/{MarkdownVisualization-8O9kTr-2.js → MarkdownVisualization-ylXaAxev.js} +1 -1
  54. zenml/zen_server/dashboard/assets/NestedCollapsible-DYbgyKxK.js +1 -0
  55. zenml/zen_server/dashboard/assets/{NumberBox-T9eELfLZ.js → NumberBox-Dtp3J6g5.js} +1 -1
  56. zenml/zen_server/dashboard/assets/Partials-03iZf8-N.js +1 -0
  57. zenml/zen_server/dashboard/assets/{PasswordChecker-CW0kqY0W.js → PasswordChecker-B0nadgh6.js} +1 -1
  58. zenml/zen_server/dashboard/assets/ProBadge-D_EB8HNo.js +1 -0
  59. zenml/zen_server/dashboard/assets/ProCta-DqNS4v3x.js +1 -0
  60. zenml/zen_server/dashboard/assets/ProviderIcon-Bki2aw8w.js +1 -0
  61. zenml/zen_server/dashboard/assets/{ProviderRadio-BROY1700.js → ProviderRadio-8f43sPD4.js} +1 -1
  62. zenml/zen_server/dashboard/assets/RunSelector-DkPiIiNr.js +1 -0
  63. zenml/zen_server/dashboard/assets/RunsBody-07YEO7qI.js +1 -0
  64. zenml/zen_server/dashboard/assets/SearchField-lp1KgU4e.js +1 -0
  65. zenml/zen_server/dashboard/assets/{SecretTooltip-C_qByGWB.js → SecretTooltip-CgnbyeOx.js} +1 -1
  66. zenml/zen_server/dashboard/assets/{SetPassword-7pRB00El.js → SetPassword-CpP418A2.js} +1 -1
  67. zenml/zen_server/dashboard/assets/StackList-WvuKQusZ.js +1 -0
  68. zenml/zen_server/dashboard/assets/Tabs-BktHkCJJ.js +1 -0
  69. zenml/zen_server/dashboard/assets/Tick-BlMoIlJT.js +1 -0
  70. zenml/zen_server/dashboard/assets/{UpdatePasswordSchemas-DckMEkFf.js → UpdatePasswordSchemas-Sc0A0pP-.js} +1 -1
  71. zenml/zen_server/dashboard/assets/{UsageReason-DVceN14P.js → UsageReason-YYduL4fj.js} +1 -1
  72. zenml/zen_server/dashboard/assets/{WizardFooter-CW0Cvd70.js → WizardFooter-dgmizSJC.js} +1 -1
  73. zenml/zen_server/dashboard/assets/all-pipeline-runs-query-D-c2G6lV.js +1 -0
  74. zenml/zen_server/dashboard/assets/check-DloQpStc.js +1 -0
  75. zenml/zen_server/dashboard/assets/{check-circle-Dwxliy1Z.js → check-circle-jNbX5-sR.js} +1 -1
  76. zenml/zen_server/dashboard/assets/{chevron-down-8wLBS5pQ.js → chevron-down-6JyMkfjR.js} +1 -1
  77. zenml/zen_server/dashboard/assets/{chevron-right-double-DoD8iXWM.js → chevron-right-double-D7ojK9Co.js} +1 -1
  78. zenml/zen_server/dashboard/assets/{code-browser-CZUQs3Wa.js → code-browser-CUFUIHfp.js} +1 -1
  79. zenml/zen_server/dashboard/assets/{copy-CaSMXwiU.js → copy-C8XQA2Ug.js} +1 -1
  80. zenml/zen_server/dashboard/assets/create-stack-DM_JPgef.js +1 -0
  81. zenml/zen_server/dashboard/assets/delete-run-CJdh1P_h.js +1 -0
  82. zenml/zen_server/dashboard/assets/{docker-BFNgg-z3.js → docker-BdA9vrnW.js} +1 -1
  83. zenml/zen_server/dashboard/assets/{dots-horizontal-DK5Duzx4.js → dots-horizontal-otGBOSDJ.js} +1 -1
  84. zenml/zen_server/dashboard/assets/{form-schemas-1AyOCx90.js → form-schemas-K6FYKjwa.js} +1 -1
  85. zenml/zen_server/dashboard/assets/{gcp-7M2Yf3ZK.js → gcp-CFtm4BA7.js} +1 -1
  86. zenml/zen_server/dashboard/assets/{help-Dam461dC.js → help-Cc9bBIJH.js} +1 -1
  87. zenml/zen_server/dashboard/assets/index-B1mVPYxf.js +1 -0
  88. zenml/zen_server/dashboard/assets/index-BAkC7FXi.js +1 -0
  89. zenml/zen_server/dashboard/assets/{index-QQb7wQEC.js → index-CCOPpudF.js} +8 -8
  90. zenml/zen_server/dashboard/assets/index-CEV4Cvaf.js +1 -0
  91. zenml/zen_server/dashboard/assets/index-DlGvJQPn.css +1 -0
  92. zenml/zen_server/dashboard/assets/{index-BVJ8n2-j.js → index-Uu49AX48.js} +1 -1
  93. zenml/zen_server/dashboard/assets/{index.esm-cuVep_NJ.js → index.esm-Dy6Z9Ung.js} +1 -1
  94. zenml/zen_server/dashboard/assets/{kubernetes--g7r02Zu.js → kubernetes-B2wmAJ1d.js} +1 -1
  95. zenml/zen_server/dashboard/assets/{layout-DCSYN7-C.js → layout-BtHBmE4w.js} +1 -1
  96. zenml/zen_server/dashboard/assets/{link-external-CBEk6kEG.js → link-external-b9AXw_sW.js} +1 -1
  97. zenml/zen_server/dashboard/assets/{login-mutation-DTcAFP1l.js → login-mutation-hf-lK87O.js} +1 -1
  98. zenml/zen_server/dashboard/assets/{logs-D5bdJGur.js → logs-WMSM52RF.js} +1 -1
  99. zenml/zen_server/dashboard/assets/{not-found-Cc-JkRH2.js → not-found-BGirLjU-.js} +1 -1
  100. zenml/zen_server/dashboard/assets/{package-Cs35Szwh.js → package-C6uypY4h.js} +1 -1
  101. zenml/zen_server/dashboard/assets/page-0JE_-Ec1.js +1 -0
  102. zenml/zen_server/dashboard/assets/{page-DH_Z7iW1.js → page-6m6yHHlE.js} +1 -1
  103. zenml/zen_server/dashboard/assets/page-BDigxVpo.js +1 -0
  104. zenml/zen_server/dashboard/assets/page-BR68V0V1.js +1 -0
  105. zenml/zen_server/dashboard/assets/page-BRLpxOt0.js +1 -0
  106. zenml/zen_server/dashboard/assets/{page-BQQKaabe.js → page-BU7huvKw.js} +3 -3
  107. zenml/zen_server/dashboard/assets/page-BvqLv2Ky.js +1 -0
  108. zenml/zen_server/dashboard/assets/page-C00YAkaB.js +1 -0
  109. zenml/zen_server/dashboard/assets/{page-N4qoPHKb.js → page-CD-DcWoy.js} +1 -1
  110. zenml/zen_server/dashboard/assets/page-COXXJj1k.js +1 -0
  111. zenml/zen_server/dashboard/assets/page-CbpvrsDL.js +1 -0
  112. zenml/zen_server/dashboard/assets/page-CdMWnQak.js +1 -0
  113. zenml/zen_server/dashboard/assets/{page-ClUVkl-O.js → page-CjGdWY13.js} +1 -1
  114. zenml/zen_server/dashboard/assets/page-CwxrFarU.js +1 -0
  115. zenml/zen_server/dashboard/assets/{page-DLixvR-7.js → page-D01JhjQB.js} +1 -1
  116. zenml/zen_server/dashboard/assets/page-D6uU2ax4.js +1 -0
  117. zenml/zen_server/dashboard/assets/page-D7S3aCbF.js +1 -0
  118. zenml/zen_server/dashboard/assets/{page-9yplj5JT.js → page-DLC-bNBP.js} +1 -1
  119. zenml/zen_server/dashboard/assets/page-DXSTpqRD.js +1 -0
  120. zenml/zen_server/dashboard/assets/{page-DzpVUZ8f.js → page-DakHVWXF.js} +1 -1
  121. zenml/zen_server/dashboard/assets/{page-DIOXwhiD.js → page-Df-Fw0aq.js} +1 -1
  122. zenml/zen_server/dashboard/assets/{page-B-y2XKIc.js → page-DfbXf_8s.js} +1 -1
  123. zenml/zen_server/dashboard/assets/page-DjRJCGb3.js +1 -0
  124. zenml/zen_server/dashboard/assets/{page-C0N5q3l7.js → page-Djikxq_S.js} +1 -1
  125. zenml/zen_server/dashboard/assets/page-Dnovpa0i.js +3 -0
  126. zenml/zen_server/dashboard/assets/page-Dot3LPmL.js +1 -0
  127. zenml/zen_server/dashboard/assets/page-Vcxara9U.js +1 -0
  128. zenml/zen_server/dashboard/assets/page-Xynx4btY.js +14 -0
  129. zenml/zen_server/dashboard/assets/page-YpKAqVSa.js +1 -0
  130. zenml/zen_server/dashboard/assets/page-yYC9OI-E.js +1 -0
  131. zenml/zen_server/dashboard/assets/{persist-DNb5cdrU.js → persist-Coz7ZWvz.js} +1 -1
  132. zenml/zen_server/dashboard/assets/{persist-CP0JmYZ4.js → persist-GjC8PZoC.js} +1 -1
  133. zenml/zen_server/dashboard/assets/{plus-C9IxgN2M.js → plus-tf1V2hTJ.js} +1 -1
  134. zenml/zen_server/dashboard/assets/{refresh-BVu22P_C.js → refresh-BjOeWlEq.js} +1 -1
  135. zenml/zen_server/dashboard/assets/{rocket-CONEmRmB.js → rocket-DjT2cDvG.js} +1 -1
  136. zenml/zen_server/dashboard/assets/sharedSchema-CQb14VSr.js +14 -0
  137. zenml/zen_server/dashboard/assets/stack-detail-query-OPEW-cDJ.js +1 -0
  138. zenml/zen_server/dashboard/assets/{tick-circle-CM1ZScbQ.js → tick-circle-BEX_Tp4v.js} +1 -1
  139. zenml/zen_server/dashboard/assets/{trash-DkJHMOg7.js → trash-arLUMWMS.js} +1 -1
  140. zenml/zen_server/dashboard/assets/{update-server-settings-mutation-DsU8cNVl.js → update-server-settings-mutation-LwuQfHYn.js} +1 -1
  141. zenml/zen_server/dashboard/assets/upgrade-form-CwRHBuXB.webp +0 -0
  142. zenml/zen_server/dashboard/assets/url-CkvKAnwF.js +1 -0
  143. zenml/zen_server/dashboard/assets/{zod-D89GC_vc.js → zod-BwEbpOxH.js} +1 -1
  144. zenml/zen_server/dashboard/index.html +7 -7
  145. zenml/zen_server/deploy/helm/Chart.yaml +1 -1
  146. zenml/zen_server/deploy/helm/README.md +2 -2
  147. zenml/zen_server/exceptions.py +2 -0
  148. zenml/zen_server/jwt.py +30 -13
  149. zenml/zen_server/routers/auth_endpoints.py +134 -102
  150. zenml/zen_server/routers/logs_endpoints.py +66 -0
  151. zenml/zen_server/template_execution/utils.py +14 -16
  152. zenml/zen_server/utils.py +27 -0
  153. zenml/zen_server/zen_server_api.py +6 -1
  154. zenml/zen_stores/migrations/versions/0.70.0_release.py +23 -0
  155. zenml/zen_stores/migrations/versions/904464ea4041_add_pipeline_model_run_unique_constraints.py +192 -0
  156. zenml/zen_stores/rest_zen_store.py +13 -10
  157. zenml/zen_stores/schemas/model_schemas.py +25 -1
  158. zenml/zen_stores/schemas/pipeline_run_schemas.py +5 -0
  159. zenml/zen_stores/schemas/pipeline_schemas.py +8 -2
  160. zenml/zen_stores/sql_zen_store.py +215 -121
  161. {zenml_nightly-0.68.1.dev20241111.dist-info → zenml_nightly-0.70.0.dev20241114.dist-info}/METADATA +2 -2
  162. {zenml_nightly-0.68.1.dev20241111.dist-info → zenml_nightly-0.70.0.dev20241114.dist-info}/RECORD +165 -151
  163. zenml/zen_server/dashboard/assets/AlertDialogDropdownItem-C6N2rGrB.js +0 -1
  164. zenml/zen_server/dashboard/assets/ComponentBadge-DUiEYJHu.js +0 -1
  165. zenml/zen_server/dashboard/assets/ComponentFallbackDialog-BFoH5K4V.js +0 -1
  166. zenml/zen_server/dashboard/assets/ComponentIcon-CAIoUis2.js +0 -1
  167. zenml/zen_server/dashboard/assets/Partials-YPBB3V4q.js +0 -1
  168. zenml/zen_server/dashboard/assets/ProviderIcon-Bb3Xha5A.js +0 -1
  169. zenml/zen_server/dashboard/assets/RunSelector-DCiL3M1c.js +0 -1
  170. zenml/zen_server/dashboard/assets/SearchField-DfUiGFVd.js +0 -1
  171. zenml/zen_server/dashboard/assets/Tick-CykQFPj2.js +0 -1
  172. zenml/zen_server/dashboard/assets/cloud-only-B-s_HMDm.js +0 -1
  173. zenml/zen_server/dashboard/assets/codespaces-BitYDX9d.gif +0 -0
  174. zenml/zen_server/dashboard/assets/create-stack-CEmaPZ4c.js +0 -1
  175. zenml/zen_server/dashboard/assets/delete-run-D-LKbGyz.js +0 -1
  176. zenml/zen_server/dashboard/assets/index-Bpmj40BI.js +0 -1
  177. zenml/zen_server/dashboard/assets/index-CbU4Ln_E.css +0 -1
  178. zenml/zen_server/dashboard/assets/index-DKPhqP2B.js +0 -1
  179. zenml/zen_server/dashboard/assets/page-BBpOxVcY.js +0 -1
  180. zenml/zen_server/dashboard/assets/page-BRInM1Lg.js +0 -1
  181. zenml/zen_server/dashboard/assets/page-BjjlMk7s.js +0 -1
  182. zenml/zen_server/dashboard/assets/page-Bvd7YH2A.js +0 -1
  183. zenml/zen_server/dashboard/assets/page-CT3Nep8W.js +0 -1
  184. zenml/zen_server/dashboard/assets/page-C_f47pBf.js +0 -1
  185. zenml/zen_server/dashboard/assets/page-Cmv8C_yM.js +0 -3
  186. zenml/zen_server/dashboard/assets/page-CyN2bdWG.js +0 -1
  187. zenml/zen_server/dashboard/assets/page-CzzXH4fs.js +0 -1
  188. zenml/zen_server/dashboard/assets/page-DTlGjgnG.js +0 -1
  189. zenml/zen_server/dashboard/assets/page-Dbpl86h0.js +0 -1
  190. zenml/zen_server/dashboard/assets/page-Ddgy6kDS.js +0 -1
  191. zenml/zen_server/dashboard/assets/page-DtCAfBLy.js +0 -9
  192. zenml/zen_server/dashboard/assets/page-Dx16z7nA.js +0 -1
  193. zenml/zen_server/dashboard/assets/page-McUyYbo1.js +0 -1
  194. zenml/zen_server/dashboard/assets/page-T1P3RyAR.js +0 -1
  195. zenml/zen_server/dashboard/assets/page-bKaULTGG.js +0 -1
  196. zenml/zen_server/dashboard/assets/page-sbXUJy9t.js +0 -1
  197. zenml/zen_server/dashboard/assets/sharedSchema-TMLu-nYQ.js +0 -14
  198. zenml/zen_server/dashboard/assets/stack-detail-query-xmYxSsUY.js +0 -1
  199. zenml/zen_server/dashboard/assets/url-D5le3J4q.js +0 -1
  200. {zenml_nightly-0.68.1.dev20241111.dist-info → zenml_nightly-0.70.0.dev20241114.dist-info}/LICENSE +0 -0
  201. {zenml_nightly-0.68.1.dev20241111.dist-info → zenml_nightly-0.70.0.dev20241114.dist-info}/WHEEL +0 -0
  202. {zenml_nightly-0.68.1.dev20241111.dist-info → zenml_nightly-0.70.0.dev20241114.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,192 @@
1
+ """Add pipeline, model and run unique constraints [904464ea4041].
2
+
3
+ Revision ID: 904464ea4041
4
+ Revises: b557b2871693
5
+ Create Date: 2024-11-04 10:27:05.450092
6
+
7
+ """
8
+
9
+ from collections import defaultdict
10
+ from typing import Any, Dict, Set
11
+
12
+ import sqlalchemy as sa
13
+ from alembic import op
14
+
15
+ from zenml.logger import get_logger
16
+
17
+ logger = get_logger(__name__)
18
+
19
+ # revision identifiers, used by Alembic.
20
+ revision = "904464ea4041"
21
+ down_revision = "b557b2871693"
22
+ branch_labels = None
23
+ depends_on = None
24
+
25
+
26
+ def resolve_duplicate_entities() -> None:
27
+ """Resolve duplicate entities."""
28
+ connection = op.get_bind()
29
+ meta = sa.MetaData()
30
+ meta.reflect(
31
+ bind=connection,
32
+ only=("pipeline_run", "pipeline", "model", "model_version"),
33
+ )
34
+
35
+ # Remove duplicate names for runs, pipelines and models
36
+ for table_name in ["pipeline_run", "pipeline", "model"]:
37
+ table = sa.Table(table_name, meta)
38
+ result = connection.execute(
39
+ sa.select(table.c.id, table.c.name, table.c.workspace_id)
40
+ ).all()
41
+ existing: Dict[str, Set[str]] = defaultdict(set)
42
+
43
+ for id_, name, workspace_id in result:
44
+ names_in_workspace = existing[workspace_id]
45
+
46
+ if name in names_in_workspace:
47
+ new_name = f"{name}_{id_[:6]}"
48
+ logger.warning(
49
+ "Migrating %s name from %s to %s to resolve duplicate name.",
50
+ table_name,
51
+ name,
52
+ new_name,
53
+ )
54
+ connection.execute(
55
+ sa.update(table)
56
+ .where(table.c.id == id_)
57
+ .values(name=new_name)
58
+ )
59
+ names_in_workspace.add(new_name)
60
+ else:
61
+ names_in_workspace.add(name)
62
+
63
+ # Remove duplicate names and version numbers for model versions
64
+ model_version_table = sa.Table("model_version", meta)
65
+ result = connection.execute(
66
+ sa.select(
67
+ model_version_table.c.id,
68
+ model_version_table.c.name,
69
+ model_version_table.c.number,
70
+ model_version_table.c.model_id,
71
+ )
72
+ ).all()
73
+
74
+ existing_names: Dict[str, Set[str]] = defaultdict(set)
75
+ existing_numbers: Dict[str, Set[int]] = defaultdict(set)
76
+
77
+ needs_update = []
78
+
79
+ for id_, name, number, model_id in result:
80
+ names_for_model = existing_names[model_id]
81
+ numbers_for_model = existing_numbers[model_id]
82
+
83
+ needs_new_name = name in names_for_model
84
+ needs_new_number = number in numbers_for_model
85
+
86
+ if needs_new_name or needs_new_number:
87
+ needs_update.append(
88
+ (id_, name, number, model_id, needs_new_name, needs_new_number)
89
+ )
90
+
91
+ names_for_model.add(name)
92
+ numbers_for_model.add(number)
93
+
94
+ for (
95
+ id_,
96
+ name,
97
+ number,
98
+ model_id,
99
+ needs_new_name,
100
+ needs_new_number,
101
+ ) in needs_update:
102
+ values: Dict[str, Any] = {}
103
+
104
+ is_numeric_version = str(number) == name
105
+ next_numeric_version = max(existing_numbers[model_id]) + 1
106
+
107
+ if is_numeric_version:
108
+ # No matter if the name or number clashes, we need to update both
109
+ values["number"] = next_numeric_version
110
+ values["name"] = str(next_numeric_version)
111
+ existing_numbers[model_id].add(next_numeric_version)
112
+ logger.warning(
113
+ "Migrating model version %s to %s to resolve duplicate name.",
114
+ name,
115
+ values["name"],
116
+ )
117
+ else:
118
+ if needs_new_name:
119
+ values["name"] = f"{name}_{id_[:6]}"
120
+ logger.warning(
121
+ "Migrating model version %s to %s to resolve duplicate name.",
122
+ name,
123
+ values["name"],
124
+ )
125
+
126
+ if needs_new_number:
127
+ values["number"] = next_numeric_version
128
+ existing_numbers[model_id].add(next_numeric_version)
129
+
130
+ connection.execute(
131
+ sa.update(model_version_table)
132
+ .where(model_version_table.c.id == id_)
133
+ .values(**values)
134
+ )
135
+
136
+
137
+ def upgrade() -> None:
138
+ """Upgrade database schema and/or data, creating a new revision."""
139
+ # ### commands auto generated by Alembic - please adjust! ###
140
+
141
+ resolve_duplicate_entities()
142
+
143
+ with op.batch_alter_table("pipeline", schema=None) as batch_op:
144
+ batch_op.create_unique_constraint(
145
+ "unique_pipeline_name_in_workspace", ["name", "workspace_id"]
146
+ )
147
+
148
+ with op.batch_alter_table("pipeline_run", schema=None) as batch_op:
149
+ batch_op.create_unique_constraint(
150
+ "unique_run_name_in_workspace", ["name", "workspace_id"]
151
+ )
152
+
153
+ with op.batch_alter_table("model", schema=None) as batch_op:
154
+ batch_op.create_unique_constraint(
155
+ "unique_model_name_in_workspace", ["name", "workspace_id"]
156
+ )
157
+
158
+ with op.batch_alter_table("model_version", schema=None) as batch_op:
159
+ batch_op.create_unique_constraint(
160
+ "unique_version_for_model_id", ["name", "model_id"]
161
+ )
162
+ batch_op.create_unique_constraint(
163
+ "unique_version_number_for_model_id", ["number", "model_id"]
164
+ )
165
+ # ### end Alembic commands ###
166
+
167
+
168
+ def downgrade() -> None:
169
+ """Downgrade database schema and/or data back to the previous revision."""
170
+ # ### commands auto generated by Alembic - please adjust! ###
171
+ with op.batch_alter_table("model_version", schema=None) as batch_op:
172
+ batch_op.drop_constraint(
173
+ "unique_version_number_for_model_id", type_="unique"
174
+ )
175
+ batch_op.drop_constraint("unique_version_for_model_id", type_="unique")
176
+
177
+ with op.batch_alter_table("model", schema=None) as batch_op:
178
+ batch_op.drop_constraint(
179
+ "unique_model_name_in_workspace", type_="unique"
180
+ )
181
+
182
+ with op.batch_alter_table("pipeline_run", schema=None) as batch_op:
183
+ batch_op.drop_constraint(
184
+ "unique_run_name_in_workspace", type_="unique"
185
+ )
186
+
187
+ with op.batch_alter_table("pipeline", schema=None) as batch_op:
188
+ batch_op.drop_constraint(
189
+ "unique_pipeline_name_in_workspace", type_="unique"
190
+ )
191
+
192
+ # ### end Alembic commands ###
@@ -110,6 +110,7 @@ from zenml.constants import (
110
110
  WORKSPACES,
111
111
  )
112
112
  from zenml.enums import (
113
+ APITokenType,
113
114
  OAuthGrantTypes,
114
115
  StackDeploymentProvider,
115
116
  StoreType,
@@ -3872,17 +3873,16 @@ class RestZenStore(BaseZenStore):
3872
3873
 
3873
3874
  def get_api_token(
3874
3875
  self,
3875
- pipeline_id: Optional[UUID] = None,
3876
3876
  schedule_id: Optional[UUID] = None,
3877
- expires_minutes: Optional[int] = None,
3877
+ pipeline_run_id: Optional[UUID] = None,
3878
+ step_run_id: Optional[UUID] = None,
3878
3879
  ) -> str:
3879
3880
  """Get an API token for a workload.
3880
3881
 
3881
3882
  Args:
3882
- pipeline_id: The ID of the pipeline to get a token for.
3883
3883
  schedule_id: The ID of the schedule to get a token for.
3884
- expires_minutes: The number of minutes for which the token should
3885
- be valid. If not provided, the token will be valid indefinitely.
3884
+ pipeline_run_id: The ID of the pipeline run to get a token for.
3885
+ step_run_id: The ID of the step run to get a token for.
3886
3886
 
3887
3887
  Returns:
3888
3888
  The API token.
@@ -3890,13 +3890,16 @@ class RestZenStore(BaseZenStore):
3890
3890
  Raises:
3891
3891
  ValueError: if the server response is not valid.
3892
3892
  """
3893
- params: Dict[str, Any] = {}
3894
- if pipeline_id:
3895
- params["pipeline_id"] = pipeline_id
3893
+ params: Dict[str, Any] = {
3894
+ # Python clients may only request workload tokens.
3895
+ "token_type": APITokenType.WORKLOAD.value,
3896
+ }
3896
3897
  if schedule_id:
3897
3898
  params["schedule_id"] = schedule_id
3898
- if expires_minutes:
3899
- params["expires_minutes"] = expires_minutes
3899
+ if pipeline_run_id:
3900
+ params["pipeline_run_id"] = pipeline_run_id
3901
+ if step_run_id:
3902
+ params["step_run_id"] = step_run_id
3900
3903
  response_body = self.get(API_TOKEN, params=params)
3901
3904
  if not isinstance(response_body, str):
3902
3905
  raise ValueError(
@@ -19,7 +19,7 @@ from typing import TYPE_CHECKING, Any, Dict, List, Optional, cast
19
19
  from uuid import UUID
20
20
 
21
21
  from pydantic import ConfigDict
22
- from sqlalchemy import BOOLEAN, INTEGER, TEXT, Column
22
+ from sqlalchemy import BOOLEAN, INTEGER, TEXT, Column, UniqueConstraint
23
23
  from sqlmodel import Field, Relationship
24
24
 
25
25
  from zenml.enums import MetadataResourceTypes, TaggableResourceTypes
@@ -62,6 +62,13 @@ class ModelSchema(NamedSchema, table=True):
62
62
  """SQL Model for model."""
63
63
 
64
64
  __tablename__ = "model"
65
+ __table_args__ = (
66
+ UniqueConstraint(
67
+ "name",
68
+ "workspace_id",
69
+ name="unique_model_name_in_workspace",
70
+ ),
71
+ )
65
72
 
66
73
  workspace_id: UUID = build_foreign_key_field(
67
74
  source=__tablename__,
@@ -220,6 +227,23 @@ class ModelVersionSchema(NamedSchema, table=True):
220
227
  """SQL Model for model version."""
221
228
 
222
229
  __tablename__ = MODEL_VERSION_TABLENAME
230
+ __table_args__ = (
231
+ # We need two unique constraints here:
232
+ # - The first to ensure that each model version for a
233
+ # model has a unique version number
234
+ # - The second one to ensure that explicit names given by
235
+ # users are unique
236
+ UniqueConstraint(
237
+ "number",
238
+ "model_id",
239
+ name="unique_version_number_for_model_id",
240
+ ),
241
+ UniqueConstraint(
242
+ "name",
243
+ "model_id",
244
+ name="unique_version_for_model_id",
245
+ ),
246
+ )
223
247
 
224
248
  workspace_id: UUID = build_foreign_key_field(
225
249
  source=__tablename__,
@@ -72,6 +72,11 @@ class PipelineRunSchema(NamedSchema, table=True):
72
72
  "orchestrator_run_id",
73
73
  name="unique_orchestrator_run_id_for_deployment_id",
74
74
  ),
75
+ UniqueConstraint(
76
+ "name",
77
+ "workspace_id",
78
+ name="unique_run_name_in_workspace",
79
+ ),
75
80
  )
76
81
 
77
82
  # Fields
@@ -17,7 +17,7 @@ from datetime import datetime
17
17
  from typing import TYPE_CHECKING, Any, List, 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 TaggableResourceTypes
@@ -50,7 +50,13 @@ class PipelineSchema(NamedSchema, table=True):
50
50
  """SQL Model for pipelines."""
51
51
 
52
52
  __tablename__ = "pipeline"
53
-
53
+ __table_args__ = (
54
+ UniqueConstraint(
55
+ "name",
56
+ "workspace_id",
57
+ name="unique_pipeline_name_in_workspace",
58
+ ),
59
+ )
54
60
  # Fields
55
61
  description: Optional[str] = Field(sa_column=Column(TEXT, nullable=True))
56
62