zenml-nightly 0.70.0.dev20241125__py3-none-any.whl → 0.71.0.dev20241220__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 (254) hide show
  1. README.md +4 -4
  2. RELEASE_NOTES.md +112 -0
  3. zenml/VERSION +1 -1
  4. zenml/artifact_stores/base_artifact_store.py +2 -2
  5. zenml/artifacts/artifact_config.py +15 -6
  6. zenml/artifacts/utils.py +59 -32
  7. zenml/cli/__init__.py +22 -4
  8. zenml/cli/base.py +5 -5
  9. zenml/cli/login.py +26 -0
  10. zenml/cli/pipeline.py +111 -62
  11. zenml/cli/server.py +20 -20
  12. zenml/cli/service_connectors.py +3 -3
  13. zenml/cli/stack.py +0 -3
  14. zenml/cli/stack_components.py +0 -1
  15. zenml/cli/utils.py +0 -5
  16. zenml/client.py +62 -20
  17. zenml/config/compiler.py +12 -3
  18. zenml/config/pipeline_configurations.py +20 -0
  19. zenml/config/pipeline_run_configuration.py +1 -0
  20. zenml/config/secret_reference_mixin.py +1 -1
  21. zenml/config/server_config.py +4 -0
  22. zenml/config/step_configurations.py +21 -0
  23. zenml/constants.py +10 -0
  24. zenml/enums.py +1 -0
  25. zenml/image_builders/base_image_builder.py +5 -2
  26. zenml/image_builders/build_context.py +7 -16
  27. zenml/image_builders/local_image_builder.py +13 -3
  28. zenml/integrations/__init__.py +1 -0
  29. zenml/integrations/aws/__init__.py +3 -0
  30. zenml/integrations/aws/flavors/__init__.py +6 -0
  31. zenml/integrations/aws/flavors/aws_image_builder_flavor.py +146 -0
  32. zenml/integrations/aws/image_builders/__init__.py +20 -0
  33. zenml/integrations/aws/image_builders/aws_image_builder.py +307 -0
  34. zenml/integrations/aws/orchestrators/sagemaker_orchestrator.py +14 -6
  35. zenml/integrations/constants.py +1 -0
  36. zenml/integrations/feast/__init__.py +1 -1
  37. zenml/integrations/feast/feature_stores/feast_feature_store.py +13 -9
  38. zenml/integrations/gcp/orchestrators/vertex_orchestrator.py +1 -1
  39. zenml/integrations/kaniko/image_builders/kaniko_image_builder.py +2 -1
  40. zenml/integrations/kubernetes/flavors/kubernetes_orchestrator_flavor.py +11 -0
  41. zenml/integrations/kubernetes/orchestrators/kube_utils.py +46 -2
  42. zenml/integrations/kubernetes/orchestrators/kubernetes_orchestrator.py +13 -2
  43. zenml/integrations/kubernetes/orchestrators/kubernetes_orchestrator_entrypoint.py +3 -1
  44. zenml/integrations/kubernetes/orchestrators/manifest_utils.py +3 -2
  45. zenml/integrations/kubernetes/step_operators/kubernetes_step_operator.py +3 -2
  46. zenml/integrations/lightning/flavors/lightning_orchestrator_flavor.py +11 -0
  47. zenml/integrations/modal/__init__.py +46 -0
  48. zenml/integrations/modal/flavors/__init__.py +26 -0
  49. zenml/integrations/modal/flavors/modal_step_operator_flavor.py +125 -0
  50. zenml/integrations/modal/step_operators/__init__.py +22 -0
  51. zenml/integrations/modal/step_operators/modal_step_operator.py +242 -0
  52. zenml/integrations/neptune/experiment_trackers/neptune_experiment_tracker.py +7 -5
  53. zenml/integrations/neptune/experiment_trackers/run_state.py +69 -53
  54. zenml/integrations/registry.py +2 -2
  55. zenml/integrations/skypilot/flavors/skypilot_orchestrator_base_vm_config.py +12 -0
  56. zenml/integrations/wandb/flavors/wandb_experiment_tracker_flavor.py +13 -5
  57. zenml/io/filesystem.py +2 -2
  58. zenml/io/local_filesystem.py +3 -3
  59. zenml/materializers/built_in_materializer.py +18 -1
  60. zenml/materializers/structured_string_materializer.py +8 -3
  61. zenml/model/model.py +23 -101
  62. zenml/model/utils.py +21 -17
  63. zenml/models/__init__.py +6 -0
  64. zenml/models/v2/base/filter.py +26 -30
  65. zenml/models/v2/base/scoped.py +258 -5
  66. zenml/models/v2/core/artifact_version.py +21 -29
  67. zenml/models/v2/core/code_repository.py +1 -12
  68. zenml/models/v2/core/component.py +5 -68
  69. zenml/models/v2/core/flavor.py +1 -11
  70. zenml/models/v2/core/model.py +1 -57
  71. zenml/models/v2/core/model_version.py +11 -36
  72. zenml/models/v2/core/model_version_artifact.py +11 -3
  73. zenml/models/v2/core/model_version_pipeline_run.py +14 -3
  74. zenml/models/v2/core/pipeline.py +47 -55
  75. zenml/models/v2/core/pipeline_build.py +67 -12
  76. zenml/models/v2/core/pipeline_deployment.py +0 -10
  77. zenml/models/v2/core/pipeline_run.py +110 -32
  78. zenml/models/v2/core/run_metadata.py +30 -9
  79. zenml/models/v2/core/run_template.py +21 -29
  80. zenml/models/v2/core/schedule.py +0 -10
  81. zenml/models/v2/core/secret.py +0 -14
  82. zenml/models/v2/core/service.py +9 -16
  83. zenml/models/v2/core/service_connector.py +0 -11
  84. zenml/models/v2/core/stack.py +21 -30
  85. zenml/models/v2/core/step_run.py +24 -18
  86. zenml/models/v2/core/trigger.py +19 -3
  87. zenml/models/v2/misc/run_metadata.py +38 -0
  88. zenml/orchestrators/base_orchestrator.py +13 -1
  89. zenml/orchestrators/input_utils.py +19 -6
  90. zenml/orchestrators/output_utils.py +5 -1
  91. zenml/orchestrators/publish_utils.py +12 -5
  92. zenml/orchestrators/step_launcher.py +16 -16
  93. zenml/orchestrators/step_run_utils.py +18 -197
  94. zenml/orchestrators/step_runner.py +40 -3
  95. zenml/orchestrators/utils.py +79 -50
  96. zenml/pipelines/build_utils.py +12 -0
  97. zenml/pipelines/pipeline_decorator.py +4 -0
  98. zenml/pipelines/pipeline_definition.py +26 -8
  99. zenml/pipelines/run_utils.py +9 -5
  100. zenml/service_connectors/service_connector_utils.py +3 -9
  101. zenml/stack/stack_component.py +1 -1
  102. zenml/stack_deployments/aws_stack_deployment.py +22 -0
  103. zenml/steps/base_step.py +11 -1
  104. zenml/steps/entrypoint_function_utils.py +7 -3
  105. zenml/steps/step_decorator.py +4 -0
  106. zenml/steps/utils.py +23 -7
  107. zenml/types.py +4 -0
  108. zenml/utils/archivable.py +65 -36
  109. zenml/utils/code_utils.py +8 -4
  110. zenml/utils/docker_utils.py +9 -0
  111. zenml/utils/metadata_utils.py +186 -153
  112. zenml/utils/string_utils.py +41 -16
  113. zenml/utils/visualization_utils.py +4 -1
  114. zenml/zen_server/auth.py +9 -10
  115. zenml/zen_server/cloud_utils.py +3 -1
  116. zenml/zen_server/dashboard/assets/{404-NVXKFp-x.js → 404-Cqu3EDCm.js} +1 -1
  117. zenml/zen_server/dashboard/assets/{@reactflow-CK0KJUen.js → @reactflow-D2Y7BWwz.js} +1 -1
  118. zenml/zen_server/dashboard/assets/{AlertDialogDropdownItem-DezXKmDf.js → AlertDialogDropdownItem-BHd71pVS.js} +1 -1
  119. zenml/zen_server/dashboard/assets/{CodeSnippet-JzR8CEtw.js → CodeSnippet-DIonwetW.js} +1 -1
  120. zenml/zen_server/dashboard/assets/{CollapsibleCard-DQW_ktMO.js → CollapsibleCard-CDnC97pB.js} +1 -1
  121. zenml/zen_server/dashboard/assets/{Commands-DL2kwkRd.js → Commands-BVEXKAOj.js} +1 -1
  122. zenml/zen_server/dashboard/assets/{ComponentBadge-D_g62Wv8.js → ComponentBadge-CrRvovox.js} +1 -1
  123. zenml/zen_server/dashboard/assets/{CopyButton-LNcWaa14.js → CopyButton-B6wGAhQv.js} +1 -1
  124. zenml/zen_server/dashboard/assets/{CsvVizualization-DknpE5ej.js → CsvVizualization-CjcT7LMm.js} +5 -5
  125. zenml/zen_server/dashboard/assets/DeleteAlertDialog-D2ELtM2W.js +1 -0
  126. zenml/zen_server/dashboard/assets/{DialogItem-Bxf8FuAT.js → DialogItem-DXIMhBgU.js} +1 -1
  127. zenml/zen_server/dashboard/assets/{Error-DYflYyps.js → Error-B8uUfTpL.js} +1 -1
  128. zenml/zen_server/dashboard/assets/{ExecutionStatus-C7zyIQKZ.js → ExecutionStatus-ibAdY-dG.js} +1 -1
  129. zenml/zen_server/dashboard/assets/{Helpbox-oYSGpLqd.js → Helpbox-BfAfhKHw.js} +1 -1
  130. zenml/zen_server/dashboard/assets/{Infobox-Cx4xGoXR.js → Infobox-M_SMOu96.js} +1 -1
  131. zenml/zen_server/dashboard/assets/{InlineAvatar-DiGOWNKF.js → InlineAvatar-DBA0a0-a.js} +1 -1
  132. zenml/zen_server/dashboard/assets/{NestedCollapsible-DYbgyKxK.js → NestedCollapsible-DpgmEFKw.js} +1 -1
  133. zenml/zen_server/dashboard/assets/{Partials-03iZf8-N.js → Partials-D_ldD9if.js} +1 -1
  134. zenml/zen_server/dashboard/assets/{ProBadge-D_EB8HNo.js → ProBadge-DQbfFotM.js} +1 -1
  135. zenml/zen_server/dashboard/assets/{ProCta-DqNS4v3x.js → ProCta-Bcpb4rcY.js} +1 -1
  136. zenml/zen_server/dashboard/assets/{ProviderIcon-Bki2aw8w.js → ProviderIcon-BZpgPigN.js} +1 -1
  137. zenml/zen_server/dashboard/assets/{ProviderRadio-8f43sPD4.js → ProviderRadio-DWPnMuQ1.js} +1 -1
  138. zenml/zen_server/dashboard/assets/RunSelector-DgRGaAc6.js +1 -0
  139. zenml/zen_server/dashboard/assets/{RunsBody-07YEO7qI.js → RunsBody-KecfSkjY.js} +1 -1
  140. zenml/zen_server/dashboard/assets/{SearchField-lp1KgU4e.js → SearchField-n-ILHnaP.js} +1 -1
  141. zenml/zen_server/dashboard/assets/{SecretTooltip-CgnbyeOx.js → SecretTooltip-B8MrX5yu.js} +1 -1
  142. zenml/zen_server/dashboard/assets/{SetPassword-CpP418A2.js → SetPassword-B_IVq_wg.js} +1 -1
  143. zenml/zen_server/dashboard/assets/StackList-TWPBYnkF.js +1 -0
  144. zenml/zen_server/dashboard/assets/{Tabs-BktHkCJJ.js → Tabs-Rg857zmd.js} +1 -1
  145. zenml/zen_server/dashboard/assets/{Tick-BlMoIlJT.js → Tick-COg4A-xo.js} +1 -1
  146. zenml/zen_server/dashboard/assets/{UpdatePasswordSchemas-Sc0A0pP-.js → UpdatePasswordSchemas-C6Aj3hm6.js} +1 -1
  147. zenml/zen_server/dashboard/assets/{UsageReason-YYduL4fj.js → UsageReason-BTLbx7w4.js} +1 -1
  148. zenml/zen_server/dashboard/assets/{WizardFooter-dgmizSJC.js → WizardFooter-BCAj69Vj.js} +1 -1
  149. zenml/zen_server/dashboard/assets/{all-pipeline-runs-query-D-c2G6lV.js → all-pipeline-runs-query-DMXkDrV2.js} +1 -1
  150. zenml/zen_server/dashboard/assets/code-snippets-CqONne41.js +13 -0
  151. zenml/zen_server/dashboard/assets/{create-stack-DM_JPgef.js → create-stack-HfdbhLs4.js} +1 -1
  152. zenml/zen_server/dashboard/assets/dates-3pMLCNrD.js +1 -0
  153. zenml/zen_server/dashboard/assets/delete-run-DZ4hIXff.js +1 -0
  154. zenml/zen_server/dashboard/assets/{form-schemas-K6FYKjwa.js → form-schemas-B0AVEd9b.js} +1 -1
  155. zenml/zen_server/dashboard/assets/{index-BAkC7FXi.js → index-DPqSWjug.js} +1 -1
  156. zenml/zen_server/dashboard/assets/{index-CEV4Cvaf.js → index-DScjfBRb.js} +1 -1
  157. zenml/zen_server/dashboard/assets/index-DXvT1_Um.css +1 -0
  158. zenml/zen_server/dashboard/assets/{index-CCOPpudF.js → index-FO-p0GU7.js} +5 -5
  159. zenml/zen_server/dashboard/assets/{index-B1mVPYxf.js → index-I3bKUGUj.js} +1 -1
  160. zenml/zen_server/dashboard/assets/key-icon-aH-QIa5R.js +1 -0
  161. zenml/zen_server/dashboard/assets/login-command-CkqxPtV3.js +1 -0
  162. zenml/zen_server/dashboard/assets/{login-mutation-hf-lK87O.js → login-mutation-BQeo4wTY.js} +1 -1
  163. zenml/zen_server/dashboard/assets/{not-found-BGirLjU-.js → not-found-gAJ5aDdR.js} +1 -1
  164. zenml/zen_server/dashboard/assets/page-9Y9-gig0.js +1 -0
  165. zenml/zen_server/dashboard/assets/{page-DjRJCGb3.js → page-AUwiQ14W.js} +1 -1
  166. zenml/zen_server/dashboard/assets/page-B6XU7yYT.js +2 -0
  167. zenml/zen_server/dashboard/assets/{page-C00YAkaB.js → page-BKZYc2Zv.js} +1 -1
  168. zenml/zen_server/dashboard/assets/{page-CdMWnQak.js → page-BU9FG4sR.js} +1 -1
  169. zenml/zen_server/dashboard/assets/{page-D7S3aCbF.js → page-B_Apk3xg.js} +1 -1
  170. zenml/zen_server/dashboard/assets/{page-Djikxq_S.js → page-BdowiCbr.js} +1 -1
  171. zenml/zen_server/dashboard/assets/page-Bg8OjTRe.js +1 -0
  172. zenml/zen_server/dashboard/assets/page-BxL4qD4_.js +1 -0
  173. zenml/zen_server/dashboard/assets/{page-DakHVWXF.js → page-CWxT5K5J.js} +1 -1
  174. zenml/zen_server/dashboard/assets/page-CXuQufSe.js +1 -0
  175. zenml/zen_server/dashboard/assets/{page-DLC-bNBP.js → page-CcQr8CPP.js} +1 -1
  176. zenml/zen_server/dashboard/assets/{page-CD-DcWoy.js → page-Ce4Hrjnr.js} +1 -1
  177. zenml/zen_server/dashboard/assets/page-CiYxgZP_.js +1 -0
  178. zenml/zen_server/dashboard/assets/page-Cldq1mpe.js +1 -0
  179. zenml/zen_server/dashboard/assets/{page-BDigxVpo.js → page-D4wdonLm.js} +1 -1
  180. zenml/zen_server/dashboard/assets/{page-D6uU2ax4.js → page-D8ObrbH8.js} +1 -1
  181. zenml/zen_server/dashboard/assets/{page-DXSTpqRD.js → page-DFuAUGt4.js} +1 -1
  182. zenml/zen_server/dashboard/assets/{page-CbpvrsDL.js → page-DGazBpuP.js} +1 -1
  183. zenml/zen_server/dashboard/assets/{page-COXXJj1k.js → page-DO1UcqPX.js} +1 -1
  184. zenml/zen_server/dashboard/assets/page-DRYXdL5o.js +1 -0
  185. zenml/zen_server/dashboard/assets/{page-Df-Fw0aq.js → page-DYEquBC2.js} +1 -1
  186. zenml/zen_server/dashboard/assets/page-Dk32IeZm.js +1 -0
  187. zenml/zen_server/dashboard/assets/{page-yYC9OI-E.js → page-I3nKFGie.js} +1 -1
  188. zenml/zen_server/dashboard/assets/{page-6m6yHHlE.js → page-M0w-n6vn.js} +1 -1
  189. zenml/zen_server/dashboard/assets/{page-Vcxara9U.js → page-R5dx3xGF.js} +1 -1
  190. zenml/zen_server/dashboard/assets/{page-BR68V0V1.js → page-bT5pOvcB.js} +1 -1
  191. zenml/zen_server/dashboard/assets/page-hUqK889I.js +6 -0
  192. zenml/zen_server/dashboard/assets/{page-CjGdWY13.js → page-h_Stveon.js} +1 -1
  193. zenml/zen_server/dashboard/assets/{page-D01JhjQB.js → page-r8XK5vR7.js} +1 -1
  194. zenml/zen_server/dashboard/assets/page-u_-ZXBKb.js +1 -0
  195. zenml/zen_server/dashboard/assets/page-zaMqB_ao.js +1 -0
  196. zenml/zen_server/dashboard/assets/{persist-GjC8PZoC.js → persist-AppN1B0J.js} +1 -1
  197. zenml/zen_server/dashboard/assets/{persist-Coz7ZWvz.js → persist-DAUi_3za.js} +1 -1
  198. zenml/zen_server/dashboard/assets/service-BqqeXLEe.js +2 -0
  199. zenml/zen_server/dashboard/assets/{sharedSchema-CQb14VSr.js → sharedSchema-uXN9FLLk.js} +1 -1
  200. zenml/zen_server/dashboard/assets/{stack-detail-query-OPEW-cDJ.js → stack-detail-query-XfZBiBP2.js} +1 -1
  201. zenml/zen_server/dashboard/assets/{update-server-settings-mutation-LwuQfHYn.js → update-server-settings-mutation-BWmgVJwA.js} +1 -1
  202. zenml/zen_server/dashboard/assets/{url-CkvKAnwF.js → url-BLwMbzES.js} +1 -1
  203. zenml/zen_server/dashboard/index.html +4 -4
  204. zenml/zen_server/deploy/helm/Chart.yaml +1 -1
  205. zenml/zen_server/deploy/helm/README.md +2 -2
  206. zenml/zen_server/rbac/endpoint_utils.py +6 -4
  207. zenml/zen_server/rbac/models.py +3 -2
  208. zenml/zen_server/rbac/rbac_sql_zen_store.py +173 -0
  209. zenml/zen_server/rbac/utils.py +4 -7
  210. zenml/zen_server/routers/auth_endpoints.py +22 -11
  211. zenml/zen_server/routers/steps_endpoints.py +7 -1
  212. zenml/zen_server/routers/users_endpoints.py +35 -37
  213. zenml/zen_server/routers/workspaces_endpoints.py +44 -55
  214. zenml/zen_server/template_execution/utils.py +4 -1
  215. zenml/zen_server/utils.py +4 -3
  216. zenml/zen_stores/base_zen_store.py +10 -2
  217. zenml/zen_stores/migrations/versions/0.71.0_release.py +23 -0
  218. zenml/zen_stores/migrations/versions/26351d482b9e_add_step_run_unique_constraint.py +37 -0
  219. zenml/zen_stores/migrations/versions/a1237ba94fd8_add_model_version_producer_run_unique_.py +68 -0
  220. zenml/zen_stores/migrations/versions/b73bc71f1106_remove_component_spec_path.py +36 -0
  221. zenml/zen_stores/migrations/versions/cc269488e5a9_separate_run_metadata.py +135 -0
  222. zenml/zen_stores/migrations/versions/ec6307720f92_simplify_model_version_links.py +7 -6
  223. zenml/zen_stores/rest_zen_store.py +76 -43
  224. zenml/zen_stores/schemas/__init__.py +5 -1
  225. zenml/zen_stores/schemas/artifact_schemas.py +12 -11
  226. zenml/zen_stores/schemas/component_schemas.py +0 -3
  227. zenml/zen_stores/schemas/model_schemas.py +55 -17
  228. zenml/zen_stores/schemas/pipeline_deployment_schemas.py +7 -7
  229. zenml/zen_stores/schemas/pipeline_run_schemas.py +52 -18
  230. zenml/zen_stores/schemas/pipeline_schemas.py +5 -0
  231. zenml/zen_stores/schemas/run_metadata_schemas.py +66 -31
  232. zenml/zen_stores/schemas/step_run_schemas.py +40 -13
  233. zenml/zen_stores/schemas/utils.py +47 -3
  234. zenml/zen_stores/sql_zen_store.py +462 -134
  235. {zenml_nightly-0.70.0.dev20241125.dist-info → zenml_nightly-0.71.0.dev20241220.dist-info}/METADATA +5 -5
  236. {zenml_nightly-0.70.0.dev20241125.dist-info → zenml_nightly-0.71.0.dev20241220.dist-info}/RECORD +239 -217
  237. zenml/utils/cloud_utils.py +0 -40
  238. zenml/zen_server/dashboard/assets/RunSelector-DkPiIiNr.js +0 -1
  239. zenml/zen_server/dashboard/assets/StackList-WvuKQusZ.js +0 -1
  240. zenml/zen_server/dashboard/assets/delete-run-CJdh1P_h.js +0 -1
  241. zenml/zen_server/dashboard/assets/index-DlGvJQPn.css +0 -1
  242. zenml/zen_server/dashboard/assets/page-0JE_-Ec1.js +0 -1
  243. zenml/zen_server/dashboard/assets/page-BRLpxOt0.js +0 -1
  244. zenml/zen_server/dashboard/assets/page-BU7huvKw.js +0 -6
  245. zenml/zen_server/dashboard/assets/page-BvqLv2Ky.js +0 -1
  246. zenml/zen_server/dashboard/assets/page-CwxrFarU.js +0 -1
  247. zenml/zen_server/dashboard/assets/page-DfbXf_8s.js +0 -1
  248. zenml/zen_server/dashboard/assets/page-Dnovpa0i.js +0 -3
  249. zenml/zen_server/dashboard/assets/page-Dot3LPmL.js +0 -1
  250. zenml/zen_server/dashboard/assets/page-Xynx4btY.js +0 -14
  251. zenml/zen_server/dashboard/assets/page-YpKAqVSa.js +0 -1
  252. {zenml_nightly-0.70.0.dev20241125.dist-info → zenml_nightly-0.71.0.dev20241220.dist-info}/LICENSE +0 -0
  253. {zenml_nightly-0.70.0.dev20241125.dist-info → zenml_nightly-0.71.0.dev20241220.dist-info}/WHEEL +0 -0
  254. {zenml_nightly-0.70.0.dev20241125.dist-info → zenml_nightly-0.71.0.dev20241220.dist-info}/entry_points.txt +0 -0
