zenml-nightly 0.70.0.dev20241125__py3-none-any.whl → 0.70.0.dev20241201__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 (91) hide show
  1. zenml/VERSION +1 -1
  2. zenml/artifact_stores/base_artifact_store.py +2 -2
  3. zenml/artifacts/artifact_config.py +7 -1
  4. zenml/artifacts/utils.py +56 -31
  5. zenml/cli/__init__.py +18 -0
  6. zenml/cli/base.py +4 -4
  7. zenml/cli/login.py +26 -0
  8. zenml/cli/pipeline.py +80 -0
  9. zenml/cli/server.py +1 -1
  10. zenml/cli/service_connectors.py +3 -3
  11. zenml/cli/stack.py +0 -3
  12. zenml/cli/stack_components.py +0 -1
  13. zenml/cli/utils.py +0 -5
  14. zenml/client.py +8 -18
  15. zenml/config/compiler.py +12 -3
  16. zenml/config/pipeline_configurations.py +20 -0
  17. zenml/config/pipeline_run_configuration.py +1 -0
  18. zenml/config/step_configurations.py +21 -0
  19. zenml/enums.py +1 -0
  20. zenml/image_builders/local_image_builder.py +13 -3
  21. zenml/integrations/__init__.py +1 -0
  22. zenml/integrations/aws/orchestrators/sagemaker_orchestrator.py +14 -6
  23. zenml/integrations/constants.py +1 -0
  24. zenml/integrations/feast/__init__.py +1 -1
  25. zenml/integrations/feast/feature_stores/feast_feature_store.py +13 -9
  26. zenml/integrations/kubernetes/orchestrators/kube_utils.py +46 -2
  27. zenml/integrations/kubernetes/orchestrators/kubernetes_orchestrator.py +13 -2
  28. zenml/integrations/kubernetes/orchestrators/kubernetes_orchestrator_entrypoint.py +3 -1
  29. zenml/integrations/kubernetes/orchestrators/manifest_utils.py +3 -2
  30. zenml/integrations/kubernetes/step_operators/kubernetes_step_operator.py +3 -1
  31. zenml/integrations/modal/__init__.py +46 -0
  32. zenml/integrations/modal/flavors/__init__.py +26 -0
  33. zenml/integrations/modal/flavors/modal_step_operator_flavor.py +125 -0
  34. zenml/integrations/modal/step_operators/__init__.py +22 -0
  35. zenml/integrations/modal/step_operators/modal_step_operator.py +242 -0
  36. zenml/io/filesystem.py +2 -2
  37. zenml/io/local_filesystem.py +3 -3
  38. zenml/materializers/built_in_materializer.py +18 -1
  39. zenml/materializers/structured_string_materializer.py +8 -3
  40. zenml/model/model.py +11 -85
  41. zenml/model/utils.py +18 -16
  42. zenml/models/__init__.py +6 -0
  43. zenml/models/v2/core/artifact_version.py +6 -3
  44. zenml/models/v2/core/component.py +0 -22
  45. zenml/models/v2/core/model_version.py +6 -3
  46. zenml/models/v2/core/pipeline_run.py +19 -3
  47. zenml/models/v2/core/run_metadata.py +30 -9
  48. zenml/models/v2/core/step_run.py +6 -4
  49. zenml/models/v2/misc/run_metadata.py +38 -0
  50. zenml/orchestrators/input_utils.py +19 -6
  51. zenml/orchestrators/publish_utils.py +12 -5
  52. zenml/orchestrators/step_launcher.py +7 -3
  53. zenml/orchestrators/step_run_utils.py +26 -9
  54. zenml/orchestrators/step_runner.py +40 -3
  55. zenml/orchestrators/utils.py +24 -23
  56. zenml/pipelines/pipeline_decorator.py +4 -0
  57. zenml/pipelines/pipeline_definition.py +26 -8
  58. zenml/pipelines/run_utils.py +9 -5
  59. zenml/steps/base_step.py +11 -1
  60. zenml/steps/entrypoint_function_utils.py +7 -3
  61. zenml/steps/step_decorator.py +4 -0
  62. zenml/steps/utils.py +23 -7
  63. zenml/types.py +4 -0
  64. zenml/utils/metadata_utils.py +186 -153
  65. zenml/utils/string_utils.py +41 -16
  66. zenml/utils/visualization_utils.py +4 -1
  67. zenml/zen_server/cloud_utils.py +3 -1
  68. zenml/zen_server/rbac/endpoint_utils.py +6 -4
  69. zenml/zen_server/rbac/models.py +3 -2
  70. zenml/zen_server/rbac/utils.py +4 -7
  71. zenml/zen_server/routers/users_endpoints.py +35 -37
  72. zenml/zen_server/routers/workspaces_endpoints.py +44 -55
  73. zenml/zen_server/template_execution/utils.py +1 -0
  74. zenml/zen_stores/migrations/versions/b73bc71f1106_remove_component_spec_path.py +36 -0
  75. zenml/zen_stores/migrations/versions/cc269488e5a9_separate_run_metadata.py +135 -0
  76. zenml/zen_stores/migrations/versions/ec6307720f92_simplify_model_version_links.py +7 -6
  77. zenml/zen_stores/schemas/__init__.py +5 -1
  78. zenml/zen_stores/schemas/artifact_schemas.py +12 -11
  79. zenml/zen_stores/schemas/component_schemas.py +0 -3
  80. zenml/zen_stores/schemas/model_schemas.py +13 -11
  81. zenml/zen_stores/schemas/pipeline_run_schemas.py +44 -16
  82. zenml/zen_stores/schemas/run_metadata_schemas.py +66 -31
  83. zenml/zen_stores/schemas/step_run_schemas.py +32 -12
  84. zenml/zen_stores/schemas/utils.py +47 -3
  85. zenml/zen_stores/sql_zen_store.py +130 -34
  86. {zenml_nightly-0.70.0.dev20241125.dist-info → zenml_nightly-0.70.0.dev20241201.dist-info}/METADATA +1 -1
  87. {zenml_nightly-0.70.0.dev20241125.dist-info → zenml_nightly-0.70.0.dev20241201.dist-info}/RECORD +90 -83
  88. zenml/utils/cloud_utils.py +0 -40
  89. {zenml_nightly-0.70.0.dev20241125.dist-info → zenml_nightly-0.70.0.dev20241201.dist-info}/LICENSE +0 -0
  90. {zenml_nightly-0.70.0.dev20241125.dist-info → zenml_nightly-0.70.0.dev20241201.dist-info}/WHEEL +0 -0
  91. {zenml_nightly-0.70.0.dev20241125.dist-info → zenml_nightly-0.70.0.dev20241201.dist-info}/entry_points.txt +0 -0
