zenml-nightly 0.58.2.dev20240626__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 (214) hide show
  1. README.md +30 -9
  2. RELEASE_NOTES.md +240 -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 +946 -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 +10 -1
  16. zenml/container_registries/base_container_registry.py +1 -0
  17. zenml/enums.py +7 -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/google_credentials_mixin.py +1 -1
  28. zenml/integrations/gcp/service_connectors/gcp_service_connector.py +320 -64
  29. zenml/integrations/huggingface/__init__.py +1 -0
  30. zenml/integrations/integration.py +24 -0
  31. zenml/integrations/kubeflow/__init__.py +3 -0
  32. zenml/integrations/kubeflow/flavors/kubeflow_orchestrator_flavor.py +1 -1
  33. zenml/integrations/kubeflow/orchestrators/kubeflow_orchestrator.py +0 -1
  34. zenml/integrations/kubernetes/__init__.py +3 -1
  35. zenml/integrations/kubernetes/orchestrators/kube_utils.py +4 -1
  36. zenml/integrations/label_studio/annotators/label_studio_annotator.py +1 -0
  37. zenml/integrations/langchain/__init__.py +1 -0
  38. zenml/integrations/mlflow/__init__.py +3 -1
  39. zenml/integrations/neural_prophet/__init__.py +1 -0
  40. zenml/integrations/polars/__init__.py +1 -0
  41. zenml/integrations/prodigy/__init__.py +1 -0
  42. zenml/integrations/pycaret/__init__.py +6 -0
  43. zenml/integrations/registry.py +37 -0
  44. zenml/integrations/s3/artifact_stores/s3_artifact_store.py +17 -6
  45. zenml/integrations/seldon/__init__.py +1 -0
  46. zenml/integrations/seldon/model_deployers/seldon_model_deployer.py +1 -0
  47. zenml/integrations/skypilot/flavors/skypilot_orchestrator_base_vm_config.py +2 -2
  48. zenml/integrations/skypilot/orchestrators/skypilot_base_vm_orchestrator.py +1 -1
  49. zenml/integrations/skypilot/orchestrators/skypilot_orchestrator_entrypoint.py +2 -2
  50. zenml/integrations/skypilot_aws/__init__.py +2 -1
  51. zenml/integrations/skypilot_azure/__init__.py +1 -1
  52. zenml/integrations/skypilot_gcp/__init__.py +1 -1
  53. zenml/integrations/skypilot_lambda/__init__.py +1 -1
  54. zenml/integrations/skypilot_lambda/flavors/skypilot_orchestrator_lambda_vm_flavor.py +1 -1
  55. zenml/integrations/slack/__init__.py +1 -0
  56. zenml/integrations/tekton/__init__.py +1 -0
  57. zenml/integrations/tensorboard/__init__.py +0 -1
  58. zenml/integrations/tensorflow/__init__.py +18 -6
  59. zenml/integrations/wandb/__init__.py +1 -0
  60. zenml/models/__init__.py +11 -0
  61. zenml/models/v2/core/component.py +18 -0
  62. zenml/models/v2/core/model.py +1 -2
  63. zenml/models/v2/core/service_connector.py +17 -0
  64. zenml/models/v2/core/stack.py +31 -0
  65. zenml/models/v2/misc/full_stack.py +97 -0
  66. zenml/models/v2/misc/stack_deployment.py +86 -0
  67. zenml/new/pipelines/pipeline.py +1 -1
  68. zenml/orchestrators/input_utils.py +3 -6
  69. zenml/stack/stack.py +3 -6
  70. zenml/stack_deployments/__init__.py +14 -0
  71. zenml/stack_deployments/aws_stack_deployment.py +254 -0
  72. zenml/stack_deployments/gcp_stack_deployment.py +260 -0
  73. zenml/stack_deployments/stack_deployment.py +208 -0
  74. zenml/stack_deployments/utils.py +44 -0
  75. zenml/utils/function_utils.py +1 -1
  76. zenml/utils/pagination_utils.py +7 -5
  77. zenml/utils/pipeline_docker_image_builder.py +97 -68
  78. zenml/utils/pydantic_utils.py +6 -5
  79. zenml/zen_server/cloud_utils.py +18 -3
  80. zenml/zen_server/dashboard/assets/{404-CDPQCl4D.js → 404-DpJaNHKF.js} +1 -1
  81. zenml/zen_server/dashboard/assets/@radix-CFOkMR_E.js +85 -0
  82. zenml/zen_server/dashboard/assets/{@react-router-DYovave8.js → @react-router-CO-OsFwI.js} +2 -2
  83. zenml/zen_server/dashboard/assets/{@reactflow-CHBapDaj.js → @reactflow-DJfzkHO1.js} +2 -2
  84. zenml/zen_server/dashboard/assets/@tanstack-DYiOyJUL.js +22 -0
  85. zenml/zen_server/dashboard/assets/AwarenessChannel-BYDLT2xC.js +1 -0
  86. zenml/zen_server/dashboard/assets/{CodeSnippet-BidtnWOi.js → CodeSnippet-BkOuRmyq.js} +2 -2
  87. zenml/zen_server/dashboard/assets/Commands-ZvWR1BRs.js +1 -0
  88. zenml/zen_server/dashboard/assets/CopyButton-DVwLkafa.js +2 -0
  89. zenml/zen_server/dashboard/assets/{CsvVizualization-BOuez-fG.js → CsvVizualization-C2IiqX4I.js} +7 -7
  90. zenml/zen_server/dashboard/assets/DisplayDate-DYgIjlDF.js +1 -0
  91. zenml/zen_server/dashboard/assets/EmptyState-BMLnFVlB.js +1 -0
  92. zenml/zen_server/dashboard/assets/Error-CqX0VqW_.js +1 -0
  93. zenml/zen_server/dashboard/assets/ExecutionStatus-BoLUXR9t.js +1 -0
  94. zenml/zen_server/dashboard/assets/Helpbox-LFydyVwh.js +1 -0
  95. zenml/zen_server/dashboard/assets/Infobox-DnENC0sh.js +1 -0
  96. zenml/zen_server/dashboard/assets/InlineAvatar-CbJtYr0t.js +1 -0
  97. zenml/zen_server/dashboard/assets/{MarkdownVisualization-DsB2QZiK.js → MarkdownVisualization-xp3hhULl.js} +2 -2
  98. zenml/zen_server/dashboard/assets/Pagination-DEbVUupy.js +1 -0
  99. zenml/zen_server/dashboard/assets/PasswordChecker-DUveqlva.js +1 -0
  100. zenml/zen_server/dashboard/assets/SetPassword-BYBdbQDo.js +1 -0
  101. zenml/zen_server/dashboard/assets/SuccessStep-Nx743hll.js +1 -0
  102. zenml/zen_server/dashboard/assets/{UpdatePasswordSchemas-DnM-c11H.js → UpdatePasswordSchemas-DF9gSzE0.js} +1 -1
  103. zenml/zen_server/dashboard/assets/{aws-t0gKCj_R.js → aws-BgKTfTfx.js} +1 -1
  104. zenml/zen_server/dashboard/assets/{check-circle-BVvhm5dy.js → check-circle-i56092KI.js} +1 -1
  105. zenml/zen_server/dashboard/assets/{chevron-down-zcvCWmyP.js → chevron-down-D_ZlKMqH.js} +1 -1
  106. zenml/zen_server/dashboard/assets/{chevron-right-double-CJ50E9Gr.js → chevron-right-double-BiEMg7rd.js} +1 -1
  107. zenml/zen_server/dashboard/assets/cloud-only-DVbIeckv.js +1 -0
  108. zenml/zen_server/dashboard/assets/{copy-BRhQz3j-.js → copy-BXNk6BjL.js} +1 -1
  109. zenml/zen_server/dashboard/assets/{database-CRRnyFWh.js → database-1xWSgZfO.js} +1 -1
  110. zenml/zen_server/dashboard/assets/{docker-BAonhm6G.js → docker-CQMVm_4d.js} +1 -1
  111. zenml/zen_server/dashboard/assets/{file-text-CbVERUON.js → file-text-CqD_iu6l.js} +1 -1
  112. zenml/zen_server/dashboard/assets/{help-B8rqCvqn.js → help-bu_DgLKI.js} +1 -1
  113. zenml/zen_server/dashboard/assets/index-C_CrU4vI.js +1 -0
  114. zenml/zen_server/dashboard/assets/index-DK1ynKjA.js +55 -0
  115. zenml/zen_server/dashboard/assets/index-inApY3KQ.css +1 -0
  116. zenml/zen_server/dashboard/assets/index-rK_Wuy2W.js +1 -0
  117. zenml/zen_server/dashboard/assets/index.esm-Corw4lXQ.js +1 -0
  118. zenml/zen_server/dashboard/assets/{login-mutation-wzzl23C6.js → login-mutation-BUnVASxp.js} +1 -1
  119. zenml/zen_server/dashboard/assets/not-found-B4VnX8gK.js +1 -0
  120. zenml/zen_server/dashboard/assets/package-CsUhPmou.js +1 -0
  121. zenml/zen_server/dashboard/assets/{page-BmkSiYeQ.js → page-3efNCDeb.js} +2 -2
  122. zenml/zen_server/dashboard/assets/page-7zTHbhhI.js +1 -0
  123. zenml/zen_server/dashboard/assets/page-BEs6jK71.js +1 -0
  124. zenml/zen_server/dashboard/assets/page-BpSqIf4B.js +1 -0
  125. zenml/zen_server/dashboard/assets/{page-AQKopn_4.js → page-Bx6o0ARS.js} +1 -1
  126. zenml/zen_server/dashboard/assets/page-C43QGHTt.js +9 -0
  127. zenml/zen_server/dashboard/assets/page-CR0OG7ss.js +1 -0
  128. zenml/zen_server/dashboard/assets/page-CRTJ0UuR.js +1 -0
  129. zenml/zen_server/dashboard/assets/page-CUZIGO-3.js +1 -0
  130. zenml/zen_server/dashboard/assets/page-CaopxiU1.js +1 -0
  131. zenml/zen_server/dashboard/assets/{page-CuT1SUik.js → page-Cx67M0QT.js} +1 -1
  132. zenml/zen_server/dashboard/assets/page-D7Z399xy.js +1 -0
  133. zenml/zen_server/dashboard/assets/page-D93kd7Xj.js +1 -0
  134. zenml/zen_server/dashboard/assets/{page-BzVZGExK.js → page-DKlIdAe5.js} +1 -1
  135. zenml/zen_server/dashboard/assets/{page-Bi5AI0S7.js → page-DMOYZppS.js} +1 -1
  136. zenml/zen_server/dashboard/assets/page-DMsSn3dv.js +2 -0
  137. zenml/zen_server/dashboard/assets/{page-BW6Ket3a.js → page-Dc_7KMQE.js} +1 -1
  138. zenml/zen_server/dashboard/assets/page-DvCvroOM.js +1 -0
  139. zenml/zen_server/dashboard/assets/page-Hus2pr9T.js +1 -0
  140. zenml/zen_server/dashboard/assets/page-JyfeDUfu.js +1 -0
  141. zenml/zen_server/dashboard/assets/{page-yN4rZ-ZS.js → page-Sxn82W-5.js} +1 -1
  142. zenml/zen_server/dashboard/assets/page-TKXERe16.js +1 -0
  143. zenml/zen_server/dashboard/assets/page-Xu8JEjSU.js +1 -0
  144. zenml/zen_server/dashboard/assets/{play-circle-DK5QMJyp.js → play-circle-CNtZKDnW.js} +1 -1
  145. zenml/zen_server/dashboard/assets/plus-DOeLmm7C.js +1 -0
  146. zenml/zen_server/dashboard/assets/{terminal-B2ovgWuz.js → terminal-By9cErXc.js} +1 -1
  147. zenml/zen_server/dashboard/assets/{update-server-settings-mutation-0Wgz8pUE.js → update-server-settings-mutation-CR8e3Sir.js} +1 -1
  148. zenml/zen_server/dashboard/assets/{url-6_xv0WJS.js → url-DuQMeqYA.js} +1 -1
  149. zenml/zen_server/dashboard/assets/{zod-DrZvVLjd.js → zod-BhoGpZ63.js} +1 -1
  150. zenml/zen_server/dashboard/index.html +7 -7
  151. zenml/zen_server/dashboard_legacy/asset-manifest.json +4 -4
  152. zenml/zen_server/dashboard_legacy/index.html +1 -1
  153. zenml/zen_server/dashboard_legacy/{precache-manifest.f4abc5b7cfa7d90c1caf5521918e29a8.js → precache-manifest.c8c57fb0d2132b1d3c2119e776b7dfb3.js} +4 -4
  154. zenml/zen_server/dashboard_legacy/service-worker.js +1 -1
  155. zenml/zen_server/dashboard_legacy/static/js/{main.ac2f17d0.chunk.js → main.382439a7.chunk.js} +2 -2
  156. zenml/zen_server/dashboard_legacy/static/js/{main.ac2f17d0.chunk.js.map → main.382439a7.chunk.js.map} +1 -1
  157. zenml/zen_server/deploy/helm/Chart.yaml +1 -1
  158. zenml/zen_server/deploy/helm/README.md +2 -2
  159. zenml/zen_server/feature_gate/zenml_cloud_feature_gate.py +11 -5
  160. zenml/zen_server/pipeline_deployment/utils.py +57 -44
  161. zenml/zen_server/rbac/zenml_cloud_rbac.py +11 -5
  162. zenml/zen_server/routers/stack_deployment_endpoints.py +158 -0
  163. zenml/zen_server/routers/workspaces_endpoints.py +64 -0
  164. zenml/zen_server/zen_server_api.py +2 -0
  165. zenml/zen_stores/migrations/utils.py +1 -1
  166. zenml/zen_stores/migrations/versions/0.60.0_release.py +23 -0
  167. zenml/zen_stores/migrations/versions/0.61.0_release.py +23 -0
  168. zenml/zen_stores/migrations/versions/0d707865f404_adding_labels_to_stacks.py +30 -0
  169. zenml/zen_stores/rest_zen_store.py +145 -4
  170. zenml/zen_stores/schemas/stack_schemas.py +10 -0
  171. zenml/zen_stores/schemas/step_run_schemas.py +27 -11
  172. zenml/zen_stores/sql_zen_store.py +300 -6
  173. zenml/zen_stores/zen_store_interface.py +80 -0
  174. {zenml_nightly-0.58.2.dev20240626.dist-info → zenml_nightly-0.61.0.dev20240712.dist-info}/METADATA +32 -10
  175. {zenml_nightly-0.58.2.dev20240626.dist-info → zenml_nightly-0.61.0.dev20240712.dist-info}/RECORD +178 -162
  176. zenml/zen_server/dashboard/assets/@radix-C9DBgJhe.js +0 -77
  177. zenml/zen_server/dashboard/assets/@tanstack-CEbkxrhX.js +0 -30
  178. zenml/zen_server/dashboard/assets/AwarenessChannel-nXGpmj_f.js +0 -1
  179. zenml/zen_server/dashboard/assets/Cards-nwsvQLVS.js +0 -1
  180. zenml/zen_server/dashboard/assets/Commands-DuIWKg_Q.js +0 -1
  181. zenml/zen_server/dashboard/assets/CopyButton-B_YSm-Ds.js +0 -2
  182. zenml/zen_server/dashboard/assets/DisplayDate-BdguISQF.js +0 -1
  183. zenml/zen_server/dashboard/assets/EmptyState-BkooiGtL.js +0 -1
  184. zenml/zen_server/dashboard/assets/Error-B6M0dPph.js +0 -1
  185. zenml/zen_server/dashboard/assets/Helpbox-BQoqCm04.js +0 -1
  186. zenml/zen_server/dashboard/assets/Infobox-Ce9mefqU.js +0 -1
  187. zenml/zen_server/dashboard/assets/InlineAvatar-DGf3dVhV.js +0 -1
  188. zenml/zen_server/dashboard/assets/PageHeader-DGaemzjc.js +0 -1
  189. zenml/zen_server/dashboard/assets/Pagination-DVYfBCCc.js +0 -1
  190. zenml/zen_server/dashboard/assets/PasswordChecker-DSLBp7Vl.js +0 -1
  191. zenml/zen_server/dashboard/assets/SetPassword-B5s7DJug.js +0 -1
  192. zenml/zen_server/dashboard/assets/SuccessStep-ZzczaM7g.js +0 -1
  193. zenml/zen_server/dashboard/assets/cloud-only-Ba_ShBR5.js +0 -1
  194. zenml/zen_server/dashboard/assets/index-CWJ3xbIf.css +0 -1
  195. zenml/zen_server/dashboard/assets/index-QORVVTMN.js +0 -55
  196. zenml/zen_server/dashboard/assets/index.esm-F7nqy9zY.js +0 -1
  197. zenml/zen_server/dashboard/assets/not-found-Dh2la7kh.js +0 -1
  198. zenml/zen_server/dashboard/assets/page-B-5jAKoO.js +0 -1
  199. zenml/zen_server/dashboard/assets/page-B-vWk8a6.js +0 -1
  200. zenml/zen_server/dashboard/assets/page-B0BrqfS8.js +0 -1
  201. zenml/zen_server/dashboard/assets/page-BQxVFlUl.js +0 -1
  202. zenml/zen_server/dashboard/assets/page-ByrHy6Ss.js +0 -1
  203. zenml/zen_server/dashboard/assets/page-CPtY4Kv_.js +0 -1
  204. zenml/zen_server/dashboard/assets/page-CmmukLsl.js +0 -1
  205. zenml/zen_server/dashboard/assets/page-D2D-7qyr.js +0 -9
  206. zenml/zen_server/dashboard/assets/page-DAQQyLxT.js +0 -1
  207. zenml/zen_server/dashboard/assets/page-DHkUMl_E.js +0 -1
  208. zenml/zen_server/dashboard/assets/page-DZCbwOEs.js +0 -2
  209. zenml/zen_server/dashboard/assets/page-DdaIt20-.js +0 -1
  210. zenml/zen_server/dashboard/assets/page-LqLs24Ot.js +0 -1
  211. zenml/zen_server/dashboard/assets/page-lebv0c7C.js +0 -1
  212. {zenml_nightly-0.58.2.dev20240626.dist-info → zenml_nightly-0.61.0.dev20240712.dist-info}/LICENSE +0 -0
  213. {zenml_nightly-0.58.2.dev20240626.dist-info → zenml_nightly-0.61.0.dev20240712.dist-info}/WHEEL +0 -0
  214. {zenml_nightly-0.58.2.dev20240626.dist-info → zenml_nightly-0.61.0.dev20240712.dist-info}/entry_points.txt +0 -0
