zenml-nightly 0.84.3.dev20250903__py3-none-any.whl → 0.84.3.dev20250905__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 (29) hide show
  1. zenml/VERSION +1 -1
  2. zenml/artifacts/utils.py +3 -0
  3. zenml/config/__init__.py +3 -12
  4. zenml/config/cache_policy.py +104 -0
  5. zenml/config/compiler.py +1 -0
  6. zenml/config/pipeline_configurations.py +2 -0
  7. zenml/config/pipeline_run_configuration.py +2 -0
  8. zenml/config/step_configurations.py +5 -0
  9. zenml/materializers/base_materializer.py +11 -0
  10. zenml/materializers/built_in_materializer.py +66 -0
  11. zenml/materializers/pydantic_materializer.py +21 -1
  12. zenml/materializers/structured_string_materializer.py +16 -1
  13. zenml/materializers/uuid_materializer.py +15 -0
  14. zenml/models/v2/core/artifact_version.py +18 -0
  15. zenml/orchestrators/cache_utils.py +28 -9
  16. zenml/orchestrators/step_run_utils.py +1 -5
  17. zenml/pipelines/pipeline_decorator.py +5 -0
  18. zenml/pipelines/pipeline_definition.py +7 -0
  19. zenml/steps/base_step.py +10 -0
  20. zenml/steps/step_decorator.py +5 -0
  21. zenml/zen_stores/migrations/versions/aae4eed923b5_add_content_hash_column.py +36 -0
  22. zenml/zen_stores/schemas/artifact_schemas.py +3 -0
  23. zenml/zen_stores/schemas/step_run_schemas.py +1 -1
  24. zenml/zen_stores/sql_zen_store.py +9 -4
  25. {zenml_nightly-0.84.3.dev20250903.dist-info → zenml_nightly-0.84.3.dev20250905.dist-info}/METADATA +1 -1
  26. {zenml_nightly-0.84.3.dev20250903.dist-info → zenml_nightly-0.84.3.dev20250905.dist-info}/RECORD +29 -27
  27. {zenml_nightly-0.84.3.dev20250903.dist-info → zenml_nightly-0.84.3.dev20250905.dist-info}/LICENSE +0 -0
  28. {zenml_nightly-0.84.3.dev20250903.dist-info → zenml_nightly-0.84.3.dev20250905.dist-info}/WHEEL +0 -0
  29. {zenml_nightly-0.84.3.dev20250903.dist-info → zenml_nightly-0.84.3.dev20250905.dist-info}/entry_points.txt +0 -0