@@ -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__:
@@ -534,11 +540,18 @@ To avoid this consider setting pipeline parameters only in one place (config or
534
540
  """
535
541
  with track_handler(event=AnalyticsEvent.BUILD_PIPELINE):
536
542
  self._prepare_if_possible()
537
- deployment, _, _ = self._compile(
538
- config_path=config_path,
539
- steps=step_configurations,
540
- settings=settings,
541
- )
543
+
544
+ compile_args = self._run_args.copy()
545
+ compile_args.pop("unlisted", None)
546
+ compile_args.pop("prevent_build_reuse", None)
547
+ if config_path:
548
+ compile_args["config_path"] = config_path
549
+ if step_configurations:
550
+ compile_args["step_configurations"] = step_configurations
551
+ if settings:
552
+ compile_args["settings"] = settings
553
+
554
+ deployment, _, _ = self._compile(**compile_args)
542
555
  pipeline_id = self._register().id
543
556
 
544
557
  local_repo = code_repository_utils.find_active_code_repository()
@@ -570,6 +583,7 @@ To avoid this consider setting pipeline parameters only in one place (config or
570
583
  config_path: Optional[str] = None,
571
584
  unlisted: bool = False,
572
585
  prevent_build_reuse: bool = False,
586
+ skip_schedule_registration: bool = False,
573
587
  ) -> PipelineDeploymentResponse:
574
588
  """Create a pipeline deployment.
575
589
 
@@ -596,6 +610,7 @@ To avoid this consider setting pipeline parameters only in one place (config or
596
610
  to any pipeline).
597
611
  prevent_build_reuse: DEPRECATED: Use
598
612
  `DockerSettings.prevent_build_reuse` instead.
613
+ skip_schedule_registration: Whether to skip schedule registration.
599
614
 
600
615
  Returns:
601
616
  The pipeline deployment.
@@ -636,7 +651,7 @@ To avoid this consider setting pipeline parameters only in one place (config or
636
651
  stack.validate()
637
652
 
638
653
  schedule_id = None
639
- if schedule:
654
+ if schedule and not skip_schedule_registration:
640
655
  if not stack.orchestrator.config.is_schedulable:
641
656
  raise ValueError(
642
657
  f"Stack {stack.name} does not support scheduling. "
@@ -649,7 +664,8 @@ To avoid this consider setting pipeline parameters only in one place (config or
649
664
  schedule_name = schedule.name
650
665
  else:
651
666
  schedule_name = format_name_template(
652
- deployment.run_name_template
667
+ deployment.run_name_template,
668
+ substitutions=deployment.pipeline_configuration.substitutions,
653
669
  )
654
670
  components = Client().active_stack_model.components
655
671
  orchestrator = components[StackComponentType.ORCHESTRATOR][0]
@@ -1431,7 +1447,9 @@ To avoid this consider setting pipeline parameters only in one place (config or
1431
1447
  The created run template.
1432
1448
  """
1433
1449
  self._prepare_if_possible()
1434
- deployment = self._create_deployment(**self._run_args)
1450
+ deployment = self._create_deployment(
1451
+ **self._run_args, skip_schedule_registration=True
1452
+ )
1435
1453
 
1436
1454
  return Client().create_run_template(
1437
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
 
@@ -195,7 +195,9 @@ class EntrypointFunctionDefinition(NamedTuple):
195
195
  parameter: The function parameter for which the value was provided.
196
196
  value: The input value.
197
197
  """
198
- config_dict = ConfigDict(arbitrary_types_allowed=False)
198
+ # We allow passing None for optional annotations that would otherwise
199
+ # not be allowed as a parameter
200
+ config_dict = ConfigDict(arbitrary_types_allowed=value is None)
199
201
 
200
202
  # Create a pydantic model with just a single required field with the
201
203
  # type annotation of the parameter to verify the input type including
@@ -209,7 +211,8 @@ class EntrypointFunctionDefinition(NamedTuple):
209
211
 
210
212
 
211
213
  def validate_entrypoint_function(
212
- func: Callable[..., Any], reserved_arguments: Sequence[str] = ()
214
+ func: Callable[..., Any],
215
+ reserved_arguments: Sequence[str] = (),
213
216
  ) -> EntrypointFunctionDefinition:
214
217
  """Validates a step entrypoint function.
215
218
 
@@ -256,7 +259,8 @@ def validate_entrypoint_function(
256
259
  inputs[key] = parameter
257
260
 
258
261
  outputs = parse_return_type_annotations(
259
- func=func, enforce_type_annotations=ENFORCE_TYPE_ANNOTATIONS
262
+ func=func,
263
+ enforce_type_annotations=ENFORCE_TYPE_ANNOTATIONS,
260
264
  )
261
265
 
262
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."""