zenml-nightly 0.60.0.dev20240627__py3-none-any.whl → 0.61.0.dev20240710__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 (210) hide show
  1. README.md +30 -9
  2. RELEASE_NOTES.md +34 -0
  3. zenml/VERSION +1 -1
  4. zenml/analytics/enums.py +3 -0
  5. zenml/cli/__init__.py +28 -0
  6. zenml/cli/artifact.py +1 -2
  7. zenml/cli/integration.py +9 -8
  8. zenml/cli/server.py +6 -0
  9. zenml/cli/stack.py +797 -39
  10. zenml/cli/stack_components.py +7 -0
  11. zenml/cli/text_utils.py +35 -1
  12. zenml/cli/utils.py +127 -10
  13. zenml/client.py +23 -14
  14. zenml/config/docker_settings.py +8 -5
  15. zenml/constants.py +5 -1
  16. zenml/container_registries/base_container_registry.py +1 -0
  17. zenml/enums.py +6 -0
  18. zenml/event_hub/event_hub.py +5 -8
  19. zenml/integrations/aws/__init__.py +1 -0
  20. zenml/integrations/azure/__init__.py +1 -0
  21. zenml/integrations/deepchecks/__init__.py +1 -0
  22. zenml/integrations/discord/__init__.py +1 -0
  23. zenml/integrations/evidently/__init__.py +1 -0
  24. zenml/integrations/facets/__init__.py +1 -0
  25. zenml/integrations/feast/__init__.py +1 -0
  26. zenml/integrations/gcp/__init__.py +3 -1
  27. zenml/integrations/gcp/service_connectors/gcp_service_connector.py +203 -44
  28. zenml/integrations/huggingface/__init__.py +1 -0
  29. zenml/integrations/integration.py +24 -0
  30. zenml/integrations/kubeflow/__init__.py +3 -0
  31. zenml/integrations/kubeflow/flavors/kubeflow_orchestrator_flavor.py +1 -1
  32. zenml/integrations/kubeflow/orchestrators/kubeflow_orchestrator.py +0 -1
  33. zenml/integrations/kubernetes/__init__.py +3 -1
  34. zenml/integrations/kubernetes/orchestrators/kube_utils.py +4 -1
  35. zenml/integrations/label_studio/annotators/label_studio_annotator.py +1 -0
  36. zenml/integrations/langchain/__init__.py +1 -0
  37. zenml/integrations/mlflow/__init__.py +3 -1
  38. zenml/integrations/neural_prophet/__init__.py +1 -0
  39. zenml/integrations/polars/__init__.py +1 -0
  40. zenml/integrations/prodigy/__init__.py +1 -0
  41. zenml/integrations/pycaret/__init__.py +6 -0
  42. zenml/integrations/registry.py +37 -0
  43. zenml/integrations/s3/artifact_stores/s3_artifact_store.py +17 -6
  44. zenml/integrations/seldon/__init__.py +1 -0
  45. zenml/integrations/seldon/model_deployers/seldon_model_deployer.py +1 -0
  46. zenml/integrations/skypilot/flavors/skypilot_orchestrator_base_vm_config.py +2 -2
  47. zenml/integrations/skypilot/orchestrators/skypilot_base_vm_orchestrator.py +1 -1
  48. zenml/integrations/skypilot/orchestrators/skypilot_orchestrator_entrypoint.py +2 -2
  49. zenml/integrations/skypilot_aws/__init__.py +2 -1
  50. zenml/integrations/skypilot_azure/__init__.py +1 -1
  51. zenml/integrations/skypilot_gcp/__init__.py +1 -1
  52. zenml/integrations/skypilot_lambda/__init__.py +1 -1
  53. zenml/integrations/skypilot_lambda/flavors/skypilot_orchestrator_lambda_vm_flavor.py +1 -1
  54. zenml/integrations/slack/__init__.py +1 -0
  55. zenml/integrations/tekton/__init__.py +1 -0
  56. zenml/integrations/tensorboard/__init__.py +0 -1
  57. zenml/integrations/tensorflow/__init__.py +18 -6
  58. zenml/integrations/wandb/__init__.py +1 -0
  59. zenml/models/__init__.py +9 -0
  60. zenml/models/v2/core/component.py +18 -0
  61. zenml/models/v2/core/model.py +1 -2
  62. zenml/models/v2/core/service_connector.py +17 -0
  63. zenml/models/v2/core/stack.py +31 -0
  64. zenml/models/v2/misc/full_stack.py +97 -0
  65. zenml/models/v2/misc/stack_deployment.py +66 -0
  66. zenml/new/pipelines/pipeline.py +1 -1
  67. zenml/orchestrators/input_utils.py +3 -6
  68. zenml/stack/stack.py +3 -6
  69. zenml/stack_deployments/__init__.py +14 -0
  70. zenml/stack_deployments/aws_stack_deployment.py +289 -0
  71. zenml/stack_deployments/stack_deployment.py +130 -0
  72. zenml/stack_deployments/utils.py +40 -0
  73. zenml/utils/function_utils.py +1 -1
  74. zenml/utils/pagination_utils.py +7 -5
  75. zenml/utils/pipeline_docker_image_builder.py +97 -68
  76. zenml/utils/pydantic_utils.py +6 -5
  77. zenml/zen_server/cloud_utils.py +18 -3
  78. zenml/zen_server/dashboard/assets/{404-C1mcUujL.js → 404-DpJaNHKF.js} +1 -1
  79. zenml/zen_server/dashboard/assets/@radix-CFOkMR_E.js +85 -0
  80. zenml/zen_server/dashboard/assets/{@react-router-DYovave8.js → @react-router-CO-OsFwI.js} +2 -2
  81. zenml/zen_server/dashboard/assets/{@reactflow-DYIyhCfd.js → @reactflow-DJfzkHO1.js} +2 -2
  82. zenml/zen_server/dashboard/assets/@tanstack-DYiOyJUL.js +22 -0
  83. zenml/zen_server/dashboard/assets/AwarenessChannel-BYDLT2xC.js +1 -0
  84. zenml/zen_server/dashboard/assets/{CodeSnippet-WEzpO0az.js → CodeSnippet-BkOuRmyq.js} +2 -2
  85. zenml/zen_server/dashboard/assets/Commands-ZvWR1BRs.js +1 -0
  86. zenml/zen_server/dashboard/assets/CopyButton-DVwLkafa.js +2 -0
  87. zenml/zen_server/dashboard/assets/{CsvVizualization-Bx931j4U.js → CsvVizualization-C2IiqX4I.js} +7 -7
  88. zenml/zen_server/dashboard/assets/DisplayDate-DYgIjlDF.js +1 -0
  89. zenml/zen_server/dashboard/assets/EmptyState-BMLnFVlB.js +1 -0
  90. zenml/zen_server/dashboard/assets/Error-CqX0VqW_.js +1 -0
  91. zenml/zen_server/dashboard/assets/ExecutionStatus-BoLUXR9t.js +1 -0
  92. zenml/zen_server/dashboard/assets/Helpbox-LFydyVwh.js +1 -0
  93. zenml/zen_server/dashboard/assets/Infobox-DnENC0sh.js +1 -0
  94. zenml/zen_server/dashboard/assets/InlineAvatar-CbJtYr0t.js +1 -0
  95. zenml/zen_server/dashboard/assets/{MarkdownVisualization-DsB2QZiK.js → MarkdownVisualization-xp3hhULl.js} +2 -2
  96. zenml/zen_server/dashboard/assets/Pagination-DEbVUupy.js +1 -0
  97. zenml/zen_server/dashboard/assets/PasswordChecker-DUveqlva.js +1 -0
  98. zenml/zen_server/dashboard/assets/SetPassword-BYBdbQDo.js +1 -0
  99. zenml/zen_server/dashboard/assets/SuccessStep-Nx743hll.js +1 -0
  100. zenml/zen_server/dashboard/assets/{UpdatePasswordSchemas-CKrd3UZz.js → UpdatePasswordSchemas-DF9gSzE0.js} +1 -1
  101. zenml/zen_server/dashboard/assets/{aws-t0gKCj_R.js → aws-BgKTfTfx.js} +1 -1
  102. zenml/zen_server/dashboard/assets/{check-circle-BVvhm5dy.js → check-circle-i56092KI.js} +1 -1
  103. zenml/zen_server/dashboard/assets/{chevron-down-zcvCWmyP.js → chevron-down-D_ZlKMqH.js} +1 -1
  104. zenml/zen_server/dashboard/assets/{chevron-right-double-CJ50E9Gr.js → chevron-right-double-BiEMg7rd.js} +1 -1
  105. zenml/zen_server/dashboard/assets/cloud-only-DVbIeckv.js +1 -0
  106. zenml/zen_server/dashboard/assets/{copy-BRhQz3j-.js → copy-BXNk6BjL.js} +1 -1
  107. zenml/zen_server/dashboard/assets/{database-CRRnyFWh.js → database-1xWSgZfO.js} +1 -1
  108. zenml/zen_server/dashboard/assets/{docker-BAonhm6G.js → docker-CQMVm_4d.js} +1 -1
  109. zenml/zen_server/dashboard/assets/{file-text-CbVERUON.js → file-text-CqD_iu6l.js} +1 -1
  110. zenml/zen_server/dashboard/assets/{help-B8rqCvqn.js → help-bu_DgLKI.js} +1 -1
  111. zenml/zen_server/dashboard/assets/index-C_CrU4vI.js +1 -0
  112. zenml/zen_server/dashboard/assets/index-DK1ynKjA.js +55 -0
  113. zenml/zen_server/dashboard/assets/index-inApY3KQ.css +1 -0
  114. zenml/zen_server/dashboard/assets/index-rK_Wuy2W.js +1 -0
  115. zenml/zen_server/dashboard/assets/index.esm-Corw4lXQ.js +1 -0
  116. zenml/zen_server/dashboard/assets/{login-mutation-Bk2tn324.js → login-mutation-BUnVASxp.js} +1 -1
  117. zenml/zen_server/dashboard/assets/not-found-B4VnX8gK.js +1 -0
  118. zenml/zen_server/dashboard/assets/package-CsUhPmou.js +1 -0
  119. zenml/zen_server/dashboard/assets/{page-D12Rvf0j.js → page-3efNCDeb.js} +2 -2
  120. zenml/zen_server/dashboard/assets/page-7zTHbhhI.js +1 -0
  121. zenml/zen_server/dashboard/assets/page-BEs6jK71.js +1 -0
  122. zenml/zen_server/dashboard/assets/page-BpSqIf4B.js +1 -0
  123. zenml/zen_server/dashboard/assets/{page-8vRWJ5b8.js → page-Bx6o0ARS.js} +1 -1
  124. zenml/zen_server/dashboard/assets/page-C43QGHTt.js +9 -0
  125. zenml/zen_server/dashboard/assets/page-CR0OG7ss.js +1 -0
  126. zenml/zen_server/dashboard/assets/{page-CBuSUrE9.js → page-CRTJ0UuR.js} +1 -1
  127. zenml/zen_server/dashboard/assets/page-CUZIGO-3.js +1 -0
  128. zenml/zen_server/dashboard/assets/page-CaopxiU1.js +1 -0
  129. zenml/zen_server/dashboard/assets/{page-CCtCgG-x.js → page-Cx67M0QT.js} +1 -1
  130. zenml/zen_server/dashboard/assets/page-D7Z399xy.js +1 -0
  131. zenml/zen_server/dashboard/assets/page-D93kd7Xj.js +1 -0
  132. zenml/zen_server/dashboard/assets/{page-Dw9-aJV6.js → page-DKlIdAe5.js} +1 -1
  133. zenml/zen_server/dashboard/assets/{page-COafKNbw.js → page-DMOYZppS.js} +1 -1
  134. zenml/zen_server/dashboard/assets/page-DMsSn3dv.js +2 -0
  135. zenml/zen_server/dashboard/assets/{page-C6v3o0Qj.js → page-Dc_7KMQE.js} +1 -1
  136. zenml/zen_server/dashboard/assets/page-DvCvroOM.js +1 -0
  137. zenml/zen_server/dashboard/assets/page-Hus2pr9T.js +1 -0
  138. zenml/zen_server/dashboard/assets/page-JyfeDUfu.js +1 -0
  139. zenml/zen_server/dashboard/assets/{page-CH26py0a.js → page-Sxn82W-5.js} +1 -1
  140. zenml/zen_server/dashboard/assets/page-TKXERe16.js +1 -0
  141. zenml/zen_server/dashboard/assets/page-Xu8JEjSU.js +1 -0
  142. zenml/zen_server/dashboard/assets/{play-circle-DK5QMJyp.js → play-circle-CNtZKDnW.js} +1 -1
  143. zenml/zen_server/dashboard/assets/plus-DOeLmm7C.js +1 -0
  144. zenml/zen_server/dashboard/assets/{terminal-B2ovgWuz.js → terminal-By9cErXc.js} +1 -1
  145. zenml/zen_server/dashboard/assets/{update-server-settings-mutation-bKxf7U9h.js → update-server-settings-mutation-CR8e3Sir.js} +1 -1
  146. zenml/zen_server/dashboard/assets/{url-CgvM-IVM.js → url-DuQMeqYA.js} +1 -1
  147. zenml/zen_server/dashboard/assets/{zod-DrZvVLjd.js → zod-BhoGpZ63.js} +1 -1
  148. zenml/zen_server/dashboard/index.html +7 -7
  149. zenml/zen_server/dashboard_legacy/asset-manifest.json +4 -4
  150. zenml/zen_server/dashboard_legacy/index.html +1 -1
  151. zenml/zen_server/dashboard_legacy/{precache-manifest.e7c29295aae591541ef59d1734d79387.js → precache-manifest.c8c57fb0d2132b1d3c2119e776b7dfb3.js} +4 -4
  152. zenml/zen_server/dashboard_legacy/service-worker.js +1 -1
  153. zenml/zen_server/dashboard_legacy/static/js/{main.53857d8b.chunk.js → main.382439a7.chunk.js} +2 -2
  154. zenml/zen_server/dashboard_legacy/static/js/{main.53857d8b.chunk.js.map → main.382439a7.chunk.js.map} +1 -1
  155. zenml/zen_server/deploy/helm/Chart.yaml +1 -1
  156. zenml/zen_server/deploy/helm/README.md +2 -2
  157. zenml/zen_server/feature_gate/zenml_cloud_feature_gate.py +11 -5
  158. zenml/zen_server/pipeline_deployment/utils.py +57 -44
  159. zenml/zen_server/rbac/zenml_cloud_rbac.py +11 -5
  160. zenml/zen_server/routers/stack_deployment_endpoints.py +144 -0
  161. zenml/zen_server/routers/workspaces_endpoints.py +64 -0
  162. zenml/zen_server/zen_server_api.py +2 -0
  163. zenml/zen_stores/migrations/utils.py +1 -1
  164. zenml/zen_stores/migrations/versions/0.61.0_release.py +23 -0
  165. zenml/zen_stores/migrations/versions/0d707865f404_adding_labels_to_stacks.py +30 -0
  166. zenml/zen_stores/rest_zen_store.py +117 -0
  167. zenml/zen_stores/schemas/stack_schemas.py +10 -0
  168. zenml/zen_stores/schemas/step_run_schemas.py +27 -11
  169. zenml/zen_stores/sql_zen_store.py +283 -0
  170. zenml/zen_stores/zen_store_interface.py +79 -0
  171. {zenml_nightly-0.60.0.dev20240627.dist-info → zenml_nightly-0.61.0.dev20240710.dist-info}/METADATA +32 -10
  172. {zenml_nightly-0.60.0.dev20240627.dist-info → zenml_nightly-0.61.0.dev20240710.dist-info}/RECORD +175 -161
  173. zenml/zen_server/dashboard/assets/@radix-C9DBgJhe.js +0 -77
  174. zenml/zen_server/dashboard/assets/@tanstack-CEbkxrhX.js +0 -30
  175. zenml/zen_server/dashboard/assets/AwarenessChannel-B2KR83Tr.js +0 -1
  176. zenml/zen_server/dashboard/assets/Cards-DSEdjsk8.js +0 -1
  177. zenml/zen_server/dashboard/assets/Commands-CTlhyic5.js +0 -1
  178. zenml/zen_server/dashboard/assets/CopyButton-CTrzKmUO.js +0 -2
  179. zenml/zen_server/dashboard/assets/DisplayDate-BdguISQF.js +0 -1
  180. zenml/zen_server/dashboard/assets/EmptyState-BkooiGtL.js +0 -1
  181. zenml/zen_server/dashboard/assets/Error-4sKxHad4.js +0 -1
  182. zenml/zen_server/dashboard/assets/Helpbox-DW21i5LD.js +0 -1
  183. zenml/zen_server/dashboard/assets/Infobox-C7bf70VS.js +0 -1
  184. zenml/zen_server/dashboard/assets/InlineAvatar-Dxrtafpg.js +0 -1
  185. zenml/zen_server/dashboard/assets/PageHeader-B0pUife2.js +0 -1
  186. zenml/zen_server/dashboard/assets/Pagination-B9WG_9cJ.js +0 -1
  187. zenml/zen_server/dashboard/assets/PasswordChecker-DSLBp7Vl.js +0 -1
  188. zenml/zen_server/dashboard/assets/SetPassword-CiNhT15a.js +0 -1
  189. zenml/zen_server/dashboard/assets/SuccessStep-CykrFndS.js +0 -1
  190. zenml/zen_server/dashboard/assets/cloud-only-Bkawp7CJ.js +0 -1
  191. zenml/zen_server/dashboard/assets/index-BawkpTlr.js +0 -55
  192. zenml/zen_server/dashboard/assets/index-CRmm7QhS.css +0 -1
  193. zenml/zen_server/dashboard/assets/index.esm-F7nqy9zY.js +0 -1
  194. zenml/zen_server/dashboard/assets/not-found-BAuhP4Jb.js +0 -1
  195. zenml/zen_server/dashboard/assets/page--5YvAHg3.js +0 -1
  196. zenml/zen_server/dashboard/assets/page-B0RAq4s_.js +0 -1
  197. zenml/zen_server/dashboard/assets/page-BePtEPHl.js +0 -1
  198. zenml/zen_server/dashboard/assets/page-C1pra1Bc.js +0 -9
  199. zenml/zen_server/dashboard/assets/page-CSs4C9jL.js +0 -1
  200. zenml/zen_server/dashboard/assets/page-Cf2XSej0.js +0 -1
  201. zenml/zen_server/dashboard/assets/page-ClPUAE_f.js +0 -1
  202. zenml/zen_server/dashboard/assets/page-D8pf2vis.js +0 -1
  203. zenml/zen_server/dashboard/assets/page-DHKMmIQH.js +0 -1
  204. zenml/zen_server/dashboard/assets/page-DMZ0VOda.js +0 -1
  205. zenml/zen_server/dashboard/assets/page-Dcg-yQv_.js +0 -1
  206. zenml/zen_server/dashboard/assets/page-DoAK5FSB.js +0 -1
  207. zenml/zen_server/dashboard/assets/page-iXiDqE0J.js +0 -2
  208. {zenml_nightly-0.60.0.dev20240627.dist-info → zenml_nightly-0.61.0.dev20240710.dist-info}/LICENSE +0 -0
  209. {zenml_nightly-0.60.0.dev20240627.dist-info → zenml_nightly-0.61.0.dev20240710.dist-info}/WHEEL +0 -0
  210. {zenml_nightly-0.60.0.dev20240627.dist-info → zenml_nightly-0.61.0.dev20240710.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
zenml/client.py CHANGED
@@ -19,7 +19,6 @@ import os
19
19
  from abc import ABCMeta
20
20
  from collections import Counter
21
21
  from datetime import datetime
22
- from functools import partial
23
22
  from pathlib import Path
24
23
  from typing import (
25
24
  TYPE_CHECKING,
@@ -1153,6 +1152,7 @@ class Client(metaclass=ClientMetaClass):
1153
1152
  name: str,
1154
1153
  components: Mapping[StackComponentType, Union[str, UUID]],
1155
1154
  stack_spec_file: Optional[str] = None,
1155
+ labels: Optional[Dict[str, Any]] = None,
1156
1156
  ) -> StackResponse:
1157
1157
  """Registers a stack and its components.
1158
1158
 
@@ -1160,6 +1160,7 @@ class Client(metaclass=ClientMetaClass):
1160
1160
  name: The name of the stack to register.
1161
1161
  components: dictionary which maps component types to component names
1162
1162
  stack_spec_file: path to the stack spec file
1163
+ labels: The labels of the stack.
1163
1164
 
1164
1165
  Returns:
1165
1166
  The model of the registered stack.
@@ -1184,6 +1185,7 @@ class Client(metaclass=ClientMetaClass):
1184
1185
  stack_spec_path=stack_spec_file,
1185
1186
  workspace=self.active_workspace.id,
1186
1187
  user=self.active_user.id,
1188
+ labels=labels,
1187
1189
  )
1188
1190
 
1189
1191
  self._validate_stack_configuration(stack=stack)
@@ -1227,8 +1229,8 @@ class Client(metaclass=ClientMetaClass):
1227
1229
  size: int = PAGE_SIZE_DEFAULT,
1228
1230
  logical_operator: LogicalOperators = LogicalOperators.AND,
1229
1231
  id: Optional[Union[UUID, str]] = None,
1230
- created: Optional[datetime] = None,
1231
- updated: Optional[datetime] = None,
1232
+ created: Optional[Union[datetime, str]] = None,
1233
+ updated: Optional[Union[datetime, str]] = None,
1232
1234
  name: Optional[str] = None,
1233
1235
  description: Optional[str] = None,
1234
1236
  workspace_id: Optional[Union[str, UUID]] = None,
@@ -1279,6 +1281,7 @@ class Client(metaclass=ClientMetaClass):
1279
1281
  name_id_or_prefix: Optional[Union[UUID, str]] = None,
1280
1282
  name: Optional[str] = None,
1281
1283
  stack_spec_file: Optional[str] = None,
1284
+ labels: Optional[Dict[str, Any]] = None,
1282
1285
  description: Optional[str] = None,
1283
1286
  component_updates: Optional[
1284
1287
  Dict[StackComponentType, List[Union[UUID, str]]]
@@ -1289,7 +1292,8 @@ class Client(metaclass=ClientMetaClass):
1289
1292
  Args:
1290
1293
  name_id_or_prefix: The name, id or prefix of the stack to update.
1291
1294
  name: the new name of the stack.
1292
- stack_spec_file: path to the stack spec file
1295
+ stack_spec_file: path to the stack spec file.
1296
+ labels: The new labels of the stack component.
1293
1297
  description: the new description of the stack.
1294
1298
  component_updates: dictionary which maps stack component types to
1295
1299
  lists of new stack component names or ids.
@@ -1343,6 +1347,15 @@ class Client(metaclass=ClientMetaClass):
1343
1347
  for c_type, c_list in components_dict.items()
1344
1348
  }
1345
1349
 
1350
+ if labels is not None:
1351
+ existing_labels = stack.labels or {}
1352
+ existing_labels.update(labels)
1353
+
1354
+ existing_labels = {
1355
+ k: v for k, v in existing_labels.items() if v is not None
1356
+ }
1357
+ update_model.labels = existing_labels
1358
+
1346
1359
  updated_stack = self.zen_store.update_stack(
1347
1360
  stack_id=stack.id,
1348
1361
  stack_update=update_model,
@@ -2439,9 +2452,7 @@ class Client(metaclass=ClientMetaClass):
2439
2452
  )
2440
2453
 
2441
2454
  for pipeline in depaginate(
2442
- functools.partial(
2443
- Client().list_pipelines, name=name_id_or_prefix
2444
- )
2455
+ Client().list_pipelines, name=name_id_or_prefix
2445
2456
  ):
2446
2457
  Client().delete_pipeline(pipeline.id)
2447
2458
  else:
@@ -2579,11 +2590,9 @@ class Client(metaclass=ClientMetaClass):
2579
2590
  )
2580
2591
 
2581
2592
  builds = depaginate(
2582
- partial(
2583
- self.list_builds,
2584
- pipeline_id=pipeline.id,
2585
- stack_id=stack.id if stack else None,
2586
- )
2593
+ self.list_builds,
2594
+ pipeline_id=pipeline.id,
2595
+ stack_id=stack.id if stack else None,
2587
2596
  )
2588
2597
 
2589
2598
  for build in builds:
@@ -3942,7 +3951,7 @@ class Client(metaclass=ClientMetaClass):
3942
3951
  """
3943
3952
  if delete_from_artifact_store:
3944
3953
  unused_artifact_versions = depaginate(
3945
- partial(self.list_artifact_versions, only_unused=True)
3954
+ self.list_artifact_versions, only_unused=True
3946
3955
  )
3947
3956
  for unused_artifact_version in unused_artifact_versions:
3948
3957
  self._delete_artifact_from_artifact_store(
@@ -4151,7 +4160,7 @@ class Client(metaclass=ClientMetaClass):
4151
4160
  ValueError: If the artifact version is still used in any runs.
4152
4161
  """
4153
4162
  if artifact_version not in depaginate(
4154
- partial(self.list_artifact_versions, only_unused=True)
4163
+ self.list_artifact_versions, only_unused=True
4155
4164
  ):
4156
4165
  raise ValueError(
4157
4166
  "The metadata of artifact versions that are used in runs "
@@ -102,10 +102,11 @@ class DockerSettings(BaseSettings):
102
102
  Depending on the configuration of this object, requirements will be
103
103
  installed in the following order (each step optional):
104
104
  - The packages installed in your local python environment
105
- - The packages specified via the `requirements` attribute
106
- - The packages specified via the `required_integrations` and potentially
107
- stack requirements
108
105
  - The packages specified via the `required_hub_plugins` attribute
106
+ - The packages required by the stack unless this is disabled by setting
107
+ `install_stack_requirements=False`.
108
+ - The packages specified via the `required_integrations`
109
+ - The packages specified via the `requirements` attribute
109
110
 
110
111
  Attributes:
111
112
  parent_image: Full name of the Docker image that should be
@@ -141,7 +142,9 @@ class DockerSettings(BaseSettings):
141
142
  target_repository: Name of the Docker repository to which the
142
143
  image should be pushed. This repository will be appended to the
143
144
  registry URI of the container registry of your stack and should
144
- therefore **not** include any registry.
145
+ therefore **not** include any registry. If not specified, the
146
+ default repository name configured in the container registry
147
+ stack component settings will be used.
145
148
  python_package_installer: The package installer to use for python
146
149
  packages.
147
150
  python_package_installer_args: Arguments to pass to the python package
@@ -200,7 +203,7 @@ class DockerSettings(BaseSettings):
200
203
  build_options: Dict[str, Any] = {}
201
204
  parent_image_build_config: Optional[DockerBuildConfig] = None
202
205
  skip_build: bool = False
203
- target_repository: str = "zenml"
206
+ target_repository: Optional[str] = None
204
207
  python_package_installer: PythonPackageInstaller = (
205
208
  PythonPackageInstaller.PIP
206
209
  )
zenml/constants.py CHANGED
@@ -346,6 +346,7 @@ EMAIL_ANALYTICS = "/email-opt-in"
346
346
  EVENT_FLAVORS = "/event-flavors"
347
347
  EVENT_SOURCES = "/event-sources"
348
348
  FLAVORS = "/flavors"
349
+ FULL_STACK = "/full-stack"
349
350
  GET_OR_CREATE = "/get-or-create"
350
351
  GRAPH = "/graph"
351
352
  HEALTH = "/health"
@@ -372,13 +373,14 @@ SERVICE_CONNECTOR_CLIENT = "/client"
372
373
  SERVICE_CONNECTOR_RESOURCES = "/resources"
373
374
  SERVICE_CONNECTOR_TYPES = "/service_connector_types"
374
375
  SERVICE_CONNECTOR_VERIFY = "/verify"
375
- SERVICE_CONNECTOR_RESOURCES = "/resources"
376
376
  MODELS = "/models"
377
377
  MODEL_VERSIONS = "/model_versions"
378
378
  MODEL_VERSION_ARTIFACTS = "/model_version_artifacts"
379
379
  MODEL_VERSION_PIPELINE_RUNS = "/model_version_pipeline_runs"
380
380
  SERVICES = "/services"
381
381
  SERVICE_CONNECTORS = "/service_connectors"
382
+ STACK = "/stack"
383
+ STACK_DEPLOYMENT = "/stack-deployment"
382
384
  STACKS = "/stacks"
383
385
  STACK_COMPONENTS = "/components"
384
386
  STATISTICS = "/statistics"
@@ -389,6 +391,7 @@ TAGS = "/tags"
389
391
  TRIGGERS = "/triggers"
390
392
  TRIGGER_EXECUTIONS = "/trigger_executions"
391
393
  USERS = "/users"
394
+ URL = "/url"
392
395
  VERSION_1 = "/v1"
393
396
  VISUALIZE = "/visualize"
394
397
  WEBHOOKS = "/webhooks"
@@ -458,6 +461,7 @@ MLSTACKS_SUPPORTED_STACK_COMPONENTS = [
458
461
  "step_operator",
459
462
  ]
460
463
 
464
+
461
465
  # Parameters for internal ZenML Models
462
466
  TEXT_FIELD_MAX_LENGTH = 65535
463
467
  STR_FIELD_MAX_LENGTH = 255
@@ -41,6 +41,7 @@ class BaseContainerRegistryConfig(AuthenticationConfigMixin):
41
41
  """
42
42
 
43
43
  uri: str
44
+ default_repository: Optional[str] = None
44
45
 
45
46
  @field_validator("uri")
46
47
  @classmethod
zenml/enums.py CHANGED
@@ -384,3 +384,9 @@ class PluginSubType(StrEnum):
384
384
  WEBHOOK = "webhook"
385
385
  # Action Subtypes
386
386
  PIPELINE_RUN = "pipeline_run"
387
+
388
+
389
+ class StackDeploymentProvider(StrEnum):
390
+ """All possible stack deployment providers."""
391
+
392
+ AWS = "aws"
@@ -13,7 +13,6 @@
13
13
  # permissions and limitations under the License.
14
14
  """Base class for all the Event Hub."""
15
15
 
16
- from functools import partial
17
16
  from typing import List
18
17
 
19
18
  from pydantic import ValidationError
@@ -125,13 +124,11 @@ class InternalEventHub(BaseEventHub):
125
124
  """
126
125
  # get all event sources configured for this flavor
127
126
  triggers: List[TriggerResponse] = depaginate(
128
- partial(
129
- self.zen_store.list_triggers,
130
- trigger_filter_model=TriggerFilter(
131
- event_source_id=event_source.id, is_active=True
132
- ),
133
- hydrate=True,
134
- )
127
+ self.zen_store.list_triggers,
128
+ trigger_filter_model=TriggerFilter(
129
+ event_source_id=event_source.id, is_active=True
130
+ ),
131
+ hydrate=True,
135
132
  )
136
133
 
137
134
  trigger_list: List[TriggerResponse] = []
@@ -43,6 +43,7 @@ class AWSIntegration(Integration):
43
43
  "kubernetes",
44
44
  "aws-profile-manager",
45
45
  ]
46
+ REQUIREMENTS_IGNORED_ON_UNINSTALL = ["kubernetes"]
46
47
 
47
48
  @staticmethod
48
49
  def activate() -> None:
@@ -48,6 +48,7 @@ class AzureIntegration(Integration):
48
48
  "azure-storage-blob==12.17.0", # temporary fix for https://github.com/Azure/azure-sdk-for-python/issues/32056
49
49
  "kubernetes",
50
50
  ]
51
+ REQUIREMENTS_IGNORED_ON_UNINSTALL = ["kubernetes"]
51
52
 
52
53
  @staticmethod
53
54
  def activate() -> None:
@@ -44,6 +44,7 @@ class DeepchecksIntegration(Integration):
44
44
  "tenacity!=8.4.0", # https://github.com/jd/tenacity/issues/471
45
45
  ]
46
46
  APT_PACKAGES = ["ffmpeg", "libsm6", "libxext6"]
47
+ REQUIREMENTS_IGNORED_ON_UNINSTALL = ["pandas","torchvision","tenacity"]
47
48
 
48
49
  @staticmethod
49
50
  def activate() -> None:
@@ -31,6 +31,7 @@ class DiscordIntegration(Integration):
31
31
 
32
32
  NAME = DISCORD
33
33
  REQUIREMENTS = ["discord.py>=2.3.2", "aiohttp>=3.8.1", "asyncio"]
34
+ REQUIREMENTS_IGNORED_ON_UNINSTALL = ["aiohttp","asyncio"]
34
35
 
35
36
  @classmethod
36
37
  def flavors(cls) -> List[Type[Flavor]]:
@@ -57,6 +57,7 @@ class EvidentlyIntegration(Integration):
57
57
  "evidently>=0.4.16,<=0.4.22",
58
58
  "tenacity!=8.4.0", # https://github.com/jd/tenacity/issues/471
59
59
  ]
60
+ REQUIREMENTS_IGNORED_ON_UNINSTALL = ["tenacity"]
60
61
 
61
62
  @classmethod
62
63
  def flavors(cls) -> List[Type[Flavor]]:
@@ -22,6 +22,7 @@ class FacetsIntegration(Integration):
22
22
 
23
23
  NAME = FACETS
24
24
  REQUIREMENTS = ["facets-overview>=1.0.0", "pandas"]
25
+ REQUIREMENTS_IGNORED_ON_UNINSTALL = ["pandas"]
25
26
 
26
27
  @staticmethod
27
28
  def activate() -> None:
@@ -34,6 +34,7 @@ class FeastIntegration(Integration):
34
34
  # click is added to keep the feast click version
35
35
  # in sync with ZenML's click
36
36
  REQUIREMENTS = ["feast<=0.37.1", "click>=8.0.1,<8.1.4"]
37
+ REQUIREMENTS_IGNORED_ON_UNINSTALL = ["click"]
37
38
 
38
39
  @classmethod
39
40
  def flavors(cls) -> List[Type[Flavor]]:
@@ -43,15 +43,17 @@ class GcpIntegration(Integration):
43
43
 
44
44
  NAME = GCP
45
45
  REQUIREMENTS = [
46
- "kfp>=1.8.22",
46
+ "kfp>=2.6.0",
47
47
  "gcsfs",
48
48
  "google-cloud-secret-manager",
49
49
  "google-cloud-container>=2.21.0",
50
+ "google-cloud-artifact-registry>=1.11.3",
50
51
  "google-cloud-storage>=2.9.0",
51
52
  "google-cloud-aiplatform>=1.34.0", # includes shapely pin fix
52
53
  "google-cloud-build>=3.11.0",
53
54
  "kubernetes",
54
55
  ]
56
+ REQUIREMENTS_IGNORED_ON_UNINSTALL = ["kubernetes","kfp"]
55
57
 
56
58
  @staticmethod
57
59
  def activate() -> None: