zenml-nightly 0.81.0.dev20250428__py3-none-any.whl → 0.81.0.dev20250429__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 (26) hide show
  1. zenml/VERSION +1 -1
  2. zenml/config/build_configuration.py +4 -0
  3. zenml/entrypoints/base_entrypoint_configuration.py +1 -1
  4. zenml/environment.py +1 -30
  5. zenml/exceptions.py +0 -78
  6. zenml/integrations/aws/__init__.py +1 -1
  7. zenml/integrations/evidently/__init__.py +1 -0
  8. zenml/integrations/gcp/flavors/vertex_orchestrator_flavor.py +6 -0
  9. zenml/integrations/gcp/orchestrators/vertex_orchestrator.py +49 -28
  10. zenml/integrations/kubeflow/orchestrators/kubeflow_orchestrator.py +7 -29
  11. zenml/integrations/kubernetes/flavors/kubernetes_orchestrator_flavor.py +6 -0
  12. zenml/integrations/kubernetes/orchestrators/kubernetes_orchestrator.py +12 -5
  13. zenml/integrations/kubernetes/orchestrators/kubernetes_orchestrator_entrypoint.py +31 -18
  14. zenml/integrations/kubernetes/orchestrators/manifest_utils.py +21 -0
  15. zenml/integrations/kubernetes/pod_settings.py +6 -1
  16. zenml/integrations/numpy/__init__.py +4 -1
  17. zenml/integrations/numpy/materializers/numpy_materializer.py +75 -6
  18. zenml/integrations/tekton/orchestrators/tekton_orchestrator.py +8 -28
  19. zenml/orchestrators/dag_runner.py +50 -14
  20. zenml/utils/code_utils.py +1 -1
  21. zenml/zen_server/exceptions.py +0 -2
  22. {zenml_nightly-0.81.0.dev20250428.dist-info → zenml_nightly-0.81.0.dev20250429.dist-info}/METADATA +2 -2
  23. {zenml_nightly-0.81.0.dev20250428.dist-info → zenml_nightly-0.81.0.dev20250429.dist-info}/RECORD +26 -26
  24. {zenml_nightly-0.81.0.dev20250428.dist-info → zenml_nightly-0.81.0.dev20250429.dist-info}/LICENSE +0 -0
  25. {zenml_nightly-0.81.0.dev20250428.dist-info → zenml_nightly-0.81.0.dev20250429.dist-info}/WHEEL +0 -0
  26. {zenml_nightly-0.81.0.dev20250428.dist-info → zenml_nightly-0.81.0.dev20250429.dist-info}/entry_points.txt +0 -0
zenml/VERSION CHANGED
@@ -1 +1 @@
1
- 0.81.0.dev20250428
1
+ 0.81.0.dev20250429
@@ -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(
@@ -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,10 @@
15
15
 
16
16
  import os
17
17
  import platform
18
- from pathlib import Path
19
18
  from typing import Dict
20
19
 
21
20
  import distro
22
21
 
23
- from zenml import __version__
24
22
  from zenml.constants import INSIDE_ZENML_CONTAINER
25
23
  from zenml.enums import EnvironmentType
26
24
  from zenml.logger import get_logger
@@ -88,35 +86,8 @@ def get_environment() -> str:
88
86
  return EnvironmentType.NATIVE
89
87
 
90
88
 
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
89
  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
- """
90
+ """Provides environment information."""
120
91
 
121
92
  def __init__(self) -> None:
122
93
  """Initializes an Environment instance.
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
 
@@ -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
 
@@ -15,7 +15,7 @@
15
15
 
16
16
  import argparse
17
17
  import socket
18
- from typing import Any, Dict
18
+ from typing import Any, Dict, cast
19
19
  from uuid import UUID
20
20
 
21
21
  from kubernetes import client as k8s_client
@@ -41,7 +41,10 @@ from zenml.integrations.kubernetes.orchestrators.manifest_utils import (
41
41
  from zenml.logger import get_logger
42
42
  from zenml.orchestrators import publish_utils
43
43
  from zenml.orchestrators.dag_runner import NodeStatus, ThreadedDagRunner
44
- from zenml.orchestrators.utils import get_config_environment_vars
44
+ from zenml.orchestrators.utils import (
45
+ get_config_environment_vars,
46
+ get_orchestrator_run_name,
47
+ )
45
48
 
46
49
  logger = get_logger(__name__)
47
50
 
@@ -103,8 +106,27 @@ def main() -> None:
103
106
  Raises:
104
107
  Exception: If the pod fails to start.
105
108
  """
106
- # Define Kubernetes pod name.
107
- pod_name = f"{orchestrator_run_id}-{step_name}"
109
+ step_config = deployment_config.step_configurations[step_name].config
110
+ settings = step_config.settings.get("orchestrator.kubernetes", None)
111
+ settings = KubernetesOrchestratorSettings.model_validate(
112
+ settings.model_dump() if settings else {}
113
+ )
114
+
115
+ if settings.pod_name_prefix and not orchestrator_run_id.startswith(
116
+ settings.pod_name_prefix
117
+ ):
118
+ max_length = (
119
+ kube_utils.calculate_max_pod_name_length_for_namespace(
120
+ namespace=args.kubernetes_namespace
121
+ )
122
+ )
123
+ pod_name_prefix = get_orchestrator_run_name(
124
+ settings.pod_name_prefix, max_length=max_length
125
+ )
126
+ pod_name = f"{pod_name_prefix}-{step_name}"
127
+ else:
128
+ pod_name = f"{orchestrator_run_id}-{step_name}"
129
+
108
130
  pod_name = kube_utils.sanitize_pod_name(
109
131
  pod_name, namespace=args.kubernetes_namespace
110
132
  )
@@ -116,20 +138,6 @@ def main() -> None:
116
138
  step_name=step_name, deployment_id=deployment_config.id
117
139
  )
118
140
 
119
- step_config = deployment_config.step_configurations[step_name].config
120
-
121
- kubernetes_settings = step_config.settings.get(
122
- "orchestrator.kubernetes", None
123
- )
124
-
125
- orchestrator_settings = {}
126
- if kubernetes_settings is not None:
127
- orchestrator_settings = kubernetes_settings.model_dump()
128
-
129
- settings = KubernetesOrchestratorSettings.model_validate(
130
- orchestrator_settings
131
- )
132
-
133
141
  # We set some default minimum memory resource requests for the step pod
134
142
  # here if the user has not specified any, because the step pod takes up
135
143
  # some memory resources itself and, if not specified, the pod will be
@@ -274,12 +282,17 @@ def main() -> None:
274
282
  parallel_node_startup_waiting_period = (
275
283
  orchestrator.config.parallel_step_startup_waiting_period or 0.0
276
284
  )
285
+ settings = cast(
286
+ KubernetesOrchestratorSettings,
287
+ orchestrator.get_settings(deployment_config),
288
+ )
277
289
  try:
278
290
  ThreadedDagRunner(
279
291
  dag=pipeline_dag,
280
292
  run_fn=run_step_on_kubernetes,
281
293
  finalize_fn=finalize_run,
282
294
  parallel_node_startup_waiting_period=parallel_node_startup_waiting_period,
295
+ max_parallelism=settings.max_parallelism,
283
296
  ).run()
284
297
  logger.info("Orchestration pod completed.")
285
298
  finally:
@@ -28,6 +28,9 @@ from zenml.integrations.airflow.orchestrators.dag_generator import (
28
28
  )
29
29
  from zenml.integrations.kubernetes.orchestrators import kube_utils
30
30
  from zenml.integrations.kubernetes.pod_settings import KubernetesPodSettings
31
+ from zenml.logger import get_logger
32
+
33
+ logger = get_logger(__name__)
31
34
 
32
35
 
33
36
  def add_local_stores_mount(
@@ -244,6 +247,24 @@ def add_pod_settings(
244
247
  if settings.host_ipc:
245
248
  pod_spec.host_ipc = settings.host_ipc
246
249
 
250
+ if settings.scheduler_name:
251
+ pod_spec.scheduler_name = settings.scheduler_name
252
+
253
+ for key, value in settings.additional_pod_spec_args.items():
254
+ if not hasattr(pod_spec, key):
255
+ logger.warning(f"Ignoring invalid Pod Spec argument `{key}`.")
256
+ else:
257
+ if value is None:
258
+ continue
259
+
260
+ existing_value = getattr(pod_spec, key)
261
+ if isinstance(existing_value, list):
262
+ existing_value.extend(value)
263
+ elif isinstance(existing_value, dict):
264
+ existing_value.update(value)
265
+ else:
266
+ setattr(pod_spec, key, value)
267
+
247
268
 
248
269
  def build_cron_job_manifest(
249
270
  cron_expression: str,
@@ -13,7 +13,7 @@
13
13
  # permissions and limitations under the License.
14
14
  """Kubernetes pod settings."""
15
15
 
16
- from typing import Any, Dict, List
16
+ from typing import Any, Dict, List, Optional
17
17
 
18
18
  from pydantic import field_validator
19
19
 
@@ -33,10 +33,13 @@ class KubernetesPodSettings(BaseSettings):
33
33
  volumes: Volumes to mount in the pod.
34
34
  volume_mounts: Volume mounts to apply to the pod containers.
35
35
  host_ipc: Whether to enable host IPC for the pod.
36
+ scheduler_name: The name of the scheduler to use for the pod.
36
37
  image_pull_secrets: Image pull secrets to use for the pod.
37
38
  labels: Labels to apply to the pod.
38
39
  env: Environment variables to apply to the container.
39
40
  env_from: Environment variables to apply to the container.
41
+ additional_pod_spec_args: Additional arguments to pass to the pod. These
42
+ will be applied to the pod spec.
40
43
  """
41
44
 
42
45
  node_selectors: Dict[str, str] = {}
@@ -47,10 +50,12 @@ class KubernetesPodSettings(BaseSettings):
47
50
  volumes: List[Dict[str, Any]] = []
48
51
  volume_mounts: List[Dict[str, Any]] = []
49
52
  host_ipc: bool = False
53
+ scheduler_name: Optional[str] = None
50
54
  image_pull_secrets: List[str] = []
51
55
  labels: Dict[str, str] = {}
52
56
  env: List[Dict[str, Any]] = []
53
57
  env_from: List[Dict[str, Any]] = []
58
+ additional_pod_spec_args: Dict[str, Any] = {}
54
59
 
55
60
  @field_validator("volumes", mode="before")
56
61
  @classmethod
@@ -21,7 +21,10 @@ class NumpyIntegration(Integration):
21
21
  """Definition of Numpy integration for ZenML."""
22
22
 
23
23
  NAME = NUMPY
24
- REQUIREMENTS = ["numpy<2.0.0"]
24
+ # Support both NumPy 1.x and 2.x
25
+ # Note: Some other integrations (like evidently) may require NumPy <2.0
26
+ # until they are updated for NumPy 2.0 compatibility
27
+ REQUIREMENTS = ["numpy<3.0"]
25
28
 
26
29
  @classmethod
27
30
  def activate(cls) -> None:
@@ -15,7 +15,16 @@
15
15
 
16
16
  import os
17
17
  from collections import Counter
18
- from typing import TYPE_CHECKING, Any, ClassVar, Dict, Tuple, Type
18
+ from typing import (
19
+ TYPE_CHECKING,
20
+ Any,
21
+ ClassVar,
22
+ Dict,
23
+ Optional,
24
+ Tuple,
25
+ Type,
26
+ Union,
27
+ )
19
28
 
20
29
  import numpy as np
21
30
 
@@ -36,6 +45,48 @@ DATA_FILENAME = "data.parquet"
36
45
  SHAPE_FILENAME = "shape.json"
37
46
  DATA_VAR = "data_var"
38
47
 
48
+ # Check NumPy version for compatibility handling
49
+ IS_NUMPY_2 = np.lib.NumpyVersion(np.__version__) >= "2.0.0"
50
+
51
+ # In NumPy 2.0, np.object_ is deprecated in favor of object
52
+ # Let's use the right type based on the NumPy version
53
+ NUMPY_OBJECT_TYPE = object if IS_NUMPY_2 else np.object_
54
+
55
+
56
+ def _ensure_dtype_compatibility(arr: "NDArray[Any]") -> "NDArray[Any]":
57
+ """Ensure consistent dtype handling across NumPy versions.
58
+
59
+ Args:
60
+ arr: NumPy array to ensure compatible dtype handling
61
+
62
+ Returns:
63
+ NumPy array with consistent dtype behavior
64
+ """
65
+ if IS_NUMPY_2:
66
+ return arr # NumPy 2.0 already preserves precision
67
+ else:
68
+ # For 1.x, explicitly preserve precision when needed
69
+ return arr.astype(arr.dtype, copy=False)
70
+
71
+
72
+ def _create_array(
73
+ data: Any, dtype: Optional[Union["np.dtype[Any]", Type[Any]]] = None
74
+ ) -> "NDArray[Any]":
75
+ """Create arrays with consistent behavior across NumPy versions.
76
+
77
+ Args:
78
+ data: Data to convert to array
79
+ dtype: Optional dtype to use
80
+
81
+ Returns:
82
+ NumPy array with consistent creation behavior
83
+ """
84
+ if IS_NUMPY_2:
85
+ return np.asarray(data, dtype=dtype)
86
+ else:
87
+ # In NumPy 1.x, copy behavior is different
88
+ return np.array(data, dtype=dtype, copy=False)
89
+
39
90
 
40
91
  class NumpyMaterializer(BaseMaterializer):
41
92
  """Materializer to read data to and from pandas."""
@@ -60,7 +111,9 @@ class NumpyMaterializer(BaseMaterializer):
60
111
 
61
112
  if self.artifact_store.exists(numpy_file):
62
113
  with self.artifact_store.open(numpy_file, "rb") as f:
63
- return np.load(f, allow_pickle=True)
114
+ arr = np.load(f, allow_pickle=True)
115
+ # Ensure consistent dtype handling
116
+ return _ensure_dtype_compatibility(arr)
64
117
  elif self.artifact_store.exists(os.path.join(self.uri, DATA_FILENAME)):
65
118
  logger.warning(
66
119
  "A legacy artifact was found. "
@@ -86,7 +139,9 @@ class NumpyMaterializer(BaseMaterializer):
86
139
  input_stream = pa.input_stream(f)
87
140
  data = pq.read_table(input_stream)
88
141
  vals = getattr(data.to_pandas(), DATA_VAR).values
89
- return np.reshape(vals, shape_tuple)
142
+ arr = np.reshape(vals, shape_tuple)
143
+ # Ensure consistent dtype handling
144
+ return _ensure_dtype_compatibility(arr)
90
145
  except ImportError:
91
146
  raise ImportError(
92
147
  "You have an old version of a `NumpyMaterializer` ",
@@ -101,6 +156,9 @@ class NumpyMaterializer(BaseMaterializer):
101
156
  Args:
102
157
  arr: The numpy array to write.
103
158
  """
159
+ # Ensure consistent dtype handling before saving
160
+ arr = _ensure_dtype_compatibility(arr)
161
+
104
162
  with self.artifact_store.open(
105
163
  os.path.join(self.uri, NUMPY_FILENAME), "wb"
106
164
  ) as f:
@@ -186,8 +244,8 @@ class NumpyMaterializer(BaseMaterializer):
186
244
  """
187
245
  if np.issubdtype(arr.dtype, np.number):
188
246
  return self._extract_numeric_metadata(arr)
189
- elif np.issubdtype(arr.dtype, np.unicode_) or np.issubdtype(
190
- arr.dtype, np.object_
247
+ elif np.issubdtype(arr.dtype, np.str_) or np.issubdtype(
248
+ arr.dtype, NUMPY_OBJECT_TYPE
191
249
  ):
192
250
  return self._extract_text_metadata(arr)
193
251
  else:
@@ -204,6 +262,9 @@ class NumpyMaterializer(BaseMaterializer):
204
262
  Returns:
205
263
  A dictionary of metadata.
206
264
  """
265
+ # Ensure consistent precision handling
266
+ arr = _ensure_dtype_compatibility(arr)
267
+
207
268
  min_val = np.min(arr).item()
208
269
  max_val = np.max(arr).item()
209
270
 
@@ -228,7 +289,15 @@ class NumpyMaterializer(BaseMaterializer):
228
289
  Returns:
229
290
  A dictionary of metadata.
230
291
  """
231
- text = " ".join(arr)
292
+ # Convert all array elements to strings explicitly to handle
293
+ # mixed types and ensure NumPy 2.0 compatibility
294
+ str_items = [str(item) for item in arr.flat]
295
+ # Use dtype='U' (unicode string) instead of str to avoid type issues
296
+ str_arr = _create_array(str_items, dtype=np.dtype("U")).reshape(
297
+ arr.shape
298
+ )
299
+
300
+ text = " ".join(str_arr)
232
301
  words = text.split()
233
302
  word_counts = Counter(words)
234
303
  unique_words = len(word_counts)
@@ -524,36 +524,16 @@ class TektonOrchestrator(ContainerizedOrchestrator):
524
524
  node_selector_constraint: Optional[Tuple[str, str]] = None
525
525
  pod_settings = step_settings.pod_settings
526
526
  if pod_settings:
527
- if pod_settings.host_ipc:
527
+ ignored_fields = pod_settings.model_fields_set - {
528
+ "node_selectors"
529
+ }
530
+ if ignored_fields:
528
531
  logger.warning(
529
- "Host IPC is set to `True` but not supported in "
530
- "this orchestrator. Ignoring..."
531
- )
532
- if pod_settings.affinity:
533
- logger.warning(
534
- "Affinity is set but not supported in Tekton with "
535
- "Tekton Pipelines 2.x. Ignoring..."
536
- )
537
- if pod_settings.tolerations:
538
- logger.warning(
539
- "Tolerations are set but not supported in "
540
- "Tekton with Tekton Pipelines 2.x. Ignoring..."
541
- )
542
- if pod_settings.volumes:
543
- logger.warning(
544
- "Volumes are set but not supported in Tekton with "
545
- "Tekton Pipelines 2.x. Ignoring..."
546
- )
547
- if pod_settings.volume_mounts:
548
- logger.warning(
549
- "Volume mounts are set but not supported in "
550
- "Tekton with Tekton Pipelines 2.x. Ignoring..."
551
- )
552
- if pod_settings.env or pod_settings.env_from:
553
- logger.warning(
554
- "Environment variables are set but not supported "
555
- "in Tekton with Tekton Pipelines 2.x. Ignoring..."
532
+ f"The following pod settings are not supported in "
533
+ f"Tekton with Tekton Pipelines 2.x and will be "
534
+ f"ignored: {list(ignored_fields)}."
556
535
  )
536
+
557
537
  # apply pod settings
558
538
  if (
559
539
  KFP_ACCELERATOR_NODE_SELECTOR_CONSTRAINT_LABEL
@@ -51,10 +51,11 @@ def reverse_dag(dag: Dict[str, List[str]]) -> Dict[str, List[str]]:
51
51
  class NodeStatus(Enum):
52
52
  """Status of the execution of a node."""
53
53
 
54
- WAITING = "Waiting"
55
- RUNNING = "Running"
56
- COMPLETED = "Completed"
57
- FAILED = "Failed"
54
+ NOT_STARTED = "not_started"
55
+ PENDING = "pending"
56
+ RUNNING = "running"
57
+ COMPLETED = "completed"
58
+ FAILED = "failed"
58
59
 
59
60
 
60
61
  class ThreadedDagRunner:
@@ -73,6 +74,7 @@ class ThreadedDagRunner:
73
74
  run_fn: Callable[[str], Any],
74
75
  finalize_fn: Optional[Callable[[Dict[str, NodeStatus]], None]] = None,
75
76
  parallel_node_startup_waiting_period: float = 0.0,
77
+ max_parallelism: Optional[int] = None,
76
78
  ) -> None:
77
79
  """Define attributes and initialize all nodes in waiting state.
78
80
 
@@ -85,16 +87,26 @@ class ThreadedDagRunner:
85
87
  when all nodes have completed.
86
88
  parallel_node_startup_waiting_period: Delay in seconds to wait in
87
89
  between starting parallel nodes.
90
+ max_parallelism: Maximum number of nodes to run in parallel
91
+
92
+ Raises:
93
+ ValueError: If max_parallelism is not greater than 0.
88
94
  """
95
+ if max_parallelism is not None and max_parallelism <= 0:
96
+ raise ValueError("max_parallelism must be greater than 0")
97
+
89
98
  self.parallel_node_startup_waiting_period = (
90
99
  parallel_node_startup_waiting_period
91
100
  )
101
+ self.max_parallelism = max_parallelism
92
102
  self.dag = dag
93
103
  self.reversed_dag = reverse_dag(dag)
94
104
  self.run_fn = run_fn
95
105
  self.finalize_fn = finalize_fn
96
106
  self.nodes = dag.keys()
97
- self.node_states = {node: NodeStatus.WAITING for node in self.nodes}
107
+ self.node_states = {
108
+ node: NodeStatus.NOT_STARTED for node in self.nodes
109
+ }
98
110
  self._lock = threading.Lock()
99
111
 
100
112
  def _can_run(self, node: str) -> bool:
@@ -109,8 +121,7 @@ class ThreadedDagRunner:
109
121
  Returns:
110
122
  True if the node can run else False.
111
123
  """
112
- # Check that node has not run yet.
113
- if not self.node_states[node] == NodeStatus.WAITING:
124
+ if not self.node_states[node] == NodeStatus.NOT_STARTED:
114
125
  return False
115
126
 
116
127
  # Check that all upstream nodes of this node have already completed.
@@ -120,6 +131,33 @@ class ThreadedDagRunner:
120
131
 
121
132
  return True
122
133
 
134
+ def _prepare_node_run(self, node: str) -> None:
135
+ """Prepare a node run.
136
+
137
+ Args:
138
+ node: The node.
139
+ """
140
+ if self.max_parallelism is None:
141
+ with self._lock:
142
+ self.node_states[node] = NodeStatus.RUNNING
143
+ else:
144
+ while True:
145
+ with self._lock:
146
+ logger.debug(f"Checking if {node} can run.")
147
+ running_nodes = len(
148
+ [
149
+ state
150
+ for state in self.node_states.values()
151
+ if state == NodeStatus.RUNNING
152
+ ]
153
+ )
154
+ if running_nodes < self.max_parallelism:
155
+ self.node_states[node] = NodeStatus.RUNNING
156
+ break
157
+
158
+ logger.debug(f"Waiting for {running_nodes} nodes to finish.")
159
+ time.sleep(10)
160
+
123
161
  def _run_node(self, node: str) -> None:
124
162
  """Run a single node.
125
163
 
@@ -128,6 +166,8 @@ class ThreadedDagRunner:
128
166
  Args:
129
167
  node: The node.
130
168
  """
169
+ self._prepare_node_run(node)
170
+
131
171
  try:
132
172
  self.run_fn(node)
133
173
  self._finish_node(node)
@@ -138,19 +178,15 @@ class ThreadedDagRunner:
138
178
  def _run_node_in_thread(self, node: str) -> threading.Thread:
139
179
  """Run a single node in a separate thread.
140
180
 
141
- First updates the node status to running.
142
- Then calls self._run_node() in a new thread and returns the thread.
143
-
144
181
  Args:
145
182
  node: The node.
146
183
 
147
184
  Returns:
148
185
  The thread in which the node was run.
149
186
  """
150
- # Update node status to running.
151
- assert self.node_states[node] == NodeStatus.WAITING
187
+ assert self.node_states[node] == NodeStatus.NOT_STARTED
152
188
  with self._lock:
153
- self.node_states[node] = NodeStatus.RUNNING
189
+ self.node_states[node] = NodeStatus.PENDING
154
190
 
155
191
  # Run node in new thread.
156
192
  thread = threading.Thread(target=self._run_node, args=(node,))
@@ -225,7 +261,7 @@ class ThreadedDagRunner:
225
261
  for node in self.nodes:
226
262
  if self.node_states[node] == NodeStatus.FAILED:
227
263
  failed_nodes.append(node)
228
- elif self.node_states[node] == NodeStatus.WAITING:
264
+ elif self.node_states[node] == NodeStatus.NOT_STARTED:
229
265
  skipped_nodes.append(node)
230
266
 
231
267
  if failed_nodes:
zenml/utils/code_utils.py CHANGED
@@ -283,7 +283,7 @@ def download_code_from_artifact_store(
283
283
  artifact_store._register()
284
284
 
285
285
  extract_dir = os.path.abspath("code")
286
- os.makedirs(extract_dir)
286
+ os.makedirs(extract_dir, exist_ok=True)
287
287
 
288
288
  download_and_extract_code(code_path=code_path, extract_dir=extract_dir)
289
289
 
@@ -22,7 +22,6 @@ from zenml.exceptions import (
22
22
  AuthorizationException,
23
23
  CredentialsNotValid,
24
24
  DoesNotExistException,
25
- DuplicateRunNameError,
26
25
  EntityCreationError,
27
26
  EntityExistsError,
28
27
  IllegalOperationError,
@@ -69,7 +68,6 @@ error_response = dict(model=ErrorModel)
69
68
  # different status codes (e.g. `ValueError` and the 400 and 422 status codes).
70
69
  REST_API_EXCEPTIONS: List[Tuple[Type[Exception], int]] = [
71
70
  # 409 Conflict
72
- (DuplicateRunNameError, 409),
73
71
  (EntityExistsError, 409),
74
72
  # 403 Forbidden
75
73
  (IllegalOperationError, 403),
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: zenml-nightly
3
- Version: 0.81.0.dev20250428
3
+ Version: 0.81.0.dev20250429
4
4
  Summary: ZenML: Write production-ready ML code.
5
5
  License: Apache-2.0
6
6
  Keywords: machine learning,production,pipeline,mlops,devops
@@ -110,7 +110,7 @@ Requires-Dist: requests (>=2.27.11,<3.0.0) ; extra == "connectors-azure"
110
110
  Requires-Dist: rich[jupyter] (>=12.0.0)
111
111
  Requires-Dist: ruff (>=0.1.7) ; extra == "templates" or extra == "dev"
112
112
  Requires-Dist: s3fs (>=2022.11.0,!=2025.3.1) ; extra == "s3fs"
113
- Requires-Dist: sagemaker (>=2.199.0) ; extra == "sagemaker"
113
+ Requires-Dist: sagemaker (>=2.237.3) ; extra == "sagemaker"
114
114
  Requires-Dist: secure (>=0.3.0,<0.4.0) ; extra == "server"
115
115
  Requires-Dist: setuptools
116
116
  Requires-Dist: sqlalchemy (>=2.0.0,<3.0.0)
@@ -1,5 +1,5 @@
1
1
  zenml/README.md,sha256=827dekbOWAs1BpW7VF1a4d7EbwPbjwccX-2zdXBENZo,1777
2
- zenml/VERSION,sha256=mqIIfKSgM9a747yV1iWctiuoWQks6eRjizzoouMuDDg,19
2
+ zenml/VERSION,sha256=fikJ9F_ekw4wug-gVMiZuNsv_TnkQEfUs2JTtk2Acvw,19
3
3
  zenml/__init__.py,sha256=CKEyepFK-7akXYiMrNVh92Nb01Cjs23w4_YyI6sgdc8,2242
4
4
  zenml/actions/__init__.py,sha256=mrt6wPo73iKRxK754_NqsGyJ3buW7RnVeIGXr1xEw8Y,681
5
5
  zenml/actions/base_action.py,sha256=UcaHev6BTuLDwuswnyaPjdA8AgUqB5xPZ-lRtuvf2FU,25553
@@ -64,7 +64,7 @@ zenml/code_repositories/git/local_git_repository_context.py,sha256=hfX7zVDQ27Le0
64
64
  zenml/code_repositories/local_repository_context.py,sha256=1VyiYkJBDVg0iGusgRQDToGRPJuu9lx7jTBDpplukDg,2816
65
65
  zenml/config/__init__.py,sha256=DZEic7euSbwI9Yb3FMRQhTgfhqz-C6OdAiYmOb0-opI,1519
66
66
  zenml/config/base_settings.py,sha256=itoLqc1cOwEYhgSGdZmSKSaBevQkvYH7NQh7PUamazc,1700
67
- zenml/config/build_configuration.py,sha256=Jsng7ebpeaRbzXlbszU-uYkaVihgQ4OrD839yWwD3ZY,5126
67
+ zenml/config/build_configuration.py,sha256=vpea4cXTWfxRyijMFMo3U6jtHpC7wgL01NAIzp721RI,5263
68
68
  zenml/config/compiler.py,sha256=jzyyTmM8nTxtpIVTSjZ-jrVOBJ1roVoJ3fs1A1nwv9M,24130
69
69
  zenml/config/constants.py,sha256=QvSgMwXWxtspcJ45CrFDP1ZY3w6gS3bIhXLOtIDAbZA,713
70
70
  zenml/config/docker_settings.py,sha256=KTUR9FaRn3ivcagzFgpLe4eev8fvd5Wq1oV8wGNMB-g,13322
@@ -96,12 +96,12 @@ zenml/container_registries/github_container_registry.py,sha256=rbcGkFfPDk-Il0T9F
96
96
  zenml/data_validators/__init__.py,sha256=9Fa0jiUSQ_JsLMHYjqDayWQl4m_uuai9tQjIP60OTk8,886
97
97
  zenml/data_validators/base_data_validator.py,sha256=reGUJ6NEFfd_wocrcYBSU5QHCSBOll-pP_suTP_bfv0,9839
98
98
  zenml/entrypoints/__init__.py,sha256=2CMemOrHIJauxAss6k7dKFtsCFqgYR-JbAx4REoCaE8,946
99
- zenml/entrypoints/base_entrypoint_configuration.py,sha256=5GY0W-29pabMmtb8WlnEKtg3H-ywFEpXzpud3hC12_o,12516
99
+ zenml/entrypoints/base_entrypoint_configuration.py,sha256=t7sU2MEEPVomX9dZCpPhk1f3SVjcN7whQRLsY2uGXu0,12531
100
100
  zenml/entrypoints/entrypoint.py,sha256=XNgXBCMKoidmP0_AYgMpqo-neG8Y8jG0rj43ofTDZ9E,2033
101
101
  zenml/entrypoints/pipeline_entrypoint_configuration.py,sha256=To-vTP29qAE36ndJDF1fRw9wL2Nk2bsBuO-ayAwvSmo,1646
102
102
  zenml/entrypoints/step_entrypoint_configuration.py,sha256=fJuTvJnGuhKc60CH1VMQL5EHomGXkYZulv6pVgd9M6w,7316
103
103
  zenml/enums.py,sha256=m18yol20jS9JNhuf7UPBYUsgNRCtbyCaWPNpeEAJeXY,11199
104
- zenml/environment.py,sha256=dw9sU28d8vsobGl2byUyhVbYXVhgtvpRrEAx4_fHMI8,11624
104
+ zenml/environment.py,sha256=VUS8aPTNa1c5VhXIyeL6VaFTQA7K5Q3ltLu24IYP2oI,10694
105
105
  zenml/event_hub/__init__.py,sha256=-fD9mPOslf4J-_XFBPp5gYlPz7-6ZaAKHa5jxf_nyAo,757
106
106
  zenml/event_hub/base_event_hub.py,sha256=PqKrnvOye0UUS3s09zGgjI5dtj0IwzEBDbavA_PgfZQ,6579
107
107
  zenml/event_hub/event_hub.py,sha256=e1eCRB1qAabOFIx2OJCAoNqN1QQIW0CSTukiWuGMOi8,6502
@@ -110,7 +110,7 @@ zenml/event_sources/base_event.py,sha256=irrpiYi4fDYewzaXtb6_gPsqyFlYYLSap2BTGQz
110
110
  zenml/event_sources/base_event_source.py,sha256=04ramQhcPhGD9Mo9BcJZR-b9fJb8a4wzvlPVMAb9Dyk,25893
111
111
  zenml/event_sources/webhooks/__init__.py,sha256=VsHzSn1oKFaUs495ZqsKCfXiYxtaeGsnSGuvuqbGXCg,658
112
112
  zenml/event_sources/webhooks/base_webhook_event_source.py,sha256=2zADrL3cNpD-akZRdemUePUnTl8pPMPVX6eFQgWeUSo,7371
113
- zenml/exceptions.py,sha256=-Zt5yOEsj8MkbIGLceLa0JGjQl-PinpQifT0j5bAt2c,9043
113
+ zenml/exceptions.py,sha256=KPEz9kQGyC6VbgjNXFTUsVehvAUIe2ayOOy1j5QJdUI,6757
114
114
  zenml/experiment_trackers/__init__.py,sha256=b5XlKoRtMR1WBQVEiItolkpsa0iJ1IqxTmmRatr4YDw,1119
115
115
  zenml/experiment_trackers/base_experiment_tracker.py,sha256=K92w7c0r45qLPIsA3YmwPflaIl_WTK8-_Hh_1MQiLkE,2218
116
116
  zenml/feature_stores/__init__.py,sha256=tSW7YnDa3NDnlkX3yA_CTdX7ocWB9gsfF-7X9sc6i8Y,1415
@@ -135,7 +135,7 @@ zenml/integrations/argilla/annotators/__init__.py,sha256=QjRMxIQ-skulcLN94GuHuuk
135
135
  zenml/integrations/argilla/annotators/argilla_annotator.py,sha256=aIA5rcwfOYLnUVp2c_aaTAUnVW8GV9gP8myze_jY_qY,15586
136
136
  zenml/integrations/argilla/flavors/__init__.py,sha256=MTogEeiZ1k7nLzGKok3azK_VhKUAJl0GL6OQvsvMlZo,917
137
137
  zenml/integrations/argilla/flavors/argilla_annotator_flavor.py,sha256=NAy6QKLWYXHPTCoWc9RIovsngcRGMwseu3rdNjiCpo4,4473
138
- zenml/integrations/aws/__init__.py,sha256=48ssbSeI3EUyjZN__Xs350wX5pLKoFdUZpXiXLaDDs4,2452
138
+ zenml/integrations/aws/__init__.py,sha256=WevXkUf7tNGrxkY2wFYPohuBM2Fd40wRE8ff2y0k-ks,2452
139
139
  zenml/integrations/aws/container_registries/__init__.py,sha256=fOwo84MiaX_7XhNQEXeyVh8AyOlcIl6nSu_ig68GkSs,827
140
140
  zenml/integrations/aws/container_registries/aws_container_registry.py,sha256=SCxKj_w79Ka0LdxYOdDmaXitketTQRDHrQ4XQ0_f4hs,6091
141
141
  zenml/integrations/aws/flavors/__init__.py,sha256=XYL9fpwKzeFfHCjakU0iJ3SyHVRJk63QT7luOy9Giek,1480
@@ -230,7 +230,7 @@ zenml/integrations/discord/flavors/discord_alerter_flavor.py,sha256=9hX7R7dfxSwi
230
230
  zenml/integrations/discord/steps/__init__.py,sha256=stSDntUMzrHzwMJm1V1-jm7otII7uW6Fxj7qYB7MWrc,663
231
231
  zenml/integrations/discord/steps/discord_alerter_ask_step.py,sha256=puBERGjhpBRaift8GCygAgnjgZHbeqclRywxJjjjEG8,2553
232
232
  zenml/integrations/discord/steps/discord_alerter_post_step.py,sha256=te4M4Q47e1nShPHLLv414bjDuG_r7XCxDUbLgwGXEtI,2283
233
- zenml/integrations/evidently/__init__.py,sha256=ZNbkmtHPsk4qs4AColYU9a2VN8oV5XPtUrmb78UTDg0,3185
233
+ zenml/integrations/evidently/__init__.py,sha256=csvwza0td2EQExJCGdZqZXk1NVJY9miyEOszglZPCwU,3254
234
234
  zenml/integrations/evidently/column_mapping.py,sha256=slZwGaArhYZNZnXfwYFXZEt7bqq2jswvb1vwkedvGRE,3555
235
235
  zenml/integrations/evidently/data_validators/__init__.py,sha256=7H1HCXAefk-asnSAYqfud-l17rsBFfhCrgps2abhmFY,830
236
236
  zenml/integrations/evidently/data_validators/evidently_data_validator.py,sha256=V34Nze3Mi4JpTlJJQf-i582WxAZrg5-yAv1HcUf7ULE,10316
@@ -263,13 +263,13 @@ zenml/integrations/gcp/flavors/__init__.py,sha256=GcB8EvYjXM_VSku16jnDSNyJYMgKc2
263
263
  zenml/integrations/gcp/flavors/gcp_artifact_store_flavor.py,sha256=Ts2jvR3IgGH8YyaFBT6OQtx2kCKD9dgZgceKiRAv_QI,3560
264
264
  zenml/integrations/gcp/flavors/gcp_image_builder_flavor.py,sha256=K6sE9D-okbdlctNwNeDYEfhWmMXXW-S92x342dnhjqY,4451
265
265
  zenml/integrations/gcp/flavors/vertex_experiment_tracker_flavor.py,sha256=icexIPoqyJ_tsO6M5-Vncd1TAUaKTGbdUG0cDOYC6Kc,6834
266
- zenml/integrations/gcp/flavors/vertex_orchestrator_flavor.py,sha256=Cm31d1uNZ6C6E1oQV8ep91IzvboFnyRwpH2ZKojsctg,10096
266
+ zenml/integrations/gcp/flavors/vertex_orchestrator_flavor.py,sha256=dIZP35SR63RHb9QY1bz_yDWrzQ9pz2KKxAorShqUMkg,10494
267
267
  zenml/integrations/gcp/flavors/vertex_step_operator_flavor.py,sha256=hY38MoNXZbvylsrbVdQ7PtkNw9QmHj6G8P1BWrRUyv8,5231
268
268
  zenml/integrations/gcp/google_credentials_mixin.py,sha256=bPy3JYCCcyuTmPiVFqbY81YJ5g1yRdzHLlBlokvbeqg,4026
269
269
  zenml/integrations/gcp/image_builders/__init__.py,sha256=2IvTL6U2YpUoxGQXeXew-6WFoL5hHIxkqr4DaA5Ez9w,786
270
270
  zenml/integrations/gcp/image_builders/gcp_image_builder.py,sha256=5T6BXsHxLhvp1BF_rslXl1oZzykJUPuZ3E_7-9ZZYLk,9019
271
271
  zenml/integrations/gcp/orchestrators/__init__.py,sha256=6xLFJKZKQk73fHPF-XdpbQO87zjQNGTsNHjJjLfG_Kg,805
272
- zenml/integrations/gcp/orchestrators/vertex_orchestrator.py,sha256=_OCr6NGhBHRuR4t9kOyyvjlSu4EQPC0EY-mrYM56VvU,41354
272
+ zenml/integrations/gcp/orchestrators/vertex_orchestrator.py,sha256=qoMCr36buZUz0y4CyTFQde3RDslkaGLAG0FjXc0XEPU,42100
273
273
  zenml/integrations/gcp/service_connectors/__init__.py,sha256=fdydawaor8KAtMYvRZieiTuA1i5QATxXXgI-yV1lsn8,788
274
274
  zenml/integrations/gcp/service_connectors/gcp_service_connector.py,sha256=JGrFTKkQV4ZDn_yTEqX-AtBMraFasFgzLVws2mvhS64,94915
275
275
  zenml/integrations/gcp/step_operators/__init__.py,sha256=iPkob2LtPIQ-OHszhbNz_ojhoovL6SprmTx37It4EJ8,808
@@ -330,19 +330,19 @@ zenml/integrations/kubeflow/__init__.py,sha256=4kP4BuSbRs9xXyymv38rgb5l-LJIxb7te
330
330
  zenml/integrations/kubeflow/flavors/__init__.py,sha256=l560A0oIpYeTpVVrdrVVYj-2-Y5CeyCSQMfwErZROxY,878
331
331
  zenml/integrations/kubeflow/flavors/kubeflow_orchestrator_flavor.py,sha256=b7W4oASHLYN9o2n__-W3zajb_MXhPaY0UutecsW0Xw4,10381
332
332
  zenml/integrations/kubeflow/orchestrators/__init__.py,sha256=J879DBt9WbpojBTdOXy7CO6F5OuTMntBeZ8aUY2EGO8,821
333
- zenml/integrations/kubeflow/orchestrators/kubeflow_orchestrator.py,sha256=6IxKpOgCmTP0kPnhsGDi3rNGDCb3RnHIFu7DflxOP0Q,39690
333
+ zenml/integrations/kubeflow/orchestrators/kubeflow_orchestrator.py,sha256=OuTGD7ggsw_tYILOTRT1xz8uiTJNhp0Pkx3Sz_MMFWM,38521
334
334
  zenml/integrations/kubeflow/orchestrators/local_deployment_utils.py,sha256=qszoOdvBpgIp40XkncphXAr9dRKnyZzGiz2mJ56bYmw,15448
335
335
  zenml/integrations/kubernetes/__init__.py,sha256=k1bfrdI1u5RBnAh7yT4w-m-4SWgZ7b4L5uu7dPRc0SI,1809
336
336
  zenml/integrations/kubernetes/flavors/__init__.py,sha256=a5gU45qCj3FkLwl_uVjlIkL_2F5DHk-w1gdcZrvVjBI,1266
337
- zenml/integrations/kubernetes/flavors/kubernetes_orchestrator_flavor.py,sha256=VOfb5yOXGpQ8gcKP0nt4bYO48LqG8ZjzGhpw8XGXAzk,9253
337
+ zenml/integrations/kubernetes/flavors/kubernetes_orchestrator_flavor.py,sha256=bO_2RZ6TIO0Qp2zduha324m2zrg6cGw-ymK51Nm2E9o,9505
338
338
  zenml/integrations/kubernetes/flavors/kubernetes_step_operator_flavor.py,sha256=xFO7cSusji-mgbRrt4mU29gdyC9iEjEHKtomdFLp9mM,6265
339
339
  zenml/integrations/kubernetes/orchestrators/__init__.py,sha256=TJID3OTieZBox36WpQpzD0jdVRA_aZVcs_bNtfXS8ik,811
340
340
  zenml/integrations/kubernetes/orchestrators/kube_utils.py,sha256=oU0EYP-x35oG7PAy7NZKeFA8_89Eckgq6hibwc9v5l0,18108
341
- zenml/integrations/kubernetes/orchestrators/kubernetes_orchestrator.py,sha256=iESgw3Yx7biqt3D05Q1R8u_fhOTuNKpy8H17ntmHuS4,25518
342
- zenml/integrations/kubernetes/orchestrators/kubernetes_orchestrator_entrypoint.py,sha256=aA_1CozChqrAuylzuG8_13JR0eR5HrXCsq_k-Y5PDqc,11499
341
+ zenml/integrations/kubernetes/orchestrators/kubernetes_orchestrator.py,sha256=tzGhxFyf2of7soyEiEYAixuU9uDjT49-StAqhRJLMVo,25730
342
+ zenml/integrations/kubernetes/orchestrators/kubernetes_orchestrator_entrypoint.py,sha256=krsIXrHUk2EZAVpqMCn8KgICNhD_YtVlySarQD5C4bI,12039
343
343
  zenml/integrations/kubernetes/orchestrators/kubernetes_orchestrator_entrypoint_configuration.py,sha256=KjHfQK9VQEQkkkM2i9w51AzqolgIU01M5dgb2YGamvY,2754
344
- zenml/integrations/kubernetes/orchestrators/manifest_utils.py,sha256=Owyuz5Iix-QvCnKObC6xhcuQtNG_ik-8Vbdmk13eWfc,12557
345
- zenml/integrations/kubernetes/pod_settings.py,sha256=fP2NeHf1XxT__D4g_6oHQf8pkiiamFUFYmfNor2OoP8,6386
344
+ zenml/integrations/kubernetes/orchestrators/manifest_utils.py,sha256=Mte6q_NX0bU_JTivtN7ByQtfQX32iI2z2sElIpQhj7g,13271
345
+ zenml/integrations/kubernetes/pod_settings.py,sha256=QPV8Fq8SHZ7pwKavplcADJep-Y9olIbC3RlG10HI0pw,6683
346
346
  zenml/integrations/kubernetes/serialization_utils.py,sha256=cPSe4szdBLzDnUZT9nQc2CCA8h84aj5oTA8vsUE36ig,7000
347
347
  zenml/integrations/kubernetes/service_connectors/__init__.py,sha256=Uf6zlHIapYrRDl3xOPWQ2jA7jt85SXx1U7DmSxzxTvQ,818
348
348
  zenml/integrations/kubernetes/service_connectors/kubernetes_service_connector.py,sha256=Cv4tiVxoQOz9ex0lf3JdJrooEkgMwfDfwt5GOeNRpQU,19669
@@ -411,9 +411,9 @@ zenml/integrations/neptune/neptune_constants.py,sha256=-VddhrALS1HMBhGtFiGDKaRah
411
411
  zenml/integrations/neural_prophet/__init__.py,sha256=mVou7yCAImlDA6Qtyh1jhBfL51oFhgl96Sj9dn7PwG4,1309
412
412
  zenml/integrations/neural_prophet/materializers/__init__.py,sha256=7O-qwxLjxLmvqeUgeLWBOHe5pvxwDFRg5hCOhffyd0k,802
413
413
  zenml/integrations/neural_prophet/materializers/neural_prophet_materializer.py,sha256=U8OvRObumGAk66UJFHLKWtez-I3wU2zd1j-XvCbSBr4,1570
414
- zenml/integrations/numpy/__init__.py,sha256=iElEW7S10JEHnW50vbqTs5dhm4bSIiB70cJSx38Lnco,1066
414
+ zenml/integrations/numpy/__init__.py,sha256=2VlwCUAne0MYpYGPkgk19yq2gntUCe9IMytLrjY9KEw,1234
415
415
  zenml/integrations/numpy/materializers/__init__.py,sha256=txwv8We-dLehTWqY-eDYx40njg4Ld8eQrs1O0MZiiIk,766
416
- zenml/integrations/numpy/materializers/numpy_materializer.py,sha256=rNIcoZkU6JZcqEc6yt3x3yHvmmWnLAfKy74hLxKXbM8,8477
416
+ zenml/integrations/numpy/materializers/numpy_materializer.py,sha256=LMnchlRl6xOBrQcAi_A_jQZtzEkkix2WQl8cU4z--nU,10602
417
417
  zenml/integrations/openai/__init__.py,sha256=Qh9ZDYm5Zn6thmEBpW1WxBUaqOChDYa5sdNzHB4zB4U,919
418
418
  zenml/integrations/openai/hooks/__init__.py,sha256=8VfiVOyIrjya9G_VK5GPEqq9G5i9w5u4ngf-Oo_oHT4,811
419
419
  zenml/integrations/openai/hooks/open_ai_failure_hook.py,sha256=tQe-dUO7_w24ABfN96TZ7Zc2inJMI5u9sdE8gBxrDyM,4702
@@ -531,7 +531,7 @@ zenml/integrations/tekton/__init__.py,sha256=fR4Swt09E3VWCV-5to3zbCOaZcsDPtDs22z
531
531
  zenml/integrations/tekton/flavors/__init__.py,sha256=-S5XuwcZKWyGb9tVfl_gEFJj1KSXX6kwIfe-EhE0TmM,864
532
532
  zenml/integrations/tekton/flavors/tekton_orchestrator_flavor.py,sha256=XgFgzJUlje9J1o5zwBvs_ycpgQjGdi50KZFA9_tT0vc,8268
533
533
  zenml/integrations/tekton/orchestrators/__init__.py,sha256=yCJEM-PCechO4DF_YQeg82y76nwBKeXTy_SIXRWX2DE,811
534
- zenml/integrations/tekton/orchestrators/tekton_orchestrator.py,sha256=RnoVj5o3JYqfhcIFfzOunXqbVeSMHNWT9VVKKQmqwlE,35735
534
+ zenml/integrations/tekton/orchestrators/tekton_orchestrator.py,sha256=tRhMNhe9a7hVr1HFYMdfH15nB_xrVlJwrLs9R8qbXec,34614
535
535
  zenml/integrations/tensorboard/__init__.py,sha256=mrzcQooqOlOYrzGLyZxxn1VPl99ot9Usg75akPC0Uc0,1612
536
536
  zenml/integrations/tensorboard/services/__init__.py,sha256=Y-YVPLxJkFSpXNDZSk8gEBISsXJGk_DgGIyVIIFIa40,798
537
537
  zenml/integrations/tensorboard/services/tensorboard_service.py,sha256=OgIO0UTndzGqiDz_OJjCzm9zHa0F0P7kjxzrz83U77g,4434
@@ -682,7 +682,7 @@ zenml/orchestrators/__init__.py,sha256=p4Y9Ni7Lp33fZ6UrjgI7qu-rrg8LrlyafCM-K1WC8
682
682
  zenml/orchestrators/base_orchestrator.py,sha256=q0N0o7neQEcnsNHOeGUssbqC_MoQLFuBFavMD-W_QZY,12837
683
683
  zenml/orchestrators/cache_utils.py,sha256=G9mIZZOa1TixUHZnvwwroMl7a4YCVqvrNVwPCMVNFos,4306
684
684
  zenml/orchestrators/containerized_orchestrator.py,sha256=rdebgBW0Bk--JcHcT0NpLkAbyhY0VS5xO1uwWEgkLpA,3230
685
- zenml/orchestrators/dag_runner.py,sha256=N3gp1K1kZ8aEHPYyxcjpxmfRFFQa8Z0Nm5QuVz_rVYw,8172
685
+ zenml/orchestrators/dag_runner.py,sha256=4oAGc52nHv8HeI_Vj7GH1jzjJom1uwUJ_la9usQoOFY,9404
686
686
  zenml/orchestrators/input_utils.py,sha256=GKDKZBjPLUkXn46bPxzhN28SJwRSvYLvlhB9eEKKPgA,7660
687
687
  zenml/orchestrators/local/__init__.py,sha256=qlU91hgqGKeycw-Qntrn-iMuoMTaNrq-RgfOFeqwlM4,662
688
688
  zenml/orchestrators/local/local_orchestrator.py,sha256=UhgxC68A_6N7Vp1zNixSUr7qb9_S79Gg-ZnjMJcViw0,5668
@@ -762,7 +762,7 @@ zenml/utils/__init__.py,sha256=jaMTbjm8tLYkaRoxlZ0Em4ye_ZHOHKgP2goPTTiYGUQ,797
762
762
  zenml/utils/archivable.py,sha256=QuLe1IhyABTrE6Y0hAT3tKjaUCpcze5ffZ_RKoKtJwY,6549
763
763
  zenml/utils/callback_registry.py,sha256=QBWdaraLAxBxi8DKbv9X1SUpTKDhhj-XE0JomB2Ax2Y,2411
764
764
  zenml/utils/code_repository_utils.py,sha256=-Zw8TvCSPfISB30Gmj0Yryk-RYrpzwCkqH7_c7Hq9ZY,5334
765
- zenml/utils/code_utils.py,sha256=SsfE4sHcBX3yPyrk3QWZXpXfsTcjycbVIuqVV6zKPDY,11463
765
+ zenml/utils/code_utils.py,sha256=P9o6jRmvfmq-MKBGJ2XazMnMmDEuSvsFBEhqin4eaws,11478
766
766
  zenml/utils/cuda_utils.py,sha256=RR21m__Zs-OnI5n-veFUzWniZjwLSbalHE5QV3jK1Hw,1624
767
767
  zenml/utils/daemon.py,sha256=GZ7Dx6GLHK04SR50wBxpKYmFhxPBfdLWxJiAWzJC6cM,11863
768
768
  zenml/utils/dashboard_utils.py,sha256=V4pas-zgMn3vOpXWZ-yoW11ZLZi__oFQw9jvhiXhK1A,8345
@@ -1011,7 +1011,7 @@ zenml/zen_server/deploy/docker/docker_provider.py,sha256=18pNpxvP8xqbxS_KxvYTEIu
1011
1011
  zenml/zen_server/deploy/docker/docker_zen_server.py,sha256=83-bjRmtlE-WDCavbvL9uTXOn5fMJ4yPDDb2ewSr4Do,7480
1012
1012
  zenml/zen_server/deploy/exceptions.py,sha256=tX0GNnLB_GMkeN7zGNlJRwtlrpZ5Slvyj_unVYVmGxk,1396
1013
1013
  zenml/zen_server/download_utils.py,sha256=g366TqytIWR4L4u9dd0jg-ouSWpDwdAh_-F2zryFzfo,4224
1014
- zenml/zen_server/exceptions.py,sha256=H4F9SbbwCiVLnJTdzpWN016Knt6zvoOVmOWxTgXEAsA,9686
1014
+ zenml/zen_server/exceptions.py,sha256=NAXARDHLvfnVIQ87MHce0mfaWCmKhMKgwmw-_X49HxQ,9625
1015
1015
  zenml/zen_server/feature_gate/__init__.py,sha256=yabe4fBY6NSusn-QlKQDLOvXVLERNpcAQgigsyWQIbQ,612
1016
1016
  zenml/zen_server/feature_gate/endpoint_utils.py,sha256=o6sBVlqqlc9KokMaEsRTYeMra7f2a6kCt3FrB-oHhCw,2227
1017
1017
  zenml/zen_server/feature_gate/feature_gate_interface.py,sha256=XCgsqUN5yYCipodHCIDmCHRhyYMyt483Pp5mdpqzwHA,1647
@@ -1316,8 +1316,8 @@ zenml/zen_stores/secrets_stores/sql_secrets_store.py,sha256=nEO0bAPlULBLxLVk-UTR
1316
1316
  zenml/zen_stores/sql_zen_store.py,sha256=diS6mZwE0A5v2wKf69CDtwCr1Bveot8QSQc-WE44rw4,442103
1317
1317
  zenml/zen_stores/template_utils.py,sha256=GWBP5QEOyvhzndS_MLPmvh28sQaOPpPoZFXCIX9CRL4,9065
1318
1318
  zenml/zen_stores/zen_store_interface.py,sha256=fF_uL_FplnvGvM5o3jOQ8i1zHXhuhKLL2n4nvIKSR7E,92090
1319
- zenml_nightly-0.81.0.dev20250428.dist-info/LICENSE,sha256=wbnfEnXnafPbqwANHkV6LUsPKOtdpsd-SNw37rogLtc,11359
1320
- zenml_nightly-0.81.0.dev20250428.dist-info/METADATA,sha256=uKUnevy1dcQwb6j6e8g6u7KeEJYGXskQPXiWGvuzIpw,24304
1321
- zenml_nightly-0.81.0.dev20250428.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
1322
- zenml_nightly-0.81.0.dev20250428.dist-info/entry_points.txt,sha256=QK3ETQE0YswAM2mWypNMOv8TLtr7EjnqAFq1br_jEFE,43
1323
- zenml_nightly-0.81.0.dev20250428.dist-info/RECORD,,
1319
+ zenml_nightly-0.81.0.dev20250429.dist-info/LICENSE,sha256=wbnfEnXnafPbqwANHkV6LUsPKOtdpsd-SNw37rogLtc,11359
1320
+ zenml_nightly-0.81.0.dev20250429.dist-info/METADATA,sha256=XFMW9u3QQraG74PaFweznntiXitFHQRSV7w-eY_ijLk,24304
1321
+ zenml_nightly-0.81.0.dev20250429.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
1322
+ zenml_nightly-0.81.0.dev20250429.dist-info/entry_points.txt,sha256=QK3ETQE0YswAM2mWypNMOv8TLtr7EjnqAFq1br_jEFE,43
1323
+ zenml_nightly-0.81.0.dev20250429.dist-info/RECORD,,