zenml-nightly 0.73.0.dev20250123__py3-none-any.whl → 0.73.0.dev20250124__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.
zenml/VERSION CHANGED
@@ -1 +1 @@
1
- 0.73.0.dev20250123
1
+ 0.73.0.dev20250124
zenml/cli/login.py CHANGED
@@ -249,6 +249,7 @@ def connect_to_pro_server(
249
249
  from zenml.login.pro.tenant.models import TenantStatus
250
250
 
251
251
  pro_api_url = pro_api_url or ZENML_PRO_API_URL
252
+ pro_api_url = pro_api_url.rstrip("/")
252
253
 
253
254
  server_id, server_url, server_name = None, None, None
254
255
  login = False
@@ -434,6 +435,7 @@ def is_pro_server(
434
435
  from zenml.login.credentials_store import get_credentials_store
435
436
  from zenml.login.server_info import get_server_info
436
437
 
438
+ url = url.rstrip("/")
437
439
  # First, check the credentials store
438
440
  credentials_store = get_credentials_store()
439
441
  credentials = credentials_store.get_credentials(url)
zenml/cli/server.py CHANGED
@@ -578,6 +578,7 @@ def server_list(
578
578
  from zenml.login.pro.tenant.models import TenantRead, TenantStatus
579
579
 
580
580
  pro_api_url = pro_api_url or ZENML_PRO_API_URL
581
+ pro_api_url = pro_api_url.rstrip("/")
581
582
 
582
583
  credentials_store = get_credentials_store()
583
584
  pro_token = credentials_store.get_pro_token(
zenml/enums.py CHANGED
@@ -376,6 +376,7 @@ class MetadataResourceTypes(StrEnum):
376
376
  STEP_RUN = "step_run"
377
377
  ARTIFACT_VERSION = "artifact_version"
378
378
  MODEL_VERSION = "model_version"
379
+ SCHEDULE = "schedule"
379
380
 
380
381
 
381
382
  class DatabaseBackupStrategy(StrEnum):
@@ -35,12 +35,13 @@ AWS_RESOURCE_TYPE = "aws-generic"
35
35
  S3_RESOURCE_TYPE = "s3-bucket"
36
36
  AWS_IMAGE_BUILDER_FLAVOR = "aws"
37
37
 
38
+
38
39
  class AWSIntegration(Integration):
39
40
  """Definition of AWS integration for ZenML."""
40
41
 
41
42
  NAME = AWS
42
43
  REQUIREMENTS = [
43
- "sagemaker>=2.117.0",
44
+ "sagemaker>=2.199.0",
44
45
  "kubernetes",
45
46
  "aws-profile-manager",
46
47
  ]
@@ -85,6 +85,7 @@ class SagemakerOrchestratorSettings(BaseSettings):
85
85
  to the container is configured with input_data_s3_mode. Two possible
86
86
  input types:
87
87
  - str: S3 location where training data is saved.
88
+ - Dict[str, str]: (ChannelName, S3Location) which represent
88
89
  - Dict[str, str]: (ChannelName, S3Location) which represent
89
90
  channels (e.g. training, validation, testing) where
90
91
  specific parts of the data are saved in S3.
@@ -184,6 +185,10 @@ class SagemakerOrchestratorConfig(
184
185
 
185
186
  Attributes:
186
187
  execution_role: The IAM role ARN to use for the pipeline.
188
+ scheduler_role: The ARN of the IAM role that will be assumed by
189
+ the EventBridge service to launch Sagemaker pipelines
190
+ (For more details regarding the required permissions, please check:
191
+ https://docs.zenml.io/stack-components/orchestrators/sagemaker#required-iam-permissions-for-schedules)
187
192
  aws_access_key_id: The AWS access key ID to use to authenticate to AWS.
188
193
  If not provided, the value from the default AWS config will be used.
189
194
  aws_secret_access_key: The AWS secret access key to use to authenticate
@@ -203,6 +208,7 @@ class SagemakerOrchestratorConfig(
203
208
  """
204
209
 
205
210
  execution_role: str
211
+ scheduler_role: Optional[str] = None
206
212
  aws_access_key_id: Optional[str] = SecretField(default=None)
207
213
  aws_secret_access_key: Optional[str] = SecretField(default=None)
208
214
  aws_profile: Optional[str] = None
@@ -232,6 +238,15 @@ class SagemakerOrchestratorConfig(
232
238
  """
233
239
  return self.synchronous
234
240
 
241
+ @property
242
+ def is_schedulable(self) -> bool:
243
+ """Whether the orchestrator is schedulable or not.
244
+
245
+ Returns:
246
+ Whether the orchestrator is schedulable or not.
247
+ """
248
+ return True
249
+
235
250
 
236
251
  class SagemakerOrchestratorFlavor(BaseOrchestratorFlavor):
237
252
  """Flavor for the Sagemaker orchestrator."""
@@ -15,6 +15,7 @@
15
15
 
16
16
  import os
17
17
  import re
18
+ from datetime import datetime, timezone
18
19
  from typing import (
19
20
  TYPE_CHECKING,
20
21
  Any,
@@ -35,14 +36,20 @@ from sagemaker.processing import ProcessingInput, ProcessingOutput
35
36
  from sagemaker.workflow.execution_variables import ExecutionVariables
36
37
  from sagemaker.workflow.pipeline import Pipeline
37
38
  from sagemaker.workflow.steps import ProcessingStep, TrainingStep
39
+ from sagemaker.workflow.triggers import PipelineSchedule
38
40
 
41
+ from zenml.client import Client
39
42
  from zenml.config.base_settings import BaseSettings
40
43
  from zenml.constants import (
41
44
  METADATA_ORCHESTRATOR_LOGS_URL,
42
45
  METADATA_ORCHESTRATOR_RUN_ID,
43
46
  METADATA_ORCHESTRATOR_URL,
44
47
  )
45
- from zenml.enums import ExecutionStatus, StackComponentType
48
+ from zenml.enums import (
49
+ ExecutionStatus,
50
+ MetadataResourceTypes,
51
+ StackComponentType,
52
+ )
46
53
  from zenml.integrations.aws.flavors.sagemaker_orchestrator_flavor import (
47
54
  SagemakerOrchestratorConfig,
48
55
  SagemakerOrchestratorSettings,
@@ -69,6 +76,36 @@ POLLING_DELAY = 30
69
76
  logger = get_logger(__name__)
70
77
 
71
78
 
79
+ def dissect_schedule_arn(
80
+ schedule_arn: str,
81
+ ) -> Tuple[Optional[str], Optional[str]]:
82
+ """Extracts the region and the name from an EventBridge schedule ARN.
83
+
84
+ Args:
85
+ schedule_arn: The ARN of the EventBridge schedule.
86
+
87
+ Returns:
88
+ Region Name, Schedule Name (including the group name)
89
+
90
+ Raises:
91
+ ValueError: If the input is not a properly formatted ARN.
92
+ """
93
+ # Split the ARN into parts
94
+ arn_parts = schedule_arn.split(":")
95
+
96
+ # Validate ARN structure
97
+ if len(arn_parts) < 6 or not arn_parts[5].startswith("schedule/"):
98
+ raise ValueError("Invalid EventBridge schedule ARN format.")
99
+
100
+ # Extract the region
101
+ region = arn_parts[3]
102
+
103
+ # Extract the group name and schedule name
104
+ name = arn_parts[5].split("schedule/")[1]
105
+
106
+ return region, name
107
+
108
+
72
109
  def dissect_pipeline_execution_arn(
73
110
  pipeline_execution_arn: str,
74
111
  ) -> Tuple[Optional[str], Optional[str], Optional[str]]:
@@ -237,21 +274,15 @@ class SagemakerOrchestrator(ContainerizedOrchestrator):
237
274
  environment.
238
275
 
239
276
  Raises:
240
- RuntimeError: If a connector is used that does not return a
241
- `boto3.Session` object.
277
+ RuntimeError: If there is an error creating or scheduling the
278
+ pipeline.
242
279
  TypeError: If the network_config passed is not compatible with the
243
280
  AWS SageMaker NetworkConfig class.
281
+ ValueError: If the schedule is not valid.
244
282
 
245
283
  Yields:
246
284
  A dictionary of metadata related to the pipeline run.
247
285
  """
248
- if deployment.schedule:
249
- logger.warning(
250
- "The Sagemaker Orchestrator currently does not support the "
251
- "use of schedules. The `schedule` will be ignored "
252
- "and the pipeline will be run immediately."
253
- )
254
-
255
286
  # sagemaker requires pipelineName to use alphanum and hyphens only
256
287
  unsanitized_orchestrator_run_name = get_orchestrator_run_name(
257
288
  pipeline_name=deployment.pipeline_configuration.name
@@ -459,7 +490,7 @@ class SagemakerOrchestrator(ContainerizedOrchestrator):
459
490
 
460
491
  sagemaker_steps.append(sagemaker_step)
461
492
 
462
- # construct the pipeline from the sagemaker_steps
493
+ # Create the pipeline
463
494
  pipeline = Pipeline(
464
495
  name=orchestrator_run_name,
465
496
  steps=sagemaker_steps,
@@ -479,39 +510,207 @@ class SagemakerOrchestrator(ContainerizedOrchestrator):
479
510
  if settings.pipeline_tags
480
511
  else None,
481
512
  )
482
- execution = pipeline.start()
483
- logger.warning(
484
- "Steps can take 5-15 minutes to start running "
485
- "when using the Sagemaker Orchestrator."
486
- )
487
513
 
488
- # Yield metadata based on the generated execution object
489
- yield from self.compute_metadata(
490
- execution=execution, settings=settings
491
- )
514
+ # Handle scheduling if specified
515
+ if deployment.schedule:
516
+ if settings.synchronous:
517
+ logger.warning(
518
+ "The 'synchronous' setting is ignored for scheduled "
519
+ "pipelines since they run independently of the "
520
+ "deployment process."
521
+ )
492
522
 
493
- # mainly for testing purposes, we wait for the pipeline to finish
494
- if settings.synchronous:
495
- logger.info(
496
- "Executing synchronously. Waiting for pipeline to finish... \n"
497
- "At this point you can `Ctrl-C` out without cancelling the "
498
- "execution."
523
+ schedule_name = orchestrator_run_name
524
+ next_execution = None
525
+
526
+ # Create PipelineSchedule based on schedule type
527
+ if deployment.schedule.cron_expression:
528
+ cron_exp = self._validate_cron_expression(
529
+ deployment.schedule.cron_expression
530
+ )
531
+ schedule = PipelineSchedule(
532
+ name=schedule_name,
533
+ cron=cron_exp,
534
+ start_date=deployment.schedule.start_time,
535
+ enabled=True,
536
+ )
537
+ elif deployment.schedule.interval_second:
538
+ # This is necessary because SageMaker's PipelineSchedule rate
539
+ # expressions require minutes as the minimum time unit.
540
+ # Even if a user specifies an interval of less than 60 seconds,
541
+ # it will be rounded up to 1 minute.
542
+ minutes = max(
543
+ 1,
544
+ int(
545
+ deployment.schedule.interval_second.total_seconds()
546
+ / 60
547
+ ),
548
+ )
549
+ schedule = PipelineSchedule(
550
+ name=schedule_name,
551
+ rate=(minutes, "minutes"),
552
+ start_date=deployment.schedule.start_time,
553
+ enabled=True,
554
+ )
555
+ next_execution = (
556
+ deployment.schedule.start_time
557
+ or datetime.now(timezone.utc)
558
+ ) + deployment.schedule.interval_second
559
+ else:
560
+ # One-time schedule
561
+ execution_time = (
562
+ deployment.schedule.run_once_start_time
563
+ or deployment.schedule.start_time
564
+ )
565
+ if not execution_time:
566
+ raise ValueError(
567
+ "A start time must be specified for one-time "
568
+ "schedule execution"
569
+ )
570
+ schedule = PipelineSchedule(
571
+ name=schedule_name,
572
+ at=execution_time.astimezone(timezone.utc),
573
+ enabled=True,
574
+ )
575
+ next_execution = execution_time
576
+
577
+ # Get the current role ARN if not explicitly configured
578
+ if self.config.scheduler_role is None:
579
+ logger.info(
580
+ "No scheduler_role configured. Trying to extract it from "
581
+ "the client side authentication."
582
+ )
583
+ sts = session.boto_session.client("sts")
584
+ try:
585
+ scheduler_role_arn = sts.get_caller_identity()["Arn"]
586
+ # If this is a user ARN, try to get the role ARN
587
+ if ":user/" in scheduler_role_arn:
588
+ logger.warning(
589
+ f"Using IAM user credentials "
590
+ f"({scheduler_role_arn}). For production "
591
+ "environments, it's recommended to use IAM roles "
592
+ "instead."
593
+ )
594
+ # If this is an assumed role, extract the role ARN
595
+ elif ":assumed-role/" in scheduler_role_arn:
596
+ # Convert assumed-role ARN format to role ARN format
597
+ # From: arn:aws:sts::123456789012:assumed-role/role-name/session-name
598
+ # To: arn:aws:iam::123456789012:role/role-name
599
+ scheduler_role_arn = re.sub(
600
+ r"arn:aws:sts::(\d+):assumed-role/([^/]+)/.*",
601
+ r"arn:aws:iam::\1:role/\2",
602
+ scheduler_role_arn,
603
+ )
604
+ elif ":role/" not in scheduler_role_arn:
605
+ raise RuntimeError(
606
+ f"Unexpected credential type "
607
+ f"({scheduler_role_arn}). Please use IAM "
608
+ f"roles for SageMaker pipeline scheduling."
609
+ )
610
+ else:
611
+ raise RuntimeError(
612
+ "The ARN of the caller identity "
613
+ f"`{scheduler_role_arn}` does not "
614
+ "include a user or a proper role."
615
+ )
616
+ except Exception:
617
+ raise RuntimeError(
618
+ "Failed to get current role ARN. This means the "
619
+ "your client side credentials that you are "
620
+ "is not configured correctly to schedule sagemaker "
621
+ "pipelines. For more information, please check:"
622
+ "https://docs.zenml.io/stack-components/orchestrators/sagemaker#required-iam-permissions-for-schedules"
623
+ )
624
+ else:
625
+ scheduler_role_arn = self.config.scheduler_role
626
+
627
+ # Attach schedule to pipeline
628
+ triggers = pipeline.put_triggers(
629
+ triggers=[schedule],
630
+ role_arn=scheduler_role_arn,
499
631
  )
632
+ logger.info(f"The schedule ARN is: {triggers[0]}")
633
+
500
634
  try:
501
- execution.wait(
502
- delay=POLLING_DELAY, max_attempts=MAX_POLLING_ATTEMPTS
635
+ from zenml.models import RunMetadataResource
636
+
637
+ schedule_metadata = self.generate_schedule_metadata(
638
+ schedule_arn=triggers[0]
503
639
  )
504
- logger.info("Pipeline completed successfully.")
505
- except WaiterError:
506
- raise RuntimeError(
507
- "Timed out while waiting for pipeline execution to "
508
- "finish. For long-running pipelines we recommend "
509
- "configuring your orchestrator for asynchronous execution. "
510
- "The following command does this for you: \n"
511
- f"`zenml orchestrator update {self.name} "
512
- f"--synchronous=False`"
640
+
641
+ Client().create_run_metadata(
642
+ metadata=schedule_metadata, # type: ignore[arg-type]
643
+ resources=[
644
+ RunMetadataResource(
645
+ id=deployment.schedule.id,
646
+ type=MetadataResourceTypes.SCHEDULE,
647
+ )
648
+ ],
649
+ )
650
+ except Exception as e:
651
+ logger.debug(
652
+ "There was an error attaching metadata to the "
653
+ f"schedule: {e}"
513
654
  )
514
655
 
656
+ logger.info(
657
+ f"Successfully scheduled pipeline with name: {schedule_name}\n"
658
+ + (
659
+ f"First execution will occur at: "
660
+ f"{next_execution.strftime('%Y-%m-%d %H:%M:%S UTC')}"
661
+ if next_execution
662
+ else f"Using cron expression: "
663
+ f"{deployment.schedule.cron_expression}"
664
+ )
665
+ + (
666
+ f" (and every {minutes} minutes after)"
667
+ if deployment.schedule.interval_second
668
+ else ""
669
+ )
670
+ )
671
+ logger.info(
672
+ "\n\nIn order to cancel the schedule, you can use execute "
673
+ "the following command:\n"
674
+ )
675
+ logger.info(
676
+ f"`aws scheduler delete-schedule --name {schedule_name}`"
677
+ )
678
+ else:
679
+ # Execute the pipeline immediately if no schedule is specified
680
+ execution = pipeline.start()
681
+ logger.warning(
682
+ "Steps can take 5-15 minutes to start running "
683
+ "when using the Sagemaker Orchestrator."
684
+ )
685
+
686
+ # Yield metadata based on the generated execution object
687
+ yield from self.compute_metadata(
688
+ execution_arn=execution.arn, settings=settings
689
+ )
690
+
691
+ # mainly for testing purposes, we wait for the pipeline to finish
692
+ if settings.synchronous:
693
+ logger.info(
694
+ "Executing synchronously. Waiting for pipeline to "
695
+ "finish... \n"
696
+ "At this point you can `Ctrl-C` out without cancelling the "
697
+ "execution."
698
+ )
699
+ try:
700
+ execution.wait(
701
+ delay=POLLING_DELAY, max_attempts=MAX_POLLING_ATTEMPTS
702
+ )
703
+ logger.info("Pipeline completed successfully.")
704
+ except WaiterError:
705
+ raise RuntimeError(
706
+ "Timed out while waiting for pipeline execution to "
707
+ "finish. For long-running pipelines we recommend "
708
+ "configuring your orchestrator for asynchronous "
709
+ "execution. The following command does this for you: \n"
710
+ f"`zenml orchestrator update {self.name} "
711
+ f"--synchronous=False`"
712
+ )
713
+
515
714
  def get_pipeline_run_metadata(
516
715
  self, run_id: UUID
517
716
  ) -> Dict[str, "MetadataType"]:
@@ -523,10 +722,22 @@ class SagemakerOrchestrator(ContainerizedOrchestrator):
523
722
  Returns:
524
723
  A dictionary of metadata.
525
724
  """
526
- pipeline_execution_arn = os.environ[ENV_ZENML_SAGEMAKER_RUN_ID]
527
- run_metadata: Dict[str, "MetadataType"] = {
528
- "pipeline_execution_arn": pipeline_execution_arn,
529
- }
725
+ from zenml import get_step_context
726
+
727
+ execution_arn = os.environ[ENV_ZENML_SAGEMAKER_RUN_ID]
728
+
729
+ run_metadata: Dict[str, "MetadataType"] = {}
730
+
731
+ settings = cast(
732
+ SagemakerOrchestratorSettings,
733
+ self.get_settings(get_step_context().pipeline_run),
734
+ )
735
+
736
+ for metadata in self.compute_metadata(
737
+ execution_arn=execution_arn,
738
+ settings=settings,
739
+ ):
740
+ run_metadata.update(metadata)
530
741
 
531
742
  return run_metadata
532
743
 
@@ -588,56 +799,57 @@ class SagemakerOrchestrator(ContainerizedOrchestrator):
588
799
 
589
800
  def compute_metadata(
590
801
  self,
591
- execution: Any,
802
+ execution_arn: str,
592
803
  settings: SagemakerOrchestratorSettings,
593
804
  ) -> Iterator[Dict[str, MetadataType]]:
594
805
  """Generate run metadata based on the generated Sagemaker Execution.
595
806
 
596
807
  Args:
597
- execution: The corresponding _PipelineExecution object.
808
+ execution_arn: The ARN of the pipeline execution.
598
809
  settings: The Sagemaker orchestrator settings.
599
810
 
600
811
  Yields:
601
812
  A dictionary of metadata related to the pipeline run.
602
813
  """
603
- # Metadata
604
- metadata: Dict[str, MetadataType] = {}
605
-
606
814
  # Orchestrator Run ID
607
- if run_id := self._compute_orchestrator_run_id(execution):
608
- metadata[METADATA_ORCHESTRATOR_RUN_ID] = run_id
815
+ metadata: Dict[str, MetadataType] = {
816
+ "pipeline_execution_arn": execution_arn,
817
+ METADATA_ORCHESTRATOR_RUN_ID: execution_arn,
818
+ }
609
819
 
610
820
  # URL to the Sagemaker's pipeline view
611
- if orchestrator_url := self._compute_orchestrator_url(execution):
821
+ if orchestrator_url := self._compute_orchestrator_url(
822
+ execution_arn=execution_arn
823
+ ):
612
824
  metadata[METADATA_ORCHESTRATOR_URL] = Uri(orchestrator_url)
613
825
 
614
826
  # URL to the corresponding CloudWatch page
615
827
  if logs_url := self._compute_orchestrator_logs_url(
616
- execution, settings
828
+ execution_arn=execution_arn, settings=settings
617
829
  ):
618
830
  metadata[METADATA_ORCHESTRATOR_LOGS_URL] = Uri(logs_url)
619
831
 
620
832
  yield metadata
621
833
 
622
- @staticmethod
623
834
  def _compute_orchestrator_url(
624
- pipeline_execution: Any,
835
+ self,
836
+ execution_arn: Any,
625
837
  ) -> Optional[str]:
626
838
  """Generate the Orchestrator Dashboard URL upon pipeline execution.
627
839
 
628
840
  Args:
629
- pipeline_execution: The corresponding _PipelineExecution object.
841
+ execution_arn: The ARN of the pipeline execution.
630
842
 
631
843
  Returns:
632
844
  the URL to the dashboard view in SageMaker.
633
845
  """
634
846
  try:
635
847
  region_name, pipeline_name, execution_id = (
636
- dissect_pipeline_execution_arn(pipeline_execution.arn)
848
+ dissect_pipeline_execution_arn(execution_arn)
637
849
  )
638
850
 
639
851
  # Get the Sagemaker session
640
- session = pipeline_execution.sagemaker_session
852
+ session = self._get_sagemaker_session()
641
853
 
642
854
  # List the Studio domains and get the Studio Domain ID
643
855
  domains_response = session.sagemaker_client.list_domains()
@@ -657,13 +869,13 @@ class SagemakerOrchestrator(ContainerizedOrchestrator):
657
869
 
658
870
  @staticmethod
659
871
  def _compute_orchestrator_logs_url(
660
- pipeline_execution: Any,
872
+ execution_arn: Any,
661
873
  settings: SagemakerOrchestratorSettings,
662
874
  ) -> Optional[str]:
663
875
  """Generate the CloudWatch URL upon pipeline execution.
664
876
 
665
877
  Args:
666
- pipeline_execution: The corresponding _PipelineExecution object.
878
+ execution_arn: The ARN of the pipeline execution.
667
879
  settings: The Sagemaker orchestrator settings.
668
880
 
669
881
  Returns:
@@ -671,7 +883,7 @@ class SagemakerOrchestrator(ContainerizedOrchestrator):
671
883
  """
672
884
  try:
673
885
  region_name, _, execution_id = dissect_pipeline_execution_arn(
674
- pipeline_execution.arn
886
+ execution_arn
675
887
  )
676
888
 
677
889
  use_training_jobs = True
@@ -693,22 +905,48 @@ class SagemakerOrchestrator(ContainerizedOrchestrator):
693
905
  return None
694
906
 
695
907
  @staticmethod
696
- def _compute_orchestrator_run_id(
697
- pipeline_execution: Any,
698
- ) -> Optional[str]:
699
- """Fetch the Orchestrator Run ID upon pipeline execution.
908
+ def generate_schedule_metadata(schedule_arn: str) -> Dict[str, str]:
909
+ """Attaches metadata to the ZenML Schedules.
700
910
 
701
911
  Args:
702
- pipeline_execution: The corresponding _PipelineExecution object.
912
+ schedule_arn: The trigger ARNs that is generated on the AWS side.
703
913
 
704
914
  Returns:
705
- the Execution ID of the run in SageMaker.
915
+ a dictionary containing metadata related to the schedule.
706
916
  """
707
- try:
708
- return str(pipeline_execution.arn)
917
+ region, name = dissect_schedule_arn(schedule_arn=schedule_arn)
709
918
 
710
- except Exception as e:
711
- logger.warning(
712
- f"There was an issue while extracting the pipeline run ID: {e}"
919
+ return {
920
+ "trigger_url": (
921
+ f"https://{region}.console.aws.amazon.com/scheduler/home"
922
+ f"?region={region}#schedules/{name}"
923
+ ),
924
+ }
925
+
926
+ @staticmethod
927
+ def _validate_cron_expression(cron_expression: str) -> str:
928
+ """Validates and formats a cron expression for SageMaker schedules.
929
+
930
+ Args:
931
+ cron_expression: The cron expression to validate
932
+
933
+ Returns:
934
+ The formatted cron expression
935
+
936
+ Raises:
937
+ ValueError: If the cron expression is invalid
938
+ """
939
+ # Strip any "cron(" prefix if it exists
940
+ cron_exp = cron_expression.replace("cron(", "").replace(")", "")
941
+
942
+ # Split into components
943
+ parts = cron_exp.split()
944
+ if len(parts) not in [6, 7]: # AWS cron requires 6 or 7 fields
945
+ raise ValueError(
946
+ f"Invalid cron expression: {cron_expression}. AWS cron "
947
+ "expressions must have 6 or 7 fields: minute hour day-of-month "
948
+ "month day-of-week year(optional). Example: '15 10 ? * 6L "
949
+ "2022-2023'"
713
950
  )
714
- return None
951
+
952
+ return cron_exp
@@ -47,16 +47,11 @@ class HuggingfaceIntegration(Integration):
47
47
  A list of requirements.
48
48
  """
49
49
  requirements = [
50
- "datasets",
50
+ "datasets>=2.16.0",
51
51
  "huggingface_hub>0.19.0",
52
52
  "accelerate",
53
53
  "bitsandbytes>=0.41.3",
54
54
  "peft",
55
- # temporary fix for CI issue similar to:
56
- # - https://github.com/huggingface/datasets/issues/6737
57
- # - https://github.com/huggingface/datasets/issues/6697
58
- # TODO try relaxing it back going forward
59
- "fsspec<=2023.12.0",
60
55
  "transformers",
61
56
  ]
62
57
 
@@ -14,13 +14,14 @@
14
14
  """Models representing schedules."""
15
15
 
16
16
  import datetime
17
- from typing import Optional, Union
17
+ from typing import Dict, Optional, Union
18
18
  from uuid import UUID
19
19
 
20
20
  from pydantic import Field, model_validator
21
21
 
22
22
  from zenml.constants import STR_FIELD_MAX_LENGTH
23
23
  from zenml.logger import get_logger
24
+ from zenml.metadata.metadata_types import MetadataType
24
25
  from zenml.models.v2.base.base import BaseUpdate
25
26
  from zenml.models.v2.base.scoped import (
26
27
  WorkspaceScopedFilter,
@@ -136,6 +137,11 @@ class ScheduleResponseMetadata(WorkspaceScopedResponseMetadata):
136
137
  orchestrator_id: Optional[UUID]
137
138
  pipeline_id: Optional[UUID]
138
139
 
140
+ run_metadata: Dict[str, MetadataType] = Field(
141
+ title="Metadata associated with this schedule.",
142
+ default={},
143
+ )
144
+
139
145
 
140
146
  class ScheduleResponseResources(WorkspaceScopedResponseResources):
141
147
  """Class for all resource models associated with the schedule entity."""
@@ -272,6 +278,15 @@ class ScheduleResponse(
272
278
  """
273
279
  return self.get_metadata().pipeline_id
274
280
 
281
+ @property
282
+ def run_metadata(self) -> Dict[str, MetadataType]:
283
+ """The `run_metadata` property.
284
+
285
+ Returns:
286
+ the value of the property.
287
+ """
288
+ return self.get_metadata().run_metadata
289
+
275
290
 
276
291
  # ------------------ Filter Model ------------------
277
292
 
@@ -29,7 +29,11 @@ from zenml.config.step_run_info import StepRunInfo
29
29
  from zenml.enums import StackComponentType
30
30
  from zenml.exceptions import AuthorizationException
31
31
  from zenml.logger import get_logger
32
- from zenml.models import ServiceConnectorRequirements, StepRunResponse
32
+ from zenml.models import (
33
+ PipelineRunResponse,
34
+ ServiceConnectorRequirements,
35
+ StepRunResponse,
36
+ )
33
37
  from zenml.utils import (
34
38
  pydantic_utils,
35
39
  secret_utils,
@@ -496,6 +500,7 @@ class StackComponent:
496
500
  "StepRunInfo",
497
501
  "PipelineDeploymentBase",
498
502
  "PipelineDeploymentResponse",
503
+ "PipelineRunResponse",
499
504
  ],
500
505
  ) -> "BaseSettings":
501
506
  """Gets settings for this stack component.
@@ -527,7 +532,10 @@ class StackComponent:
527
532
 
528
533
  all_settings = (
529
534
  container.config.settings
530
- if isinstance(container, (Step, StepRunResponse, StepRunInfo))
535
+ if isinstance(
536
+ container,
537
+ (Step, StepRunResponse, StepRunInfo, PipelineRunResponse),
538
+ )
531
539
  else container.pipeline_configuration.settings
532
540
  )
533
541
 
@@ -1009,6 +1009,8 @@ def create_run_metadata(
1009
1009
  verify_models.append(zen_store().get_artifact_version(resource.id))
1010
1010
  elif resource.type == MetadataResourceTypes.MODEL_VERSION:
1011
1011
  verify_models.append(zen_store().get_model_version(resource.id))
1012
+ elif resource.type == MetadataResourceTypes.SCHEDULE:
1013
+ verify_models.append(zen_store().get_schedule(resource.id))
1012
1014
  else:
1013
1015
  raise RuntimeError(f"Unknown resource type: {resource.type}")
1014
1016
 
@@ -269,6 +269,13 @@ class PipelineRunSchema(NamedSchema, RunMetadataInterface, table=True):
269
269
  for k, v in step_metadata.items():
270
270
  metadata_collection[f"{s.name}::{k}"] = v
271
271
 
272
+ # Fetch the metadata related to the schedule of this run
273
+ if self.deployment is not None:
274
+ if schedule := self.deployment.schedule:
275
+ schedule_metadata = schedule.fetch_metadata_collection()
276
+ for k, v in schedule_metadata.items():
277
+ metadata_collection[f"schedule:{k}"] = v
278
+
272
279
  return metadata_collection
273
280
 
274
281
  def to_model(
@@ -14,11 +14,12 @@
14
14
  """SQL Model Implementations for Pipeline Schedules."""
15
15
 
16
16
  from datetime import datetime, timedelta, timezone
17
- from typing import TYPE_CHECKING, Any, Optional
17
+ from typing import TYPE_CHECKING, Any, List, Optional
18
18
  from uuid import UUID
19
19
 
20
20
  from sqlmodel import Field, Relationship
21
21
 
22
+ from zenml.enums import MetadataResourceTypes
22
23
  from zenml.models import (
23
24
  ScheduleRequest,
24
25
  ScheduleResponse,
@@ -31,15 +32,19 @@ from zenml.zen_stores.schemas.component_schemas import StackComponentSchema
31
32
  from zenml.zen_stores.schemas.pipeline_schemas import PipelineSchema
32
33
  from zenml.zen_stores.schemas.schema_utils import build_foreign_key_field
33
34
  from zenml.zen_stores.schemas.user_schemas import UserSchema
35
+ from zenml.zen_stores.schemas.utils import RunMetadataInterface
34
36
  from zenml.zen_stores.schemas.workspace_schemas import WorkspaceSchema
35
37
 
36
38
  if TYPE_CHECKING:
37
39
  from zenml.zen_stores.schemas.pipeline_deployment_schemas import (
38
40
  PipelineDeploymentSchema,
39
41
  )
42
+ from zenml.zen_stores.schemas.run_metadata_schemas import (
43
+ RunMetadataSchema,
44
+ )
40
45
 
41
46
 
42
- class ScheduleSchema(NamedSchema, table=True):
47
+ class ScheduleSchema(NamedSchema, RunMetadataInterface, table=True):
43
48
  """SQL Model for schedules."""
44
49
 
45
50
  __tablename__ = "schedule"
@@ -89,6 +94,15 @@ class ScheduleSchema(NamedSchema, table=True):
89
94
  back_populates="schedules"
90
95
  )
91
96
 
97
+ run_metadata: List["RunMetadataSchema"] = Relationship(
98
+ sa_relationship_kwargs=dict(
99
+ secondary="run_metadata_resource",
100
+ primaryjoin=f"and_(foreign(RunMetadataResourceSchema.resource_type)=='{MetadataResourceTypes.SCHEDULE.value}', foreign(RunMetadataResourceSchema.resource_id)==ScheduleSchema.id)",
101
+ secondaryjoin="RunMetadataSchema.id==foreign(RunMetadataResourceSchema.run_metadata_id)",
102
+ overlaps="run_metadata",
103
+ ),
104
+ )
105
+
92
106
  active: bool
93
107
  cron_expression: Optional[str] = Field(nullable=True)
94
108
  start_time: Optional[datetime] = Field(nullable=True)
@@ -196,6 +210,7 @@ class ScheduleSchema(NamedSchema, table=True):
196
210
  workspace=self.workspace.to_model(),
197
211
  pipeline_id=self.pipeline_id,
198
212
  orchestrator_id=self.orchestrator_id,
213
+ run_metadata=self.fetch_metadata(),
199
214
  )
200
215
 
201
216
  return ScheduleResponse(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: zenml-nightly
3
- Version: 0.73.0.dev20250123
3
+ Version: 0.73.0.dev20250124
4
4
  Summary: ZenML: Write production-ready ML code.
5
5
  License: Apache-2.0
6
6
  Keywords: machine learning,production,pipeline,mlops,devops
@@ -107,7 +107,7 @@ Requires-Dist: pyyaml-include (<2.0) ; extra == "templates"
107
107
  Requires-Dist: rich[jupyter] (>=12.0.0)
108
108
  Requires-Dist: ruff (>=0.1.7) ; extra == "templates" or extra == "dev"
109
109
  Requires-Dist: s3fs (>=2022.11.0) ; extra == "s3fs"
110
- Requires-Dist: sagemaker (>=2.117.0) ; extra == "sagemaker"
110
+ Requires-Dist: sagemaker (>=2.199.0) ; extra == "sagemaker"
111
111
  Requires-Dist: secure (>=0.3.0,<0.4.0) ; extra == "server"
112
112
  Requires-Dist: setuptools
113
113
  Requires-Dist: sqlalchemy (>=2.0.0,<3.0.0)
@@ -1,5 +1,5 @@
1
1
  zenml/README.md,sha256=827dekbOWAs1BpW7VF1a4d7EbwPbjwccX-2zdXBENZo,1777
2
- zenml/VERSION,sha256=P-h8BOwYobDN-LFlz12ZBuP6qTiuqzpvfYqAN84tN2Y,19
2
+ zenml/VERSION,sha256=gRmaRlGlJ7ZaMuJI31aQHZYICElalVxTmqx4tPcWKDs,19
3
3
  zenml/__init__.py,sha256=SkMObQA41ajqdZqGErN00S1Vf3KAxpLvbZ-OBy5uYoo,2130
4
4
  zenml/actions/__init__.py,sha256=mrt6wPo73iKRxK754_NqsGyJ3buW7RnVeIGXr1xEw8Y,681
5
5
  zenml/actions/base_action.py,sha256=UcaHev6BTuLDwuswnyaPjdA8AgUqB5xPZ-lRtuvf2FU,25553
@@ -38,13 +38,13 @@ zenml/cli/downgrade.py,sha256=eTpXts8y4s3wEUwOlvZGWsTngoMV8Stuzj0K-SAQUGU,1887
38
38
  zenml/cli/feature.py,sha256=Q8tNvWBlRze3FUyn0_VpOdl316ZW87476j7ezJb16GA,4387
39
39
  zenml/cli/formatter.py,sha256=OoAzgxpOEXrzT9FSFG0Bs5VRtVFEYck0gDYo02GCjzI,6440
40
40
  zenml/cli/integration.py,sha256=IsG1WR9H7tEEQl2bxm-i2P5hWU63sGCKAMbraJtRN9s,16208
41
- zenml/cli/login.py,sha256=ze-SY-ffaZCFN_oY5c67GRfsiLBuofWRGxdyQLODfLk,37939
41
+ zenml/cli/login.py,sha256=h5L1TZuD_hbr2FC4jtYV231EeyUN8HasIzL_1Ungmrw,38007
42
42
  zenml/cli/model.py,sha256=hXRXkMUOOf0eTo07WnQHNeeDDQLiH0m76E-xypFLYF0,22993
43
43
  zenml/cli/model_registry.py,sha256=zzxWXXFhKu2B1Wp0u7prKVnN1ftM-JdGdQwlD-5G-QM,20786
44
44
  zenml/cli/pipeline.py,sha256=ZK_J_GE1OGZkLCBsdTiHnSh7BBp29QiigtxvQNifxAc,19228
45
45
  zenml/cli/secret.py,sha256=dn0Pbmlwt6XoLmdJp1JbBhv6nDRVJcUnPYHmUCTVNOk,20120
46
46
  zenml/cli/served_model.py,sha256=3w1UcAbg6Geu37fr7ej1_81GBCt3fF7j3Ge799YE4Mc,14974
47
- zenml/cli/server.py,sha256=XkLRSkhDZfJy2JJn0CFHm2iNUSbR9dU_zUj1TnAJm04,26048
47
+ zenml/cli/server.py,sha256=gd-gwPpDUKNL2yokRywIo3GlmICnK5YQtotiMsb0EEE,26090
48
48
  zenml/cli/service_accounts.py,sha256=kl2YSUCsfy3V5ezjbnEjy7i29QgHw-UhLr26rdvz938,17789
49
49
  zenml/cli/service_connectors.py,sha256=VnQm7L327L8o0P2a_pL1D_pMlkUuVUQsjcp9nuBK2PA,74408
50
50
  zenml/cli/stack.py,sha256=NcZ0DswuBmJ-VRefp7wb_XoVXm319ar2xvAuKMWan_g,67409
@@ -100,7 +100,7 @@ zenml/entrypoints/base_entrypoint_configuration.py,sha256=7l_AAj3qBPSj1fdjoc712R
100
100
  zenml/entrypoints/entrypoint.py,sha256=XNgXBCMKoidmP0_AYgMpqo-neG8Y8jG0rj43ofTDZ9E,2033
101
101
  zenml/entrypoints/pipeline_entrypoint_configuration.py,sha256=To-vTP29qAE36ndJDF1fRw9wL2Nk2bsBuO-ayAwvSmo,1646
102
102
  zenml/entrypoints/step_entrypoint_configuration.py,sha256=fETr5E7eH8QEWYqgaarIrLQzrPrdLEr194xhd3H5yU4,7206
103
- zenml/enums.py,sha256=SrJKndwIdLyLcXVvjeutHdrrRH5hEpT3gjMbLWXHF70,10758
103
+ zenml/enums.py,sha256=H-pVQyN7C17ujDClD8ctLAO5cHc_SAUmioUA_-U4z38,10784
104
104
  zenml/environment.py,sha256=dw9sU28d8vsobGl2byUyhVbYXVhgtvpRrEAx4_fHMI8,11624
105
105
  zenml/event_hub/__init__.py,sha256=-fD9mPOslf4J-_XFBPp5gYlPz7-6ZaAKHa5jxf_nyAo,757
106
106
  zenml/event_hub/base_event_hub.py,sha256=6HFyhCAA_m2GHxULnwy3WSBgvcPXHuBQkgjaAPQlr9w,6593
@@ -135,18 +135,18 @@ zenml/integrations/argilla/annotators/__init__.py,sha256=QjRMxIQ-skulcLN94GuHuuk
135
135
  zenml/integrations/argilla/annotators/argilla_annotator.py,sha256=aIA5rcwfOYLnUVp2c_aaTAUnVW8GV9gP8myze_jY_qY,15586
136
136
  zenml/integrations/argilla/flavors/__init__.py,sha256=MTogEeiZ1k7nLzGKok3azK_VhKUAJl0GL6OQvsvMlZo,917
137
137
  zenml/integrations/argilla/flavors/argilla_annotator_flavor.py,sha256=NAy6QKLWYXHPTCoWc9RIovsngcRGMwseu3rdNjiCpo4,4473
138
- zenml/integrations/aws/__init__.py,sha256=x-Ym8FlmeX7bAjL7zBxUp40U11IVZGyfcClRIeEydlI,2489
138
+ zenml/integrations/aws/__init__.py,sha256=rC9cwfOvCUncSkM2ibg9SHUBqnb74JCf2JIs4a8rXVg,2490
139
139
  zenml/integrations/aws/container_registries/__init__.py,sha256=fOwo84MiaX_7XhNQEXeyVh8AyOlcIl6nSu_ig68GkSs,827
140
140
  zenml/integrations/aws/container_registries/aws_container_registry.py,sha256=SCxKj_w79Ka0LdxYOdDmaXitketTQRDHrQ4XQ0_f4hs,6091
141
141
  zenml/integrations/aws/flavors/__init__.py,sha256=XYL9fpwKzeFfHCjakU0iJ3SyHVRJk63QT7luOy9Giek,1480
142
142
  zenml/integrations/aws/flavors/aws_container_registry_flavor.py,sha256=GIDLOySz1zF08YSkmKIj89TxBqSLWueXLAHyxYwm-NI,4169
143
143
  zenml/integrations/aws/flavors/aws_image_builder_flavor.py,sha256=XobJOw5ymbY22i7YHWGYOKDQoJQAqTeMIfvkADt-DDc,5343
144
- zenml/integrations/aws/flavors/sagemaker_orchestrator_flavor.py,sha256=UyHXFP9rn9DQ-Erd9Rtqun9GTcp3Rftbn2a9Xysh_TU,12826
144
+ zenml/integrations/aws/flavors/sagemaker_orchestrator_flavor.py,sha256=Shcvegidrxq0ogue4ya4Hm7fVjp6_hBd7O0LGdnnBio,13498
145
145
  zenml/integrations/aws/flavors/sagemaker_step_operator_flavor.py,sha256=OnNokixzGvOTBoZJQ5TDG3k4FFsP1pJmxbiij2VLW4s,5978
146
146
  zenml/integrations/aws/image_builders/__init__.py,sha256=91hgH1OphG2i-vk-G8N4yKBFIzK89Wu7BK4-T5yOA7E,786
147
147
  zenml/integrations/aws/image_builders/aws_image_builder.py,sha256=UcPYYYjJjfsicY3hV4OZeJt552AVmwPZPlv-AsG1g1I,11489
148
148
  zenml/integrations/aws/orchestrators/__init__.py,sha256=Wh0Fhtt_uo6YrkvXY9kL0M478FL7XpapjoFreUZbgUg,794
149
- zenml/integrations/aws/orchestrators/sagemaker_orchestrator.py,sha256=OlnXr_KTWE8fOyO6bNmsCbRdRaCPqWGrUEX4gyVbD80,26801
149
+ zenml/integrations/aws/orchestrators/sagemaker_orchestrator.py,sha256=eqOS4FG52J-qsXcU6q8Uyg8rQbKz52srdobMGBRd2Gs,36256
150
150
  zenml/integrations/aws/orchestrators/sagemaker_orchestrator_entrypoint_config.py,sha256=WXCWdVojIZxx5_3-g1T95S2vsJ-RLNGcp-V409wgme0,1555
151
151
  zenml/integrations/aws/service_connectors/__init__.py,sha256=w2Md40yG89PwmU9eBceh6dGy3XYZ3MKusNAZ51sGOgE,783
152
152
  zenml/integrations/aws/service_connectors/aws_service_connector.py,sha256=O524UfOHJ3wRiPq7jpGPmgIWmn9ezhgmS5iilbyfNvg,92327
@@ -296,7 +296,7 @@ zenml/integrations/great_expectations/steps/__init__.py,sha256=OGsp32yJs9GItypFR
296
296
  zenml/integrations/great_expectations/steps/ge_profiler.py,sha256=ea6WLF1B8pvkGe-dBaAX3tNV2W8mVhUhk6WQpKgqKEA,2141
297
297
  zenml/integrations/great_expectations/steps/ge_validator.py,sha256=kdFzhkzJtQZGOul8E8BE5_315mYGvMuDINYagPflKVk,2946
298
298
  zenml/integrations/great_expectations/utils.py,sha256=4DXjAfsKUVcp_lSGAPiAsAI-WLNjr_DLMsGJOYGkSjE,3138
299
- zenml/integrations/huggingface/__init__.py,sha256=dsGh3rvdXMeiUdXJTkTyzH7q8y5HCFnpcKKvafYL3S0,2822
299
+ zenml/integrations/huggingface/__init__.py,sha256=1gduA_xFUgJsWtFtvftA78o5pF6PaaeT94ffgvTeOA0,2554
300
300
  zenml/integrations/huggingface/flavors/__init__.py,sha256=NXMxZXrS7fHdZnz1G_Sf83k4zkE84C5UoYJzxXSY-R0,970
301
301
  zenml/integrations/huggingface/flavors/huggingface_model_deployer_flavor.py,sha256=QITTxFrpKu5JNH29A_riAWiC0-gY3qcxGWQf__0aQII,4032
302
302
  zenml/integrations/huggingface/materializers/__init__.py,sha256=HoiSCzfMTxtcvkDBconFm_-pdGZXzXDelkuPtcrJIgA,1267
@@ -648,7 +648,7 @@ zenml/models/v2/core/pipeline_deployment.py,sha256=6PbpnEUAbTT-_jPmyNtKuTJHFGdGL
648
648
  zenml/models/v2/core/pipeline_run.py,sha256=41TqY_CzUCWlunnyX6GBJ-OmcRtGIm9sHAXB4pIuwMo,32669
649
649
  zenml/models/v2/core/run_metadata.py,sha256=YDiPVRzTUMVHqW4T_Ke4GJMdscp0aS_g8I4P8n70szc,2436
650
650
  zenml/models/v2/core/run_template.py,sha256=A_dezNA9o1uJW-o1B9fYaSSWHwwglJYP3jvhWhGcJK4,12971
651
- zenml/models/v2/core/schedule.py,sha256=RZL5XNci9i6k0D5mCmG3DGZ0Lli4XAlL9hTWhqrd4jg,9874
651
+ zenml/models/v2/core/schedule.py,sha256=p158MgzCJmUS1J3MtSyPQoND75aQ0tkIQUdLaqcqtrY,10297
652
652
  zenml/models/v2/core/secret.py,sha256=LoY5BMZIrU6KYa39layHt6cbAnmMR7yXizv_1Qqse6Q,11460
653
653
  zenml/models/v2/core/server_settings.py,sha256=al6LAXhoQHsBiTv2qlwFn1AlI2F8miogGB4xjDE6KeA,6267
654
654
  zenml/models/v2/core/service.py,sha256=lwCDOFk-OXmfhB_bOOJy7rhbkR40tCScQsWnllgL7II,14973
@@ -732,7 +732,7 @@ zenml/stack/authentication_mixin.py,sha256=sg7GkpB-Ao9Gsa7Po0jxMn-_mVYUB42etmspZ
732
732
  zenml/stack/flavor.py,sha256=F60xxZaqsNRK51K1g-SIWAK9dFxRQXaIErtr3evQ-ng,9775
733
733
  zenml/stack/flavor_registry.py,sha256=IL0fRrxxQJ9YkCYCeADP7nwWEQo4XBElJY4owMjKGbQ,6108
734
734
  zenml/stack/stack.py,sha256=k9e9MGflY9IZFVKUXVqXk8VIvfsVx3OaPlRvMYh5QnM,32933
735
- zenml/stack/stack_component.py,sha256=BRwF5KvVyYejxa0SFiwTSFYYixvoGw6k0rILbd3LrY8,29498
735
+ zenml/stack/stack_component.py,sha256=NqUqvufQ3dClK8rdo491K7KRAgv6VbUteA0JApC49VE,29639
736
736
  zenml/stack/stack_validator.py,sha256=hWbvvGIeWLj6NwSsF4GCc6RAxAWvxHXTcBZL9nJvcak,3111
737
737
  zenml/stack/utils.py,sha256=qHMFi8SVMSDFeZTFO4KkvaLUbF-l3B0_JZ5SSMxYrwI,6406
738
738
  zenml/stack_deployments/__init__.py,sha256=-7593cQ_ZgRn774Ol-8AKXXQquIU4DSiaThVEr6TfWM,644
@@ -1055,7 +1055,7 @@ zenml/zen_server/routers/tags_endpoints.py,sha256=oK-A-EqAsrIXXgl7A870I2PT8_fct1
1055
1055
  zenml/zen_server/routers/triggers_endpoints.py,sha256=1fHKDRDr6WsjnGCvkV7SOcX9cggw1rvHzce27uAzM9A,10190
1056
1056
  zenml/zen_server/routers/users_endpoints.py,sha256=sXCu6fdSl5LtPl1ZCGesz96h2Ea3SA48MwpVLpJ05h0,25019
1057
1057
  zenml/zen_server/routers/webhook_endpoints.py,sha256=KOJsuykv_TMjL3oEItpC4OWWP75p-OEvVjRSUBd5Mro,3983
1058
- zenml/zen_server/routers/workspaces_endpoints.py,sha256=9XmiwwF4ilSPdarE50kX06Qb_sLqH5DDfChmz_GS0Dc,46269
1058
+ zenml/zen_server/routers/workspaces_endpoints.py,sha256=Rt_OcguRLW5YXS9WH3JSsSSOPZMvc_jSMwvtROEnaBs,46403
1059
1059
  zenml/zen_server/secure_headers.py,sha256=glh6QujnjyeoH1_FK-tAS-105G-qKS_34AqSzqJ6TRc,4182
1060
1060
  zenml/zen_server/template_execution/__init__.py,sha256=79knXLKfegsvVSVSWecpqrepq6iAavTUA4hKuiDk-WE,613
1061
1061
  zenml/zen_server/template_execution/runner_entrypoint_configuration.py,sha256=Y8aYJhqqs8Kv8I1q-dM1WemS5VBIfyoaaYH_YkzC7iY,1541
@@ -1262,11 +1262,11 @@ zenml/zen_stores/schemas/logs_schemas.py,sha256=qv6fs3JiVgzlmTXJqb_gG5NsU5q_50e0
1262
1262
  zenml/zen_stores/schemas/model_schemas.py,sha256=0YVxOBJIkLn9H7Qoxd0T7UqPRirwoSziHG-mBKSm2u8,24801
1263
1263
  zenml/zen_stores/schemas/pipeline_build_schemas.py,sha256=QK3sVPYhumUx_x-H3YZ-RfnsxGhKfkMGdP5FC9WrQgU,5718
1264
1264
  zenml/zen_stores/schemas/pipeline_deployment_schemas.py,sha256=fdsROPBE1QrWKvSkaZYz2Sc1MwXogAembs8TfZML3ks,10201
1265
- zenml/zen_stores/schemas/pipeline_run_schemas.py,sha256=3E95xZ6duIGwUJ1moXJ7POz37lzg53ac7saG7ccWXzo,17720
1265
+ zenml/zen_stores/schemas/pipeline_run_schemas.py,sha256=8GgX8W5LtRJjEmLjsHxrRuarzJPxuQgaG7dMI6bRPus,18068
1266
1266
  zenml/zen_stores/schemas/pipeline_schemas.py,sha256=KAgzeg7atQJw1X9VroNFoys_joz9oHJEMn7yAUdiEYg,6380
1267
1267
  zenml/zen_stores/schemas/run_metadata_schemas.py,sha256=hP3tQ_OyH-ga6Whl6_5Yy8W0BkwBWXT2camu2X6gXL0,3362
1268
1268
  zenml/zen_stores/schemas/run_template_schemas.py,sha256=G4HTcNwpb7useWENrL95Aupbe6URk1LwmhMmPImUolk,8964
1269
- zenml/zen_stores/schemas/schedule_schema.py,sha256=thX5GNrzD4CaeMAXrs7ZKOyn3ECPW9qn9QtD2soxRqk,7373
1269
+ zenml/zen_stores/schemas/schedule_schema.py,sha256=oMAmdMb301_eGehDq1hylPR-jUqjIEaLo8h_rQvWqVE,8153
1270
1270
  zenml/zen_stores/schemas/schema_utils.py,sha256=2qPNPfasnTmCW1RPeViXoTAp6oO-uRnUpEZ_rugcoNw,2612
1271
1271
  zenml/zen_stores/schemas/secret_schemas.py,sha256=Jdiy3TvSTerfX9VYB6dZnBEKIOTOIlzkQIIfj2kUmjw,9903
1272
1272
  zenml/zen_stores/schemas/server_settings_schemas.py,sha256=fViUiwKlsrrA9aqSdWbsNlBhl9szo6_YMR2cfzNRfmg,4284
@@ -1291,8 +1291,8 @@ zenml/zen_stores/secrets_stores/sql_secrets_store.py,sha256=Bq1djrUP9saoD7vECjS7
1291
1291
  zenml/zen_stores/sql_zen_store.py,sha256=7DrChdedvWx98k6iSx6ipWZYpq2sEof5i8Ft8IBYkqo,416926
1292
1292
  zenml/zen_stores/template_utils.py,sha256=EKYBgmDLTS_PSMWaIO5yvHPLiQvMqHcsAe6NUCrv-i4,9068
1293
1293
  zenml/zen_stores/zen_store_interface.py,sha256=vf2gKBWfUUPtcGZC35oQB6pPNVzWVyQC8nWxVLjfrxM,92692
1294
- zenml_nightly-0.73.0.dev20250123.dist-info/LICENSE,sha256=wbnfEnXnafPbqwANHkV6LUsPKOtdpsd-SNw37rogLtc,11359
1295
- zenml_nightly-0.73.0.dev20250123.dist-info/METADATA,sha256=MlTE7YzLkQGqq3ZxOYo-0Xxei5SlIH6quXyjExHlYqY,21355
1296
- zenml_nightly-0.73.0.dev20250123.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
1297
- zenml_nightly-0.73.0.dev20250123.dist-info/entry_points.txt,sha256=QK3ETQE0YswAM2mWypNMOv8TLtr7EjnqAFq1br_jEFE,43
1298
- zenml_nightly-0.73.0.dev20250123.dist-info/RECORD,,
1294
+ zenml_nightly-0.73.0.dev20250124.dist-info/LICENSE,sha256=wbnfEnXnafPbqwANHkV6LUsPKOtdpsd-SNw37rogLtc,11359
1295
+ zenml_nightly-0.73.0.dev20250124.dist-info/METADATA,sha256=CO2m8ZXHGvHKrY82qfix8y5OcsCENx-MwoOGVE3RWtI,21355
1296
+ zenml_nightly-0.73.0.dev20250124.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
1297
+ zenml_nightly-0.73.0.dev20250124.dist-info/entry_points.txt,sha256=QK3ETQE0YswAM2mWypNMOv8TLtr7EjnqAFq1br_jEFE,43
1298
+ zenml_nightly-0.73.0.dev20250124.dist-info/RECORD,,