zenml-nightly 0.70.0.dev20241128__py3-none-any.whl → 0.70.0.dev20241130__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 (65) hide show
  1. zenml/VERSION +1 -1
  2. zenml/artifacts/artifact_config.py +7 -1
  3. zenml/artifacts/utils.py +55 -30
  4. zenml/cli/__init__.py +15 -0
  5. zenml/cli/base.py +4 -4
  6. zenml/cli/pipeline.py +80 -0
  7. zenml/cli/server.py +1 -1
  8. zenml/cli/stack.py +0 -3
  9. zenml/cli/stack_components.py +0 -1
  10. zenml/cli/utils.py +0 -5
  11. zenml/client.py +8 -18
  12. zenml/config/compiler.py +12 -3
  13. zenml/config/pipeline_configurations.py +20 -0
  14. zenml/config/pipeline_run_configuration.py +1 -0
  15. zenml/config/step_configurations.py +21 -0
  16. zenml/enums.py +1 -0
  17. zenml/integrations/feast/__init__.py +1 -1
  18. zenml/integrations/feast/feature_stores/feast_feature_store.py +13 -9
  19. zenml/materializers/built_in_materializer.py +18 -1
  20. zenml/materializers/structured_string_materializer.py +8 -3
  21. zenml/model/model.py +11 -3
  22. zenml/model/utils.py +18 -16
  23. zenml/models/__init__.py +6 -0
  24. zenml/models/v2/core/artifact_version.py +6 -3
  25. zenml/models/v2/core/component.py +0 -22
  26. zenml/models/v2/core/model_version.py +6 -3
  27. zenml/models/v2/core/pipeline_run.py +19 -3
  28. zenml/models/v2/core/run_metadata.py +30 -9
  29. zenml/models/v2/core/step_run.py +6 -4
  30. zenml/models/v2/misc/run_metadata.py +38 -0
  31. zenml/orchestrators/input_utils.py +19 -6
  32. zenml/orchestrators/publish_utils.py +12 -5
  33. zenml/orchestrators/step_launcher.py +7 -3
  34. zenml/orchestrators/step_run_utils.py +18 -6
  35. zenml/orchestrators/step_runner.py +39 -2
  36. zenml/orchestrators/utils.py +0 -21
  37. zenml/pipelines/pipeline_decorator.py +4 -0
  38. zenml/pipelines/pipeline_definition.py +14 -3
  39. zenml/pipelines/run_utils.py +9 -5
  40. zenml/steps/base_step.py +11 -1
  41. zenml/steps/entrypoint_function_utils.py +4 -2
  42. zenml/steps/step_decorator.py +4 -0
  43. zenml/steps/utils.py +23 -7
  44. zenml/types.py +4 -0
  45. zenml/utils/metadata_utils.py +186 -153
  46. zenml/utils/string_utils.py +41 -16
  47. zenml/utils/visualization_utils.py +4 -1
  48. zenml/zen_server/routers/workspaces_endpoints.py +19 -19
  49. zenml/zen_server/template_execution/utils.py +1 -0
  50. zenml/zen_stores/migrations/versions/b73bc71f1106_remove_component_spec_path.py +36 -0
  51. zenml/zen_stores/migrations/versions/cc269488e5a9_separate_run_metadata.py +135 -0
  52. zenml/zen_stores/schemas/__init__.py +5 -1
  53. zenml/zen_stores/schemas/artifact_schemas.py +12 -11
  54. zenml/zen_stores/schemas/component_schemas.py +0 -3
  55. zenml/zen_stores/schemas/model_schemas.py +13 -11
  56. zenml/zen_stores/schemas/pipeline_run_schemas.py +44 -16
  57. zenml/zen_stores/schemas/run_metadata_schemas.py +66 -31
  58. zenml/zen_stores/schemas/step_run_schemas.py +32 -12
  59. zenml/zen_stores/schemas/utils.py +47 -3
  60. zenml/zen_stores/sql_zen_store.py +117 -34
  61. {zenml_nightly-0.70.0.dev20241128.dist-info → zenml_nightly-0.70.0.dev20241130.dist-info}/METADATA +1 -1
  62. {zenml_nightly-0.70.0.dev20241128.dist-info → zenml_nightly-0.70.0.dev20241130.dist-info}/RECORD +65 -62
  63. {zenml_nightly-0.70.0.dev20241128.dist-info → zenml_nightly-0.70.0.dev20241130.dist-info}/LICENSE +0 -0
  64. {zenml_nightly-0.70.0.dev20241128.dist-info → zenml_nightly-0.70.0.dev20241130.dist-info}/WHEEL +0 -0
  65. {zenml_nightly-0.70.0.dev20241128.dist-info → zenml_nightly-0.70.0.dev20241130.dist-info}/entry_points.txt +0 -0
@@ -56,7 +56,7 @@ from zenml.steps.utils import (
56
56
  parse_return_type_annotations,
57
57
  resolve_type_annotation,
58
58
  )
59
- from zenml.utils import materializer_utils, source_utils
59
+ from zenml.utils import materializer_utils, source_utils, string_utils
60
60
  from zenml.utils.typing_utils import get_origin, is_union
61
61
 
62
62
  if TYPE_CHECKING:
@@ -152,6 +152,15 @@ class StepRunner:
152
152
  func=step_instance.entrypoint
153
153
  )
154
154
 
155
+ self._evaluate_artifact_names_in_collections(
156
+ step_run,
157
+ output_annotations,
158
+ [
159
+ output_artifact_uris,
160
+ output_materializers,
161
+ ],
162
+ )
163
+
155
164
  self._stack.prepare_step_run(info=step_run_info)
156
165
 
157
166
  # Initialize the step context singleton
@@ -257,7 +266,9 @@ class StepRunner:
257
266
 
258
267
  # Update the status and output artifacts of the step run.
259
268
  output_artifact_ids = {
260
- output_name: artifact.id
269
+ output_name: [
270
+ artifact.id,
271
+ ]
261
272
  for output_name, artifact in output_artifacts.items()
262
273
  }
263
274
  publish_successful_step_run(
@@ -265,6 +276,32 @@ class StepRunner:
265
276
  output_artifact_ids=output_artifact_ids,
266
277
  )
267
278
 
279
+ def _evaluate_artifact_names_in_collections(
280
+ self,
281
+ step_run: "StepRunResponse",
282
+ output_annotations: Dict[str, OutputSignature],
283
+ collections: List[Dict[str, Any]],
284
+ ) -> None:
285
+ """Evaluates the artifact names in the collections.
286
+
287
+ Args:
288
+ step_run: The step run.
289
+ output_annotations: The output annotations of the step function
290
+ (also evaluated).
291
+ collections: The collections to evaluate.
292
+ """
293
+ collections.append(output_annotations)
294
+ for k, v in list(output_annotations.items()):
295
+ name = k
296
+ if v.artifact_config and v.artifact_config.name:
297
+ name = string_utils.format_name_template(
298
+ v.artifact_config.name,
299
+ substitutions=step_run.config.substitutions,
300
+ )
301
+
302
+ for d in collections:
303
+ d[name] = d.pop(k)
304
+
268
305
  def _load_step(self) -> "BaseStep":
269
306
  """Load the step instance.
270
307
 
@@ -32,7 +32,6 @@ from zenml.constants import (
32
32
  from zenml.enums import AuthScheme, StackComponentType, StoreType
33
33
  from zenml.logger import get_logger
34
34
  from zenml.stack import StackComponent
35
- from zenml.utils.string_utils import format_name_template
36
35
 
37
36
  logger = get_logger(__name__)
38
37
 
@@ -196,26 +195,6 @@ def get_config_environment_vars(
196
195
  return environment_vars
197
196
 
198
197
 
199
- def get_run_name(run_name_template: str) -> str:
200
- """Fill out the run name template to get a complete run name.
201
-
202
- Args:
203
- run_name_template: The run name template to fill out.
204
-
205
- Raises:
206
- ValueError: If the run name is empty.
207
-
208
- Returns:
209
- The run name derived from the template.
210
- """
211
- run_name = format_name_template(run_name_template)
212
-
213
- if run_name == "":
214
- raise ValueError("Empty run names are not allowed.")
215
-
216
- return run_name
217
-
218
-
219
198
  class register_artifact_store_filesystem:
220
199
  """Context manager for the artifact_store/filesystem_registry dependency.