@@ -31,6 +31,9 @@ class KubeflowIntegration(Integration):
31
31
 
32
32
  NAME = KUBEFLOW
33
33
  REQUIREMENTS = ["kfp>=2.6.0", "kfp-kubernetes>=1.1.0"] # Only 1.x version that supports pyyaml 6
34
+ REQUIREMENTS_IGNORED_ON_UNINSTALL = [
35
+ "kfp", # it is used by GCP as well
36
+ ]
34
37
 
35
38
  @classmethod
36
39
  def flavors(cls) -> List[Type[Flavor]]:
@@ -149,7 +149,7 @@ class KubeflowOrchestratorConfig(
149
149
 
150
150
  kubeflow_hostname: Optional[str] = None
151
151
  kubeflow_namespace: str = "kubeflow"
152
- kubernetes_context: Optional[str] # TODO: Potential setting
152
+ kubernetes_context: Optional[str] = None # TODO: Potential setting
153
153
 
154
154
  @model_validator(mode="before")
155
155
  @classmethod
@@ -433,7 +433,6 @@ class KubeflowOrchestrator(ContainerizedOrchestrator):
433
433
  The dynamic container component.
434
434
  """
435
435
 
436
- @dsl.container_component # type: ignore[misc]
437
436
  def dynamic_container_component() -> dsl.ContainerSpec:
438
437
  """Dynamic container component.
439
438
 
@@ -31,7 +31,9 @@ class KubernetesIntegration(Integration):
31
31
 
32
32
  NAME = KUBERNETES
33
33
  REQUIREMENTS = ["kubernetes>=21.7,<26"]
34
-
34
+ REQUIREMENTS_IGNORED_ON_UNINSTALL = [
35
+ "kfp", # it is used by many others
36
+ ]
35
37
  @classmethod
36
38
  def flavors(cls) -> List[Type[Flavor]]:
37
39
  """Declare the stack component flavors for the Kubernetes integration.
@@ -225,8 +225,11 @@ def wait_pod(
225
225
  response = core_api.read_namespaced_pod_log(
226
226
  name=pod_name,
227
227
  namespace=namespace,
228
+ _preload_content=False,
228
229
  )
229
- logs = response.splitlines()
230
+ raw_data = response.data
231
+ decoded_log = raw_data.decode("utf-8", errors="replace")
232
+ logs = decoded_log.splitlines()
230
233
  if len(logs) > logged_lines:
231
234
  for line in logs[logged_lines:]:
232
235
  logger.info(line)
@@ -527,6 +527,7 @@ class LabelStudioAnnotator(BaseAnnotator, AuthenticationMixin):
527
527
  aws_access_key_id,
528
528
  aws_secret_access_key,
529
529
  aws_session_token,
530
+ _,
530
531
  ) = artifact_store.get_credentials()
531
532
 
532
533
  if aws_access_key_id and aws_secret_access_key:
@@ -30,6 +30,7 @@ class LangchainIntegration(Integration):
30
30
  "pyyaml>=6.0.1",
31
31
  "tenacity!=8.4.0", # https://github.com/jd/tenacity/issues/471
32
32
  ]
33
+ REQUIREMENTS_IGNORED_ON_UNINSTALL = ["pyyaml","tenacity"]
33
34
 
34
35
  @classmethod
35
36
  def activate(cls) -> None:
@@ -45,9 +45,11 @@ class MlflowIntegration(Integration):
45
45
  # This downgrades pydantic to v1 even though mlflow does not have
46
46
  # any issues with v2. This is why we have to pin it here so a downgrade
47
47
  # will not happen.
48
- "pydantic>=2.7.0,<2.8.0"
48
+ "pydantic>=2.7.0,<2.8.0",
49
49
  ]
50
50
 
51
+ REQUIREMENTS_IGNORED_ON_UNINSTALL = ["python-rapidjson", "pydantic"]
52
+
51
53
  @classmethod
52
54
  def activate(cls) -> None:
53
55
  """Activate the MLflow integration."""
@@ -26,6 +26,7 @@ class NeuralProphetIntegration(Integration):
26
26
  "holidays>=0.4.1,<0.25.0",
27
27
  "tenacity!=8.4.0", # https://github.com/jd/tenacity/issues/471
28
28
  ]
29
+ REQUIREMENTS_IGNORED_ON_UNINSTALL = ["tenacity"]
29
30
 
30
31
  @classmethod
31
32
  def activate(cls) -> None:
@@ -25,6 +25,7 @@ class PolarsIntegration(Integration):
25
25
  "polars>=0.19.5",
26
26
  "pyarrow>=12.0.0"
27
27
  ]
28
+ REQUIREMENTS_IGNORED_ON_UNINSTALL = ["pyarrow"]
28
29
 
29
30
  @classmethod
30
31
  def activate(cls) -> None:
@@ -29,6 +29,7 @@ class ProdigyIntegration(Integration):
29
29
  "prodigy",
30
30
  "urllib3<2",
31
31
  ]
32
+ REQUIREMENTS_IGNORED_ON_UNINSTALL = ["urllib3"]
32
33
 
33
34
  @classmethod
34
35
  def flavors(cls) -> List[Type[Flavor]]:
@@ -28,6 +28,12 @@ class PyCaretIntegration(Integration):
28
28
  "catboost",
29
29
  "lightgbm",
30
30
  ]
31
+ REQUIREMENTS_IGNORED_ON_UNINSTALL = [
32
+ "scikit-learn",
33
+ "xgboost",
34
+ "catboost",
35
+ "lightgbm",
36
+ ]
31
37
 
32
38
  @classmethod
33
39
  def activate(cls) -> None:
@@ -124,6 +124,43 @@ class IntegrationRegistry(object):
124
124
  )
125
125
  ]
126
126
 
127
+ def select_uninstall_requirements(
128
+ self,
129
+ integration_name: Optional[str] = None,
130
+ target_os: Optional[str] = None,
131
+ ) -> List[str]:
132
+ """Select the uninstall requirements for a given integration or all integrations.
133
+
134
+ Args:
135
+ integration_name: Name of the integration to check.
136
+ target_os: Target OS for the requirements.
137
+
138
+ Returns:
139
+ List of requirements for the integration uninstall.
140
+
141
+ Raises:
142
+ KeyError: If the integration is not found.
143
+ """
144
+ if integration_name:
145
+ if integration_name in self.list_integration_names:
146
+ return self._integrations[
147
+ integration_name
148
+ ].get_uninstall_requirements(target_os=target_os)
149
+ else:
150
+ raise KeyError(
151
+ f"Version {integration_name} does not exist. "
152
+ f"Currently the following integrations are implemented. "
153
+ f"{self.list_integration_names}"
154
+ )
155
+ else:
156
+ return [
157
+ requirement
158
+ for name in self.list_integration_names
159
+ for requirement in self._integrations[
160
+ name
161
+ ].get_uninstall_requirements(target_os=target_os)
162
+ ]
163
+
127
164
  def is_installed(self, integration_name: Optional[str] = None) -> bool:
128
165
  """Checks if all requirements for an integration are installed.
129
166
 
@@ -122,7 +122,7 @@ class S3ArtifactStore(BaseArtifactStore, AuthenticationMixin):
122
122
 
123
123
  def get_credentials(
124
124
  self,
125
- ) -> Tuple[Optional[str], Optional[str], Optional[str]]:
125
+ ) -> Tuple[Optional[str], Optional[str], Optional[str], Optional[str]]:
126
126
  """Gets authentication credentials.
127
127
 
128
128
  If an authentication secret is configured, the secret values are
@@ -130,8 +130,8 @@ class S3ArtifactStore(BaseArtifactStore, AuthenticationMixin):
130
130
  attributes.
131
131
 
132
132
  Returns:
133
- Tuple (key, secret, token) of credentials used to authenticate with
134
- the S3 filesystem.
133
+ Tuple (key, secret, token, region) of credentials used to
134
+ authenticate with the S3 filesystem.
135
135
 
136
136
  Raises:
137
137
  RuntimeError: If the AWS connector behaves unexpectedly.
@@ -151,6 +151,7 @@ class S3ArtifactStore(BaseArtifactStore, AuthenticationMixin):
151
151
  credentials.access_key,
152
152
  credentials.secret_key,
153
153
  credentials.token,
154
+ client.meta.region_name,
154
155
  )
155
156
 
156
157
  secret = self.get_typed_authentication_secret(
@@ -161,9 +162,10 @@ class S3ArtifactStore(BaseArtifactStore, AuthenticationMixin):
161
162
  secret.aws_access_key_id,
162
163
  secret.aws_secret_access_key,
163
164
  secret.aws_session_token,
165
+ None,
164
166
  )
165
167
  else:
166
- return self.config.key, self.config.secret, self.config.token
168
+ return self.config.key, self.config.secret, self.config.token, None
167
169
 
168
170
  @property
169
171
  def filesystem(self) -> ZenMLS3Filesystem:
@@ -176,13 +178,22 @@ class S3ArtifactStore(BaseArtifactStore, AuthenticationMixin):
176
178
  if self._filesystem and not self.connector_has_expired():
177
179
  return self._filesystem
178
180
 
179
- key, secret, token = self.get_credentials()
181
+ key, secret, token, region = self.get_credentials()
182
+
183
+ # Use the region from the connector if available, otherwise some
184
+ # remote workloads (e.g. Sagemaker) might not work correctly because
185
+ # they look for the bucket in the wrong region
186
+ client_kwargs = {}
187
+ if region:
188
+ client_kwargs["region_name"] = region
189
+ if self.config.client_kwargs:
190
+ client_kwargs.update(self.config.client_kwargs)
180
191
 
181
192
  self._filesystem = ZenMLS3Filesystem(
182
193
  key=key,
183
194
  secret=secret,
184
195
  token=token,
185
- client_kwargs=self.config.client_kwargs,
196
+ client_kwargs=client_kwargs,
186
197
  config_kwargs=self.config.config_kwargs,
187
198
  s3_additional_kwargs=self.config.s3_additional_kwargs,
188
199
  )
@@ -33,6 +33,7 @@ class SeldonIntegration(Integration):
33
33
  REQUIREMENTS = [
34
34
  "kubernetes==18.20.0",
35
35
  ]
36
+ REQUIREMENTS_IGNORED_ON_UNINSTALL = ["kubernetes"]
36
37
 
37
38
  @classmethod
38
39
  def activate(cls) -> None:
@@ -290,6 +290,7 @@ class SeldonModelDeployer(BaseModelDeployer):
290
290
  assert isinstance(artifact_store, S3ArtifactStore)
291
291
 
292
292
  (
293
+ region_name,
293
294
  aws_access_key_id,
294
295
  aws_secret_access_key,
295
296
  aws_session_token,
@@ -43,7 +43,7 @@ class SkypilotBaseOrchestratorSettings(BaseSettings):
43
43
  `{'tpu_vm': True, 'runtime_version': 'tpu-vm-base'}` for TPUs.
44
44
  use_spot: whether to use spot instances. If None, defaults to
45
45
  False.
46
- spot_recovery: the spot recovery strategy to use for the managed
46
+ job_recovery: the spot recovery strategy to use for the managed
47
47
  spot to recover the cluster from preemption. Refer to
48
48
  `recovery_strategy module <https://github.com/skypilot-org/skypilot/blob/master/sky/spot/recovery_strategy.py>`__ # pylint: disable=line-too-long
49
49
  for more details.
@@ -103,7 +103,7 @@ class SkypilotBaseOrchestratorSettings(BaseSettings):
103
103
  )
104
104
  accelerator_args: Optional[Dict[str, str]] = None
105
105
  use_spot: Optional[bool] = None
106
- spot_recovery: Optional[str] = None
106
+ job_recovery: Optional[str] = None
107
107
  region: Optional[str] = None
108
108
  zone: Optional[str] = None
109
109
  image_id: Union[Dict[str, str], str, None] = Field(
@@ -303,7 +303,7 @@ class SkypilotBaseOrchestrator(ContainerizedOrchestrator):
303
303
  accelerators=settings.accelerators,
304
304
  accelerator_args=settings.accelerator_args,
305
305
  use_spot=settings.use_spot,
306
- spot_recovery=settings.spot_recovery,
306
+ job_recovery=settings.job_recovery,
307
307
  region=settings.region,
308
308
  zone=settings.zone,
309
309
  image_id=settings.image_id,
@@ -136,7 +136,7 @@ def main() -> None:
136
136
  settings.disk_size, # Assuming disk_size is part of the settings
137
137
  settings.disk_tier, # Assuming disk_tier is part of the settings
138
138
  settings.use_spot,
139
- settings.spot_recovery,
139
+ settings.job_recovery,
140
140
  settings.region,
141
141
  settings.zone,
142
142
  accelerators_hashable,
@@ -213,7 +213,7 @@ def main() -> None:
213
213
  accelerators=settings.accelerators,
214
214
  accelerator_args=settings.accelerator_args,
215
215
  use_spot=settings.use_spot,
216
- spot_recovery=settings.spot_recovery,
216
+ job_recovery=settings.job_recovery,
217
217
  region=settings.region,
218
218
  zone=settings.zone,
219
219
  image_id=settings.image_id,
@@ -31,7 +31,8 @@ class SkypilotAWSIntegration(Integration):
31
31
  """Definition of Skypilot AWS Integration for ZenML."""
32
32
 
33
33
  NAME = SKYPILOT_AWS
34
- REQUIREMENTS = ["skypilot[aws]<=0.5.0"]
34
+ # all 0.6.x versions of skypilot[aws] are compatible
35
+ REQUIREMENTS = ["skypilot[aws]~=0.6.0"]
35
36
  APT_PACKAGES = ["openssh-client", "rsync"]
36
37
 
37
38
  @classmethod
@@ -33,7 +33,7 @@ class SkypilotAzureIntegration(Integration):
33
33
  """Definition of Skypilot (Azure) Integration for ZenML."""
34
34
 
35
35
  NAME = SKYPILOT_AZURE
36
- REQUIREMENTS = ["skypilot[azure]<=0.5.0"]
36
+ REQUIREMENTS = ["skypilot[azure]~=0.6.0"]
37
37
  APT_PACKAGES = ["openssh-client", "rsync"]
38
38
 
39
39
  @classmethod
@@ -31,7 +31,7 @@ class SkypilotGCPIntegration(Integration):
31
31
  """Definition of Skypilot (GCP) Integration for ZenML."""
32
32
 
33
33
  NAME = SKYPILOT_GCP
34
- REQUIREMENTS = ["skypilot[gcp]<=0.5.0"]
34
+ REQUIREMENTS = ["skypilot[gcp]~=0.6.0"]
35
35
  APT_PACKAGES = ["openssh-client", "rsync"]
36
36
 
37
37
  @classmethod
@@ -31,7 +31,7 @@ class SkypilotLambdaIntegration(Integration):
31
31
  """Definition of Skypilot Lambda Integration for ZenML."""
32
32
 
33
33
  NAME = SKYPILOT_LAMBDA
34
- REQUIREMENTS = ["skypilot[lambda]<=0.5.0"]
34
+ REQUIREMENTS = ["skypilot[lambda]<=0.6.0"]
35
35
 
36
36
  @classmethod
37
37
  def flavors(cls) -> List[Type[Flavor]]:
@@ -40,7 +40,7 @@ class SkypilotLambdaOrchestratorSettings(SkypilotBaseOrchestratorSettings):
40
40
 
41
41
  _UNSUPPORTED_FEATURES = {
42
42
  "use_spot": "Spot instances not supported for Lambda orchestrator.",
43
- "spot_recovery": "Spot recovery not supported for Lambda orchestrator.",
43
+ "job_recovery": "Job recovery not supported for Lambda orchestrator.",
44
44
  "image_id": "Custom image IDs not supported for Lambda orchestrator.",
45
45
  # Add other unsupported features as needed
46
46
  }
@@ -31,6 +31,7 @@ class SlackIntegration(Integration):
31
31
 
32
32
  NAME = SLACK
33
33
  REQUIREMENTS = ["slack-sdk>=3.16.1", "aiohttp>=3.8.1"]
34
+ REQUIREMENTS_IGNORED_ON_UNINSTALL = ["aiohttp"]
34
35
 
35
36
  @classmethod
36
37
  def flavors(cls) -> List[Type[Flavor]]:
@@ -32,6 +32,7 @@ class TektonIntegration(Integration):
32
32
 
33
33
  NAME = TEKTON
34
34
  REQUIREMENTS = ["kfp>=2.6.0", "kfp-kubernetes>=1.1.0"]
35
+ REQUIREMENTS_IGNORED_ON_UNINSTALL = ["kfp"]
35
36
 
36
37
  @classmethod
37
38
  def flavors(cls) -> List[Type[Flavor]]:
@@ -13,7 +13,6 @@
13
13
  # permissions and limitations under the License.
14
14
  """Initialization for TensorBoard integration."""
15
15
 
16
- import sys
17
16
  from typing import List, Optional
18
17
  from zenml.integrations.constants import TENSORBOARD
19
18
  from zenml.integrations.integration import Integration
@@ -18,6 +18,9 @@ import sys
18
18
  from typing import List, Optional
19
19
  from zenml.integrations.constants import TENSORFLOW
20
20
  from zenml.integrations.integration import Integration
21
+ from zenml.logger import get_logger
22
+
23
+ logger = get_logger(__name__)
21
24
 
22
25
 
23
26
  class TensorflowIntegration(Integration):
@@ -25,20 +28,27 @@ class TensorflowIntegration(Integration):
25
28
 
26
29
  NAME = TENSORFLOW
27
30
  REQUIREMENTS = []
31
+ REQUIREMENTS_IGNORED_ON_UNINSTALL = ["typing-extensions"]
28
32
 
29
33
  @classmethod
30
34
  def activate(cls) -> None:
31
35
  """Activates the integration."""
32
36
  # need to import this explicitly to load the Tensorflow file IO support
33
37
  # for S3 and other file systems
34
- if (
35
- not platform.system() == "Darwin"
36
- or not platform.machine() == "arm64"
37
- ):
38
+ if not platform.system() == "Darwin" or not platform.machine() == "arm64":
38
39
  import tensorflow_io # type: ignore
39
40
 
40
41
  from zenml.integrations.tensorflow import materializers # noqa
41
42
 
43
+ if sys.version_info.minor == 8:
44
+ logger.warning(
45
+ "Python 3.8 with TensorFlow is not fully "
46
+ "compatible with Pydantic 2 requirements. "
47
+ "Consider upgrading to a higher Python "
48
+ "version if you would like to use the "
49
+ "Tensorflow integration."
50
+ )
51
+
42
52
  @classmethod
43
53
  def get_requirements(cls, target_os: Optional[str] = None) -> List[str]:
44
54
  """Defines platform specific requirements for the integration.