zenml/VERSION CHANGED
@@ -1 +1 @@
1
- 0.84.3.dev20250903
1
+ 0.84.3.dev20250905
zenml/artifacts/utils.py CHANGED
@@ -178,6 +178,8 @@ def _store_artifact_data_and_prepare_request(
178
178
  # the materializer
179
179
  combined_metadata.update(metadata or {})
180
180
 
181
+ content_hash = materializer.compute_content_hash(data)
182
+
181
183
  artifact_version_request = ArtifactVersionRequest(
182
184
  artifact_name=name,
183
185
  version=version,
@@ -186,6 +188,7 @@ def _store_artifact_data_and_prepare_request(
186
188
  uri=materializer.uri,
187
189
  materializer=source_utils.resolve(materializer.__class__),
188
190
  data_type=source_utils.resolve(data_type),
191
+ content_hash=content_hash,
189
192
  project=Client().active_project.id,
190
193
  artifact_store_id=artifact_store.id,
191
194
  visualizations=visualizations,
zenml/config/__init__.py CHANGED
@@ -11,18 +11,7 @@
11
11
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
12
12
  # or implied. See the License for the specific language governing
13
13
  # permissions and limitations under the License.
14
- """The `config` module contains classes and functions that manage user-specific configuration.
15
-
16
- ZenML's configuration is stored in a file called
17
- ``config.yaml``, located on the user's directory for configuration files.
18
- (The exact location differs from operating system to operating system.)
19
-
20
- The ``GlobalConfiguration`` class is the main class in this module. It provides
21
- a Pydantic configuration object that is used to store and retrieve
22
- configuration. This ``GlobalConfiguration`` object handles the serialization and
23
- deserialization of the configuration options that are stored in the file in
24
- order to persist the configuration across sessions.
25
- """
14
+ """Config classes."""
26
15
  from zenml.config.docker_settings import (
27
16
  DockerSettings,
28
17
  PythonPackageInstaller,
@@ -32,6 +21,7 @@ from zenml.config.resource_settings import ResourceSettings, ByteUnit
32
21
  from zenml.config.retry_config import StepRetryConfig
33
22
  from zenml.config.schedule import Schedule
34
23
  from zenml.config.store_config import StoreConfiguration
24
+ from zenml.config.cache_policy import CachePolicy
35
25
 
36
26
  __all__ = [
37
27
  "DockerSettings",
@@ -42,4 +32,5 @@ __all__ = [
42
32
  "StepRetryConfig",
43
33
  "Schedule",
44
34
  "StoreConfiguration",
35
+ "CachePolicy",
45
36
  ]
@@ -0,0 +1,104 @@
1
+ # Copyright (c) ZenML GmbH 2025. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at:
6
+ #
7
+ # https://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
12
+ # or implied. See the License for the specific language governing
13
+ # permissions and limitations under the License.
14
+ """Cache policy."""
15
+
16
+ from typing import Any, List, Optional, Union
17
+
18
+ from pydantic import BaseModel, BeforeValidator, Field
19
+ from typing_extensions import Annotated
20
+
21
+ from zenml.logger import get_logger
22
+
23
+ logger = get_logger(__name__)
24
+
25
+
26
+ class CachePolicy(BaseModel):
27
+ """Cache policy."""
28
+
29
+ include_step_code: bool = Field(
30
+ default=True,
31
+ description="Whether to include the step code in the cache key.",
32
+ )
33
+ include_step_parameters: bool = Field(
34
+ default=True,
35
+ description="Whether to include the step parameters in the cache key.",
36
+ )
37
+ include_artifact_values: bool = Field(
38
+ default=True,
39
+ description="Whether to include the artifact values in the cache key. "
40
+ "If the materializer for an artifact doesn't support generating a "
41
+ "content hash, the artifact ID will be used as a fallback if enabled.",
42
+ )
43
+ include_artifact_ids: bool = Field(
44
+ default=True,
45
+ description="Whether to include the artifact IDs in the cache key.",
46
+ )
47
+ ignored_inputs: Optional[List[str]] = Field(
48
+ default=None,
49
+ description="List of input names to ignore in the cache key.",
50
+ )
51
+
52
+ @classmethod
53
+ def default(cls) -> "CachePolicy":
54
+ """Default cache policy.
55
+
56
+ Returns:
57
+ The default cache policy.
58
+ """
59
+ return cls(
60
+ include_step_code=True,
61
+ include_step_parameters=True,
62
+ include_artifact_values=True,
63
+ include_artifact_ids=True,
64
+ ignored_inputs=None,
65
+ )
66
+
67
+ @classmethod
68
+ def from_string(cls, value: str) -> "CachePolicy":
69
+ """Create a cache policy from a string.
70
+
71
+ Args:
72
+ value: The string to create a cache policy from.
73
+
74
+ Raises:
75
+ ValueError: If the string is not a valid cache policy.
76
+
77
+ Returns:
78
+ The cache policy.
79
+ """
80
+ if value.lower() == "default":
81
+ return cls.default()
82
+ else:
83
+ raise ValueError(f"Invalid cache policy: {value}")
84
+
85
+
86
+ def _convert_cache_policy(value: Any) -> Any:
87
+ """Converts a potential cache policy string to a cache policy object.
88
+
89
+ Args:
90
+ value: The value to convert.
91
+
92
+ Returns:
93
+ The converted value.
94
+ """
95
+ if isinstance(value, str):
96
+ return CachePolicy.from_string(value)
97
+
98
+ return value
99
+
100
+
101
+ CachePolicyWithValidator = Annotated[
102
+ CachePolicy, BeforeValidator(_convert_cache_policy)
103
+ ]
104
+ CachePolicyOrString = Union[CachePolicy, str]
zenml/config/compiler.py CHANGED
@@ -208,6 +208,7 @@ class Compiler:
208
208
  model=config.model,
209
209
  retry=config.retry,
210
210
  parameters=config.parameters,
211
+ cache_policy=config.cache_policy,
211
212
  )
212
213
 
213
214
  invalid_step_configs = set(config.steps) - set(pipeline.invocations)
@@ -18,6 +18,7 @@ from typing import TYPE_CHECKING, Any, Dict, List, Optional, Union
18
18
 
19
19
  from pydantic import SerializeAsAny, field_validator
20
20
 
21
+ from zenml.config.cache_policy import CachePolicyWithValidator
21
22
  from zenml.config.constants import DOCKER_SETTINGS_KEY
22
23
  from zenml.config.retry_config import StepRetryConfig
23
24
  from zenml.config.source import SourceWithValidator
@@ -51,6 +52,7 @@ class PipelineConfigurationUpdate(StrictBaseModel):
51
52
  parameters: Optional[Dict[str, Any]] = None
52
53
  retry: Optional[StepRetryConfig] = None
53
54
  substitutions: Dict[str, str] = {}
55
+ cache_policy: Optional[CachePolicyWithValidator] = None
54
56
 
55
57
  def finalize_substitutions(
56
58
  self, start_time: Optional[datetime] = None, inplace: bool = False
@@ -19,6 +19,7 @@ from uuid import UUID
19
19
  from pydantic import Field, SerializeAsAny
20
20
 
21
21
  from zenml.config.base_settings import BaseSettings
22
+ from zenml.config.cache_policy import CachePolicyWithValidator
22
23
  from zenml.config.retry_config import StepRetryConfig
23
24
  from zenml.config.schedule import Schedule
24
25
  from zenml.config.source import SourceWithValidator
@@ -55,3 +56,4 @@ class PipelineRunConfiguration(
55
56
  failure_hook_source: Optional[SourceWithValidator] = None
56
57
  success_hook_source: Optional[SourceWithValidator] = None
57
58
  substitutions: Dict[str, str] = {}
59
+ cache_policy: Optional[CachePolicyWithValidator] = None
@@ -37,6 +37,7 @@ from zenml.artifacts.external_artifact_config import (
37
37
  )
38
38
  from zenml.client_lazy_loader import ClientLazyLoader
39
39
  from zenml.config.base_settings import BaseSettings, SettingsOrDict
40
+ from zenml.config.cache_policy import CachePolicy, CachePolicyWithValidator
40
41
  from zenml.config.constants import DOCKER_SETTINGS_KEY, RESOURCE_SETTINGS_KEY
41
42
  from zenml.config.retry_config import StepRetryConfig
42
43
  from zenml.config.source import Source, SourceWithValidator
@@ -155,6 +156,7 @@ class StepConfigurationUpdate(StrictBaseModel):
155
156
  model: Optional[Model] = None
156
157
  retry: Optional[StepRetryConfig] = None
157
158
  substitutions: Dict[str, str] = {}
159
+ cache_policy: Optional[CachePolicyWithValidator] = None
158
160
 
159
161
  outputs: Mapping[str, PartialArtifactConfiguration] = {}
160
162
 
@@ -200,6 +202,7 @@ class PartialStepConfiguration(StepConfigurationUpdate):
200
202
  model_artifacts_or_metadata: Mapping[str, ModelVersionDataLazyLoader] = {}
201
203
  client_lazy_loaders: Mapping[str, ClientLazyLoader] = {}
202
204
  outputs: Mapping[str, PartialArtifactConfiguration] = {}
205
+ cache_policy: CachePolicyWithValidator = CachePolicy.default()
203
206
 
204
207
  # TODO: In Pydantic v2, the `model_` is a protected namespaces for all
205
208
  # fields defined under base models. If not handled, this raises a warning.
@@ -291,6 +294,7 @@ class StepConfiguration(PartialStepConfiguration):
291
294
  "success_hook_source",
292
295
  "retry",
293
296
  "substitutions",
297
+ "cache_policy",
294
298
  },
295
299
  exclude_none=True,
296
300
  )
@@ -303,6 +307,7 @@ class StepConfiguration(PartialStepConfiguration):
303
307
  "success_hook_source",
304
308
  "retry",
305
309
  "substitutions",
310
+ "cache_policy",
306
311
  },
307
312
  exclude_none=True,
308
313
  )
@@ -229,6 +229,17 @@ class BaseMaterializer(metaclass=BaseMaterializerMeta):
229
229
  # Optionally, extract some metadata from `data` for ZenML to store.
230
230
  return {}
231
231
 
232
+ def compute_content_hash(self, data: Any) -> Optional[str]:
233
+ """Compute the content hash of the given data.
234
+
235
+ Args:
236
+ data: The data to compute the content hash of.
237
+
238
+ Returns:
239
+ The content hash of the given data.
240
+ """
241
+ return None
242
+
232
243
  # ================
233
244
  # Internal Methods
234
245
  # ================
@@ -13,6 +13,8 @@
13
13
  # permissions and limitations under the License.
14
14
  """Implementation of ZenML's builtin materializer."""
15
15
 
16
+ import hashlib
17
+ import json
16
18
  import os
17
19
  from typing import (
18
20
  TYPE_CHECKING,
@@ -138,6 +140,20 @@ class BuiltInMaterializer(BaseMaterializer):
138
140
 
139
141
  return {}
140
142
 
143
+ def compute_content_hash(self, data: Any) -> Optional[str]:
144
+ """Compute the content hash of the given data.
145
+
146
+ Args:
147
+ data: The data to compute the content hash of.
148
+
149
+ Returns:
150
+ The content hash of the given data.
151
+ """
152
+ hash_ = hashlib.md5(usedforsecurity=False)
153
+ hash_.update(self.__class__.__name__.encode())
154
+ hash_.update(json.dumps(data, sort_keys=True).encode())
155
+ return hash_.hexdigest()
156
+
141
157
 
142
158
  class BytesMaterializer(BaseMaterializer):
143
159
  """Handle `bytes` data type, which is not JSON serializable."""
@@ -189,6 +205,20 @@ class BytesMaterializer(BaseMaterializer):
189
205
  """
190
206
  return {self.data_path.replace("\\", "/"): VisualizationType.MARKDOWN}
191
207
 
208
+ def compute_content_hash(self, data: Any) -> Optional[str]:
209
+ """Compute the content hash of the given data.
210
+
211
+ Args:
212
+ data: The data to compute the content hash of.
213
+
214
+ Returns:
215
+ The content hash of the given data.
216
+ """
217
+ hash_ = hashlib.md5(usedforsecurity=False)
218
+ hash_.update(self.__class__.__name__.encode())
219
+ hash_.update(data)
220
+ return hash_.hexdigest()
221
+
192
222
 
193
223
  def _all_serializable(iterable: Iterable[Any]) -> bool:
194
224
  """For an iterable, check whether all of its elements are JSON-serializable.
@@ -224,6 +254,21 @@ def _is_serializable(obj: Any) -> bool:
224
254
  return False
225
255
 
226
256
 
257
+ def _custom_json_converter(obj: Any) -> Any:
258
+ """Custom JSON converter that handles sets and tuples.
259
+
260
+ Args:
261
+ obj: The object to convert.
262
+
263
+ Returns:
264
+ The converted object.
265
+ """
266
+ if isinstance(obj, (set, tuple)):
267
+ return list(obj)
268
+
269
+ return obj
270
+
271
+
227
272
  def find_type_by_str(type_str: str) -> Type[Any]:
228
273
  """Get a Python type, given its string representation.
229
274
 
@@ -489,3 +534,24 @@ class BuiltInContainerMaterializer(BaseMaterializer):
489
534
  if hasattr(data, "__len__"):
490
535
  return {"length": len(data)}
491
536
  return {}
537
+
538
+ def compute_content_hash(self, data: Any) -> Optional[str]:
539
+ """Compute the content hash of the given data.
540
+
541
+ Args:
542
+ data: The data to compute the content hash of.
543
+
544
+ Returns:
545
+ The content hash of the given data.
546
+ """
547
+ if _is_serializable(data):
548
+ hash_ = hashlib.md5(usedforsecurity=False)
549
+ hash_.update(self.__class__.__name__.encode())
550
+ hash_.update(
551
+ json.dumps(
552
+ data, sort_keys=True, default=_custom_json_converter
553
+ ).encode()
554
+ )
555
+ return hash_.hexdigest()
556
+
557
+ return None
@@ -13,8 +13,10 @@
13
13
  # permissions and limitations under the License.
14
14
  """Implementation of ZenML's pydantic materializer."""
15
15
 
16
+ import hashlib
17
+ import json
16
18
  import os
17
- from typing import TYPE_CHECKING, Any, ClassVar, Dict, Tuple, Type
19
+ from typing import TYPE_CHECKING, Any, ClassVar, Dict, Optional, Tuple, Type
18
20
 
19
21
  from pydantic import BaseModel
20
22
 
@@ -66,3 +68,21 @@ class PydanticMaterializer(BaseMaterializer):
66
68
  The extracted metadata as a dictionary.
67
69
  """
68
70
  return {"schema": data.schema()}
71
+
72
+ def compute_content_hash(self, data: BaseModel) -> Optional[str]:
73
+ """Compute the content hash of the given data.
74
+
75
+ Args:
76
+ data: The data to compute the content hash of.
77
+
78
+ Returns:
79
+ The content hash of the given data.
80
+ """
81
+ hash_ = hashlib.md5(usedforsecurity=False)
82
+ hash_.update(self.__class__.__name__.encode())
83
+
84
+ json_data = data.model_dump(mode="json")
85
+ hash_.update(json.dumps(json_data, sort_keys=True).encode())
86
+ return hash_.hexdigest()
87
+
88
+ return None
@@ -13,8 +13,9 @@
13
13
  # permissions and limitations under the License.
14
14
  """Implementation of HTMLString materializer."""
15
15
 
16
+ import hashlib
16
17
  import os
17
- from typing import Dict, Type, Union
18
+ from typing import Dict, Optional, Type, Union
18
19
 
19
20
  from zenml.enums import ArtifactType, VisualizationType
20
21
  from zenml.logger import get_logger
@@ -129,3 +130,17 @@ class StructuredStringMaterializer(BaseMaterializer):
129
130
  raise ValueError(
130
131
  f"Data type {data_type} is not supported by this materializer."
131
132
  )
133
+
134
+ def compute_content_hash(self, data: STRUCTURED_STRINGS) -> Optional[str]:
135
+ """Compute the content hash of the given data.
136
+
137
+ Args:
138
+ data: The data to compute the content hash of.
139
+
140
+ Returns:
141
+ The content hash of the given data.
142
+ """
143
+ hash_ = hashlib.md5(usedforsecurity=False)
144
+ hash_.update(self.__class__.__name__.encode())
145
+ hash_.update(data.encode())
146
+ return hash_.hexdigest()
@@ -13,6 +13,7 @@
13
13
  # permissions and limitations under the License.
14
14
  """Implementation of ZenML's UUID materializer."""
15
15
 
16
+ import hashlib
16
17
  import os
17
18
  import uuid
18
19
  from typing import Any, ClassVar, Dict, Optional, Tuple, Type
@@ -77,3 +78,17 @@ class UUIDMaterializer(BaseMaterializer):
77
78
  return {
78
79
  "string_representation": str(data),
79
80
  }
81
+
82
+ def compute_content_hash(self, data: uuid.UUID) -> Optional[str]:
83
+ """Compute the content hash of the given data.
84
+
85
+ Args:
86
+ data: The data to compute the content hash of.
87
+
88
+ Returns:
89
+ The content hash of the given data.
90
+ """
91
+ hash_ = hashlib.md5(usedforsecurity=False)
92
+ hash_.update(self.__class__.__name__.encode())
93
+ hash_.update(data.bytes)
94
+ return hash_.hexdigest()
@@ -104,6 +104,11 @@ class ArtifactVersionRequest(ProjectScopedRequest):
104
104
  data_type: SourceWithValidator = Field(
105
105
  title="Data type of the artifact.",
106
106
  )
107
+ content_hash: Optional[str] = Field(
108
+ title="The content hash of the artifact version.",
109
+ default=None,
110
+ max_length=STR_FIELD_MAX_LENGTH,
111
+ )
107
112
  tags: Optional[List[str]] = Field(
108
113
  title="Tags of the artifact.",
109
114
  description="Should be a list of plain strings, e.g., ['tag1', 'tag2']",
@@ -201,6 +206,10 @@ class ArtifactVersionResponseBody(ProjectScopedResponseBody):
201
206
  title="ID of the artifact store in which this artifact is stored.",
202
207
  default=None,
203
208
  )
209
+ content_hash: Optional[str] = Field(
210
+ title="The content hash of the artifact version.",
211
+ default=None,
212
+ )
204
213
 
205
214
  @field_validator("version")
206
215
  @classmethod
@@ -307,6 +316,15 @@ class ArtifactVersionResponse(
307
316
  """
308
317
  return self.get_body().type
309
318
 
319
+ @property
320
+ def content_hash(self) -> Optional[str]:
321
+ """The `content_hash` property.
322
+
323
+ Returns:
324
+ the value of the property.
325
+ """
326
+ return self.get_body().content_hash
327
+
310
328
  @property
311
329
  def tags(self) -> List[TagResponse]:
312
330
  """The `tags` property.
@@ -14,9 +14,10 @@
14
14
  """Utilities for caching."""
15
15
 
16
16
  import hashlib
17
- from typing import TYPE_CHECKING, Dict, Optional
17
+ from typing import TYPE_CHECKING, Mapping, Optional
18
18
 
19
19
  from zenml.client import Client
20
+ from zenml.constants import CODE_HASH_PARAMETER_NAME
20
21
  from zenml.enums import ExecutionStatus, SorterOps
21
22
  from zenml.logger import get_logger
22
23
  from zenml.orchestrators import step_run_utils
@@ -27,6 +28,7 @@ if TYPE_CHECKING:
27
28
  from zenml.artifact_stores import BaseArtifactStore
28
29
  from zenml.config.step_configurations import Step
29
30
  from zenml.models import (
31
+ ArtifactVersionResponse,
30
32
  PipelineDeploymentResponse,
31
33
  PipelineRunResponse,
32
34
  StepRunResponse,
@@ -39,7 +41,7 @@ logger = get_logger(__name__)
39
41
 
40
42
  def generate_cache_key(
41
43
  step: "Step",
42
- input_artifact_ids: Dict[str, "UUID"],
44
+ input_artifacts: Mapping[str, "ArtifactVersionResponse"],
43
45
  artifact_store: "BaseArtifactStore",
44
46
  project_id: "UUID",
45
47
  ) -> str:
@@ -60,13 +62,14 @@ def generate_cache_key(
60
62
 
61
63
  Args:
62
64
  step: The step to generate the cache key for.
63
- input_artifact_ids: The input artifact IDs for the step.
65
+ input_artifacts: The input artifacts for the step.
64
66
  artifact_store: The artifact store of the active stack.
65
67
  project_id: The ID of the active project.
66
68
 
67
69
  Returns:
68
70
  A cache key.
69
71
  """
72
+ cache_policy = step.config.cache_policy
70
73
  hash_ = hashlib.md5() # nosec
71
74
 
72
75
  # Project ID
@@ -85,15 +88,25 @@ def generate_cache_key(
85
88
  # when committing some unrelated files
86
89
  hash_.update(step.spec.source.import_path.encode())
87
90
 
88
- # Step parameters
89
- for key, value in sorted(step.config.parameters.items()):
90
- hash_.update(key.encode())
91
- hash_.update(str(value).encode())
91
+ if cache_policy.include_step_parameters:
92
+ for key, value in sorted(step.config.parameters.items()):
93
+ hash_.update(key.encode())
94
+ hash_.update(str(value).encode())
92
95
 
93
96
  # Input artifacts
94
- for name, artifact_version_id in input_artifact_ids.items():
97
+ for name, artifact_version in input_artifacts.items():
98
+ if name in (cache_policy.ignored_inputs or []):
99
+ continue
100
+
95
101
  hash_.update(name.encode())
96
- hash_.update(artifact_version_id.bytes)
102
+
103
+ if (
104
+ artifact_version.content_hash
105
+ and cache_policy.include_artifact_values
106
+ ):
107
+ hash_.update(artifact_version.content_hash.encode())
108
+ elif cache_policy.include_artifact_ids:
109
+ hash_.update(artifact_version.id.bytes)
97
110
 
98
111
  # Output artifacts and materializers
99
112
  for name, output in step.config.outputs.items():
@@ -103,6 +116,12 @@ def generate_cache_key(
103
116
 
104
117
  # Custom caching parameters
105
118
  for key, value in sorted(step.config.caching_parameters.items()):
119
+ if (
120
+ key == CODE_HASH_PARAMETER_NAME
121
+ and not cache_policy.include_step_code
122
+ ):
123
+ continue
124
+
106
125
  hash_.update(key.encode())
107
126
  hash_.update(str(value).encode())
108
127
 
@@ -117,10 +117,6 @@ class StepRunRequestFactory:
117
117
  pipeline_run=self.pipeline_run,
118
118
  step_runs=step_runs,
119
119
  )
120
- input_artifact_ids = {
121
- input_name: artifact.id
122
- for input_name, artifact in input_artifacts.items()
123
- }
124
120
 
125
121
  request.inputs = {
126
122
  name: [artifact.id] for name, artifact in input_artifacts.items()
@@ -128,7 +124,7 @@ class StepRunRequestFactory:
128
124
 
129
125
  cache_key = cache_utils.generate_cache_key(
130
126
  step=step,
131
- input_artifact_ids=input_artifact_ids,
127
+ input_artifacts=input_artifacts,
132
128
  artifact_store=self.stack.artifact_store,
133
129
  project_id=Client().active_project.id,
134
130
  )
@@ -29,6 +29,7 @@ from zenml.logger import get_logger
29
29
 
30
30
  if TYPE_CHECKING:
31
31
  from zenml.config.base_settings import SettingsOrDict
32
+ from zenml.config.cache_policy import CachePolicyOrString
32
33
  from zenml.config.retry_config import StepRetryConfig
33
34
  from zenml.model.model import Model
34
35
  from zenml.pipelines.pipeline_definition import Pipeline
@@ -60,6 +61,7 @@ def pipeline(
60
61
  model: Optional["Model"] = None,
61
62
  retry: Optional["StepRetryConfig"] = None,
62
63
  substitutions: Optional[Dict[str, str]] = None,
64
+ cache_policy: Optional["CachePolicyOrString"] = None,
63
65
  ) -> Callable[["F"], "Pipeline"]: ...
64
66
 
65
67
 
@@ -79,6 +81,7 @@ def pipeline(
79
81
  model: Optional["Model"] = None,
80
82
  retry: Optional["StepRetryConfig"] = None,
81
83
  substitutions: Optional[Dict[str, str]] = None,
84
+ cache_policy: Optional["CachePolicyOrString"] = None,
82
85
  ) -> Union["Pipeline", Callable[["F"], "Pipeline"]]:
83
86
  """Decorator to create a pipeline.
84
87
 
@@ -102,6 +105,7 @@ def pipeline(
102
105
  model: configuration of the model in the Model Control Plane.
103
106
  retry: Retry configuration for the pipeline steps.
104
107
  substitutions: Extra placeholders to use in the name templates.
108
+ cache_policy: Cache policy for this pipeline.
105
109
 
106
110
  Returns:
107
111
  A pipeline instance.
@@ -125,6 +129,7 @@ def pipeline(
125
129
  model=model,
126
130
  retry=retry,
127
131
  substitutions=substitutions,
132
+ cache_policy=cache_policy,
128
133
  )
129
134
 
130
135
  p.__doc__ = func.__doc__
@@ -104,6 +104,7 @@ if TYPE_CHECKING:
104
104
  from zenml.artifacts.external_artifact import ExternalArtifact
105
105
  from zenml.client_lazy_loader import ClientLazyLoader
106
106
  from zenml.config.base_settings import SettingsOrDict
107
+ from zenml.config.cache_policy import CachePolicyOrString
107
108
  from zenml.config.retry_config import StepRetryConfig
108
109
  from zenml.config.source import Source
109
110
  from zenml.model.lazy_load import ModelVersionDataLazyLoader
@@ -145,6 +146,7 @@ class Pipeline:
145
146
  model: Optional["Model"] = None,
146
147
  retry: Optional["StepRetryConfig"] = None,
147
148
  substitutions: Optional[Dict[str, str]] = None,
149
+ cache_policy: Optional["CachePolicyOrString"] = None,
148
150
  ) -> None:
149
151
  """Initializes a pipeline.
150
152
 
@@ -170,6 +172,7 @@ class Pipeline:
170
172
  model: configuration of the model in the Model Control Plane.
171
173
  retry: Retry configuration for the pipeline steps.
172
174
  substitutions: Extra placeholders to use in the name templates.
175
+ cache_policy: Cache policy for this pipeline.
173
176
  """
174
177
  self._invocations: Dict[str, StepInvocation] = {}
175
178
  self._run_args: Dict[str, Any] = {}
@@ -193,6 +196,7 @@ class Pipeline:
193
196
  model=model,
194
197
  retry=retry,
195
198
  substitutions=substitutions,
199
+ cache_policy=cache_policy,
196
200
  )
197
201
  self.entrypoint = entrypoint
198
202
  self._parameters: Dict[str, Any] = {}
@@ -316,6 +320,7 @@ class Pipeline:
316
320
  parameters: Optional[Dict[str, Any]] = None,
317
321
  merge: bool = True,
318
322
  substitutions: Optional[Dict[str, str]] = None,
323
+ cache_policy: Optional["CachePolicyOrString"] = None,
319
324
  ) -> Self:
320
325
  """Configures the pipeline.
321
326
 
@@ -355,6 +360,7 @@ class Pipeline:
355
360
  retry: Retry configuration for the pipeline steps.
356
361
  parameters: input parameters for the pipeline.
357
362
  substitutions: Extra placeholders to use in the name templates.
363
+ cache_policy: Cache policy for this pipeline.
358
364
 
359
365
  Returns:
360
366
  The pipeline instance that this method was called on.
@@ -390,6 +396,7 @@ class Pipeline:
390
396
  "retry": retry,
391
397
  "parameters": parameters,
392
398
  "substitutions": substitutions,
399
+ "cache_policy": cache_policy,
393
400
  }
394
401
  )
395
402
  if not self.__suppress_warnings_flag__:
zenml/steps/base_step.py CHANGED
@@ -35,6 +35,7 @@ from typing import (
35
35
  from pydantic import BaseModel, ConfigDict, ValidationError
36
36
 
37
37
  from zenml.client_lazy_loader import ClientLazyLoader
38
+ from zenml.config.cache_policy import CachePolicyOrString
38
39
  from zenml.config.retry_config import StepRetryConfig
39
40
  from zenml.config.source import Source
40
41
  from zenml.constants import (
@@ -117,6 +118,7 @@ class BaseStep:
117
118
  model: Optional["Model"] = None,
118
119
  retry: Optional[StepRetryConfig] = None,
119
120
  substitutions: Optional[Dict[str, str]] = None,
121
+ cache_policy: Optional[CachePolicyOrString] = None,
120
122
  ) -> None:
121
123
  """Initializes a step.
122
124
 
@@ -146,6 +148,7 @@ class BaseStep:
146
148
  model: configuration of the model version in the Model Control Plane.
147
149
  retry: Configuration for retrying the step in case of failure.
148
150
  substitutions: Extra placeholders to use in the name template.
151
+ cache_policy: Cache policy for this step.
149
152
  """
150
153
  from zenml.config.step_configurations import PartialStepConfiguration
151
154
 
@@ -207,6 +210,7 @@ class BaseStep:
207
210
  model=model,
208
211
  retry=retry,
209
212
  substitutions=substitutions,
213
+ cache_policy=cache_policy,
210
214
  )
211
215
 
212
216
  notebook_utils.try_to_save_notebook_cell_code(self.source_object)
@@ -616,6 +620,7 @@ class BaseStep:
616
620
  model: Optional["Model"] = None,
617
621
  retry: Optional[StepRetryConfig] = None,
618
622
  substitutions: Optional[Dict[str, str]] = None,
623
+ cache_policy: Optional[CachePolicyOrString] = None,
619
624
  merge: bool = True,
620
625
  ) -> T:
621
626
  """Configures the step.
@@ -655,6 +660,7 @@ class BaseStep:
655
660
  model: Model to use for this step.
656
661
  retry: Configuration for retrying the step in case of failure.
657
662
  substitutions: Extra placeholders to use in the name template.
663
+ cache_policy: Cache policy for this step.
658
664
  merge: If `True`, will merge the given dictionary configurations
659
665
  like `parameters` and `settings` with existing
660
666
  configurations. If `False` the given configurations will
@@ -725,6 +731,7 @@ class BaseStep:
725
731
  "model": model,
726
732
  "retry": retry,
727
733
  "substitutions": substitutions,
734
+ "cache_policy": cache_policy,
728
735
  }
729
736
  )
730
737
  config = StepConfigurationUpdate(**values)
@@ -750,6 +757,7 @@ class BaseStep:
750
757
  model: Optional["Model"] = None,
751
758
  retry: Optional[StepRetryConfig] = None,
752
759
  substitutions: Optional[Dict[str, str]] = None,
760
+ cache_policy: Optional[CachePolicyOrString] = None,
753
761
  merge: bool = True,
754
762
  ) -> "BaseStep":
755
763
  """Copies the step and applies the given configurations.
@@ -779,6 +787,7 @@ class BaseStep:
779
787
  model: Model to use for this step.
780
788
  retry: Configuration for retrying the step in case of failure.
781
789
  substitutions: Extra placeholders for the step name.
790
+ cache_policy: Cache policy for this step.
782
791
  merge: If `True`, will merge the given dictionary configurations
783
792
  like `parameters` and `settings` with existing
784
793
  configurations. If `False` the given configurations will
@@ -805,6 +814,7 @@ class BaseStep:
805
814
  model=model,
806
815
  retry=retry,
807
816
  substitutions=substitutions,
817
+ cache_policy=cache_policy,
808
818
  merge=merge,
809
819
  )
810
820
  return step_copy
@@ -31,6 +31,7 @@ from zenml.logger import get_logger
31
31
 
32
32
  if TYPE_CHECKING:
33
33
  from zenml.config.base_settings import SettingsOrDict
34
+ from zenml.config.cache_policy import CachePolicyOrString
34
35
  from zenml.config.retry_config import StepRetryConfig
35
36
  from zenml.config.source import Source
36
37
  from zenml.materializers.base_materializer import BaseMaterializer
@@ -74,6 +75,7 @@ def step(
74
75
  model: Optional["Model"] = None,
75
76
  retry: Optional["StepRetryConfig"] = None,
76
77
  substitutions: Optional[Dict[str, str]] = None,
78
+ cache_policy: Optional["CachePolicyOrString"] = None,
77
79
  ) -> Callable[["F"], "BaseStep"]: ...
78
80
 
79
81
 
@@ -95,6 +97,7 @@ def step(
95
97
  model: Optional["Model"] = None,
96
98
  retry: Optional["StepRetryConfig"] = None,
97
99
  substitutions: Optional[Dict[str, str]] = None,
100
+ cache_policy: Optional["CachePolicyOrString"] = None,
98
101
  ) -> Union["BaseStep", Callable[["F"], "BaseStep"]]:
99
102
  """Decorator to create a ZenML step.
100
103
 
@@ -127,6 +130,7 @@ def step(
127
130
  model: configuration of the model in the Model Control Plane.
128
131
  retry: configuration of step retry in case of step failure.
129
132
  substitutions: Extra placeholders for the step name.
133
+ cache_policy: Cache policy for this step.
130
134
 
131
135
  Returns:
132
136
  The step instance.
@@ -161,6 +165,7 @@ def step(
161
165
  model=model,
162
166
  retry=retry,
163
167
  substitutions=substitutions,
168
+ cache_policy=cache_policy,
164
169
  )
165
170
 
166
171
  return step_instance
@@ -0,0 +1,36 @@
1
+ """Add content hash column [aae4eed923b5].
2
+
3
+ Revision ID: aae4eed923b5
4
+ Revises: 0.84.3
5
+ Create Date: 2025-08-22 16:32:12.494008
6
+
7
+ """
8
+
9
+ import sqlalchemy as sa
10
+ from alembic import op
11
+
12
+ # revision identifiers, used by Alembic.
13
+ revision = "aae4eed923b5"
14
+ down_revision = "0.84.3"
15
+ branch_labels = None
16
+ depends_on = None
17
+
18
+
19
+ def upgrade() -> None:
20
+ """Upgrade database schema and/or data, creating a new revision."""
21
+ # ### commands auto generated by Alembic - please adjust! ###
22
+ with op.batch_alter_table("artifact_version", schema=None) as batch_op:
23
+ batch_op.add_column(
24
+ sa.Column("content_hash", sa.TEXT(), nullable=True)
25
+ )
26
+
27
+ # ### end Alembic commands ###
28
+
29
+
30
+ def downgrade() -> None:
31
+ """Downgrade database schema and/or data back to the previous revision."""
32
+ # ### commands auto generated by Alembic - please adjust! ###
33
+ with op.batch_alter_table("artifact_version", schema=None) as batch_op:
34
+ batch_op.drop_column("content_hash")
35
+
36
+ # ### end Alembic commands ###
@@ -299,6 +299,7 @@ class ArtifactVersionSchema(BaseSchema, RunMetadataInterface, table=True):
299
299
  ),
300
300
  )