221
200
 
@@ -55,6 +55,7 @@ def pipeline(
55
55
  on_failure: Optional["HookSpecification"] = None,
56
56
  on_success: Optional["HookSpecification"] = None,
57
57
  model: Optional["Model"] = None,
58
+ substitutions: Optional[Dict[str, str]] = None,
58
59
  ) -> Callable[["F"], "Pipeline"]: ...
59
60
 
60
61
 
@@ -71,6 +72,7 @@ def pipeline(
71
72
  on_failure: Optional["HookSpecification"] = None,
72
73
  on_success: Optional["HookSpecification"] = None,
73
74
  model: Optional["Model"] = None,
75
+ substitutions: Optional[Dict[str, str]] = None,
74
76
  ) -> Union["Pipeline", Callable[["F"], "Pipeline"]]:
75
77
  """Decorator to create a pipeline.
76
78
 
@@ -91,6 +93,7 @@ def pipeline(
91
93
  function with no arguments, or a source path to such a function
92
94
  (e.g. `module.my_function`).
93
95
  model: configuration of the model in the Model Control Plane.
96
+ substitutions: Extra placeholders to use in the name templates.
94
97
 
95
98
  Returns:
96
99
  A pipeline instance.
@@ -111,6 +114,7 @@ def pipeline(
111
114
  on_success=on_success,
112
115
  model=model,
113
116
  entrypoint=func,
117
+ substitutions=substitutions,
114
118
  )
115
119
 
116
120
  p.__doc__ = func.__doc__
@@ -135,6 +135,7 @@ class Pipeline:
135
135
  on_failure: Optional["HookSpecification"] = None,
136
136
  on_success: Optional["HookSpecification"] = None,
137
137
  model: Optional["Model"] = None,
138
+ substitutions: Optional[Dict[str, str]] = None,
138
139
  ) -> None:
139
140
  """Initializes a pipeline.
140
141
 
@@ -157,6 +158,7 @@ class Pipeline:
157
158
  be a function with no arguments, or a source path to such a
158
159
  function (e.g. `module.my_function`).
159
160
  model: configuration of the model in the Model Control Plane.
161
+ substitutions: Extra placeholders to use in the name templates.
160
162
  """
161
163
  self._invocations: Dict[str, StepInvocation] = {}
162
164
  self._run_args: Dict[str, Any] = {}
@@ -177,6 +179,7 @@ class Pipeline:
177
179
  on_failure=on_failure,
178
180
  on_success=on_success,
179
181
  model=model,
182
+ substitutions=substitutions,
180
183
  )
181
184
  self.entrypoint = entrypoint
182
185
  self._parameters: Dict[str, Any] = {}
@@ -297,6 +300,7 @@ class Pipeline:
297
300
  model: Optional["Model"] = None,
298
301
  parameters: Optional[Dict[str, Any]] = None,
299
302
  merge: bool = True,
303
+ substitutions: Optional[Dict[str, str]] = None,
300
304
  ) -> Self:
301
305
  """Configures the pipeline.
302
306
 
@@ -333,6 +337,7 @@ class Pipeline:
333
337
  method for an example.
334
338
  model: configuration of the model version in the Model Control Plane.
335
339
  parameters: input parameters for the pipeline.
340
+ substitutions: Extra placeholders to use in the name templates.
336
341
 
337
342
  Returns:
338
343
  The pipeline instance that this method was called on.
@@ -365,6 +370,7 @@ class Pipeline:
365
370
  "success_hook_source": success_hook_source,
366
371
  "model": model,
367
372
  "parameters": parameters,
373
+ "substitutions": substitutions,
368
374
  }
369
375
  )
370
376
  if not self.__suppress_warnings_flag__:
@@ -577,6 +583,7 @@ To avoid this consider setting pipeline parameters only in one place (config or
577
583
  config_path: Optional[str] = None,
578
584
  unlisted: bool = False,
579
585
  prevent_build_reuse: bool = False,
586
+ skip_schedule_registration: bool = False,
580
587
  ) -> PipelineDeploymentResponse:
