zenml-nightly 0.81.0.dev20250428__py3-none-any.whl → 0.81.0.dev20250430__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 (168) hide show
  1. zenml/VERSION +1 -1
  2. zenml/cli/model.py +2 -7
  3. zenml/client.py +17 -2
  4. zenml/config/build_configuration.py +4 -0
  5. zenml/config/docker_settings.py +1 -1
  6. zenml/config/resource_settings.py +1 -1
  7. zenml/config/strict_base_model.py +1 -1
  8. zenml/entrypoints/base_entrypoint_configuration.py +1 -1
  9. zenml/environment.py +37 -34
  10. zenml/exceptions.py +0 -78
  11. zenml/integrations/aws/__init__.py +1 -1
  12. zenml/integrations/evidently/__init__.py +1 -0
  13. zenml/integrations/evidently/metrics.py +1 -1
  14. zenml/integrations/evidently/tests.py +1 -1
  15. zenml/integrations/gcp/flavors/vertex_orchestrator_flavor.py +6 -0
  16. zenml/integrations/gcp/orchestrators/vertex_orchestrator.py +49 -28
  17. zenml/integrations/kubeflow/orchestrators/kubeflow_orchestrator.py +7 -29
  18. zenml/integrations/kubernetes/flavors/kubernetes_orchestrator_flavor.py +6 -0
  19. zenml/integrations/kubernetes/orchestrators/kubernetes_orchestrator.py +12 -5
  20. zenml/integrations/kubernetes/orchestrators/kubernetes_orchestrator_entrypoint.py +31 -18
  21. zenml/integrations/kubernetes/orchestrators/manifest_utils.py +21 -0
  22. zenml/integrations/kubernetes/pod_settings.py +6 -1
  23. zenml/integrations/numpy/__init__.py +4 -1
  24. zenml/integrations/numpy/materializers/numpy_materializer.py +75 -6
  25. zenml/integrations/pandas/materializers/pandas_materializer.py +118 -22
  26. zenml/integrations/tekton/orchestrators/tekton_orchestrator.py +8 -28
  27. zenml/models/v2/core/model_version.py +28 -33
  28. zenml/models/v2/core/pipeline_deployment.py +4 -4
  29. zenml/models/v2/core/pipeline_run.py +5 -12
  30. zenml/models/v2/core/user.py +1 -1
  31. zenml/orchestrators/dag_runner.py +50 -14
  32. zenml/secret/base_secret.py +1 -1
  33. zenml/stack/stack_component.py +1 -1
  34. zenml/stack/utils.py +1 -1
  35. zenml/utils/code_utils.py +1 -1
  36. zenml/zen_server/dashboard/assets/{404-o3nB5iwI.js → 404-D4aYbspS.js} +1 -1
  37. zenml/zen_server/dashboard/assets/{@react-router-BGgzhn5D.js → @react-router-CNP6g_RL.js} +1 -1
  38. zenml/zen_server/dashboard/assets/{AlertDialogDropdownItem-C_qWs-4u.js → AlertDialogDropdownItem-CRZjthRL.js} +1 -1
  39. zenml/zen_server/dashboard/assets/{CodeSnippet-nRnOvbOJ.js → CodeSnippet-Di-loaZu.js} +1 -1
  40. zenml/zen_server/dashboard/assets/CollapsibleCard-Dr5zb5T5.js +1 -0
  41. zenml/zen_server/dashboard/assets/{Commands-BwBzFj-5.js → Commands-CD9Y7FOE.js} +1 -1
  42. zenml/zen_server/dashboard/assets/{ComponentBadge-CMx2DbsV.js → ComponentBadge-BgGnzcLu.js} +1 -1
  43. zenml/zen_server/dashboard/assets/{ComponentIcon-CSxdApv8.js → ComponentIcon-B_7Y_oV-.js} +1 -1
  44. zenml/zen_server/dashboard/assets/{CsvVizualization-lxB2iyEh.js → CsvVizualization-CDrjL6bW.js} +1 -1
  45. zenml/zen_server/dashboard/assets/{DeleteAlertDialog-Bp0o-UXZ.js → DeleteAlertDialog-9RTDnEx3.js} +1 -1
  46. zenml/zen_server/dashboard/assets/DialogItem-0fWTH7ki.js +1 -0
  47. zenml/zen_server/dashboard/assets/{Error-DRhVeVHQ.js → Error-vBjUYjb-.js} +1 -1
  48. zenml/zen_server/dashboard/assets/{ExecutionStatus-HnZXi9bW.js → ExecutionStatus-B-ysY113.js} +1 -1
  49. zenml/zen_server/dashboard/assets/{Helpbox-Dsr3ZYcL.js → Helpbox-Dt3q7NGd.js} +1 -1
  50. zenml/zen_server/dashboard/assets/{Infobox-C4Op55B8.js → Infobox-Bai0JtFs.js} +1 -1
  51. zenml/zen_server/dashboard/assets/{InlineAvatar-CrAwe7Pl.js → InlineAvatar-Cpj0lVRQ.js} +1 -1
  52. zenml/zen_server/dashboard/assets/NestedCollapsible-DbhKdWx-.js +1 -0
  53. zenml/zen_server/dashboard/assets/{Partials-DjTM0Oe-.js → Partials-BNBtCjuT.js} +1 -1
  54. zenml/zen_server/dashboard/assets/ProBadge-3vtouJQf.js +1 -0
  55. zenml/zen_server/dashboard/assets/{ProCta-BYSSivgY.js → ProCta-BoTLdAdV.js} +1 -1
  56. zenml/zen_server/dashboard/assets/{ProviderIcon-B8W7AGNk.js → ProviderIcon-kkODO9tx.js} +1 -1
  57. zenml/zen_server/dashboard/assets/{ProviderRadio-BWFJPEY2.js → ProviderRadio-26EB5tY-.js} +1 -1
  58. zenml/zen_server/dashboard/assets/RunSelector-j0C_TPVp.js +1 -0
  59. zenml/zen_server/dashboard/assets/RunsBody-DexNouV4.js +1 -0
  60. zenml/zen_server/dashboard/assets/SearchField-DMCywawn.js +1 -0
  61. zenml/zen_server/dashboard/assets/{SecretTooltip-CCn9HfEh.js → SecretTooltip-LLGP7AIC.js} +1 -1
  62. zenml/zen_server/dashboard/assets/{SetPassword-BDFVwnNB.js → SetPassword-CBHW-Su8.js} +1 -1
  63. zenml/zen_server/dashboard/assets/StackList-S-9I1R4n.js +1 -0
  64. zenml/zen_server/dashboard/assets/Tabs-C2ufJX4t.js +1 -0
  65. zenml/zen_server/dashboard/assets/Tick-ay3Bgtro.js +1 -0
  66. zenml/zen_server/dashboard/assets/{UpdatePasswordSchemas-3gg2tC-H.js → UpdatePasswordSchemas-p3RX0P-Q.js} +1 -1
  67. zenml/zen_server/dashboard/assets/{UsageReason-DOMAzO02.js → UsageReason-C8sD2bOU.js} +1 -1
  68. zenml/zen_server/dashboard/assets/{Wizard-BSH_lIfi.js → Wizard-DIllc07n.js} +1 -1
  69. zenml/zen_server/dashboard/assets/{WizardFooter-CnM-50jL.js → WizardFooter-dNDpuero.js} +1 -1
  70. zenml/zen_server/dashboard/assets/{all-pipeline-runs-query-D9XfZpmV.js → all-pipeline-runs-query-BUT1PiTp.js} +1 -1
  71. zenml/zen_server/dashboard/assets/{configuration-form-Ci_QlfZC.js → configuration-form-DBZSb0FV.js} +1 -1
  72. zenml/zen_server/dashboard/assets/{create-stack-CoQ5SEJL.js → create-stack-BXLyjE58.js} +1 -1
  73. zenml/zen_server/dashboard/assets/{delete-run-B5xUZwdP.js → delete-run-DzcYxUnd.js} +1 -1
  74. zenml/zen_server/dashboard/assets/dots-horizontal-BGRJCPCs.js +1 -0
  75. zenml/zen_server/dashboard/assets/{flavor-select-DOLAl-S4.js → flavor-select-BTEwByv6.js} +1 -1
  76. zenml/zen_server/dashboard/assets/{form-schemas-BaEJ1z87.js → form-schemas-BJN_25Ua.js} +1 -1
  77. zenml/zen_server/dashboard/assets/{index-e8udi7QT.js → index-8uhUi12k.js} +1 -1
  78. zenml/zen_server/dashboard/assets/{index-hsSXyS3H.js → index-BygJE88j.js} +8 -8
  79. zenml/zen_server/dashboard/assets/{index-ojAuWXMf.js → index-D9-ukAem.js} +1 -1
  80. zenml/zen_server/dashboard/assets/index-DmTFrHJm.css +1 -0
  81. zenml/zen_server/dashboard/assets/{index-BoWZ9rXk.js → index-wYtmKLnQ.js} +1 -1
  82. zenml/zen_server/dashboard/assets/{login-mutation-CwraNa5G.js → login-mutation-DywLqguW.js} +1 -1
  83. zenml/zen_server/dashboard/assets/{not-found-BuK1QrF2.js → not-found-BOoklIG4.js} +1 -1
  84. zenml/zen_server/dashboard/assets/{page-0AIX3VK8.js → page--hSXKqyG.js} +1 -1
  85. zenml/zen_server/dashboard/assets/{page-CIDo1Ajk.js → page-2BsNK_sZ.js} +1 -1
  86. zenml/zen_server/dashboard/assets/page-4nVakAEl.js +1 -0
  87. zenml/zen_server/dashboard/assets/{page-CjRoKEQs.js → page-8AzB83Py.js} +1 -1
  88. zenml/zen_server/dashboard/assets/{page-BQVPbNps.js → page-B0r9dBEU.js} +1 -1
  89. zenml/zen_server/dashboard/assets/{page-hVng6ANV.js → page-B1Uq1S1Q.js} +1 -1
  90. zenml/zen_server/dashboard/assets/page-B3DscprQ.js +1 -0
  91. zenml/zen_server/dashboard/assets/{page-KRP_w5zH.js → page-B7Aj2XbV.js} +1 -1
  92. zenml/zen_server/dashboard/assets/{page-CZgeF_wQ.js → page-BE8jdyaM.js} +1 -1
  93. zenml/zen_server/dashboard/assets/page-BIYqUwTI.js +1 -0
  94. zenml/zen_server/dashboard/assets/page-BTzhAVEn.js +1 -0
  95. zenml/zen_server/dashboard/assets/{page-_Zt6UwiG.js → page-ByXQN8A-.js} +1 -1
  96. zenml/zen_server/dashboard/assets/page-CI4a9CXs.js +1 -0
  97. zenml/zen_server/dashboard/assets/page-CPLlVRXx.js +6 -0
  98. zenml/zen_server/dashboard/assets/page-CSQOpvvK.js +3 -0
  99. zenml/zen_server/dashboard/assets/{page-DwIlrsF0.js → page-Ccnk_5ji.js} +1 -1
  100. zenml/zen_server/dashboard/assets/{page-C-6XUKSp.js → page-Ci_n_x3a.js} +1 -1
  101. zenml/zen_server/dashboard/assets/page-D-ry_oLs.js +1 -0
  102. zenml/zen_server/dashboard/assets/{page-DbEn9V9E.js → page-D2TtSfnb.js} +1 -1
  103. zenml/zen_server/dashboard/assets/page-DHnkTzqs.js +1 -0
  104. zenml/zen_server/dashboard/assets/{page-B5clbTo4.js → page-DP2Ed-2m.js} +1 -1
  105. zenml/zen_server/dashboard/assets/{page-C30HZCTR.js → page-D_5R6E7b.js} +1 -1
  106. zenml/zen_server/dashboard/assets/page-DfTsntQI.js +1 -0
  107. zenml/zen_server/dashboard/assets/page-DkY7AIhj.js +1 -0
  108. zenml/zen_server/dashboard/assets/page-DmteSSj6.js +1 -0
  109. zenml/zen_server/dashboard/assets/page-Dt3wHeWX.js +1 -0
  110. zenml/zen_server/dashboard/assets/page-EXvws1ss.js +1 -0
  111. zenml/zen_server/dashboard/assets/{page-Czj8fu8q.js → page-K9yjbnd4.js} +1 -1
  112. zenml/zen_server/dashboard/assets/{page-DHDeVaMO.js → page-RV8wpZ_4.js} +1 -1
  113. zenml/zen_server/dashboard/assets/{page-DLVtrRa5.js → page-bUVHi7DE.js} +1 -1
  114. zenml/zen_server/dashboard/assets/page-cOEvFs_l.js +1 -0
  115. zenml/zen_server/dashboard/assets/page-kzSGEVUs.js +1 -0
  116. zenml/zen_server/dashboard/assets/{page-C7buw8xJ.js → page-uDGvpa5g.js} +2 -2
  117. zenml/zen_server/dashboard/assets/{page-BbygQpf-.js → page-uN0n_DE2.js} +1 -1
  118. zenml/zen_server/dashboard/assets/{page-CgJcperk.js → page-xa1EAPcI.js} +1 -1
  119. zenml/zen_server/dashboard/assets/{persist-xOAq24Bm.js → persist-CEeDYHW5.js} +1 -1
  120. zenml/zen_server/dashboard/assets/{persist-DLvsEXh0.js → persist-SSTTV5q0.js} +1 -1
  121. zenml/zen_server/dashboard/assets/{service-MHyqhRgp.js → service-BRoAA1Kq.js} +1 -1
  122. zenml/zen_server/dashboard/assets/sharedSchema-BACERDat.js +14 -0
  123. zenml/zen_server/dashboard/assets/{stack-detail-query-C1GoxBeK.js → stack-detail-query-ihiJr6nq.js} +1 -1
  124. zenml/zen_server/dashboard/assets/{update-server-settings-mutation-DduehrZn.js → update-server-settings-mutation-CK6COmw9.js} +1 -1
  125. zenml/zen_server/dashboard/index.html +4 -4
  126. zenml/zen_server/deploy/daemon/daemon_zen_server.py +1 -1
  127. zenml/zen_server/deploy/docker/docker_zen_server.py +1 -1
  128. zenml/zen_server/exceptions.py +0 -2
  129. zenml/zen_server/routers/model_versions_endpoints.py +10 -19
  130. zenml/zen_server/routers/runs_endpoints.py +7 -1
  131. zenml/zen_stores/schemas/pipeline_deployment_schemas.py +20 -3
  132. zenml/zen_stores/schemas/pipeline_run_schemas.py +21 -1
  133. zenml/zen_stores/secrets_stores/hashicorp_secrets_store.py +1 -1
  134. zenml/zen_stores/secrets_stores/sql_secrets_store.py +1 -1
  135. zenml/zen_stores/sql_zen_store.py +10 -34
  136. {zenml_nightly-0.81.0.dev20250428.dist-info → zenml_nightly-0.81.0.dev20250430.dist-info}/METADATA +2 -2
  137. {zenml_nightly-0.81.0.dev20250428.dist-info → zenml_nightly-0.81.0.dev20250430.dist-info}/RECORD +140 -139
  138. zenml/zen_server/dashboard/assets/CollapsibleCard-9sSz7n1R.js +0 -1
  139. zenml/zen_server/dashboard/assets/DialogItem-DHw2ihTx.js +0 -1
  140. zenml/zen_server/dashboard/assets/NestedCollapsible-Ce1bmT8N.js +0 -1
  141. zenml/zen_server/dashboard/assets/ProBadge-CDEqgzh8.js +0 -1
  142. zenml/zen_server/dashboard/assets/RunSelector-DoL_gMHJ.js +0 -1
  143. zenml/zen_server/dashboard/assets/RunsBody-B6mBjv-_.js +0 -1
  144. zenml/zen_server/dashboard/assets/SearchField-DHl5flXv.js +0 -1
  145. zenml/zen_server/dashboard/assets/StackList-dhdUtky3.js +0 -1
  146. zenml/zen_server/dashboard/assets/Tabs-BuZG8ft1.js +0 -1
  147. zenml/zen_server/dashboard/assets/Tick-C4gtED35.js +0 -1
  148. zenml/zen_server/dashboard/assets/index-6mLFgFwe.css +0 -1
  149. zenml/zen_server/dashboard/assets/page-3lW9eIer.js +0 -1
  150. zenml/zen_server/dashboard/assets/page-9PzQok8O.js +0 -1
  151. zenml/zen_server/dashboard/assets/page-BEibNYiA.js +0 -6
  152. zenml/zen_server/dashboard/assets/page-BOE2XBFy.js +0 -1
  153. zenml/zen_server/dashboard/assets/page-Bki79xdd.js +0 -1
  154. zenml/zen_server/dashboard/assets/page-BnKwJnOb.js +0 -1
  155. zenml/zen_server/dashboard/assets/page-CBGeo-7W.js +0 -2
  156. zenml/zen_server/dashboard/assets/page-Co-FJ5ds.js +0 -1
  157. zenml/zen_server/dashboard/assets/page-Cu8vuohQ.js +0 -1
  158. zenml/zen_server/dashboard/assets/page-D0QcEBi1.js +0 -1
  159. zenml/zen_server/dashboard/assets/page-DKY_U5Sz.js +0 -1
  160. zenml/zen_server/dashboard/assets/page-DQHU5o_C.js +0 -1
  161. zenml/zen_server/dashboard/assets/page-DpY1koQY.js +0 -1
  162. zenml/zen_server/dashboard/assets/page-DrS4WOup.js +0 -1
  163. zenml/zen_server/dashboard/assets/page-HIAPXq4w.js +0 -1
  164. zenml/zen_server/dashboard/assets/page-Jw2QAdxa.js +0 -1
  165. zenml/zen_server/dashboard/assets/sharedSchema-CQA5lnlU.js +0 -14
  166. {zenml_nightly-0.81.0.dev20250428.dist-info → zenml_nightly-0.81.0.dev20250430.dist-info}/LICENSE +0 -0
  167. {zenml_nightly-0.81.0.dev20250428.dist-info → zenml_nightly-0.81.0.dev20250430.dist-info}/WHEEL +0 -0
  168. {zenml_nightly-0.81.0.dev20250428.dist-info → zenml_nightly-0.81.0.dev20250430.dist-info}/entry_points.txt +0 -0