301
301
  save_type: str = Field(sa_column=Column(TEXT, nullable=False))
302
+ content_hash: Optional[str] = Field(sa_column=Column(TEXT, nullable=True))
302
303
 
303
304
  # Foreign keys
304
305
  artifact_id: UUID = build_foreign_key_field(
@@ -483,6 +484,7 @@ class ArtifactVersionSchema(BaseSchema, RunMetadataInterface, table=True):
483
484
  materializer=artifact_version_request.materializer.model_dump_json(),
484
485
  data_type=artifact_version_request.data_type.model_dump_json(),
485
486
  save_type=artifact_version_request.save_type.value,
487
+ content_hash=artifact_version_request.content_hash,
486
488
  )
487
489
 
488
490
  def to_model(
@@ -530,6 +532,7 @@ class ArtifactVersionSchema(BaseSchema, RunMetadataInterface, table=True):
530
532
  updated=self.updated,
531
533
  save_type=ArtifactSaveType(self.save_type),
532
534
  artifact_store_id=self.artifact_store_id,
535
+ content_hash=self.content_hash,
533
536
  )
534
537
 
535
538
  # Create the metadata of the model
@@ -319,7 +319,7 @@ class StepRunSchema(NamedSchema, RunMetadataInterface, table=True):
319
319
  source_code=request.source_code,