@@ -41,7 +41,6 @@ from zenml.constants import (
41
41
  from zenml.enums import (
42
42
  APITokenType,
43
43
  AuthScheme,
44
- ExecutionStatus,
45
44
  OAuthDeviceStatus,
46
45
  OAuthGrantTypes,
47
46
  )
@@ -452,6 +451,7 @@ def device_authorization(
452
451
  @handle_exceptions
453
452
  def api_token(
454
453
  token_type: APITokenType = APITokenType.GENERIC,
454
+ expires_in: Optional[int] = None,
455
455
  schedule_id: Optional[UUID] = None,
456
456
  pipeline_run_id: Optional[UUID] = None,
457
457
  step_run_id: Optional[UUID] = None,
@@ -463,7 +463,8 @@ def api_token(
463
463
  of API tokens are supported:
464
464
 
465
465
  * Generic API token: This token is short-lived and can be used for
466
- generic automation tasks.
466
+ generic automation tasks. The expiration can be set by the user, but the
467
+ server will impose a maximum expiration time.
467
468
  * Workload API token: This token is scoped to a specific pipeline run, step
468
469
  run or schedule and is used by pipeline workloads to authenticate with the
469
470
  server. A pipeline run ID, step run ID or schedule ID must be provided and
@@ -475,6 +476,10 @@ def api_token(
475
476
 
476
477
  Args:
477
478
  token_type: The type of API token to generate.
479
+ expires_in: The expiration time of the generic API token in seconds.
480
+ If not set, the server will use the default expiration time for
481
+ generic API tokens. The server also imposes a maximum expiration
482
+ time.
478
483
  schedule_id: The ID of the schedule to scope the workload API token to.
479
484
  pipeline_run_id: The ID of the pipeline run to scope the workload API
480
485
  token to.
@@ -502,9 +507,19 @@ def api_token(
502
507
 
503
508
  config = server_config()
504
509
 
510
+ if not expires_in:
511
+ expires_in = config.generic_api_token_lifetime
512
+
513
+ if expires_in > config.generic_api_token_max_lifetime:
514
+ raise ValueError(
515
+ f"The maximum expiration time for generic API tokens allowed "
516
+ f"by this server is {config.generic_api_token_max_lifetime} "
517
+ "seconds."
518
+ )
519
+
505
520
  return generate_access_token(
506
521
  user_id=token.user_id,
507
- expires_in=config.generic_api_token_lifetime,
522
+ expires_in=expires_in,
508
523
  ).access_token
509
524
 
510
525
  verify_permission(
@@ -573,10 +588,7 @@ def api_token(
573
588
  "security reasons."
574
589
  )
575
590
 
576
- if pipeline_run.status in [
577
- ExecutionStatus.FAILED,
578
- ExecutionStatus.COMPLETED,
579
- ]:
591
+ if pipeline_run.status.is_finished:
580
592
  raise ValueError(
581
593
  f"The execution of pipeline run {pipeline_run_id} has already "
582
594
  "concluded and API tokens can no longer be generated for it "
@@ -593,10 +605,7 @@ def api_token(
593
605
  "be generated for non-existent step runs for security reasons."
594
606
  )
595
607
 
596
- if step_run.status in [
597
- ExecutionStatus.FAILED,
598
- ExecutionStatus.COMPLETED,
599
- ]:
608
+ if step_run.status.is_finished:
600
609
  raise ValueError(
601
610
  f"The execution of step run {step_run_id} has already "
602
611
  "concluded and API tokens can no longer be generated for it "
@@ -611,4 +620,6 @@ def api_token(
611
620
  schedule_id=schedule_id,
612
621
  pipeline_run_id=pipeline_run_id,
613
622
  step_run_id=step_run_id,
623
+ # Never expire the token
624
+ expires_in=0,
614
625
  ).access_token
@@ -142,10 +142,16 @@ def get_step(
142
142
  Returns:
143
143
  The step.
144
144
  """
145
- step = zen_store().get_run_step(step_id, hydrate=hydrate)
145
+ # We always fetch the step hydrated because we need the pipeline_run_id
146
+ # for the permission checks. If the user requested an unhydrated response,
147
+ # we later remove the metadata
148
+ step = zen_store().get_run_step(step_id, hydrate=True)
146
149
  pipeline_run = zen_store().get_run(step.pipeline_run_id)
147
150
  verify_permission_for_model(pipeline_run, action=Action.READ)
148
151
 
152
+ if hydrate is False:
153
+ step.metadata = None
154
+
149
155
  return dehydrate_response_model(step)
150
156
 
151
157
 
@@ -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
@@ -122,13 +122,15 @@ def run_template(
122
122
  placeholder_run = create_placeholder_run(deployment=new_deployment)
123
123
  assert placeholder_run
124
124
 
125
- # We create an API token scoped to the pipeline run
125
+ # We create an API token scoped to the pipeline run that never expires
126
126
  api_token = generate_access_token(
127
127
  user_id=auth_context.user.id,
128
128
  pipeline_run_id=placeholder_run.id,
129
129
  # Keep the original API key or device scopes, if any
130
130
  api_key=auth_context.api_key,
131
131
  device=auth_context.device,
132
+ # Never expire the token
133
+ expires_in=0,
132
134
  ).access_token
133
135
 
134
136
  environment = {
@@ -363,6 +365,7 @@ def deployment_request_from_template(
363
365
  "external_input_artifacts",
364
366
  "model_artifacts_or_metadata",
365
367
  "client_lazy_loaders",
368
+ "substitutions",
366
369
  "outputs",
367
370
  }
368
371
  ),
zenml/zen_server/utils.py CHANGED
@@ -421,6 +421,8 @@ def make_dependable(cls: Type[BaseModel]) -> Callable[..., Any]:
421
421
  """
422
422
  from fastapi import Query
423
423
 
424
+ from zenml.zen_server.exceptions import error_detail
425
+
424
426
  def init_cls_and_handle_errors(*args: Any, **kwargs: Any) -> BaseModel:
425
427
  from fastapi import HTTPException
426
428
 
@@ -428,9 +430,8 @@ def make_dependable(cls: Type[BaseModel]) -> Callable[..., Any]:
428
430
  inspect.signature(init_cls_and_handle_errors).bind(*args, **kwargs)
429
431
  return cls(*args, **kwargs)
430
432
  except ValidationError as e:
431
- for error in e.errors():
432
- error["loc"] = tuple(["query"] + list(error["loc"]))
433
- raise HTTPException(422, detail=e.errors())
433
+ detail = error_detail(e, exception_type=ValueError)
434
+ raise HTTPException(422, detail=detail)
434
435
 
435
436
  params = {v.name: v for v in inspect.signature(cls).parameters.values()}
436
437
  query_params = getattr(cls, "API_MULTI_INPUT_PARAMS", [])
@@ -36,6 +36,7 @@ from zenml.constants import (
36
36
  DEFAULT_STACK_AND_COMPONENT_NAME,
37
37
  DEFAULT_WORKSPACE_NAME,
38
38
  ENV_ZENML_DEFAULT_WORKSPACE_NAME,
39
+ ENV_ZENML_SERVER,
39
40
  IS_DEBUG_ENV,
40
41
  )
41
42
  from zenml.enums import (
@@ -155,9 +156,16 @@ class BaseZenStore(
155
156
  TypeError: If the store type is unsupported.
156
157
  """
157
158
  if store_type == StoreType.SQL:
158
- from zenml.zen_stores.sql_zen_store import SqlZenStore
159
+ if os.environ.get(ENV_ZENML_SERVER):
160
+ from zenml.zen_server.rbac.rbac_sql_zen_store import (
161
+ RBACSqlZenStore,
162
+ )
163
+
164
+ return RBACSqlZenStore
165
+ else:
166
+ from zenml.zen_stores.sql_zen_store import SqlZenStore
159
167
 
160
- return SqlZenStore
168
+ return SqlZenStore
161
169
  elif store_type == StoreType.REST:
162
170
  from zenml.zen_stores.rest_zen_store import RestZenStore
163
171
 
@@ -0,0 +1,23 @@
1
+ """Release [0.71.0].
2
+
3
+ Revision ID: 0.71.0
4
+ Revises: cc269488e5a9
5
+ Create Date: 2024-12-04 20:44:19.316139
6
+
7
+ """
8
+
9
+ # revision identifiers, used by Alembic.
10
+ revision = "0.71.0"
11
+ down_revision = "cc269488e5a9"
12
+ branch_labels = None
13
+ depends_on = None
14
+
15
+
16
+ def upgrade() -> None:
17
+ """Upgrade database schema and/or data, creating a new revision."""
18
+ pass
19
+
20
+
21
+ def downgrade() -> None:
22
+ """Downgrade database schema and/or data back to the previous revision."""
23
+ pass
@@ -0,0 +1,37 @@
1
+ """Add step run unique constraint [26351d482b9e].
2
+
3
+ Revision ID: 26351d482b9e
4
+ Revises: 0.71.0
5
+ Create Date: 2024-12-03 11:46:57.541578
6
+
7
+ """
8
+
9
+ from alembic import op
10
+
11
+ # revision identifiers, used by Alembic.
12
+ revision = "26351d482b9e"
13
+ down_revision = "0.71.0"
14
+ branch_labels = None
15
+ depends_on = None
16
+
17
+
18
+ def upgrade() -> None:
19
+ """Upgrade database schema and/or data, creating a new revision."""
20
+ # ### commands auto generated by Alembic - please adjust! ###
21
+ with op.batch_alter_table("step_run", schema=None) as batch_op:
22
+ batch_op.create_unique_constraint(
23
+ "unique_step_name_for_pipeline_run", ["name", "pipeline_run_id"]
24
+ )
25
+
26
+ # ### end Alembic commands ###
27
+
28
+
29
+ def downgrade() -> None:
30
+ """Downgrade database schema and/or data back to the previous revision."""
31
+ # ### commands auto generated by Alembic - please adjust! ###
32
+ with op.batch_alter_table("step_run", schema=None) as batch_op:
33
+ batch_op.drop_constraint(
34
+ "unique_step_name_for_pipeline_run", type_="unique"
35
+ )
36
+
37
+ # ### end Alembic commands ###
@@ -0,0 +1,68 @@
1
+ """Add model version producer run unique constraint [a1237ba94fd8].
2
+
3
+ Revision ID: a1237ba94fd8
4
+ Revises: 26351d482b9e
5
+ Create Date: 2024-12-13 10:28:55.432414
6
+
7
+ """
8
+
9
+ import sqlalchemy as sa
10
+ import sqlmodel
11
+ from alembic import op
12
+
13
+ # revision identifiers, used by Alembic.
14
+ revision = "a1237ba94fd8"
15
+ down_revision = "26351d482b9e"
16
+ branch_labels = None
17
+ depends_on = None
18
+
19
+
20
+ def upgrade() -> None:
21
+ """Upgrade database schema and/or data, creating a new revision."""
22
+ # ### commands auto generated by Alembic - please adjust! ###
23
+ with op.batch_alter_table("model_version", schema=None) as batch_op:
24
+ batch_op.add_column(
25
+ sa.Column(
26
+ "producer_run_id_if_numeric",
27
+ sqlmodel.sql.sqltypes.GUID(),
28
+ nullable=True,
29
+ )
30
+ )
31
+
32
+ # Set the producer_run_id_if_numeric column to the model version ID for
33
+ # existing rows
34
+ connection = op.get_bind()
35
+ metadata = sa.MetaData()
36
+ metadata.reflect(only=("model_version",), bind=connection)
37
+ model_version_table = sa.Table("model_version", metadata)
38
+
39
+ connection.execute(
40
+ model_version_table.update().values(
41
+ producer_run_id_if_numeric=model_version_table.c.id
42
+ )
43
+ )
44
+
45
+ with op.batch_alter_table("model_version", schema=None) as batch_op:
46
+ batch_op.alter_column(
47
+ "producer_run_id_if_numeric",
48
+ existing_type=sqlmodel.sql.sqltypes.GUID(),
49
+ nullable=False,
50
+ )
51
+ batch_op.create_unique_constraint(
52
+ "unique_numeric_version_for_pipeline_run",
53
+ ["model_id", "producer_run_id_if_numeric"],
54
+ )
55
+
56
+ # ### end Alembic commands ###
57
+
58
+
59
+ def downgrade() -> None:
60
+ """Downgrade database schema and/or data back to the previous revision."""
61
+ # ### commands auto generated by Alembic - please adjust! ###
62
+ with op.batch_alter_table("model_version", schema=None) as batch_op:
63
+ batch_op.drop_constraint(
64
+ "unique_numeric_version_for_pipeline_run", type_="unique"
65
+ )
66
+ batch_op.drop_column("producer_run_id_if_numeric")
67
+
68
+ # ### end Alembic commands ###
@@ -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 ###