zenml/VERSION CHANGED
@@ -1 +1 @@
1
- 0.81.0.dev20250428
1
+ 0.81.0.dev20250430
zenml/cli/model.py CHANGED
@@ -398,18 +398,13 @@ def version() -> None:
398
398
 
399
399
  @cli_utils.list_options(ModelVersionFilter)
400
400
  @version.command("list", help="List model versions with filter.")
401
- @click.argument("model_name_or_id")
402
- def list_model_versions(model_name_or_id: str, **kwargs: Any) -> None:
401
+ def list_model_versions(**kwargs: Any) -> None:
403
402
  """List model versions with filter in the Model Control Plane.
404
403
 
405
404
  Args:
406
- model_name_or_id: The name or ID of the parent model.
407
405
  **kwargs: Keyword arguments to filter models.
408
406
  """
409
- model_versions = Client().list_model_versions(
410
- model_name_or_id=model_name_or_id,
411
- **kwargs,
412
- )
407
+ model_versions = Client().list_model_versions(**kwargs)
413
408
 
414
409
  if not model_versions:
415
410
  cli_utils.declare("No model versions found.")
zenml/client.py CHANGED
@@ -6504,7 +6504,8 @@ class Client(metaclass=ClientMetaClass):
6504
6504
 
6505
6505
  def list_model_versions(
6506
6506
  self,
6507
- model_name_or_id: Union[str, UUID],
6507
+ model: Optional[Union[str, UUID]] = None,
6508
+ model_name_or_id: Optional[Union[str, UUID]] = None,
6508
6509
  sort_by: str = "number",
6509
6510
  page: int = PAGINATION_STARTING_PAGE,
6510
6511
  size: int = PAGE_SIZE_DEFAULT,
@@ -6525,6 +6526,7 @@ class Client(metaclass=ClientMetaClass):
6525
6526
  """Get model versions by filter from Model Control Plane.
6526
6527
 
6527
6528
  Args:
6529
+ model: The model to filter by.
6528
6530
  model_name_or_id: name or id of the model containing the model
6529
6531
  version.
6530
6532
  sort_by: The column to sort by
@@ -6548,6 +6550,19 @@ class Client(metaclass=ClientMetaClass):
6548
6550
  Returns:
6549
6551
  A page object with all model versions.
6550
6552
  """
6553
+ if model_name_or_id:
6554
+ logger.warning(
6555
+ "The `model_name_or_id` argument is deprecated. "
6556
+ "Please use the `model` argument instead."
6557
+ )
6558
+ if model is None:
6559
+ model = model_name_or_id
6560
+ else:
6561
+ logger.warning(
6562
+ "Ignoring `model_name_or_id` argument as `model` argument "
6563
+ "was also provided."
6564
+ )
6565
+
6551
6566
  model_version_filter_model = ModelVersionFilter(
6552
6567
  page=page,
6553
6568
  size=size,
@@ -6563,7 +6578,7 @@ class Client(metaclass=ClientMetaClass):
6563
6578
  tag=tag,
6564
6579
  tags=tags,
6565
6580
  user=user,
6566
- model=model_name_or_id,
6581
+ model=model,
6567
6582
  project=project or self.active_project.id,
6568
6583
  )
6569
6584
 
@@ -95,6 +95,10 @@ class BuildConfiguration(BaseModel):
95
95
  for _, requirements, _ in requirements_files:
96
96
  hash_.update(requirements.encode())
97
97
 
98
+ if self.settings.dockerfile:
99
+ with open(self.settings.dockerfile, "rb") as f:
100
+ hash_.update(f.read())
101
+
98
102
  return hash_.hexdigest()
99
103
 
100
104
  def should_include_files(
@@ -309,5 +309,5 @@ class DockerSettings(BaseSettings):
309
309
  # public attributes are immutable
310
310
  frozen=True,
311
311
  # prevent extra attributes during model initialization
312
- extra="forbid",
312
+ extra="ignore",
313
313
  )
@@ -119,5 +119,5 @@ class ResourceSettings(BaseSettings):
119
119
  # public attributes are immutable
120
120
  frozen=True,
121
121
  # prevent extra attributes during model initialization
122
- extra="forbid",
122
+ extra="ignore",
123
123
  )