581
588
  """Create a pipeline deployment.
582
589
 
@@ -603,6 +610,7 @@ To avoid this consider setting pipeline parameters only in one place (config or
603
610
  to any pipeline).
604
611
  prevent_build_reuse: DEPRECATED: Use
605
612
  `DockerSettings.prevent_build_reuse` instead.
613
+ skip_schedule_registration: Whether to skip schedule registration.
606
614
 
607
615
  Returns:
608
616
  The pipeline deployment.
@@ -643,7 +651,7 @@ To avoid this consider setting pipeline parameters only in one place (config or
643
651
  stack.validate()
644
652
 
645
653
  schedule_id = None
646
- if schedule:
654
+ if schedule and not skip_schedule_registration:
647
655
  if not stack.orchestrator.config.is_schedulable:
648
656
  raise ValueError(
649
657
  f"Stack {stack.name} does not support scheduling. "
@@ -656,7 +664,8 @@ To avoid this consider setting pipeline parameters only in one place (config or
656
664
  schedule_name = schedule.name
657
665
  else:
658
666
  schedule_name = format_name_template(
659
- deployment.run_name_template
667
+ deployment.run_name_template,
668
+ substitutions=deployment.pipeline_configuration.substitutions,
660
669
  )
661
670
  components = Client().active_stack_model.components
662
671
  orchestrator = components[StackComponentType.ORCHESTRATOR][0]
@@ -1438,7 +1447,9 @@ To avoid this consider setting pipeline parameters only in one place (config or
1438
1447
  The created run template.
1439
1448
  """
1440
1449
  self._prepare_if_possible()
1441
- deployment = self._create_deployment(**self._run_args)
1450
+ deployment = self._create_deployment(
1451
+ **self._run_args, skip_schedule_registration=True
1452
+ )
1442
1453
 
1443
1454
  return Client().create_run_template(
1444
1455
  name=name, deployment_id=deployment.id, **kwargs
@@ -23,9 +23,8 @@ from zenml.models import (
23
23
  StackResponse,
24
24
  )
25
25
  from zenml.orchestrators.publish_utils import publish_failed_pipeline_run
26
- from zenml.orchestrators.utils import get_run_name
27
26
  from zenml.stack import Flavor, Stack
28
- from zenml.utils import code_utils, notebook_utils, source_utils
27
+ from zenml.utils import code_utils, notebook_utils, source_utils, string_utils
29
28
  from zenml.zen_stores.base_zen_store import BaseZenStore
30
29
 
31
30
  if TYPE_CHECKING:
@@ -66,16 +65,21 @@ def create_placeholder_run(
66
65
 
67
66
  if deployment.schedule:
68
67
  return None
69
-
68
+ start_time = datetime.utcnow()
70
69
  run_request = PipelineRunRequest(
71
- name=get_run_name(run_name_template=deployment.run_name_template),
70
+ name=string_utils.format_name_template(
71
+ name_template=deployment.run_name_template,
72
+ substitutions=deployment.pipeline_configuration._get_full_substitutions(
73
+ start_time
74
+ ),
75
+ ),
72
76
  # We set the start time on the placeholder run already to
73
77
  # make it consistent with the {time} placeholder in the
74
78
  # run name. This means the placeholder run will usually
75
79
  # have longer durations than scheduled runs, as for them
76
80
  # the start_time is only set once the first step starts
77
81
  # running.
78
- start_time=datetime.utcnow(),
82
+ start_time=start_time,
79
83
  orchestrator_run_id=None,
80
84
  user=deployment.user.id,
81
85
  workspace=deployment.workspace.id,
zenml/steps/base_step.py CHANGED
@@ -116,6 +116,7 @@ class BaseStep:
116
116
  on_success: Optional["HookSpecification"] = None,
117
117
  model: Optional["Model"] = None,
118
118
  retry: Optional[StepRetryConfig] = None,
119
+ substitutions: Optional[Dict[str, str]] = None,
119
120
  ) -> None:
120
121
  """Initializes a step.
121
122
 
@@ -144,11 +145,13 @@ class BaseStep:
144
145
  function (e.g. `module.my_function`).
145
146
  model: configuration of the model version in the Model Control Plane.
146
147
  retry: Configuration for retrying the step in case of failure.
148
+ substitutions: Extra placeholders to use in the name template.
147
149
  """
148
150
  from zenml.config.step_configurations import PartialStepConfiguration
149
151
 
150
152
  self.entrypoint_definition = validate_entrypoint_function(
151
- self.entrypoint, reserved_arguments=["after", "id"]
153
+ self.entrypoint,
154
+ reserved_arguments=["after", "id"],
152
155
  )
153
156
 
154
157
  name = name or self.__class__.__name__
@@ -203,6 +206,7 @@ class BaseStep:
203
206
  on_success=on_success,
204
207
  model=model,
205
208
  retry=retry,
209
+ substitutions=substitutions,
206
210
  )
207
211
 
208
212
  notebook_utils.try_to_save_notebook_cell_code(self.source_object)
@@ -595,6 +599,7 @@ class BaseStep:
595
599
  model: Optional["Model"] = None,
596
600
  merge: bool = True,
597
601
  retry: Optional[StepRetryConfig] = None,
602
+ substitutions: Optional[Dict[str, str]] = None,
598
603
  ) -> T:
599
604
  """Configures the step.
600
605
 
@@ -637,6 +642,7 @@ class BaseStep:
637
642
  overwrite all existing ones. See the general description of this
638
643
  method for an example.
639
644
  retry: Configuration for retrying the step in case of failure.
645
+ substitutions: Extra placeholders to use in the name template.
640
646
 
641
647
  Returns:
642
648
  The step instance that this method was called on.
@@ -701,6 +707,7 @@ class BaseStep:
701
707
  "success_hook_source": success_hook_source,
702
708
  "model": model,
703
709
  "retry": retry,
710
+ "substitutions": substitutions,
704
711
  }
705
712
  )
706
713
  config = StepConfigurationUpdate(**values)
@@ -725,6 +732,7 @@ class BaseStep:
725
732
  on_success: Optional["HookSpecification"] = None,
726
733
  model: Optional["Model"] = None,
727
734
  merge: bool = True,
735
+ substitutions: Optional[Dict[str, str]] = None,
728
736
  ) -> "BaseStep":
729
737
  """Copies the step and applies the given configurations.
730
738
 
@@ -756,6 +764,7 @@ class BaseStep:
756
764
  configurations. If `False` the given configurations will
757
765
  overwrite all existing ones. See the general description of this
758
766
  method for an example.
767
+ substitutions: Extra placeholders for the step name.
759
768
 
760
769
  Returns:
761
770
  The copied step instance.
@@ -776,6 +785,7 @@ class BaseStep:
776
785
  on_success=on_success,
777
786
  model=model,
778
787
  merge=merge,
788
+ substitutions=substitutions,
779
789
  )
780
790
  return step_copy
781
791
 
@@ -211,7 +211,8 @@ class EntrypointFunctionDefinition(NamedTuple):
211
211
 
212
212
 
213
213
  def validate_entrypoint_function(
214
- func: Callable[..., Any], reserved_arguments: Sequence[str] = ()
214
+ func: Callable[..., Any],
215
+ reserved_arguments: Sequence[str] = (),
215
216
  ) -> EntrypointFunctionDefinition:
216
217
  """Validates a step entrypoint function.
217
218
 
@@ -258,7 +259,8 @@ def validate_entrypoint_function(
258
259
  inputs[key] = parameter
259
260
 
260
261
  outputs = parse_return_type_annotations(
261
- func=func, enforce_type_annotations=ENFORCE_TYPE_ANNOTATIONS
262
+ func=func,
263
+ enforce_type_annotations=ENFORCE_TYPE_ANNOTATIONS,
262
264
  )
263
265
 
264
266
  return EntrypointFunctionDefinition(
@@ -73,6 +73,7 @@ def step(
73
73
  on_success: Optional["HookSpecification"] = None,
74
74
  model: Optional["Model"] = None,
75
75
  retry: Optional["StepRetryConfig"] = None,
76
+ substitutions: Optional[Dict[str, str]] = None,
76
77
  ) -> Callable[["F"], "BaseStep"]: ...
77
78
 
78
79
 
@@ -93,6 +94,7 @@ def step(
93
94
  on_success: Optional["HookSpecification"] = None,
94
95
  model: Optional["Model"] = None,
95
96
  retry: Optional["StepRetryConfig"] = None,
97
+ substitutions: Optional[Dict[str, str]] = None,
96
98
  ) -> Union["BaseStep", Callable[["F"], "BaseStep"]]:
97
99
  """Decorator to create a ZenML step.