320
320
  version=version,
321
321
  is_retriable=is_retriable,
322
- exception_info=json.dumps(request.exception_info)
322
+ exception_info=request.exception_info.model_dump_json()
323
323
  if request.exception_info
324
324
  else None,
325
325
  )
@@ -5401,10 +5401,15 @@ class SqlZenStore(BaseZenStore):
5401
5401
  step_id = step_run.id
5402
5402
  metadata["status"] = step_run.status
5403
5403
 
5404
- if step_run.end_time and step_run.start_time:
5405
- metadata["duration"] = (
5406
- step_run.end_time - step_run.start_time
5407
- ).total_seconds()
5404
+ if step_run.start_time:
5405
+ metadata["start_time"] = (
5406
+ step_run.start_time.isoformat()
5407
+ )
5408
+
5409
+ if step_run.end_time:
5410
+ metadata["duration"] = (
5411
+ step_run.end_time - step_run.start_time
5412
+ ).total_seconds()
5408
5413
 
5409
5414
  step_node = helper.add_step_node(
5410
5415
  node_id=helper.get_step_node_id(name=step_name),
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: zenml-nightly
3
- Version: 0.84.3.dev20250903
3
+ Version: 0.84.3.dev20250905
4
4
  Summary: ZenML: Write production-ready ML code.
5
5
  License: Apache-2.0
6
6
  Keywords: machine learning,production,pipeline,mlops,devops
@@ -1,5 +1,5 @@
1
1
  zenml/README.md,sha256=827dekbOWAs1BpW7VF1a4d7EbwPbjwccX-2zdXBENZo,1777
2
- zenml/VERSION,sha256=ouJDJKYOvUFMlyUN-y3sdOniHgu3Q8Bo4ArSugmDIOk,19
2
+ zenml/VERSION,sha256=WsKRjiTIbZhNxbOfDDrGCxiWY72mJVs7jWd3nMiiHPo,19
3
3
  zenml/__init__.py,sha256=r7JUg2SVDf_dPhS7iU6vudKusEqK4ics7_jFMZhq0o4,2731
4
4
  zenml/actions/__init__.py,sha256=mrt6wPo73iKRxK754_NqsGyJ3buW7RnVeIGXr1xEw8Y,681
5
5
  zenml/actions/base_action.py,sha256=UcaHev6BTuLDwuswnyaPjdA8AgUqB5xPZ-lRtuvf2FU,25553
@@ -25,7 +25,7 @@ zenml/artifacts/external_artifact.py,sha256=7nLANV0vsGC36H1s_B_awX4hnZgXHCGIscQ2
25
25
  zenml/artifacts/external_artifact_config.py,sha256=P172p0JOu8Xx1F8RCQut1dnRpt5lpWXGNqMbY-V90sI,3323
26
26
  zenml/artifacts/preexisting_data_materializer.py,sha256=dcahDcHUD3Lvn0-6zE2BG84bkyo_ydAgzBWxtbyJJZQ,3325
27
27
  zenml/artifacts/unmaterialized_artifact.py,sha256=JNPKq_sNifQx5wP8jEw7TGBEi26zwKirPGlWX9uxbJI,1300
28
- zenml/artifacts/utils.py,sha256=U2owJEOxOqRHG4dJ3y2HiPxUUWkaIxHVVmR5_iLn1Ow,36073
28
+ zenml/artifacts/utils.py,sha256=5O8YSHAyoXenCNprnramrv4urb_PdlL6gyO_HNwae_Q,36168
29
29
  zenml/cli/__init__.py,sha256=Q-DTKGMxUCyN8aAchAvjoWJeZ3f55Hnt4FpagiNHSbU,75655
30
30
  zenml/cli/annotator.py,sha256=JRR7_TJOWKyiKGv1kwSjG1Ay6RBWPVgm0X-D0uSBlyE,6976
31
31
  zenml/cli/artifact.py,sha256=7lsAS52DroBTFkFWxkyb-lIDOGP5jPL_Se_RDG_2jgg,9564
@@ -62,15 +62,16 @@ zenml/code_repositories/base_code_repository.py,sha256=Id6VjbUu8N3ZpNvBGhOgbahto
62
62
  zenml/code_repositories/git/__init__.py,sha256=vU8UzMp8sv9n-R2r7VKa9LdQcYER6BhO4O-z8Ppa3kM,824
63
63
  zenml/code_repositories/git/local_git_repository_context.py,sha256=PuD4GOnxBNtkSddc5QwMnnx3F2t4gClUeGmhfoLQHfs,5780
64
64
  zenml/code_repositories/local_repository_context.py,sha256=1VyiYkJBDVg0iGusgRQDToGRPJuu9lx7jTBDpplukDg,2816
65
- zenml/config/__init__.py,sha256=NIMS7QQo3-uVkNlzPvR5FbtgPdRibF2xFJB7Vr0fhCM,1826
65
+ zenml/config/__init__.py,sha256=KRAcMVUgE5R5cvoVQjs1lHUcl-IYBKmDSeBnwRIPG04,1265
66
66
  zenml/config/base_settings.py,sha256=itoLqc1cOwEYhgSGdZmSKSaBevQkvYH7NQh7PUamazc,1700
67
67
  zenml/config/build_configuration.py,sha256=jGGNwP0Cb7a80JXArNxDgxzxl9ytSZRtv-WW7_psLbM,6870
68
- zenml/config/compiler.py,sha256=uezFp9RKBhbh-zZSYMJ-QJNZQ4ksitsBsHX8mvR11jI,23802
68
+ zenml/config/cache_policy.py,sha256=_bXEbR7s8xt78JO-BUJ1V2clI3lO7FNMF3r6YbD_s8M,3121
69
+ zenml/config/compiler.py,sha256=YY1C-y_NBn0RpVCHfde0TQ01CJXLn01VOsytPpowEWg,23852
69
70
  zenml/config/constants.py,sha256=QvSgMwXWxtspcJ45CrFDP1ZY3w6gS3bIhXLOtIDAbZA,713
70
71
  zenml/config/docker_settings.py,sha256=xZvoeC6v6RG_5MFK_RgdTgrkOLu-QT6frY4SGQNZUTo,18460
71
72
  zenml/config/global_config.py,sha256=59orl6xp4moxSo2Q8tXtDfpIBX4AxJ9FHcm8s2VHyWw,29712
72
- zenml/config/pipeline_configurations.py,sha256=7trCbElpqGGgawii2FrdLW8fKaAWCR8jACkNqdG_vcQ,3983
73
- zenml/config/pipeline_run_configuration.py,sha256=Y9C5mVUH-w4gc1w1PCQFpjEmfBBpSMvb8riA_sL78hY,2311
73
+ zenml/config/pipeline_configurations.py,sha256=3AVe-VYwFkccpdpb4aH8w2JZCwD_Bh4V25f4YAufbwE,4106
74
+ zenml/config/pipeline_run_configuration.py,sha256=zZQS10-3qEnjXE9yZ7dJnnfYKh6mX-8Nwybjag-Ywpk,2434
74
75
  zenml/config/pipeline_spec.py,sha256=uWpiIfznJvXAiKs1yMIUDT1h1tYEFNO-RDVTYcIv9CE,2821
75
76
  zenml/config/resource_settings.py,sha256=0taXGHvDfXuvpMplxsuzpznB1sAvWJIGnXoVJ9-ySfw,3899
76
77
  zenml/config/retry_config.py,sha256=rld2nvjGpX67Wci6abCA5T7vAi-TVgM30gT5nT8N_8M,1009
@@ -80,7 +81,7 @@ zenml/config/secrets_store_config.py,sha256=y05zqyQhr_DGrs3IfBGa_FRoZ043hSYRT5wz
80
81
  zenml/config/server_config.py,sha256=HNHODfojAstBWMxcV5OjxcXSh8Oy9k-_0J5la60fqzQ,32616
81
82
  zenml/config/settings_resolver.py,sha256=PR9BRm_x1dy7nVKa9UqpeFdck8IEATSW6aWT8FKd-DI,4278
82
83
  zenml/config/source.py,sha256=RzUw8lin8QztUjz-AdoCzVM5Om_cSSPuroaPx-qAO4w,8226
83
- zenml/config/step_configurations.py,sha256=TFRYwzCnwWY69m1Cg9jmAl8eTUhD7wSgS05FoaMCnXg,14817
84
+ zenml/config/step_configurations.py,sha256=KVjcAAtNmEcDkEyLjW1tVPHEHBo9dnu25dCoj9JV6rg,15088
84
85
  zenml/config/step_run_info.py,sha256=KiVRSTtKmZ1GbvseDTap2imr7XwMHD3jSFVpyLNEK1I,1888
85
86
  zenml/config/store_config.py,sha256=Cla5p5dTB6nNlo8_OZDs9hod5hspi64vxwtZj882XgU,3559
86
87
  zenml/config/strict_base_model.py,sha256=t_ULrtJF2eW7TgyYBRobl1fscwwIZXATYky8ER97ev4,860
@@ -598,17 +599,17 @@ zenml/login/pro/workspace/models.py,sha256=godIY1q2dUxB0QILaOFOeqV1I3WglWUjZC11n
598
599
  zenml/login/server_info.py,sha256=-_sK2L-curHdzUv1JDOwF6GoEeAXT5vFZN0J-5Ug4wU,1663
599
600
  zenml/login/web_login.py,sha256=aAwqi4-AD5dJVJ3pCGi6aCIaa-dAFXOqnTdqRlwh-CU,9417
600
601
  zenml/materializers/__init__.py,sha256=C3lZaTmIFxwIPwCKF8oLQUkLaX2o7Dbj9hvYVFrSzt8,1758
601
- zenml/materializers/base_materializer.py,sha256=wMRLOAz0arRU2Q6tCxcYVfT62I-qg7HVHOPUd1OtKAg,13939
602
- zenml/materializers/built_in_materializer.py,sha256=HgcCHg3GpuQ4t-jecYcdg0kldUfLeUJvIpm8-wcS11I,17189
602
+ zenml/materializers/base_materializer.py,sha256=L77R7YTbFW_P_bHcbSSDNUmY4WxaqJtaZ8QVmSGTVN0,14231
603
+ zenml/materializers/built_in_materializer.py,sha256=xExGEG8f1T4CeTkjevIsG0exYy4ReNWesBz9xEVXe1o,19060
603
604
  zenml/materializers/cloudpickle_materializer.py,sha256=PIZauXg1SBYmBUi9FBd2t3LFyZupp3jYtMjZ0OTug18,4816
604
605
  zenml/materializers/materializer_registry.py,sha256=ic-aWhJ2Ex9F_rml2dDVAxhRfW3nd71QMxzfTPP6BIM,4002
605
606
  zenml/materializers/numpy_materializer.py,sha256=OLcHF9Z0tAqQ_U8TraA0vGmZjHoT7eT_XevncIutt0M,1715
606
607
  zenml/materializers/pandas_materializer.py,sha256=c4B-ly04504gysA66iCYcmEdeh0ClePRTxRCkmHqIgE,1725
607
608
  zenml/materializers/path_materializer.py,sha256=ydfKHhi14acjSb9jqizsXRRO4wKaCsSNUJg2woPw9XY,6217
608
- zenml/materializers/pydantic_materializer.py,sha256=eDp3eOR-X7FOHlpwALOJtVUtJti75Dsa7r0lzSjeQ-Q,2271
609
+ zenml/materializers/pydantic_materializer.py,sha256=PCY399H9L7i3dxHCLl2QVypoQAG3h2eAZZyZ0QZctD4,2865
609
610
  zenml/materializers/service_materializer.py,sha256=OV5HFUuIc8UF8vE5y_FTWn4_mpCz0AtJPnNA2YFAjZE,2992
610
- zenml/materializers/structured_string_materializer.py,sha256=8LIvSH3JQn_QRAWGXK5_NhPQ4NgCt5zzz6f8GnGG9q4,4442
611
- zenml/materializers/uuid_materializer.py,sha256=2lrTDZlq5TAE1EhT-S7GPP03CzrTDTzVhb7UScz9zgs,2629
611
+ zenml/materializers/structured_string_materializer.py,sha256=2rhGzoRfulwrjXV2b9WNrjoJZBk7Nibq2C47xVxuIpM,4929
612
+ zenml/materializers/uuid_materializer.py,sha256=YTJeiSTJeqd2TXuFT4IKLpncnWVHRPPu0zeh4E5Tx_k,3094
612
613
  zenml/metadata/__init__.py,sha256=iklF7cvq9BqHiYOC38qIm-LeE2I29Jl-RVl33hpS5Ao,778
613
614
  zenml/metadata/lazy_load.py,sha256=DtYSkhdTr2LDJoq2GYkwfLHy-3xcVoOFu_y4PKhVU_o,2903
614
615
  zenml/metadata/metadata_types.py,sha256=ts1EhF2qGZb8siKv1nkPSeFeyR2kbiIODkpk-hyoTxE,6745
@@ -634,7 +635,7 @@ zenml/models/v2/core/action_flavor.py,sha256=DlGlJTOcgLSDYAsrbAyXOJVdo7X2GYTFQTT
634
635
  zenml/models/v2/core/api_key.py,sha256=0iye9ftNk-Gjg4izZqYqbNgF1UR51WdRfasiAE2TqPw,11536
635
636
  zenml/models/v2/core/api_transaction.py,sha256=NepWmgi3q_1B5qiKho2nBWxAPGRVNaUzjgt-Rj5ZDCU,5104
636
637
  zenml/models/v2/core/artifact.py,sha256=1b0VZPEez3mi6pknfN5w10FgsxJeStyOgv4zjCM8uSs,8177
637
- zenml/models/v2/core/artifact_version.py,sha256=v15ZlJYZnheqvgeYN6VqPQlbFyxEBKoGfvW-Eb0k50Y,23577
638
+ zenml/models/v2/core/artifact_version.py,sha256=HWQuQqkR2qm4TzZ0GgqKJYLmqePLKbVN94gjFUXPYUY,24087
638
639
  zenml/models/v2/core/artifact_visualization.py,sha256=milAHTpfuYd8Dx_oB4hcPYJL-TMoiU0FwUI0UhB3F-E,3115
639
640
  zenml/models/v2/core/code_reference.py,sha256=9xy3Gzychq16lLUs01va3gGfwdu-AMrFgys_ua89uFY,3557
640
641
  zenml/models/v2/core/code_repository.py,sha256=qMqHF4uU2LkSShdBKb14Sg3XLGHLd7aMUEOyc_H0uZs,5556
@@ -686,7 +687,7 @@ zenml/models/v2/misc/tag.py,sha256=jUoz7wqMpDFlIUmvj4PVq8NYJJB7TMCcdRfW-DAABCU,9
686
687
  zenml/models/v2/misc/user_auth.py,sha256=1-yafNA9qK4wL8ToROjaklTVI7Mj9va0t80_4wm7w3U,6988
687
688
  zenml/orchestrators/__init__.py,sha256=Nhmc6U-q6c8TEH1Jb5l8XaKnc4KmLNspDpvvV5TcvzQ,2007
688
689
  zenml/orchestrators/base_orchestrator.py,sha256=m9qsavtb4fQv1pie8cnuQlOVxu_p2qJQ8X7jukijFZ4,21445
689
- zenml/orchestrators/cache_utils.py,sha256=QkmTs-ANfXve9_QzTqgGlyulZDEWOngoTcsiSjG5aA8,5906
690
+ zenml/orchestrators/cache_utils.py,sha256=PLZwNZREx3W4ZgRUahuIbfeTdR08uNWcwuDeoxzANac,6537
690
691
  zenml/orchestrators/containerized_orchestrator.py,sha256=-umxlNlQfezks1GLoi0SyXtXXo9dkC4Re9nA0fh_avw,3858
691
692
  zenml/orchestrators/dag_runner.py,sha256=6pDloHKuGvOTaABJ8G8OJ94f_8uPfeN-M0Nc5sFjHwA,10708
692
693
  zenml/orchestrators/input_utils.py,sha256=IwDYEwhFVcvZcdi9Myg__UB1bkZfpa8xZ0XRSwc4-go,6934
@@ -697,7 +698,7 @@ zenml/orchestrators/local_docker/local_docker_orchestrator.py,sha256=dEc1R2_xzFI
697
698
  zenml/orchestrators/output_utils.py,sha256=01vqke1ZfmfuLpgxNerF-QL2wA0VPv1zUdvlMw0OwUY,3508
698
699
  zenml/orchestrators/publish_utils.py,sha256=u0jk9Q57fLQE1QDJjrydy5KQ9xtYKUvn3CXBirDH2u8,8485
699
700
  zenml/orchestrators/step_launcher.py,sha256=dOvvMtgO_UhzPJYR3cz2H_j4L74qd9r9ggIc7EYzj40,18767
700
- zenml/orchestrators/step_run_utils.py,sha256=JXlYomV_PmC-cmjk7VWAGauKUXdijXU0ao8HBTZobmY,16802
701
+ zenml/orchestrators/step_run_utils.py,sha256=52ANscGnPTAyrOcMfMzSb3s3udxLiDL3Ly1uDvd2ZRk,16655
701
702
  zenml/orchestrators/step_runner.py,sha256=X3sX7f5NBYxT3utFGKcOJlkvCauYyEoo0LB2TB2Pp9U,27435
702
703
  zenml/orchestrators/topsort.py,sha256=D8evz3X47zwpXd90NMLsJD-_uCeXtV6ClzNfDUrq7cM,5784
703
704
  zenml/orchestrators/utils.py,sha256=6bqLc1fmdJTXg8JUwUKs8YNbmxTuMIfWmUbUpg-7hx0,12956
@@ -705,8 +706,8 @@ zenml/orchestrators/wheeled_orchestrator.py,sha256=eOnMcnd3sCzfhA2l6qRAzF0rOXzao
705
706
  zenml/pipelines/__init__.py,sha256=hpIX7hN8jsQRHT5R-xSXZL88qrHwkmrvGLQeu1rWt4o,873
706
707
  zenml/pipelines/build_utils.py,sha256=n7PyBGKPYGGc-QLuf4IfZE7iqlFMu2S2dnpI4TGAN6c,27952
707
708
  zenml/pipelines/pipeline_context.py,sha256=4BixReLcPo33VtNBDrMwnJqjKTinHjmO5AOfmoeIOQM,3659
708
- zenml/pipelines/pipeline_decorator.py,sha256=vR6prQPyxJ7lvSmr3sfb3lJ7LjEv3fx8NftmmNH9EUc,4836
709
- zenml/pipelines/pipeline_definition.py,sha256=v8wwZER4dGKztn_B2HLCXMXma1SAYydHvuV3Z480y04,60143
709
+ zenml/pipelines/pipeline_decorator.py,sha256=4UO9JZuO7PylwqEmcYpCTcWND9bFBdaMS7dK5mbd4gw,5107
710
+ zenml/pipelines/pipeline_definition.py,sha256=UeGemwJ_TMWlVCdOnm5g_b8Vk55YSvFhmQc8Uo6WOuA,60534
710
711
  zenml/pipelines/run_utils.py,sha256=VAjfdu300AKfTuwXll3uoFrwN5dt_hesXxtylndUraQ,12515
711
712
  zenml/plugins/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
712
713
  zenml/plugins/base_plugin_flavor.py,sha256=88IxFW91UB_rQ8xPlfRnIhIJh7A308NEq2epMMdlOng,2530
@@ -756,11 +757,11 @@ zenml/step_operators/__init__.py,sha256=tqj7fgnQyZubLjwUu4ITwkA-70KMQz4g37agbfF7
756
757
  zenml/step_operators/base_step_operator.py,sha256=ZRnY6lcEHY8xZskrKKdPhgKg2BlEoh2_kb8xCaM2D1g,3522
757
758
  zenml/step_operators/step_operator_entrypoint_configuration.py,sha256=wuQKmEI_ckn1CHHrxWGGdIhQyBFXG01aKC2-2b6Atjo,3690
758
759
  zenml/steps/__init__.py,sha256=KKWFOmCZGLDEikOD2E5YmDA7QHo47uPV37by21WwI0U,1453
759
- zenml/steps/base_step.py,sha256=HUNNQe3A5DyzEHm4gAbX_NCC2LiKRDI6nrngURW6WdI,44632
760
+ zenml/steps/base_step.py,sha256=6XncnFSONWfezBcWzatevo-GPRJ2P5uVuigCIY9iEIs,45156
760
761
  zenml/steps/decorated_step.py,sha256=cr4m7qi525fUc_VTkb7J16dKdUSzc4UA5eyHg8vFWQg,4275
761
762
  zenml/steps/entrypoint_function_utils.py,sha256=H0WIkHpR_R0S9gl_tWr0nX-fcBlYnm8OQ1cimvrw-qo,9555
762
763
  zenml/steps/step_context.py,sha256=sFvVVvEyKmWTrucofor8Cuxv-72jbziVaQY-OlOvFAM,15526
763
- zenml/steps/step_decorator.py,sha256=0TKxP_oAVRizjN3JhBZ8ShFd3fSBdVPU2ijytTg1h2U,6506
764
+ zenml/steps/step_decorator.py,sha256=DDuxBCDLAVjVmW3d3_ASUuKV9zK7CZkUCBwg1l2M2oY,6773
764
765
  zenml/steps/step_invocation.py,sha256=ETfOaV-P4_iXGk9y1-xK54Kfg2QRYaGoj_jTyEYZfb0,4861
765
766
  zenml/steps/utils.py,sha256=UpZ5lN46Bqu1eXyVfh969M4-UBbOZjq5R7u4PkXYDZ8,18586
766
767
  zenml/types.py,sha256=LhGWJ4t3nybBk1l9Ox3tqqHbTYSuCqhkRsL5FqO6yf4,1206
@@ -1279,6 +1280,7 @@ zenml/zen_stores/migrations/versions/__init__.py,sha256=ab-drj6BQO7OuDMGvcSlAjxG
1279
1280
  zenml/zen_stores/migrations/versions/a1237ba94fd8_add_model_version_producer_run_unique_.py,sha256=6H-TsiZWbzvhW8fvVpta3wzpK7Shc7RdHV-6At3IczI,2126
1280
1281
  zenml/zen_stores/migrations/versions/a39c4184c8ce_remove_secrets_manager_flavors.py,sha256=9bs6F1GSUu_kerajVB9nj_zIkcEa1NmLJ5N2quNFd9Q,794
1281
1282
  zenml/zen_stores/migrations/versions/a91762e6be36_artifact_version_table.py,sha256=EmViRqR-vcm2lZU6itSEKQzntJtg1FdzrE2Mmgozn6c,7818
1283
+ zenml/zen_stores/migrations/versions/aae4eed923b5_add_content_hash_column.py,sha256=r-Ewuzjb5fxftnyVkd35nmMd-LKNlUQGT-F6X3ohhz8,1018
1282
1284
  zenml/zen_stores/migrations/versions/ade72effebaf_added_logs_table.py,sha256=BP-WuS8xSM0fUARtTxzge3g9AyznNPU7OX3N3tgx6Sw,1963
1283
1285
  zenml/zen_stores/migrations/versions/alembic_start.py,sha256=707q8fI4cwfLzBqVcVqqt5aF_H9i5eI5AHWkjrt_sb0,15702
1284
1286
  zenml/zen_stores/migrations/versions/b4eccf34dfa3_add_hub_token_to_user_model.py,sha256=j9ifD7KC18pgzyCIL6tDa4rRpWi7uDY97pFvV-abTpc,1075
@@ -1314,7 +1316,7 @@ zenml/zen_stores/schemas/__init__.py,sha256=myNtX0C4sr3spHJi7fyQWY8DGOD1UVrUWzzI
1314
1316
  zenml/zen_stores/schemas/action_schemas.py,sha256=jymEro5r20seTpRcAr5iZw-g8rXZRSZFEbiEm_iFaj8,7618
1315
1317
  zenml/zen_stores/schemas/api_key_schemas.py,sha256=RJS-lH7AHHAe9oXA0CGWvtbrmYgVfNP9nMa7rhtRNnY,8379
1316
1318
  zenml/zen_stores/schemas/api_transaction_schemas.py,sha256=3shikZ5Vb9xvknEIAfwz4udcfEdUSbSwQN6E9WHLcNU,4359
1317
- zenml/zen_stores/schemas/artifact_schemas.py,sha256=P4k8w8Baj7VEM5cPBLFMUBS4dvinZ8RBOEhX8YDH7D0,19822
1319
+ zenml/zen_stores/schemas/artifact_schemas.py,sha256=626uxbBvQ4JGx1KW9YnXkYpd43d_HenKmfAGo6kK524,20009
1318
1320
  zenml/zen_stores/schemas/artifact_visualization_schemas.py,sha256=zv_Mg--WMTtAPEy5PXIkZlxq-oLrXZNLHXb_YgZbm0g,3667
1319
1321
  zenml/zen_stores/schemas/base_schemas.py,sha256=pS5aEeXgcOI5PENmY_FzfDCH-lCqPiVd3jGd-0iD2t8,2906
1320
1322
  zenml/zen_stores/schemas/code_repository_schemas.py,sha256=rC7PUoG9MvnnmtaQdm5JcOdpcEt7yqEDVzEn17v7uI8,8858
@@ -1339,7 +1341,7 @@ zenml/zen_stores/schemas/server_settings_schemas.py,sha256=usBE-idRrmK-LeLN0zDtC
1339
1341
  zenml/zen_stores/schemas/service_connector_schemas.py,sha256=SpzFZTbfxypFtMLBujPSlGOpt-kzjcHfq3IoBghPizI,11137
1340
1342
  zenml/zen_stores/schemas/service_schemas.py,sha256=Fn_DyGm-PF-qN1TPZA3Q8AhrnUOTSIX0V_MD0laZ2Bk,10685
1341
1343
  zenml/zen_stores/schemas/stack_schemas.py,sha256=DOPoNwblTqN83RpnD6cjyF80VeplA1BGUX8yuulpzKk,6829
1342
- zenml/zen_stores/schemas/step_run_schemas.py,sha256=lzisqMKUsKmzfl6AiagFlmVADOZowFvyZamltgjXxaE,20740
1344
+ zenml/zen_stores/schemas/step_run_schemas.py,sha256=WIPhUfs7ez2-mTsvArnThoFnlZZwN5D1uelS-PEp9Ks,20746
1343
1345
  zenml/zen_stores/schemas/tag_schemas.py,sha256=pwQ5ogZovtkUuRtAkHakOfMh6ixw6qofvxB4i_Gd4qA,8352
1344
1346
  zenml/zen_stores/schemas/trigger_schemas.py,sha256=LokauFEHdN5UuYeC2kf5PtJ60WMz-E82Ngcwxcv6tDA,11936
1345
1347
  zenml/zen_stores/schemas/user_schemas.py,sha256=HmfwW_QALw4UdtWplfaX7Ls6LIoTo110y1VodADmOhg,12091
@@ -1353,11 +1355,11 @@ zenml/zen_stores/secrets_stores/hashicorp_secrets_store.py,sha256=5err1a-TrV3SR5
1353
1355
  zenml/zen_stores/secrets_stores/secrets_store_interface.py,sha256=Q2Jbnt2Pp7NGlR-u1YBfRZV2g8su2Fd0ArBMdksAE-Q,2819
1354
1356
  zenml/zen_stores/secrets_stores/service_connector_secrets_store.py,sha256=DrXGMkBxQIy2n_kkux5Xh2OM3Ks3MOpqP1D4aY8bfyY,7047
1355
1357
  zenml/zen_stores/secrets_stores/sql_secrets_store.py,sha256=LPFW757WCJLP1S8vrvjsrl2Tf1yo281xUTjSBsos4qk,8788
1356
- zenml/zen_stores/sql_zen_store.py,sha256=nGuLAhFMlDUMaL9DwpwmuDCSZrJqyl60tIxdN6E3mH0,491850
1358
+ zenml/zen_stores/sql_zen_store.py,sha256=WQ-Wnyvr-Y_hhSe0ztIIFpP3vUu-_05fIHv7zWcfqo4,492024
1357
1359
  zenml/zen_stores/template_utils.py,sha256=iCXrXpqzVTY7roqop4Eh9J7DmLW6PQeILZexmw_l3b8,10074
1358
1360
  zenml/zen_stores/zen_store_interface.py,sha256=weiSULdI9AsbCE10a5TcwtybX-BJs9hKhjPJnTapWv4,93023
1359
- zenml_nightly-0.84.3.dev20250903.dist-info/LICENSE,sha256=wbnfEnXnafPbqwANHkV6LUsPKOtdpsd-SNw37rogLtc,11359
1360
- zenml_nightly-0.84.3.dev20250903.dist-info/METADATA,sha256=s-rHNx_7rfqNAYEJo66y_V94H7RzKxgTfLvyeR9AmIo,25252
1361
- zenml_nightly-0.84.3.dev20250903.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
1362
- zenml_nightly-0.84.3.dev20250903.dist-info/entry_points.txt,sha256=QK3ETQE0YswAM2mWypNMOv8TLtr7EjnqAFq1br_jEFE,43
1363
- zenml_nightly-0.84.3.dev20250903.dist-info/RECORD,,
1361
+ zenml_nightly-0.84.3.dev20250905.dist-info/LICENSE,sha256=wbnfEnXnafPbqwANHkV6LUsPKOtdpsd-SNw37rogLtc,11359
1362
+ zenml_nightly-0.84.3.dev20250905.dist-info/METADATA,sha256=ZIytS2gozwQkYBuEw8bM1QNayEnxny367SixXnPwPQ0,25252
1363
+ zenml_nightly-0.84.3.dev20250905.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
1364
+ zenml_nightly-0.84.3.dev20250905.dist-info/entry_points.txt,sha256=QK3ETQE0YswAM2mWypNMOv8TLtr7EjnqAFq1br_jEFE,43
1365
+ zenml_nightly-0.84.3.dev20250905.dist-info/RECORD,,