@@ -19,4 +19,4 @@ from pydantic import BaseModel, ConfigDict
19
19
  class StrictBaseModel(BaseModel):
20
20
  """Immutable pydantic model which prevents extra attributes."""
21
21
 
22
- model_config = ConfigDict(frozen=True, extra="forbid")
22
+ model_config = ConfigDict(frozen=True, extra="ignore")
@@ -274,7 +274,7 @@ class BaseEntrypointConfiguration(ABC):
274
274
  download_dir = os.path.join(
275
275
  code_repo_root, code_reference.subdirectory
276
276
  )
277
- os.makedirs(download_dir)
277
+ os.makedirs(download_dir, exist_ok=True)
278
278
  repo.download_files(
279
279
  commit=code_reference.commit,
280
280
  directory=download_dir,
zenml/environment.py CHANGED
@@ -15,12 +15,11 @@
15
15
 
16
16
  import os
17
17
  import platform
18
- from pathlib import Path
19
- from typing import Dict
18
+ import subprocess
19
+ from typing import Any, Dict, List
20
20
 
21
21
  import distro
22
22
 
23
- from zenml import __version__
24
23
  from zenml.constants import INSIDE_ZENML_CONTAINER
25
24
  from zenml.enums import EnvironmentType
26
25
  from zenml.logger import get_logger
@@ -29,7 +28,7 @@ from zenml.utils.singleton import SingletonMetaClass
29
28
  logger = get_logger(__name__)
30
29
 
31
30
 
32
- def get_run_environment_dict() -> Dict[str, str]:
31
+ def get_run_environment_dict() -> Dict[str, Any]:
33
32
  """Returns a dictionary of the current run environment.
34
33
 
35
34
  Everything that is returned here will be saved in the DB as
@@ -40,12 +39,24 @@ def get_run_environment_dict() -> Dict[str, str]:
40
39
  Returns:
41
40
  A dictionary of the current run environment.
42
41
  """
43
- return {
44
- "environment": get_environment(),
42
+ env_dict: Dict[str, Any] = {
43
+ "environment": str(get_environment()),
45
44
  **Environment.get_system_info(),
46
45
  "python_version": Environment.python_version(),
47
46
  }
48
47
 
48
+ try:
49
+ python_packages = Environment.get_python_packages()
50
+ except RuntimeError:
51
+ logger.warning("Failed to get list of installed Python packages")
52
+ else:
53
+ # TODO: We send the python packages as a string right now to keep
54
+ # backwards compatibility with old versions. We should update this to
55
+ # be a list of strings eventually.
56
+ env_dict["python_packages"] = "\n".join(python_packages)
57
+
58
+ return env_dict
59
+
49
60
 
50
61
  def get_environment() -> str:
51
62
  """Returns a string representing the execution environment of the pipeline.
@@ -88,35 +99,8 @@ def get_environment() -> str:
88
99
  return EnvironmentType.NATIVE
89
100
 
90
101
 
91
- def get_system_details() -> str:
92
- """Returns OS, python and ZenML information.
93
-
94
- Returns:
95
- str: OS, python and ZenML information
96
- """
97
- from zenml.integrations.registry import integration_registry
98
-
99
- info = {
100
- "ZenML version": __version__,
101
- "Install path": Path(__file__).resolve().parent,
102
- "Python version": Environment.python_version(),
103
- "Platform information": Environment.get_system_info(),
104
- "Environment": get_environment(),
105
- "Integrations": integration_registry.get_installed_integrations(),
106
- }
107
- return "\n".join(
108
- "{:>10} {}".format(k + ":", str(v).replace("\n", " "))
109
- for k, v in info.items()
110
- )
111
-
112
-
113
102
  class Environment(metaclass=SingletonMetaClass):
114
- """Provides environment information.
115
-
116
- Individual environment components can be registered separately to extend
117
- the global Environment object with additional information (see
118
- `BaseEnvironmentComponent`).
119
- """
103
+ """Provides environment information."""
120
104
 
121
105
  def __init__(self) -> None:
122
106
  """Initializes an Environment instance.
@@ -366,3 +350,22 @@ class Environment(metaclass=SingletonMetaClass):
366
350
  "LIGHTNING_CLOUD_URL" in os.environ
367
351
  and "LIGHTNING_CLOUDSPACE_HOST" in os.environ
368
352
  )
353
+
354
+ @staticmethod
355
+ def get_python_packages() -> List[str]:
356
+ """Returns a list of installed Python packages.
357
+
358
+ Raises:
359
+ RuntimeError: If the process to get the list of installed packages
360
+ fails.
361
+
362
+ Returns:
363
+ List of installed packages in pip freeze format.
364
+ """
365
+ try:
366
+ output = subprocess.check_output(["pip", "freeze"]).decode()
367
+ return output.strip().split("\n")
368
+ except subprocess.CalledProcessError:
369
+ raise RuntimeError(
370
+ "Failed to get list of installed Python packages"
371
+ )
zenml/exceptions.py CHANGED
@@ -70,40 +70,6 @@ class DoesNotExistException(ZenMLBaseException):
70
70
  super().__init__(message)
71
71
 
72
72
 
73
- class PipelineNotSucceededException(ZenMLBaseException):
74
- """Raises exception when trying to fetch artifacts from a not succeeded pipeline."""
75
-
76
- def __init__(
77
- self,
78
- name: str = "",
79
- message: str = "{} is not yet completed successfully.",
80
- ):
81
- """Initializes the exception.
82
-
83
- Args:
84
- name: Name of the pipeline.
85
- message: Message with details of exception.
86
- """
87
- super().__init__(message.format(name))
88
-
89
-
90
- class GitException(ZenMLBaseException):
91
- """Raises exception when a problem occurs in git resolution."""
92
-
93
- def __init__(
94
- self,
95
- message: str = "There is a problem with git resolution. "
96
- "Please make sure that all relevant files "
97
- "are committed.",
98
- ):
99
- """Initializes the exception.
100
-
101
- Args:
102
- message: Message with details of exception.
103
- """
104
- super().__init__(message)
105
-
106
-
107
73
  class StepInterfaceError(ZenMLBaseException):
108
74
  """Raises exception when interacting with the Step interface in an unsupported way."""
109
75
 
@@ -116,50 +82,18 @@ class StepContextError(ZenMLBaseException):
116
82
  """Raises exception when interacting with a StepContext in an unsupported way."""
117
83
 
118
84
 
119
- class PipelineInterfaceError(ZenMLBaseException):
120
- """Raises exception when interacting with the Pipeline interface in an unsupported way."""
121
-
122
-
123
- class ArtifactInterfaceError(ZenMLBaseException):
124
- """Raises exception when interacting with the Artifact interface in an unsupported way."""
125
-
126
-
127
85
  class StackComponentInterfaceError(ZenMLBaseException):
128
86
  """Raises exception when interacting with the stack components in an unsupported way."""
129
87
 
130
88
 
131
- class StackComponentDeploymentError(ZenMLBaseException):
132
- """Raises exception when deploying a stack component fails."""
133
-
134
-
135
89
  class ArtifactStoreInterfaceError(ZenMLBaseException):
136
90
  """Raises exception when interacting with the Artifact Store interface in an unsupported way."""
137
91
 
138
92
 
139
- class PipelineConfigurationError(ZenMLBaseException):
140
- """Raises exceptions when a pipeline configuration contains invalid values."""
141
-
142
-
143
93
  class IntegrationError(ZenMLBaseException):
144
94
  """Raises exceptions when a requested integration can not be activated."""
145
95
 
146
96
 
147
- class DuplicateRunNameError(RuntimeError):
148
- """Raises exception when a run with the same name already exists."""
149
-
150
- def __init__(
151
- self,
152
- message: str = "Unable to run a pipeline with a run name that "
153
- "already exists.",
154
- ):
155
- """Initializes the exception.
156
-
157
- Args:
158
- message: Message with details of exception.
159
- """
160
- super().__init__(message)
161
-
162
-
163
97
  class ValidationError(ZenMLBaseException):
164
98
  """Raised when the Model passed to the ZenStore."""
165
99
 
@@ -180,22 +114,10 @@ class StackValidationError(ZenMLBaseException):
180
114
  """Raised when a stack configuration is not valid."""
181
115
 
182
116
 
183
- class StackComponentValidationError(ZenMLBaseException):
184
- """Raised when a stack component configuration is not valid."""
185
-
186
-
187
- class ProvisioningError(ZenMLBaseException):
188
- """Raised when an error occurs when provisioning resources for a StackComponent."""
189
-
190
-
191
117
  class GitNotFoundError(ImportError):
192
118
  """Raised when ZenML CLI is used to interact with examples on a machine with no git installation."""
193
119
 
194
120
 
195
- class DuplicatedConfigurationError(ZenMLBaseException):
196
- """Raised when a configuration parameter is set twice."""
197
-
198
-
199
121
  class IllegalOperationError(ZenMLBaseException):
200
122
  """Raised when an illegal operation is attempted."""
201
123
 
@@ -41,7 +41,7 @@ class AWSIntegration(Integration):
41
41
 
42
42
  NAME = AWS
43
43
  REQUIREMENTS = [
44
- "sagemaker>=2.199.0",
44
+ "sagemaker>=2.237.3",
45
45
  "kubernetes",
46
46
  "aws-profile-manager",
47
47
  ]
@@ -56,6 +56,7 @@ class EvidentlyIntegration(Integration):
56
56
  REQUIREMENTS = [
57
57
  "evidently>=0.4.16,<=0.4.22",
58
58
  "tenacity!=8.4.0", # https://github.com/jd/tenacity/issues/471
59
+ "numpy<2.0.0", # evidently is not compatible with NumPy 2.0
59
60
  ]
60
61
  REQUIREMENTS_IGNORED_ON_UNINSTALL = ["tenacity", "pandas"]
61
62
 
@@ -361,4 +361,4 @@ class EvidentlyMetricConfig(BaseModel):
361
361
  f"`{self.class_path}`: {str(e)}"
362
362
  )