98
100
 
@@ -124,6 +126,7 @@ def step(
124
126
  (e.g. `module.my_function`).
125
127
  model: configuration of the model in the Model Control Plane.
126
128
  retry: configuration of step retry in case of step failure.
129
+ substitutions: Extra placeholders for the step name.
127
130
 
128
131
  Returns:
129
132
  The step instance.
@@ -157,6 +160,7 @@ def step(
157
160
  on_success=on_success,
158
161
  model=model,
159
162
  retry=retry,
163
+ substitutions=substitutions,
160
164
  )
161
165
 
162
166
  return step_instance
zenml/steps/utils.py CHANGED
@@ -18,7 +18,15 @@ import ast
18
18
  import contextlib
19
19
  import inspect
20
20
  import textwrap
21
- from typing import TYPE_CHECKING, Any, Callable, Dict, Optional, Tuple, Union
21
+ from typing import (
22
+ TYPE_CHECKING,
23
+ Any,
24
+ Callable,
25
+ Dict,
26
+ Optional,
27
+ Tuple,
28
+ Union,
29
+ )
22
30
  from uuid import UUID
23
31
 
24
32
  from pydantic import BaseModel
@@ -34,6 +42,7 @@ from zenml.enums import (
34
42
  from zenml.exceptions import StepInterfaceError
35
43
  from zenml.logger import get_logger
36
44
  from zenml.metadata.metadata_types import MetadataType
45
+ from zenml.models import RunMetadataResource
37
46
  from zenml.steps.step_context import get_step_context
38
47
  from zenml.utils import settings_utils, source_code_utils, typing_utils
39
48
 
@@ -94,7 +103,8 @@ def get_args(obj: Any) -> Tuple[Any, ...]:
94
103
 
95
104
 
96
105
  def parse_return_type_annotations(
97
- func: Callable[..., Any], enforce_type_annotations: bool = False
106
+ func: Callable[..., Any],
107
+ enforce_type_annotations: bool = False,
98
108
  ) -> Dict[str, OutputSignature]:
99
109
  """Parse the return type annotation of a step function.
100
110
 
@@ -228,9 +238,12 @@ def get_artifact_config_from_annotation_metadata(
228
238
 
229
239
  error_message = (
230
240
  "Artifact annotation should only contain two elements: the artifact "
231
- "type, and either an output name or an `ArtifactConfig`, e.g.: "
232
- "`Annotated[int, 'output_name']` or "
233
- "`Annotated[int, ArtifactConfig(name='output_name'), ...]`."
241
+ "type, and one of the following: { a static or dynamic name || "
242
+ "an `ArtifactConfig` }, e.g.: "
243
+ "`Annotated[int, 'output_name']` || "
244
+ "`Annotated[int, 'output_{placeholder}']` || "
245
+ "`Annotated[int, ArtifactConfig(name='output_{placeholder}')]` ||"
246
+ "`Annotated[int, ArtifactConfig(name='output_name')]`."
234
247
  )
235
248
 
236
249
  if len(metadata) > 2:
@@ -477,8 +490,11 @@ def log_step_metadata(
477
490
  step_run_id = pipeline_run.steps[step_name].id
478
491
  client.create_run_metadata(
479
492
  metadata=metadata,
480
- resource_id=step_run_id,
481
- resource_type=MetadataResourceTypes.STEP_RUN,
493
+ resources=[
494
+ RunMetadataResource(
495
+ id=step_run_id, type=MetadataResourceTypes.STEP_RUN
496
+ )
497
+ ],
482
498
  )
483
499
 
484
500
 
zenml/types.py CHANGED
@@ -33,3 +33,7 @@ class MarkdownString(str):
33
33
 
34
34
  class CSVString(str):
35
35
  """Special string class to indicate a CSV string."""
36
+
37
+
38
+ class JSONString(str):
39
+ """Special string class to indicate a JSON string."""