@@ -52,13 +62,15 @@ class TensorflowIntegration(Integration):
52
62
  target_os = target_os or platform.system()
53
63
  if target_os == "Darwin" and platform.machine() == "arm64":
54
64
  requirements = [
55
- f"tensorflow-macos>=2.12,<=2.15",
65
+ "tensorflow-macos>=2.12,<=2.15",
56
66
  ]
57
67
  else:
58
68
  requirements = [
59
- f"tensorflow>=2.12,<=2.15",
69
+ "tensorflow>=2.12,<=2.15",
60
70
  "tensorflow_io>=0.24.0",
61
71
  ]
72
+ if sys.version_info.minor == 8:
73
+ requirements.append("typing-extensions>=4.6.1")
62
74
  return requirements
63
75
 
64
76
 
@@ -31,6 +31,7 @@ class WandbIntegration(Integration):
31
31
 
32
32
  NAME = WANDB
33
33
  REQUIREMENTS = ["wandb>=0.12.12", "Pillow>=9.1.0"]
34
+ REQUIREMENTS_IGNORED_ON_UNINSTALL = ["Pillow"]
34
35
 
35
36
  @classmethod
36
37
  def flavors(cls) -> List[Type[Flavor]]:
zenml/models/__init__.py CHANGED
@@ -327,6 +327,7 @@ from zenml.models.v2.misc.service_connector_type import (
327
327
  ResourceTypeModel,
328
328
  )