363
363
 
364
- model_config = ConfigDict(extra="forbid")
364
+ model_config = ConfigDict(extra="ignore")
@@ -345,4 +345,4 @@ class EvidentlyTestConfig(BaseModel):
345
345
  f"`{self.class_path}`: {str(e)}"
346
346
  )
347
347
 
348
- model_config = ConfigDict(extra="forbid")
348
+ model_config = ConfigDict(extra="ignore")
@@ -112,6 +112,11 @@ class VertexOrchestratorConfig(
112
112
  network: the full name of the Compute Engine Network to which the job
113
113
  should be peered. For example, `projects/12345/global/networks/myVPC`
114
114
  If not provided, the job will not be peered with any network.
115
+ private_service_connect: the full name of a Private Service Connect
116
+ endpoint to which the job should be peered. For example,
117
+ `projects/12345/regions/us-central1/networkAttachments/NETWORK_ATTACHMENT_NAME`
118
+ If not provided, the job will not be peered with any private service
119
+ connect endpoint.
115
120
  cpu_limit: The maximum CPU limit for this operator. This string value
116
121
  can be a number (integer value for number of CPUs) as string,
117
122
  or a number followed by "m", which means 1/1000. You can specify
@@ -130,6 +135,7 @@ class VertexOrchestratorConfig(
130
135
  encryption_spec_key_name: Optional[str] = None
131
136
  workload_service_account: Optional[str] = None
132
137
  network: Optional[str] = None
138
+ private_service_connect: Optional[str] = None
133
139
 
134
140
  # Deprecated
135
141
  cpu_limit: Optional[str] = None
@@ -48,7 +48,15 @@ from uuid import UUID
48
48
 
49
49
  from google.api_core import exceptions as google_exceptions
50
50
  from google.cloud import aiplatform
51
+ from google.cloud.aiplatform.compat.services import (
52
+ pipeline_service_client_v1beta1,
53
+ )
54
+ from google.cloud.aiplatform.compat.types import pipeline_job_v1beta1
51
55
  from google.cloud.aiplatform_v1.types import PipelineState
56
+ from google.cloud.aiplatform_v1beta1.types.service_networking import (
57
+ PscInterfaceConfig,
58
+ )
59
+ from google.protobuf import json_format
52
60
  from google_cloud_pipeline_components.v1.custom_job.utils import (
53
61
  create_custom_training_job_from_component,
54
62
  )
@@ -495,36 +503,16 @@ class VertexOrchestrator(ContainerizedOrchestrator, GoogleCredentialsMixin):
495
503
  )
496
504
  pod_settings = step_settings.pod_settings
497
505
  if pod_settings:
498
- if pod_settings.host_ipc:
499
- logger.warning(
500
- "Host IPC is set to `True` but not supported in "
501
- "this orchestrator. Ignoring..."
502
- )
503
- if pod_settings.affinity:
504
- logger.warning(
505
- "Affinity is set but not supported in Vertex with "
506
- "Kubeflow Pipelines 2.x. Ignoring..."
507
- )
508
- if pod_settings.tolerations:
509
- logger.warning(
510
- "Tolerations are set but not supported in "
511
- "Vertex with Kubeflow Pipelines 2.x. Ignoring..."
512
- )
513
- if pod_settings.volumes:
514
- logger.warning(
515
- "Volumes are set but not supported in Vertex with "
516
- "Kubeflow Pipelines 2.x. Ignoring..."
517
- )
518
- if pod_settings.volume_mounts:
519
- logger.warning(
520
- "Volume mounts are set but not supported in "
521
- "Vertex with Kubeflow Pipelines 2.x. Ignoring..."
522
- )
523
- if pod_settings.env or pod_settings.env_from:
506
+ ignored_fields = pod_settings.model_fields_set - {
507
+ "node_selectors"
508
+ }
509
+ if ignored_fields:
524
510
  logger.warning(
525
- "Environment variables are set but not supported "
526
- "in Vertex with Vertex Pipelines 2.x. Ignoring..."
511
+ f"The following pod settings are not supported in "
512
+ f"Vertex with Vertex Pipelines 2.x and will be "
513
+ f"ignored: {list(ignored_fields)}."
527
514
  )
515
+
528
516
  for key in pod_settings.node_selectors:
529
517
  if (
530
518
  key
@@ -737,6 +725,39 @@ class VertexOrchestrator(ContainerizedOrchestrator, GoogleCredentialsMixin):
737
725
  self.config.network,
738
726
  )
739
727
 
728
+ if self.config.private_service_connect:
729
+ # The PSC setting isn't yet part of the stable v1 API. We need to
730
+ # temporarily hack the aiplatform.PipelineJob object in two places:
731
+ # * to use the v1beta1 PipelineJob primitive which supports the
732
+ # psc_interface_config field instead of the v1 PipelineJob
733
+ # primitive.
734
+ # * to use the v1beta1 PipelineServiceClient instead of the v1
735
+ # PipelineServiceClient.
736
+ #
737
+ # We achieve the first by converting the v1 PipelineJob to a
738
+ # v1beta1 PipelineJob and the second by replacing the v1
739
+ # PipelineServiceClient with a v1beta1 PipelineServiceClient.
740
+ #
741
+ # TODO: Remove this once the v1 stable API is updated to support
742
+ # the PSC setting.
743
+ pipeline_job_dict = json_format.MessageToDict(
744
+ run._gca_resource._pb, preserving_proto_field_name=True
745
+ )
746
+ run._gca_resource = pipeline_job_v1beta1.PipelineJob(
747
+ **pipeline_job_dict,
748
+ psc_interface_config=PscInterfaceConfig(
749
+ network_attachment=self.config.private_service_connect,
750
+ ),
751
+ )
752
+ run.api_client = (
753
+ pipeline_service_client_v1beta1.PipelineServiceClient(
754
+ credentials=run.credentials,
755
+ client_options={
756
+ "api_endpoint": run.api_client.api_endpoint,
757
+ },
758
+ )
759
+ )
760
+
740
761
  try:
741
762
  if schedule:
742
763
  logger.info(
@@ -555,36 +555,14 @@ class KubeflowOrchestrator(ContainerizedOrchestrator):
555
555
  )
556
556
  pod_settings = step_settings.pod_settings
557
557
  if pod_settings:
558
- if pod_settings.host_ipc:
558
+ ignored_fields = pod_settings.model_fields_set - {
559
+ "node_selectors"
560
+ }
561
+ if ignored_fields:
559
562
  logger.warning(
560
- "Host IPC is set to `True` but not supported in "
561
- "this orchestrator. Ignoring..."
562
- )
563
- if pod_settings.affinity:
564
- logger.warning(
565
- "Affinity is set but not supported in Kubeflow with "
566
- "Kubeflow Pipelines 2.x. Ignoring..."
567
- )
568
- if pod_settings.tolerations:
569
- logger.warning(
570
- "Tolerations are set but not supported in "
571
- "Kubeflow with Kubeflow Pipelines 2.x. Ignoring..."
572
- )
573
- if pod_settings.volumes:
574
- logger.warning(
575
- "Volumes are set but not supported in Kubeflow with "
576
- "Kubeflow Pipelines 2.x. Ignoring..."
577
- )
578
- if pod_settings.volume_mounts:
579
- logger.warning(
580
- "Volume mounts are set but not supported in "
581
- "Kubeflow with Kubeflow Pipelines 2.x. Ignoring..."
582
- )
583
- if pod_settings.env or pod_settings.env_from:
584
- logger.warning(
585
- "Environment variables are set but not supported "
586
- "in Kubeflow with Kubeflow Pipelines 2.x. "
587
- "Ignoring..."
563
+ f"The following pod settings are not supported in "
564
+ f"Kubeflow with Kubeflow Pipelines 2.x and will be "
565
+ f"ignored: {list(ignored_fields)}."
588
566
  )
589
567
 
590
568
  # apply pod settings
@@ -15,6 +15,8 @@
15
15
 
16
16
  from typing import TYPE_CHECKING, Optional, Type
17
17
 
18
+ from pydantic import PositiveInt
19
+
18
20
  from zenml.config.base_settings import BaseSettings
19
21
  from zenml.constants import KUBERNETES_CLUSTER_RESOURCE_TYPE
20
22
  from zenml.integrations.kubernetes import KUBERNETES_ORCHESTRATOR_FLAVOR
@@ -47,6 +49,7 @@ class KubernetesOrchestratorSettings(BaseSettings):
47
49
  pod_settings: Pod settings to apply to pods executing the steps.
48
50
  orchestrator_pod_settings: Pod settings to apply to the pod which is
49
51
  launching the actual steps.
52
+ pod_name_prefix: Prefix to use for the pod name.
50
53
  pod_startup_timeout: The maximum time to wait for a pending step pod to
51
54
  start (in seconds).
52
55
  pod_failure_max_retries: The maximum number of times to retry a step
@@ -55,6 +58,7 @@ class KubernetesOrchestratorSettings(BaseSettings):
55
58
  failure retries and pod startup retries (in seconds)
56
59
  pod_failure_backoff: The backoff factor for pod failure retries and
57
60
  pod startup retries.
61
+ max_parallelism: Maximum number of steps to run in parallel.
58
62
  """
59
63
 
60
64
  synchronous: bool = True
@@ -64,10 +68,12 @@ class KubernetesOrchestratorSettings(BaseSettings):
64
68
  privileged: bool = False
65
69
  pod_settings: Optional[KubernetesPodSettings] = None
66
70
  orchestrator_pod_settings: Optional[KubernetesPodSettings] = None
71
+ pod_name_prefix: Optional[str] = None
67
72
  pod_startup_timeout: int = 60 * 10 # Default 10 minutes
68
73
  pod_failure_max_retries: int = 3
69
74
  pod_failure_retry_delay: int = 10
70
75
  pod_failure_backoff: float = 1.0
76
+ max_parallelism: Optional[PositiveInt] = None
71
77
 
72
78
 
73
79
  class KubernetesOrchestratorConfig(
@@ -417,6 +417,9 @@ class KubernetesOrchestrator(ContainerizedOrchestrator):
417
417
  )
418
418
 
419
419
  pipeline_name = deployment.pipeline_configuration.name
420
+ settings = cast(
421
+ KubernetesOrchestratorSettings, self.get_settings(deployment)
422
+ )
420
423
 
421
424
  # We already make sure the orchestrator run name has the correct length
422
425
  # to make sure we don't cut off the randomized suffix later when
@@ -427,8 +430,16 @@ class KubernetesOrchestrator(ContainerizedOrchestrator):
427
430
  orchestrator_run_name = get_orchestrator_run_name(
428
431
  pipeline_name, max_length=max_length
429
432
  )
433
+
434
+ if settings.pod_name_prefix:
435
+ pod_name = get_orchestrator_run_name(
436
+ settings.pod_name_prefix, max_length=max_length
437
+ )
438
+ else:
439
+ pod_name = orchestrator_run_name
440
+
430
441
  pod_name = kube_utils.sanitize_pod_name(
431
- orchestrator_run_name, namespace=self.config.kubernetes_namespace
442
+ pod_name, namespace=self.config.kubernetes_namespace
432
443
  )
433
444
 
434
445
  assert stack.container_registry
@@ -455,10 +466,6 @@ class KubernetesOrchestrator(ContainerizedOrchestrator):
455
466
  run_id=placeholder_run.id if placeholder_run else None,
456
467
  )
457
468
 
458
- settings = cast(
459
- KubernetesOrchestratorSettings, self.get_settings(deployment)
460
- )
461
-
462
469
  # Authorize pod to run Kubernetes commands inside the cluster.
463
470
  service_account_name = self._get_service_account_name(settings)
464
471