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
@@ -136,9 +136,16 @@ def generate_stack_component_describe_command(
136
136
  if active_components:
137
137
  active_component_id = active_components[0].id
138
138
 
139
+ if component_.connector:
140
+ # We also need the flavor to get the connector requirements
141
+ flavor = client.get_flavor_by_name_and_type(
142
+ name=component_.flavor, component_type=component_type
143
+ )
144
+
139
145
  cli_utils.print_stack_component_configuration(
140
146
  component=component_,
141
147
  active_status=component_.id == active_component_id,
148
+ connector_requirements=flavor.connector_requirements,
142
149
  )
143
150
 
144
151
  print_model_url(get_component_url(component_))
zenml/cli/text_utils.py CHANGED
@@ -15,7 +15,9 @@
15
15
 
16
16
  from typing import List
17
17
 
18
- from rich.markdown import Markdown
18
+ from rich.console import Console, ConsoleOptions, RenderResult
19
+ from rich.markdown import Heading, Markdown
20
+ from rich.text import Text
19
21
 
20
22
  zenml_cli_welcome_message = Markdown(
21
23
  """
@@ -82,3 +84,35 @@ links below.\n
82
84
 
83
85
  """
84
86
  )
87
+
88
+
89
+ class OldSchoolMarkdownHeading(Heading):
90
+ """A traditional markdown heading."""
91
+
92
+ def __rich_console__(
93
+ self, console: Console, options: ConsoleOptions
94
+ ) -> RenderResult:
95
+ """Render the heading.
96
+
97
+ Args:
98
+ console: The console rendering the content.
99
+ options: The console options.
100
+
101
+ Yields:
102
+ RenderResult: The rendered content.
103
+ """
104
+ text = self.text
105
+ text.justify = "left"
106
+ if self.tag == "h1":
107
+ # Underline and bold h1s
108
+ yield Text("", style="bold")
109
+ yield text
110
+ yield "=" * len(text)
111
+ else:
112
+ if self.tag == "h2":
113
+ # Just underline h2s
114
+ yield Text("", style="underline")
115
+ else:
116
+ # Just bold everything else
117
+ yield Text("", style="bold")
118
+ yield text
zenml/cli/utils.py CHANGED
@@ -17,6 +17,7 @@ import contextlib
17
17
  import datetime
18
18
  import json
19
19
  import os
20
+ import platform
20
21
  import re
21
22
  import subprocess
22
23
  import sys
@@ -43,11 +44,13 @@ import pkg_resources
43
44
  import yaml
44
45
  from pydantic import BaseModel, SecretStr
45
46
  from rich import box, table
47
+ from rich.console import Console
46
48
  from rich.emoji import Emoji, NoEmoji
47
49
  from rich.markdown import Markdown
48
50
  from rich.markup import escape
49
- from rich.prompt import Confirm
51
+ from rich.prompt import Confirm, Prompt
50
52
  from rich.style import Style
53
+ from rich.table import Table
51
54
 
52
55
  from zenml.client import Client
53
56
  from zenml.console import console, zenml_style_defaults
@@ -69,6 +72,7 @@ from zenml.models import (
69
72
  BoolFilter,
70
73
  NumericFilter,
71
74
  Page,
75
+ ServiceConnectorRequirements,
72
76
  StrFilter,
73
77
  UUIDFilter,
74
78
  )
@@ -582,6 +586,23 @@ def print_stack_configuration(stack: "StackResponse", active: bool) -> None:
582
586
  for component in rich_table.columns[0]._cells
583
587
  ]
584
588
  console.print(rich_table)