329
329
  from zenml.models.v2.misc.server_models import ServerDatabaseType, ServerModel
330
+ from zenml.models.v2.misc.full_stack import FullStackRequest
330
331
  from zenml.models.v2.core.trigger import (
331
332
  TriggerRequest,
332
333
  TriggerFilter,
@@ -386,6 +387,11 @@ from zenml.models.v2.core.server_settings import (
386
387
  ServerSettingsResponseMetadata,
387
388
  ServerSettingsUpdate,
388
389
  )
390
+ from zenml.models.v2.misc.stack_deployment import (
391
+ DeployedStack,
392
+ StackDeploymentConfig,
393
+ StackDeploymentInfo,
394
+ )
389
395
 
390
396
  # ----------------------------- Forward References -----------------------------
391
397
 
@@ -405,6 +411,7 @@ EventSourceResponseMetadata.model_rebuild()
405
411
  EventSourceResponseResources.model_rebuild()
406
412
  FlavorResponseBody.model_rebuild()
407
413
  FlavorResponseMetadata.model_rebuild()
414
+ FullStackRequest.model_rebuild()
408
415
  LazyArtifactVersionResponse.model_rebuild()
409
416
  LazyRunMetadataResponse.model_rebuild()
410
417
  ModelResponseBody.model_rebuild()
@@ -701,11 +708,13 @@ __all__ = [
701
708
  "WorkspaceResponseMetadata",
702
709
  # V2 Misc
703
710
  "AuthenticationMethodModel",
711
+ "DeployedStack",
704
712
  "ServiceConnectorResourcesModel",
705
713
  "ServiceConnectorTypeModel",
706
714
  "ServiceConnectorTypedResourcesModel",
707
715
  "ServiceConnectorRequirements",
708
716
  "ResourceTypeModel",
717
+ "FullStackRequest",
709
718
  "UserAuthModel",
710
719
  "ExternalUserModel",
711
720
  "BuildItem",
@@ -718,6 +727,8 @@ __all__ = [
718
727
  "ServerModel",
719
728
  "ServerDatabaseType",
720
729
  "ServerDeploymentType",
730
+ "StackDeploymentConfig",
731
+ "StackDeploymentInfo",
721
732
  "OAuthDeviceAuthorizationRequest",
722
733
  "OAuthDeviceAuthorizationResponse",
723
734
  "OAuthDeviceTokenRequest",
@@ -238,6 +238,24 @@ class ComponentResponse(
238
238
  max_length=STR_FIELD_MAX_LENGTH,
239
239
  )
240
240
 
241
+ def get_analytics_metadata(self) -> Dict[str, Any]:
242
+ """Add the component labels to analytics metadata.
243
+
244
+ Returns:
245
+ Dict of analytics metadata.
246
+ """
247
+ metadata = super().get_analytics_metadata()
248
+
249
+ if self.labels is not None:
250
+ metadata.update(
251
+ {
252
+ label[6:]: value
253
+ for label, value in self.labels.items()
254
+ if label.startswith("zenml:")
255
+ }
256
+ )
257
+ return metadata
258
+
241
259
  def get_hydrated_version(self) -> "ComponentResponse":
242
260
  """Get the hydrated version of this component.
243
261
 
@@ -13,7 +13,6 @@
13
13
  # permissions and limitations under the License.
14
14
  """Models representing models."""
15
15
 
16
- from functools import partial
17
16
  from typing import TYPE_CHECKING, ClassVar, List, Optional, Union
18
17
  from uuid import UUID
19
18
 
@@ -303,7 +302,7 @@ class ModelResponse(
303
302
 
304
303
  client = Client()
305
304
  model_versions = depaginate(
306
- partial(client.list_model_versions, model_name_or_id=self.id)
305
+ client.list_model_versions, model_name_or_id=self.id
307
306
  )
308
307
  return [
309
308
  mv.to_model_class(suppress_class_validation_warnings=True)
@@ -493,6 +493,23 @@ class ServiceConnectorResponse(
493
493
  max_length=STR_FIELD_MAX_LENGTH,
494
494
  )
495
495
 
496
+ def get_analytics_metadata(self) -> Dict[str, Any]:
497
+ """Add the service connector labels to analytics metadata.
498
+
499
+ Returns:
500
+ Dict of analytics metadata.
501
+ """
502
+ metadata = super().get_analytics_metadata()
503
+
504
+ metadata.update(
505
+ {
506
+ label[6:]: value
507
+ for label, value in self.labels.items()
508
+ if label.startswith("zenml:")
509
+ }
510
+ )
511
+ return metadata
512
+
496
513
  def get_hydrated_version(self) -> "ServiceConnectorResponse":
497
514
  """Get the hydrated version of this service connector.
498
515
 
@@ -36,6 +36,7 @@ from zenml.models.v2.core.component import ComponentResponse
36
36
  if TYPE_CHECKING:
37
37
  from sqlalchemy.sql.elements import ColumnElement
38
38
 
39
+
39
40
  # ------------------ Request Model ------------------
40
41
 
41
42
 
@@ -59,6 +60,10 @@ class StackRequest(WorkspaceScopedRequest):
59
60
  title="A mapping of stack component types to the actual"
60
61
  "instances of components of this type.",
61
62
  )
63
+ labels: Optional[Dict[str, Any]] = Field(
64
+ default=None,
65
+ title="The stack labels.",
66
+ )
62
67
 
63
68
  @property
64
69
  def is_valid(self) -> bool:
@@ -109,6 +114,10 @@ class StackUpdate(BaseUpdate):
109
114
  "instances of components of this type.",
110
115
  default=None,
111
116
  )
117
+ labels: Optional[Dict[str, Any]] = Field(
118
+ default=None,
119
+ title="The stack labels.",
120
+ )
112
121
 
113
122
 
114
123
  # ------------------ Response Model ------------------
@@ -134,6 +143,10 @@ class StackResponseMetadata(WorkspaceScopedResponseMetadata):
134
143
  default=None,
135
144
  title="The path to the stack spec used for mlstacks deployments.",
136
145
  )
146
+ labels: Optional[Dict[str, Any]] = Field(
147
+ default=None,
148
+ title="The stack labels.",
149
+ )
137
150
 
138
151
 
139
152
  class StackResponseResources(WorkspaceScopedResponseResources):
@@ -214,6 +227,15 @@ class StackResponse(
214
227
  """
215
228
  metadata = super().get_analytics_metadata()
216
229
  metadata.update({ct: c[0].flavor for ct, c in self.components.items()})
230
+
231
+ if self.labels is not None:
232
+ metadata.update(
233
+ {
234
+ label[6:]: value
235
+ for label, value in self.labels.items()
236
+ if label.startswith("zenml:")
237
+ }
238
+ )
217
239
  return metadata
218
240
 
219
241
  @property
@@ -243,6 +265,15 @@ class StackResponse(
243
265
  """
244
266
  return self.get_metadata().components
245
267
 
268
+ @property
269
+ def labels(self) -> Optional[Dict[str, Any]]:
270
+ """The `labels` property.
271
+
272
+ Returns:
273
+ the value of the property.
274
+ """
275
+ return self.get_metadata().labels
276
+
246
277
 
247
278
  # ------------------ Filter Model ------------------
248
279