zenml-nightly 0.58.2.dev20240623__py3-none-any.whl → 0.61.0.dev20240712__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 (249) hide show
  1. README.md +30 -9
  2. RELEASE_NOTES.md +240 -0
  3. zenml/VERSION +1 -1
  4. zenml/actions/base_action.py +177 -174
  5. zenml/actions/pipeline_run/pipeline_run_action.py +28 -23
  6. zenml/analytics/enums.py +3 -0
  7. zenml/artifact_stores/base_artifact_store.py +7 -1
  8. zenml/artifacts/utils.py +13 -10
  9. zenml/cli/__init__.py +28 -0
  10. zenml/cli/artifact.py +1 -2
  11. zenml/cli/integration.py +9 -8
  12. zenml/cli/server.py +6 -0
  13. zenml/cli/service_connectors.py +1 -0
  14. zenml/cli/stack.py +946 -39
  15. zenml/cli/stack_components.py +7 -0
  16. zenml/cli/text_utils.py +35 -1
  17. zenml/cli/utils.py +127 -10
  18. zenml/client.py +257 -72
  19. zenml/config/compiler.py +10 -9
  20. zenml/config/docker_settings.py +33 -14
  21. zenml/constants.py +11 -2
  22. zenml/container_registries/base_container_registry.py +1 -0
  23. zenml/enums.py +7 -0
  24. zenml/event_hub/base_event_hub.py +5 -5
  25. zenml/event_hub/event_hub.py +20 -14
  26. zenml/event_sources/base_event.py +0 -11
  27. zenml/event_sources/base_event_source.py +7 -0
  28. zenml/event_sources/webhooks/base_webhook_event_source.py +1 -4
  29. zenml/exceptions.py +4 -0
  30. zenml/hooks/hook_validators.py +2 -3
  31. zenml/integrations/aws/__init__.py +1 -0
  32. zenml/integrations/azure/__init__.py +1 -0
  33. zenml/integrations/bitbucket/plugins/event_sources/bitbucket_webhook_event_source.py +3 -3
  34. zenml/integrations/deepchecks/__init__.py +1 -0
  35. zenml/integrations/discord/__init__.py +1 -0
  36. zenml/integrations/evidently/__init__.py +1 -0
  37. zenml/integrations/facets/__init__.py +1 -0
  38. zenml/integrations/feast/__init__.py +1 -0
  39. zenml/integrations/gcp/__init__.py +3 -1
  40. zenml/integrations/gcp/google_credentials_mixin.py +1 -1
  41. zenml/integrations/gcp/service_connectors/gcp_service_connector.py +320 -64
  42. zenml/integrations/huggingface/__init__.py +1 -0
  43. zenml/integrations/integration.py +24 -0
  44. zenml/integrations/kubeflow/__init__.py +3 -0
  45. zenml/integrations/kubeflow/flavors/kubeflow_orchestrator_flavor.py +1 -1
  46. zenml/integrations/kubeflow/orchestrators/kubeflow_orchestrator.py +0 -1
  47. zenml/integrations/kubernetes/__init__.py +3 -1
  48. zenml/integrations/kubernetes/orchestrators/kube_utils.py +4 -1
  49. zenml/integrations/label_studio/annotators/label_studio_annotator.py +1 -0
  50. zenml/integrations/langchain/__init__.py +1 -0
  51. zenml/integrations/mlflow/__init__.py +4 -2
  52. zenml/integrations/neural_prophet/__init__.py +1 -0
  53. zenml/integrations/polars/__init__.py +1 -0
  54. zenml/integrations/prodigy/__init__.py +1 -0
  55. zenml/integrations/pycaret/__init__.py +6 -0
  56. zenml/integrations/registry.py +37 -0
  57. zenml/integrations/s3/artifact_stores/s3_artifact_store.py +93 -9
  58. zenml/integrations/seldon/__init__.py +1 -0
  59. zenml/integrations/seldon/model_deployers/seldon_model_deployer.py +1 -0
  60. zenml/integrations/skypilot/flavors/skypilot_orchestrator_base_vm_config.py +2 -2
  61. zenml/integrations/skypilot/orchestrators/skypilot_base_vm_orchestrator.py +1 -1
  62. zenml/integrations/skypilot/orchestrators/skypilot_orchestrator_entrypoint.py +2 -2
  63. zenml/integrations/skypilot_aws/__init__.py +2 -1
  64. zenml/integrations/skypilot_azure/__init__.py +1 -1
  65. zenml/integrations/skypilot_gcp/__init__.py +1 -1
  66. zenml/integrations/skypilot_lambda/__init__.py +1 -1
  67. zenml/integrations/skypilot_lambda/flavors/skypilot_orchestrator_lambda_vm_flavor.py +1 -1
  68. zenml/integrations/slack/__init__.py +1 -0
  69. zenml/integrations/tekton/__init__.py +1 -0
  70. zenml/integrations/tensorboard/__init__.py +0 -1
  71. zenml/integrations/tensorflow/__init__.py +18 -6
  72. zenml/integrations/wandb/__init__.py +1 -0
  73. zenml/logging/step_logging.py +54 -51
  74. zenml/models/__init__.py +28 -0
  75. zenml/models/v2/core/action.py +276 -0
  76. zenml/models/v2/core/component.py +18 -0
  77. zenml/models/v2/core/model.py +1 -2
  78. zenml/models/v2/core/service_connector.py +17 -0
  79. zenml/models/v2/core/stack.py +31 -0
  80. zenml/models/v2/core/trigger.py +182 -141
  81. zenml/models/v2/misc/full_stack.py +97 -0
  82. zenml/models/v2/misc/stack_deployment.py +86 -0
  83. zenml/new/pipelines/pipeline.py +14 -4
  84. zenml/new/pipelines/pipeline_decorator.py +1 -2
  85. zenml/new/pipelines/run_utils.py +1 -12
  86. zenml/new/steps/step_decorator.py +2 -3
  87. zenml/orchestrators/input_utils.py +3 -6
  88. zenml/pipelines/base_pipeline.py +0 -2
  89. zenml/pipelines/pipeline_decorator.py +1 -2
  90. zenml/stack/stack.py +3 -6
  91. zenml/stack/stack_component.py +4 -0
  92. zenml/stack_deployments/__init__.py +14 -0
  93. zenml/stack_deployments/aws_stack_deployment.py +254 -0
  94. zenml/stack_deployments/gcp_stack_deployment.py +260 -0
  95. zenml/stack_deployments/stack_deployment.py +208 -0
  96. zenml/stack_deployments/utils.py +44 -0
  97. zenml/steps/base_step.py +1 -2
  98. zenml/steps/step_decorator.py +1 -2
  99. zenml/types.py +10 -1
  100. zenml/utils/function_utils.py +1 -1
  101. zenml/utils/pagination_utils.py +7 -5
  102. zenml/utils/pipeline_docker_image_builder.py +117 -73
  103. zenml/utils/pydantic_utils.py +6 -5
  104. zenml/zen_server/cloud_utils.py +18 -3
  105. zenml/zen_server/dashboard/assets/{404-CDPQCl4D.js → 404-DpJaNHKF.js} +1 -1
  106. zenml/zen_server/dashboard/assets/@radix-CFOkMR_E.js +85 -0
  107. zenml/zen_server/dashboard/assets/{@react-router-DYovave8.js → @react-router-CO-OsFwI.js} +2 -2
  108. zenml/zen_server/dashboard/assets/{@reactflow-CHBapDaj.js → @reactflow-DJfzkHO1.js} +2 -2
  109. zenml/zen_server/dashboard/assets/@tanstack-DYiOyJUL.js +22 -0
  110. zenml/zen_server/dashboard/assets/AwarenessChannel-BYDLT2xC.js +1 -0
  111. zenml/zen_server/dashboard/assets/{CodeSnippet-BidtnWOi.js → CodeSnippet-BkOuRmyq.js} +2 -2
  112. zenml/zen_server/dashboard/assets/Commands-ZvWR1BRs.js +1 -0
  113. zenml/zen_server/dashboard/assets/CopyButton-DVwLkafa.js +2 -0
  114. zenml/zen_server/dashboard/assets/{CsvVizualization-BOuez-fG.js → CsvVizualization-C2IiqX4I.js} +7 -7
  115. zenml/zen_server/dashboard/assets/DisplayDate-DYgIjlDF.js +1 -0
  116. zenml/zen_server/dashboard/assets/EmptyState-BMLnFVlB.js +1 -0
  117. zenml/zen_server/dashboard/assets/Error-CqX0VqW_.js +1 -0
  118. zenml/zen_server/dashboard/assets/ExecutionStatus-BoLUXR9t.js +1 -0
  119. zenml/zen_server/dashboard/assets/Helpbox-LFydyVwh.js +1 -0
  120. zenml/zen_server/dashboard/assets/Infobox-DnENC0sh.js +1 -0
  121. zenml/zen_server/dashboard/assets/InlineAvatar-CbJtYr0t.js +1 -0
  122. zenml/zen_server/dashboard/assets/{MarkdownVisualization-DsB2QZiK.js → MarkdownVisualization-xp3hhULl.js} +2 -2
  123. zenml/zen_server/dashboard/assets/Pagination-DEbVUupy.js +1 -0
  124. zenml/zen_server/dashboard/assets/PasswordChecker-DUveqlva.js +1 -0
  125. zenml/zen_server/dashboard/assets/SetPassword-BYBdbQDo.js +1 -0
  126. zenml/zen_server/dashboard/assets/SuccessStep-Nx743hll.js +1 -0
  127. zenml/zen_server/dashboard/assets/{UpdatePasswordSchemas-DnM-c11H.js → UpdatePasswordSchemas-DF9gSzE0.js} +1 -1
  128. zenml/zen_server/dashboard/assets/{aws-t0gKCj_R.js → aws-BgKTfTfx.js} +1 -1
  129. zenml/zen_server/dashboard/assets/{check-circle-BVvhm5dy.js → check-circle-i56092KI.js} +1 -1
  130. zenml/zen_server/dashboard/assets/{chevron-down-zcvCWmyP.js → chevron-down-D_ZlKMqH.js} +1 -1
  131. zenml/zen_server/dashboard/assets/{chevron-right-double-CJ50E9Gr.js → chevron-right-double-BiEMg7rd.js} +1 -1
  132. zenml/zen_server/dashboard/assets/cloud-only-DVbIeckv.js +1 -0
  133. zenml/zen_server/dashboard/assets/{copy-BRhQz3j-.js → copy-BXNk6BjL.js} +1 -1
  134. zenml/zen_server/dashboard/assets/{database-CRRnyFWh.js → database-1xWSgZfO.js} +1 -1
  135. zenml/zen_server/dashboard/assets/{docker-BAonhm6G.js → docker-CQMVm_4d.js} +1 -1
  136. zenml/zen_server/dashboard/assets/{file-text-CbVERUON.js → file-text-CqD_iu6l.js} +1 -1
  137. zenml/zen_server/dashboard/assets/{help-B8rqCvqn.js → help-bu_DgLKI.js} +1 -1
  138. zenml/zen_server/dashboard/assets/index-C_CrU4vI.js +1 -0
  139. zenml/zen_server/dashboard/assets/index-DK1ynKjA.js +55 -0
  140. zenml/zen_server/dashboard/assets/index-inApY3KQ.css +1 -0
  141. zenml/zen_server/dashboard/assets/index-rK_Wuy2W.js +1 -0
  142. zenml/zen_server/dashboard/assets/index.esm-Corw4lXQ.js +1 -0
  143. zenml/zen_server/dashboard/assets/{login-mutation-wzzl23C6.js → login-mutation-BUnVASxp.js} +1 -1
  144. zenml/zen_server/dashboard/assets/not-found-B4VnX8gK.js +1 -0
  145. zenml/zen_server/dashboard/assets/package-CsUhPmou.js +1 -0
  146. zenml/zen_server/dashboard/assets/{page-BmkSiYeQ.js → page-3efNCDeb.js} +2 -2
  147. zenml/zen_server/dashboard/assets/page-7zTHbhhI.js +1 -0
  148. zenml/zen_server/dashboard/assets/page-BEs6jK71.js +1 -0
  149. zenml/zen_server/dashboard/assets/page-BpSqIf4B.js +1 -0
  150. zenml/zen_server/dashboard/assets/{page-AQKopn_4.js → page-Bx6o0ARS.js} +1 -1
  151. zenml/zen_server/dashboard/assets/page-C43QGHTt.js +9 -0
  152. zenml/zen_server/dashboard/assets/page-CR0OG7ss.js +1 -0
  153. zenml/zen_server/dashboard/assets/page-CRTJ0UuR.js +1 -0
  154. zenml/zen_server/dashboard/assets/page-CUZIGO-3.js +1 -0
  155. zenml/zen_server/dashboard/assets/page-CaopxiU1.js +1 -0
  156. zenml/zen_server/dashboard/assets/{page-CuT1SUik.js → page-Cx67M0QT.js} +1 -1
  157. zenml/zen_server/dashboard/assets/page-D7Z399xy.js +1 -0
  158. zenml/zen_server/dashboard/assets/page-D93kd7Xj.js +1 -0
  159. zenml/zen_server/dashboard/assets/{page-BzVZGExK.js → page-DKlIdAe5.js} +1 -1
  160. zenml/zen_server/dashboard/assets/{page-Bi5AI0S7.js → page-DMOYZppS.js} +1 -1
  161. zenml/zen_server/dashboard/assets/page-DMsSn3dv.js +2 -0
  162. zenml/zen_server/dashboard/assets/{page-BW6Ket3a.js → page-Dc_7KMQE.js} +1 -1
  163. zenml/zen_server/dashboard/assets/page-DvCvroOM.js +1 -0
  164. zenml/zen_server/dashboard/assets/page-Hus2pr9T.js +1 -0
  165. zenml/zen_server/dashboard/assets/page-JyfeDUfu.js +1 -0
  166. zenml/zen_server/dashboard/assets/{page-yN4rZ-ZS.js → page-Sxn82W-5.js} +1 -1
  167. zenml/zen_server/dashboard/assets/page-TKXERe16.js +1 -0
  168. zenml/zen_server/dashboard/assets/page-Xu8JEjSU.js +1 -0
  169. zenml/zen_server/dashboard/assets/{play-circle-DK5QMJyp.js → play-circle-CNtZKDnW.js} +1 -1
  170. zenml/zen_server/dashboard/assets/plus-DOeLmm7C.js +1 -0
  171. zenml/zen_server/dashboard/assets/{terminal-B2ovgWuz.js → terminal-By9cErXc.js} +1 -1
  172. zenml/zen_server/dashboard/assets/{update-server-settings-mutation-0Wgz8pUE.js → update-server-settings-mutation-CR8e3Sir.js} +1 -1
  173. zenml/zen_server/dashboard/assets/{url-6_xv0WJS.js → url-DuQMeqYA.js} +1 -1
  174. zenml/zen_server/dashboard/assets/{zod-DrZvVLjd.js → zod-BhoGpZ63.js} +1 -1
  175. zenml/zen_server/dashboard/index.html +7 -7
  176. zenml/zen_server/dashboard_legacy/asset-manifest.json +4 -4
  177. zenml/zen_server/dashboard_legacy/index.html +1 -1
  178. zenml/zen_server/dashboard_legacy/{precache-manifest.f4abc5b7cfa7d90c1caf5521918e29a8.js → precache-manifest.c8c57fb0d2132b1d3c2119e776b7dfb3.js} +4 -4
  179. zenml/zen_server/dashboard_legacy/service-worker.js +1 -1
  180. zenml/zen_server/dashboard_legacy/static/js/{main.ac2f17d0.chunk.js → main.382439a7.chunk.js} +2 -2
  181. zenml/zen_server/dashboard_legacy/static/js/{main.ac2f17d0.chunk.js.map → main.382439a7.chunk.js.map} +1 -1
  182. zenml/zen_server/deploy/helm/Chart.yaml +1 -1
  183. zenml/zen_server/deploy/helm/README.md +2 -2
  184. zenml/zen_server/feature_gate/zenml_cloud_feature_gate.py +11 -5
  185. zenml/zen_server/pipeline_deployment/utils.py +57 -44
  186. zenml/zen_server/rbac/models.py +1 -0
  187. zenml/zen_server/rbac/utils.py +22 -1
  188. zenml/zen_server/rbac/zenml_cloud_rbac.py +11 -5
  189. zenml/zen_server/routers/actions_endpoints.py +324 -0
  190. zenml/zen_server/routers/stack_deployment_endpoints.py +158 -0
  191. zenml/zen_server/routers/triggers_endpoints.py +30 -158
  192. zenml/zen_server/routers/workspaces_endpoints.py +64 -0
  193. zenml/zen_server/zen_server_api.py +4 -0
  194. zenml/zen_stores/migrations/utils.py +1 -1
  195. zenml/zen_stores/migrations/versions/0.60.0_release.py +23 -0
  196. zenml/zen_stores/migrations/versions/0.61.0_release.py +23 -0
  197. zenml/zen_stores/migrations/versions/0d707865f404_adding_labels_to_stacks.py +30 -0
  198. zenml/zen_stores/migrations/versions/25155145c545_separate_actions_and_triggers.py +228 -0
  199. zenml/zen_stores/rest_zen_store.py +248 -8
  200. zenml/zen_stores/schemas/__init__.py +2 -0
  201. zenml/zen_stores/schemas/action_schemas.py +192 -0
  202. zenml/zen_stores/schemas/stack_schemas.py +10 -0
  203. zenml/zen_stores/schemas/step_run_schemas.py +27 -11
  204. zenml/zen_stores/schemas/trigger_schemas.py +43 -50
  205. zenml/zen_stores/schemas/user_schemas.py +10 -2
  206. zenml/zen_stores/schemas/workspace_schemas.py +5 -0
  207. zenml/zen_stores/sql_zen_store.py +540 -36
  208. zenml/zen_stores/zen_store_interface.py +165 -0
  209. {zenml_nightly-0.58.2.dev20240623.dist-info → zenml_nightly-0.61.0.dev20240712.dist-info}/METADATA +33 -11
  210. {zenml_nightly-0.58.2.dev20240623.dist-info → zenml_nightly-0.61.0.dev20240712.dist-info}/RECORD +213 -193
  211. zenml/zen_server/dashboard/assets/@radix-C9DBgJhe.js +0 -77
  212. zenml/zen_server/dashboard/assets/@tanstack-CEbkxrhX.js +0 -30
  213. zenml/zen_server/dashboard/assets/AwarenessChannel-nXGpmj_f.js +0 -1
  214. zenml/zen_server/dashboard/assets/Cards-nwsvQLVS.js +0 -1
  215. zenml/zen_server/dashboard/assets/Commands-DuIWKg_Q.js +0 -1
  216. zenml/zen_server/dashboard/assets/CopyButton-B_YSm-Ds.js +0 -2
  217. zenml/zen_server/dashboard/assets/DisplayDate-BdguISQF.js +0 -1
  218. zenml/zen_server/dashboard/assets/EmptyState-BkooiGtL.js +0 -1
  219. zenml/zen_server/dashboard/assets/Error-B6M0dPph.js +0 -1
  220. zenml/zen_server/dashboard/assets/Helpbox-BQoqCm04.js +0 -1
  221. zenml/zen_server/dashboard/assets/Infobox-Ce9mefqU.js +0 -1
  222. zenml/zen_server/dashboard/assets/InlineAvatar-DGf3dVhV.js +0 -1
  223. zenml/zen_server/dashboard/assets/PageHeader-DGaemzjc.js +0 -1
  224. zenml/zen_server/dashboard/assets/Pagination-DVYfBCCc.js +0 -1
  225. zenml/zen_server/dashboard/assets/PasswordChecker-DSLBp7Vl.js +0 -1
  226. zenml/zen_server/dashboard/assets/SetPassword-B5s7DJug.js +0 -1
  227. zenml/zen_server/dashboard/assets/SuccessStep-ZzczaM7g.js +0 -1
  228. zenml/zen_server/dashboard/assets/cloud-only-Ba_ShBR5.js +0 -1
  229. zenml/zen_server/dashboard/assets/index-CWJ3xbIf.css +0 -1
  230. zenml/zen_server/dashboard/assets/index-QORVVTMN.js +0 -55
  231. zenml/zen_server/dashboard/assets/index.esm-F7nqy9zY.js +0 -1
  232. zenml/zen_server/dashboard/assets/not-found-Dh2la7kh.js +0 -1
  233. zenml/zen_server/dashboard/assets/page-B-5jAKoO.js +0 -1
  234. zenml/zen_server/dashboard/assets/page-B-vWk8a6.js +0 -1
  235. zenml/zen_server/dashboard/assets/page-B0BrqfS8.js +0 -1
  236. zenml/zen_server/dashboard/assets/page-BQxVFlUl.js +0 -1
  237. zenml/zen_server/dashboard/assets/page-ByrHy6Ss.js +0 -1
  238. zenml/zen_server/dashboard/assets/page-CPtY4Kv_.js +0 -1
  239. zenml/zen_server/dashboard/assets/page-CmmukLsl.js +0 -1
  240. zenml/zen_server/dashboard/assets/page-D2D-7qyr.js +0 -9
  241. zenml/zen_server/dashboard/assets/page-DAQQyLxT.js +0 -1
  242. zenml/zen_server/dashboard/assets/page-DHkUMl_E.js +0 -1
  243. zenml/zen_server/dashboard/assets/page-DZCbwOEs.js +0 -2
  244. zenml/zen_server/dashboard/assets/page-DdaIt20-.js +0 -1
  245. zenml/zen_server/dashboard/assets/page-LqLs24Ot.js +0 -1
  246. zenml/zen_server/dashboard/assets/page-lebv0c7C.js +0 -1
  247. {zenml_nightly-0.58.2.dev20240623.dist-info → zenml_nightly-0.61.0.dev20240712.dist-info}/LICENSE +0 -0
  248. {zenml_nightly-0.58.2.dev20240623.dist-info → zenml_nightly-0.61.0.dev20240712.dist-info}/WHEEL +0 -0
  249. {zenml_nightly-0.58.2.dev20240623.dist-info → zenml_nightly-0.61.0.dev20240712.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,228 @@
1
+ """Separate actions and triggers [25155145c545].
2
+
3
+ Revision ID: 25155145c545
4
+ Revises: 0.58.2
5
+ Create Date: 2024-05-16 11:29:53.341275
6
+
7
+ """
8
+
9
+ from datetime import datetime
10
+ from uuid import uuid4
11
+
12
+ import sqlalchemy as sa
13
+ import sqlmodel
14
+ from alembic import op
15
+
16
+ # revision identifiers, used by Alembic.
17
+ revision = "25155145c545"
18
+ down_revision = "0.58.2"
19
+ branch_labels = None
20
+ depends_on = None
21
+
22
+
23
+ def migrate_actions() -> None:
24
+ """Migrate actions from the trigger table."""
25
+ conn = op.get_bind()
26
+ meta = sa.MetaData()
27
+ meta.reflect(only=("trigger", "action"), bind=op.get_bind())
28
+ trigger_table = sa.Table("trigger", meta)
29
+ action_table = sa.Table("action", meta)
30
+
31
+ triggers = conn.execute(
32
+ sa.select(
33
+ trigger_table.c.id,
34
+ trigger_table.c.name,
35
+ trigger_table.c.user_id,
36
+ trigger_table.c.workspace_id,
37
+ trigger_table.c.service_account_id,
38
+ trigger_table.c.auth_window,
39
+ trigger_table.c.action,
40
+ trigger_table.c.action_subtype,
41
+ trigger_table.c.action_flavor,
42
+ )
43
+ ).fetchall()
44
+
45
+ now = datetime.utcnow()
46
+
47
+ actions_to_insert = []
48
+ trigger_updates = {}
49
+ for trigger in triggers:
50
+ action_id = str(uuid4()).replace("-", "")
51
+
52
+ actions_to_insert.append(
53
+ {
54
+ "id": action_id,
55
+ "workspace_id": trigger.workspace_id,
56
+ "user_id": trigger.user_id,
57
+ "created": now,
58
+ "updated": now,
59
+ "name": f"{trigger.name}_action",
60
+ "description": f"Automatically migrated action for trigger {trigger.name}",
61
+ "service_account_id": trigger.service_account_id,
62
+ "auth_window": trigger.auth_window,
63
+ "configuration": trigger.action,
64
+ "flavor": trigger.action_flavor,
65
+ "plugin_subtype": trigger.action_subtype,
66
+ }
67
+ )
68
+
69
+ trigger_updates[trigger.id] = action_id
70
+
71
+ op.bulk_insert(action_table, actions_to_insert)
72
+
73
+ for trigger_id, action_id in trigger_updates.items():
74
+ query = (
75
+ sa.update(trigger_table)
76
+ .where(trigger_table.c.id.is_(trigger_id))
77
+ .values(action_id=action_id)
78
+ )
79
+ conn.execute(query)
80
+
81
+
82
+ def upgrade() -> None:
83
+ """Upgrade database schema and/or data, creating a new revision."""
84
+ # ### commands auto generated by Alembic - please adjust! ###
85
+ op.create_table(
86
+ "action",
87
+ sa.Column(
88
+ "workspace_id", sqlmodel.sql.sqltypes.GUID(), nullable=False
89
+ ),
90
+ sa.Column("user_id", sqlmodel.sql.sqltypes.GUID(), nullable=True),
91
+ sa.Column(
92
+ "service_account_id", sqlmodel.sql.sqltypes.GUID(), nullable=False
93
+ ),
94
+ sa.Column("description", sa.TEXT(), nullable=True),
95
+ sa.Column("id", sqlmodel.sql.sqltypes.GUID(), nullable=False),
96
+ sa.Column("created", sa.DateTime(), nullable=False),
97
+ sa.Column("updated", sa.DateTime(), nullable=False),
98
+ sa.Column("name", sqlmodel.sql.sqltypes.AutoString(), nullable=False),
99
+ sa.Column("auth_window", sa.Integer(), nullable=False),
100
+ sa.Column(
101
+ "flavor", sqlmodel.sql.sqltypes.AutoString(), nullable=False
102
+ ),
103
+ sa.Column(
104
+ "plugin_subtype",
105
+ sqlmodel.sql.sqltypes.AutoString(),
106
+ nullable=False,
107
+ ),
108
+ sa.Column("configuration", sa.LargeBinary(), nullable=False),
109
+ sa.ForeignKeyConstraint(
110
+ ["service_account_id"],
111
+ ["user.id"],
112
+ name="fk_action_service_account_id_user",
113
+ ondelete="CASCADE",
114
+ ),
115
+ sa.ForeignKeyConstraint(
116
+ ["user_id"],
117
+ ["user.id"],
118
+ name="fk_action_user_id_user",
119
+ ondelete="SET NULL",
120
+ ),
121
+ sa.ForeignKeyConstraint(
122
+ ["workspace_id"],
123
+ ["workspace.id"],
124
+ name="fk_action_workspace_id_workspace",
125
+ ondelete="CASCADE",
126
+ ),
127
+ sa.PrimaryKeyConstraint("id"),
128
+ )
129
+
130
+ # Add the action_id column as nullable until we migrate the actions into
131
+ # a separate table
132
+ with op.batch_alter_table("trigger", schema=None) as batch_op:
133
+ batch_op.add_column(
134
+ sa.Column("action_id", sqlmodel.sql.sqltypes.GUID(), nullable=True)
135
+ )
136
+
137
+ migrate_actions()
138
+
139
+ with op.batch_alter_table("trigger", schema=None) as batch_op:
140
+ # Make the action_id column non-nullable now that we've inserted the
141
+ # actions and the value is set for each row
142
+ batch_op.alter_column(
143
+ "action_id",
144
+ existing_type=sqlmodel.sql.sqltypes.GUID(),
145
+ existing_nullable=True,
146
+ nullable=False,
147
+ )
148
+
149
+ batch_op.add_column(
150
+ sa.Column("schedule", sa.LargeBinary(), nullable=True)
151
+ )
152
+ batch_op.alter_column(
153
+ "event_source_id", existing_type=sa.CHAR(length=32), nullable=True
154
+ )
155
+ batch_op.drop_constraint(
156
+ "fk_trigger_event_source_id_event_source", type_="foreignkey"
157
+ )
158
+ batch_op.drop_constraint(
159
+ "fk_trigger_service_account_id_user", type_="foreignkey"
160
+ )
161
+ batch_op.create_foreign_key(
162
+ "fk_trigger_event_source_id_event_source",
163
+ "event_source",
164
+ ["event_source_id"],
165
+ ["id"],
166
+ ondelete="SET NULL",
167
+ )
168
+ batch_op.create_foreign_key(
169
+ "fk_trigger_action_id_action",
170
+ "action",
171
+ ["action_id"],
172
+ ["id"],
173
+ ondelete="CASCADE",
174
+ )
175
+ batch_op.drop_column("action_subtype")
176
+ batch_op.drop_column("action_flavor")
177
+ batch_op.drop_column("action")
178
+ batch_op.drop_column("auth_window")
179
+ batch_op.drop_column("service_account_id")
180
+
181
+ # ### end Alembic commands ###
182
+
183
+
184
+ def downgrade() -> None:
185
+ """Downgrade database schema and/or data back to the previous revision."""
186
+ # ### commands auto generated by Alembic - please adjust! ###
187
+ with op.batch_alter_table("trigger", schema=None) as batch_op:
188
+ batch_op.add_column(
189
+ sa.Column("service_account_id", sa.CHAR(length=32), nullable=False)
190
+ )
191
+ batch_op.add_column(
192
+ sa.Column("auth_window", sa.INTEGER(), nullable=False)
193
+ )
194
+ batch_op.add_column(sa.Column("action", sa.BLOB(), nullable=False))
195
+ batch_op.add_column(
196
+ sa.Column("action_flavor", sa.VARCHAR(), nullable=False)
197
+ )
198
+ batch_op.add_column(
199
+ sa.Column("action_subtype", sa.VARCHAR(), nullable=False)
200
+ )
201
+ batch_op.drop_constraint(
202
+ "fk_trigger_action_id_action", type_="foreignkey"
203
+ )
204
+ batch_op.drop_constraint(
205
+ "fk_trigger_event_source_id_event_source", type_="foreignkey"
206
+ )
207
+ batch_op.create_foreign_key(
208
+ "fk_trigger_service_account_id_user",
209
+ "user",
210
+ ["service_account_id"],
211
+ ["id"],
212
+ ondelete="CASCADE",
213
+ )
214
+ batch_op.create_foreign_key(
215
+ "fk_trigger_event_source_id_event_source",
216
+ "event_source",
217
+ ["event_source_id"],
218
+ ["id"],
219
+ ondelete="CASCADE",
220
+ )
221
+ batch_op.alter_column(
222
+ "event_source_id", existing_type=sa.CHAR(length=32), nullable=False
223
+ )
224
+ batch_op.drop_column("schedule")
225
+ batch_op.drop_column("action_id")
226
+
227
+ op.drop_table("action")
228
+ # ### end Alembic commands ###
@@ -15,6 +15,7 @@
15
15
 
16
16
  import os
17
17
  import re
18
+ from datetime import datetime
18
19
  from pathlib import Path
19
20
  from typing import (
20
21
  Any,
@@ -47,6 +48,7 @@ from zenml.config.global_config import GlobalConfiguration
47
48
  from zenml.config.pipeline_run_configuration import PipelineRunConfiguration
48
49
  from zenml.config.store_config import StoreConfiguration
49
50
  from zenml.constants import (
51
+ ACTIONS,
50
52
  API,
51
53
  API_KEY_ROTATE,
52
54
  API_KEYS,
@@ -56,6 +58,7 @@ from zenml.constants import (
56
58
  ARTIFACTS,
57
59
  CODE_REFERENCES,
58
60
  CODE_REPOSITORIES,
61
+ CONFIG,
59
62
  CURRENT_USER,
60
63
  DEACTIVATE,
61
64
  DEFAULT_HTTP_TIMEOUT,
@@ -64,6 +67,7 @@ from zenml.constants import (
64
67
  ENV_ZENML_DISABLE_CLIENT_SERVER_MISMATCH_WARNING,
65
68
  EVENT_SOURCES,
66
69
  FLAVORS,
70
+ FULL_STACK,
67
71
  GET_OR_CREATE,
68
72
  INFO,
69
73
  LOGIN,
@@ -88,9 +92,12 @@ from zenml.constants import (
88
92
  SERVICE_CONNECTOR_RESOURCES,
89
93
  SERVICE_CONNECTOR_TYPES,
90
94
  SERVICE_CONNECTOR_VERIFY,
95
+ SERVICE_CONNECTOR_VERIFY_REQUEST_TIMEOUT,
91
96
  SERVICE_CONNECTORS,
92
97
  SERVICES,
98
+ STACK,
93
99
  STACK_COMPONENTS,
100
+ STACK_DEPLOYMENT,
94
101
  STACKS,
95
102
  STEPS,
96
103
  TAGS,
@@ -102,12 +109,17 @@ from zenml.constants import (
102
109
  )
103
110
  from zenml.enums import (
104
111
  OAuthGrantTypes,
112
+ StackDeploymentProvider,
105
113
  StoreType,
106
114
  )
107
115
  from zenml.exceptions import AuthorizationException, MethodNotAllowedError
108
116
  from zenml.io import fileio
109
117
  from zenml.logger import get_logger
110
118
  from zenml.models import (
119
+ ActionFilter,
120
+ ActionRequest,
121
+ ActionResponse,
122
+ ActionUpdate,
111
123
  APIKeyFilter,
112
124
  APIKeyRequest,
113
125
  APIKeyResponse,
@@ -134,6 +146,7 @@ from zenml.models import (
134
146
  ComponentRequest,
135
147
  ComponentResponse,
136
148
  ComponentUpdate,
149
+ DeployedStack,
137
150
  EventSourceFilter,
138
151
  EventSourceRequest,
139
152
  EventSourceResponse,
@@ -142,6 +155,7 @@ from zenml.models import (
142
155
  FlavorRequest,
143
156
  FlavorResponse,
144
157
  FlavorUpdate,
158
+ FullStackRequest,
145
159
  LogsResponse,
146
160
  ModelFilter,
147
161
  ModelRequest,
@@ -203,6 +217,8 @@ from zenml.models import (
203
217
  ServiceRequest,
204
218
  ServiceResponse,
205
219
  ServiceUpdate,
220
+ StackDeploymentConfig,
221
+ StackDeploymentInfo,
206
222
  StackFilter,
207
223
  StackRequest,
208
224
  StackResponse,
@@ -480,6 +496,100 @@ class RestZenStore(BaseZenStore):
480
496
  response_body = self.put(SERVER_SETTINGS, body=settings_update)
481
497
  return ServerSettingsResponse.model_validate(response_body)
482
498
 
499
+ # -------------------- Actions --------------------
500
+
501
+ def create_action(self, action: ActionRequest) -> ActionResponse:
502
+ """Create an action.
503
+
504
+ Args:
505
+ action: The action to create.
506
+
507
+ Returns:
508
+ The created action.
509
+ """
510
+ return self._create_resource(
511
+ resource=action,
512
+ route=ACTIONS,
513
+ response_model=ActionResponse,
514
+ )
515
+
516
+ def get_action(
517
+ self,
518
+ action_id: UUID,
519
+ hydrate: bool = True,
520
+ ) -> ActionResponse:
521
+ """Get an action by ID.
522
+
523
+ Args:
524
+ action_id: The ID of the action to get.
525
+ hydrate: Flag deciding whether to hydrate the output model(s)
526
+ by including metadata fields in the response.
527
+
528
+ Returns:
529
+ The action.
530
+ """
531
+ return self._get_resource(
532
+ resource_id=action_id,
533
+ route=ACTIONS,
534
+ response_model=ActionResponse,
535
+ params={"hydrate": hydrate},
536
+ )
537
+
538
+ def list_actions(
539
+ self,
540
+ action_filter_model: ActionFilter,
541
+ hydrate: bool = False,
542
+ ) -> Page[ActionResponse]:
543
+ """List all actions matching the given filter criteria.
544
+
545
+ Args:
546
+ action_filter_model: All filter parameters including pagination
547
+ params.
548
+ hydrate: Flag deciding whether to hydrate the output model(s)
549
+ by including metadata fields in the response.
550
+
551
+ Returns:
552
+ A list of all actions matching the filter criteria.
553
+ """
554
+ return self._list_paginated_resources(
555
+ route=ACTIONS,
556
+ response_model=ActionResponse,
557
+ filter_model=action_filter_model,
558
+ params={"hydrate": hydrate},
559
+ )
560
+
561
+ def update_action(
562
+ self,
563
+ action_id: UUID,
564
+ action_update: ActionUpdate,
565
+ ) -> ActionResponse:
566
+ """Update an existing action.
567
+
568
+ Args:
569
+ action_id: The ID of the action to update.
570
+ action_update: The update to be applied to the action.
571
+
572
+ Returns:
573
+ The updated action.
574
+ """
575
+ return self._update_resource(
576
+ resource_id=action_id,
577
+ resource_update=action_update,
578
+ route=ACTIONS,
579
+ response_model=ActionResponse,
580
+ )
581
+
582
+ def delete_action(self, action_id: UUID) -> None:
583
+ """Delete an action.
584
+
585
+ Args:
586
+ action_id: The ID of the action to delete.
587
+ """
588
+ self._delete_resource(
589
+ resource_id=action_id,
590
+ route=ACTIONS,
591
+ )
592
+
483
593
  # ----------------------------- API Keys -----------------------------
484
594
 
485
595
  def create_api_key(
@@ -1434,14 +1544,14 @@ class RestZenStore(BaseZenStore):
1434
1544
  run_configuration = run_configuration or PipelineRunConfiguration()
1435
1545
  try:
1436
1546
  response_body = self.post(
1437
- f"{PIPELINE_BUILDS}/{build_id}/run", body=run_configuration
1547
+ f"{PIPELINE_BUILDS}/{build_id}/runs", body=run_configuration
1438
1548
  )
1439
1549
  except MethodNotAllowedError as e:
1440
1550
  raise RuntimeError(
1441
1551
  "Running a build is not supported for this server."
1442
1552
  ) from e
1443
1553
 
1444
- return PipelineRunResponse.parse_obj(response_body)
1554
+ return PipelineRunResponse.model_validate(response_body)
1445
1555
 
1446
1556
  # -------------------------- Pipeline Deployments --------------------------
1447
1557
 
@@ -1538,7 +1648,7 @@ class RestZenStore(BaseZenStore):
1538
1648
 
1539
1649
  try:
1540
1650
  response_body = self.post(
1541
- f"{PIPELINE_DEPLOYMENTS}/{deployment_id}/run",
1651
+ f"{PIPELINE_DEPLOYMENTS}/{deployment_id}/runs",
1542
1652
  body=run_configuration,
1543
1653
  )
1544
1654
  except MethodNotAllowedError as e:
@@ -1546,7 +1656,7 @@ class RestZenStore(BaseZenStore):
1546
1656
  "Running a deployment is not supported for this server."
1547
1657
  ) from e
1548
1658
 
1549
- return PipelineRunResponse.parse_obj(response_body)
1659
+ return PipelineRunResponse.model_validate(response_body)
1550
1660
 
1551
1661
  # -------------------- Event Sources --------------------
1552
1662
 
@@ -2368,6 +2478,10 @@ class RestZenStore(BaseZenStore):
2368
2478
  f"{SERVICE_CONNECTORS}{SERVICE_CONNECTOR_VERIFY}",
2369
2479
  body=service_connector,
2370
2480
  params={"list_resources": list_resources},
2481
+ timeout=max(
2482
+ self.config.http_timeout,
2483
+ SERVICE_CONNECTOR_VERIFY_REQUEST_TIMEOUT,
2484
+ ),
2371
2485
  )
2372
2486
 
2373
2487
  resources = ServiceConnectorResourcesModel.model_validate(
@@ -2405,6 +2519,10 @@ class RestZenStore(BaseZenStore):
2405
2519
  response_body = self.put(
2406
2520
  f"{SERVICE_CONNECTORS}/{str(service_connector_id)}{SERVICE_CONNECTOR_VERIFY}",
2407
2521
  params=params,
2522
+ timeout=max(
2523
+ self.config.http_timeout,
2524
+ SERVICE_CONNECTOR_VERIFY_REQUEST_TIMEOUT,
2525
+ ),
2408
2526
  )
2409
2527
 
2410
2528
  resources = ServiceConnectorResourcesModel.model_validate(
@@ -2645,6 +2763,23 @@ class RestZenStore(BaseZenStore):
2645
2763
  response_model=StackResponse,
2646
2764
  )
2647
2765
 
2766
+ def create_full_stack(self, full_stack: FullStackRequest) -> StackResponse:
2767
+ """Register a full-stack.
2768
+
2769
+ Args:
2770
+ full_stack: The full stack configuration.
2771
+
2772
+ Returns:
2773
+ The registered stack.
2774
+ """
2775
+ assert full_stack.workspace is not None
2776
+
2777
+ return self._create_resource(
2778
+ resource=full_stack,
2779
+ response_model=StackResponse,
2780
+ route=f"{WORKSPACES}/{str(full_stack.workspace)}{FULL_STACK}",
2781
+ )
2782
+
2648
2783
  def get_stack(self, stack_id: UUID, hydrate: bool = True) -> StackResponse:
2649
2784
  """Get a stack by its unique ID.
2650
2785
 
@@ -2714,6 +2849,88 @@ class RestZenStore(BaseZenStore):
2714
2849
  route=STACKS,
2715
2850
  )
2716
2851
 
2852
+ # ---------------- Stack deployments-----------------
2853
+
2854
+ def get_stack_deployment_info(
2855
+ self,
2856
+ provider: StackDeploymentProvider,
2857
+ ) -> StackDeploymentInfo:
2858
+ """Get information about a stack deployment provider.
2859
+
2860
+ Args:
2861
+ provider: The stack deployment provider.
2862
+
2863
+ Returns:
2864
+ Information about the stack deployment provider.
2865
+ """
2866
+ body = self.get(
2867
+ f"{STACK_DEPLOYMENT}{INFO}",
2868
+ params={"provider": provider.value},
2869
+ )
2870
+ return StackDeploymentInfo.model_validate(body)
2871
+
2872
+ def get_stack_deployment_config(
2873
+ self,
2874
+ provider: StackDeploymentProvider,
2875
+ stack_name: str,
2876
+ location: Optional[str] = None,
2877
+ ) -> StackDeploymentConfig:
2878
+ """Return the cloud provider console URL and configuration needed to deploy the ZenML stack.
2879
+
2880
+ Args:
2881
+ provider: The stack deployment provider.
2882
+ stack_name: The name of the stack.
2883
+ location: The location where the stack should be deployed.
2884
+
2885
+ Returns:
2886
+ The cloud provider console URL and configuration needed to deploy
2887
+ the ZenML stack to the specified cloud provider.
2888
+ """
2889
+ params = {
2890
+ "provider": provider.value,
2891
+ "stack_name": stack_name,
2892
+ }
2893
+ if location:
2894
+ params["location"] = location
2895
+ body = self.get(f"{STACK_DEPLOYMENT}{CONFIG}", params=params)
2896
+ return StackDeploymentConfig.model_validate(body)
2897
+
2898
+ def get_stack_deployment_stack(
2899
+ self,
2900
+ provider: StackDeploymentProvider,
2901
+ stack_name: str,
2902
+ location: Optional[str] = None,
2903
+ date_start: Optional[datetime] = None,
2904
+ ) -> Optional[DeployedStack]:
2905
+ """Return a matching ZenML stack that was deployed and registered.
2906
+
2907
+ Args:
2908
+ provider: The stack deployment provider.
2909
+ stack_name: The name of the stack.
2910
+ location: The location where the stack should be deployed.
2911
+ date_start: The date when the deployment started.
2912
+
2913
+ Returns:
2914
+ The ZenML stack that was deployed and registered or None if the
2915
+ stack was not found.
2916
+ """
2917
+ params = {
2918
+ "provider": provider.value,
2919
+ "stack_name": stack_name,
2920
+ }
2921
+ if location:
2922
+ params["location"] = location
2923
+ if date_start:
2924
+ params["date_start"] = str(date_start)
2925
+ body = self.get(
2926
+ f"{STACK_DEPLOYMENT}{STACK}",
2927
+ params=params,
2928
+ )
2929
+ if body:
2930
+ return DeployedStack.model_validate(body)
2931
+
2932
+ return None
2933
+
2717
2934
  # ----------------------------- Step runs -----------------------------
2718
2935
 
2719
2936
  def create_run_step(self, step_run: StepRunRequest) -> StepRunResponse:
@@ -3865,6 +4082,7 @@ class RestZenStore(BaseZenStore):
3865
4082
  method: str,
3866
4083
  url: str,
3867
4084
  params: Optional[Dict[str, Any]] = None,
4085
+ timeout: Optional[int] = None,
3868
4086
  **kwargs: Any,
3869
4087
  ) -> Json:
3870
4088
  """Make a request to the REST API.
@@ -3873,6 +4091,7 @@ class RestZenStore(BaseZenStore):
3873
4091
  method: The HTTP method to use.
3874
4092
  url: The URL to request.
3875
4093
  params: The query parameters to pass to the endpoint.
4094
+ timeout: The request timeout in seconds.
3876
4095
  kwargs: Additional keyword arguments to pass to the request.
3877
4096
 
3878
4097
  Returns:
@@ -3895,7 +4114,7 @@ class RestZenStore(BaseZenStore):
3895
4114
  url,
3896
4115
  params=params,
3897
4116
  verify=self.config.verify_ssl,
3898
- timeout=self.config.http_timeout,
4117
+ timeout=timeout or self.config.http_timeout,
3899
4118
  **kwargs,
3900
4119
  )
3901
4120
  )
@@ -3924,13 +4143,18 @@ class RestZenStore(BaseZenStore):
3924
4143
  raise
3925
4144
 
3926
4145
  def get(
3927
- self, path: str, params: Optional[Dict[str, Any]] = None, **kwargs: Any
4146
+ self,
4147
+ path: str,
4148
+ params: Optional[Dict[str, Any]] = None,
4149
+ timeout: Optional[int] = None,
4150
+ **kwargs: Any,
3928
4151
  ) -> Json:
3929
4152
  """Make a GET request to the given endpoint path.
3930
4153
 
3931
4154
  Args:
3932
4155
  path: The path to the endpoint.
3933
4156
  params: The query parameters to pass to the endpoint.
4157
+ timeout: The request timeout in seconds.
3934
4158
  kwargs: Additional keyword arguments to pass to the request.
3935
4159
 
3936
4160
  Returns:
@@ -3938,17 +4162,26 @@ class RestZenStore(BaseZenStore):
3938
4162
  """
3939
4163
  logger.debug(f"Sending GET request to {path}...")
3940
4164
  return self._request(
3941
- "GET", self.url + API + VERSION_1 + path, params=params, **kwargs
4165
+ "GET",
4166
+ self.url + API + VERSION_1 + path,
4167
+ params=params,
4168
+ timeout=timeout,
4169
+ **kwargs,
3942
4170
  )
3943
4171
 
3944
4172
  def delete(
3945
- self, path: str, params: Optional[Dict[str, Any]] = None, **kwargs: Any
4173
+ self,
4174
+ path: str,
4175
+ params: Optional[Dict[str, Any]] = None,
4176
+ timeout: Optional[int] = None,
4177
+ **kwargs: Any,
3946
4178
  ) -> Json:
3947
4179
  """Make a DELETE request to the given endpoint path.
3948
4180
 
3949
4181
  Args:
3950
4182
  path: The path to the endpoint.
3951
4183
  params: The query parameters to pass to the endpoint.
4184
+ timeout: The request timeout in seconds.
3952
4185
  kwargs: Additional keyword arguments to pass to the request.
3953
4186
 
3954
4187
  Returns:
@@ -3959,6 +4192,7 @@ class RestZenStore(BaseZenStore):
3959
4192
  "DELETE",
3960
4193
  self.url + API + VERSION_1 + path,
3961
4194
  params=params,
4195
+ timeout=timeout,
3962
4196
  **kwargs,
3963
4197
  )
3964
4198
 
@@ -3967,6 +4201,7 @@ class RestZenStore(BaseZenStore):
3967
4201
  path: str,
3968
4202
  body: BaseModel,
3969
4203
  params: Optional[Dict[str, Any]] = None,
4204
+ timeout: Optional[int] = None,
3970
4205
  **kwargs: Any,
3971
4206
  ) -> Json:
3972
4207
  """Make a POST request to the given endpoint path.
@@ -3975,6 +4210,7 @@ class RestZenStore(BaseZenStore):
3975
4210
  path: The path to the endpoint.
3976
4211
  body: The body to send.
3977
4212
  params: The query parameters to pass to the endpoint.
4213
+ timeout: The request timeout in seconds.
3978
4214
  kwargs: Additional keyword arguments to pass to the request.
3979
4215
 
3980
4216
  Returns:
@@ -3986,6 +4222,7 @@ class RestZenStore(BaseZenStore):
3986
4222
  self.url + API + VERSION_1 + path,
3987
4223
  data=body.model_dump_json(),
3988
4224
  params=params,
4225
+ timeout=timeout,
3989
4226
  **kwargs,
3990
4227
  )
3991
4228
 
@@ -3994,6 +4231,7 @@ class RestZenStore(BaseZenStore):
3994
4231
  path: str,
3995
4232
  body: Optional[BaseModel] = None,
3996
4233
  params: Optional[Dict[str, Any]] = None,
4234
+ timeout: Optional[int] = None,
3997
4235
  **kwargs: Any,
3998
4236
  ) -> Json:
3999
4237
  """Make a PUT request to the given endpoint path.
@@ -4002,6 +4240,7 @@ class RestZenStore(BaseZenStore):
4002
4240
  path: The path to the endpoint.
4003
4241
  body: The body to send.
4004
4242
  params: The query parameters to pass to the endpoint.
4243
+ timeout: The request timeout in seconds.
4005
4244
  kwargs: Additional keyword arguments to pass to the request.
4006
4245
 
4007
4246
  Returns:
@@ -4014,6 +4253,7 @@ class RestZenStore(BaseZenStore):
4014
4253
  self.url + API + VERSION_1 + path,
4015
4254
  data=data,
4016
4255
  params=params,
4256
+ timeout=timeout,
4017
4257
  **kwargs,
4018
4258
  )
4019
4259