589
+
590
+ if not stack.labels:
591
+ declare("No labels are set for this stack.")
592
+ else:
593
+ rich_table = table.Table(
594
+ box=box.HEAVY_EDGE,
595
+ title="Labels",
596
+ show_lines=True,
597
+ )
598
+ rich_table.add_column("LABEL")
599
+ rich_table.add_column("VALUE", overflow="fold")
600
+
601
+ for label, value in stack.labels.items():
602
+ rich_table.add_row(label, str(value))
603
+
604
+ console.print(rich_table)
605
+
585
606
  declare(
586
607
  f"Stack '{stack.name}' with id '{stack.id}' is "
587
608
  f"{f'owned by user {stack.user.name}.' if stack.user else 'unowned.'}"
@@ -613,13 +634,18 @@ def print_flavor_list(flavors: Page["FlavorResponse"]) -> None:
613
634
 
614
635
 
615
636
  def print_stack_component_configuration(
616
- component: "ComponentResponse", active_status: bool
637
+ component: "ComponentResponse",
638
+ active_status: bool,
639
+ connector_requirements: Optional[ServiceConnectorRequirements] = None,
617
640
  ) -> None:
618
641
  """Prints the configuration options of a stack component.
619
642
 
620
643
  Args:
621
644
  component: The stack component to print.
622
645
  active_status: Whether the stack component is active.
646
+ connector_requirements: Connector requirements for the component, taken
647
+ from the component flavor. Only needed if the component has a
648
+ connector.
623
649
  """
624
650
  if component.user:
625
651
  user_name = component.user.name
@@ -675,7 +701,7 @@ def print_stack_component_configuration(
675
701
  rich_table.add_column("VALUE", overflow="fold")
676
702
 
677
703
  for label, value in component.labels.items():
678
- rich_table.add_row(label, value)
704
+ rich_table.add_row(label, str(value))
679
705
 
680
706
  console.print(rich_table)
681
707
 
@@ -690,11 +716,17 @@ def print_stack_component_configuration(
690
716
  rich_table.add_column("PROPERTY")
691
717
  rich_table.add_column("VALUE", overflow="fold")
692
718
 
719
+ resource_type = (
720
+ connector_requirements.resource_type
721
+ if connector_requirements
722
+ else component.connector.resource_types[0]
723
+ )
724
+
693
725
  connector_dict = {
694
726
  "ID": str(component.connector.id),
695
727
  "NAME": component.connector.name,
696
728
  "TYPE": component.connector.type,
697
- "RESOURCE TYPE": component.connector.resource_types[0],
729
+ "RESOURCE TYPE": resource_type,
698
730
  "RESOURCE NAME": component.connector_resource_id
699
731
  or component.connector.resource_id
700
732
  or "N/A",
@@ -1276,9 +1308,11 @@ def pretty_print_model_version_table(
1276
1308
  "NAME": model_version.registered_model.name,
1277
1309
  "MODEL_VERSION": model_version.version,
1278
1310
  "VERSION_DESCRIPTION": model_version.description,
1279
- "METADATA": model_version.metadata.model_dump()
1280
- if model_version.metadata
1281
- else {},
1311
+ "METADATA": (
1312
+ model_version.metadata.model_dump()
1313
+ if model_version.metadata
1314
+ else {}
1315
+ ),
1282
1316
  }
1283
1317
  for model_version in model_versions
1284
1318
  ]
@@ -1318,9 +1352,11 @@ def pretty_print_model_version_details(
1318
1352
  if model_version.last_updated_at
1319
1353
  else "N/A"
1320
1354
  ),
1321
- "METADATA": model_version.metadata.model_dump()
1322
- if model_version.metadata
1323
- else {},
1355
+ "METADATA": (
1356
+ model_version.metadata.model_dump()
1357
+ if model_version.metadata
1358
+ else {}
1359
+ ),
1324
1360
  "MODEL_SOURCE_URI": model_version.model_source_uri,
1325
1361
  "STAGE": model_version.stage.value,
1326
1362
  }
@@ -2748,3 +2784,84 @@ def is_jupyter_installed() -> bool:
2748
2784
  return True
2749
2785
  except pkg_resources.DistributionNotFound:
2750
2786
  return False
2787
+
2788
+
2789
+ def multi_choice_prompt(
2790
+ object_type: str,
2791
+ choices: List[List[Any]],
2792
+ headers: List[str],
2793
+ prompt_text: str,
2794
+ allow_zero_be_a_new_object: bool = False,
2795
+ default_choice: Optional[str] = None,
2796
+ ) -> Optional[int]:
2797
+ """Prompts the user to select a choice from a list of choices.
2798
+
2799
+ Args:
2800
+ object_type: The type of the object
2801
+ choices: The list of choices
2802
+ prompt_text: The prompt text
2803
+ headers: The list of headers.
2804
+ allow_zero_be_a_new_object: Whether to allow zero as a new object
2805
+ default_choice: The default choice
2806
+
2807
+ Returns:
2808
+ The selected choice index or None for new object
2809
+
2810
+ Raises:
2811
+ RuntimeError: If no choice is made.
2812
+ """
2813
+ table = Table(
2814
+ title=f"Available {object_type}",
2815
+ show_header=True,
2816
+ border_style=None,
2817
+ expand=True,
2818
+ show_lines=True,
2819
+ )
2820
+ table.add_column("Choice", justify="left", width=1)
2821
+ for h in headers:
2822
+ table.add_column(
2823
+ h.replace("_", " ").capitalize(), justify="left", width=10
2824
+ )
2825
+
2826
+ i_shift = 0
2827
+ if allow_zero_be_a_new_object:
2828
+ i_shift = 1
2829
+ table.add_row(
2830
+ "[0]",
2831
+ *([f"Create a new {object_type}"] * len(headers)),
2832
+ )
2833
+ for i, one_choice in enumerate(choices):
2834
+ table.add_row(f"[{i+i_shift}]", *[str(x) for x in one_choice])
2835
+ Console().print(table)
2836
+
2837
+ selected = Prompt.ask(
2838
+ prompt_text,
2839
+ choices=[str(i) for i in range(0, len(choices) + 1)],
2840
+ default=default_choice,
2841
+ show_choices=False,
2842
+ )
2843
+ if selected is None:
2844
+ raise RuntimeError(f"No {object_type} was selected")
2845
+
2846
+ if selected == "0" and allow_zero_be_a_new_object:
2847
+ return None
2848
+ else:
2849
+ return int(selected) - i_shift
2850
+
2851
+
2852
+ def requires_mac_env_var_warning() -> bool:
2853
+ """Checks if a warning needs to be shown for a local Mac server.
2854
+
2855
+ This is for the case where a user is on a macOS system, trying to run a
2856
+ local server but is missing the `OBJC_DISABLE_INITIALIZE_FORK_SAFETY`
2857
+ environment variable.
2858
+
2859
+ Returns:
2860
+ bool: True if a warning needs to be shown, False otherwise.
2861
+ """
2862
+ if sys.platform == "darwin":
2863
+ mac_version_tuple = tuple(map(int, platform.release().split(".")[:2]))
2864
+ return not os.getenv(
2865
+ "OBJC_DISABLE_INITIALIZE_FORK_SAFETY"
2866
+ ) and mac_version_tuple >= (10, 13)
2867
+ return False