zenml-nightly 0.73.0.dev20250123__py3-none-any.whl → 0.73.0.dev20250125__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 (79) hide show
  1. zenml/VERSION +1 -1
  2. zenml/analytics/context.py +2 -6
  3. zenml/cli/annotator.py +1 -1
  4. zenml/cli/login.py +17 -6
  5. zenml/cli/server.py +1 -0
  6. zenml/cli/service_connectors.py +5 -5
  7. zenml/cli/stack.py +2 -2
  8. zenml/cli/utils.py +2 -54
  9. zenml/config/pipeline_configurations.py +3 -2
  10. zenml/config/schedule.py +0 -24
  11. zenml/enums.py +1 -0
  12. zenml/event_hub/base_event_hub.py +3 -4
  13. zenml/integrations/airflow/orchestrators/airflow_orchestrator.py +3 -4
  14. zenml/integrations/aws/__init__.py +2 -1
  15. zenml/integrations/aws/flavors/sagemaker_orchestrator_flavor.py +15 -0
  16. zenml/integrations/aws/orchestrators/sagemaker_orchestrator.py +310 -70
  17. zenml/integrations/aws/service_connectors/aws_service_connector.py +8 -13
  18. zenml/integrations/azure/service_connectors/azure_service_connector.py +4 -10
  19. zenml/integrations/gcp/service_connectors/gcp_service_connector.py +3 -3
  20. zenml/integrations/huggingface/__init__.py +1 -6
  21. zenml/integrations/kubernetes/orchestrators/kube_utils.py +3 -3
  22. zenml/integrations/kubernetes/service_connectors/kubernetes_service_connector.py +6 -2
  23. zenml/integrations/whylogs/data_validators/whylogs_data_validator.py +2 -3
  24. zenml/logging/step_logging.py +7 -7
  25. zenml/login/credentials.py +6 -5
  26. zenml/login/credentials_store.py +4 -3
  27. zenml/models/v2/core/api_key.py +5 -2
  28. zenml/models/v2/core/schedule.py +19 -3
  29. zenml/orchestrators/publish_utils.py +4 -4
  30. zenml/orchestrators/step_launcher.py +3 -3
  31. zenml/orchestrators/step_run_utils.py +2 -2
  32. zenml/pipelines/run_utils.py +2 -2
  33. zenml/service_connectors/service_connector.py +7 -4
  34. zenml/stack/stack.py +5 -4
  35. zenml/stack/stack_component.py +10 -2
  36. zenml/stack_deployments/stack_deployment.py +2 -3
  37. zenml/utils/string_utils.py +2 -2
  38. zenml/utils/time_utils.py +138 -0
  39. zenml/zen_server/auth.py +8 -9
  40. zenml/zen_server/cloud_utils.py +4 -6
  41. zenml/zen_server/routers/devices_endpoints.py +2 -4
  42. zenml/zen_server/routers/workspaces_endpoints.py +2 -0
  43. zenml/zen_server/zen_server_api.py +9 -8
  44. zenml/zen_stores/migrations/versions/25155145c545_separate_actions_and_triggers.py +3 -2
  45. zenml/zen_stores/migrations/versions/3dcc5d20e82f_add_last_user_activity.py +3 -3
  46. zenml/zen_stores/migrations/versions/46506f72f0ed_add_server_settings.py +3 -2
  47. zenml/zen_stores/migrations/versions/5994f9ad0489_introduce_role_permissions.py +10 -7
  48. zenml/zen_stores/migrations/versions/7500f434b71c_remove_shared_columns.py +3 -2
  49. zenml/zen_stores/migrations/versions/a91762e6be36_artifact_version_table.py +5 -3
  50. zenml/zen_stores/schemas/action_schemas.py +2 -2
  51. zenml/zen_stores/schemas/api_key_schemas.py +5 -4
  52. zenml/zen_stores/schemas/artifact_schemas.py +3 -3
  53. zenml/zen_stores/schemas/base_schemas.py +5 -7
  54. zenml/zen_stores/schemas/code_repository_schemas.py +2 -2
  55. zenml/zen_stores/schemas/component_schemas.py +2 -2
  56. zenml/zen_stores/schemas/device_schemas.py +5 -4
  57. zenml/zen_stores/schemas/event_source_schemas.py +2 -2
  58. zenml/zen_stores/schemas/flavor_schemas.py +2 -2
  59. zenml/zen_stores/schemas/model_schemas.py +3 -3
  60. zenml/zen_stores/schemas/pipeline_run_schemas.py +11 -3
  61. zenml/zen_stores/schemas/pipeline_schemas.py +2 -2
  62. zenml/zen_stores/schemas/run_template_schemas.py +2 -2
  63. zenml/zen_stores/schemas/schedule_schema.py +20 -4
  64. zenml/zen_stores/schemas/secret_schemas.py +2 -2
  65. zenml/zen_stores/schemas/server_settings_schemas.py +6 -9
  66. zenml/zen_stores/schemas/service_connector_schemas.py +3 -2
  67. zenml/zen_stores/schemas/service_schemas.py +2 -2
  68. zenml/zen_stores/schemas/stack_schemas.py +2 -2
  69. zenml/zen_stores/schemas/step_run_schemas.py +3 -2
  70. zenml/zen_stores/schemas/tag_schemas.py +2 -2
  71. zenml/zen_stores/schemas/trigger_schemas.py +2 -2
  72. zenml/zen_stores/schemas/user_schemas.py +3 -3
  73. zenml/zen_stores/schemas/workspace_schemas.py +2 -2
  74. zenml/zen_stores/sql_zen_store.py +6 -14
  75. {zenml_nightly-0.73.0.dev20250123.dist-info → zenml_nightly-0.73.0.dev20250125.dist-info}/METADATA +2 -2
  76. {zenml_nightly-0.73.0.dev20250123.dist-info → zenml_nightly-0.73.0.dev20250125.dist-info}/RECORD +79 -78
  77. {zenml_nightly-0.73.0.dev20250123.dist-info → zenml_nightly-0.73.0.dev20250125.dist-info}/LICENSE +0 -0
  78. {zenml_nightly-0.73.0.dev20250123.dist-info → zenml_nightly-0.73.0.dev20250125.dist-info}/WHEEL +0 -0
  79. {zenml_nightly-0.73.0.dev20250123.dist-info → zenml_nightly-0.73.0.dev20250125.dist-info}/entry_points.txt +0 -0
@@ -31,7 +31,6 @@ Internal interface: no backwards compatibility guarantees.
31
31
  Adjusted from https://github.com/tensorflow/tfx/blob/master/tfx/utils/kube_utils.py.
32
32
  """
33
33
 
34
- import datetime
35
34
  import enum
36
35
  import re
37
36
  import time
@@ -47,6 +46,7 @@ from zenml.integrations.kubernetes.orchestrators.manifest_utils import (
47
46
  build_service_account_manifest,
48
47
  )
49
48
  from zenml.logger import get_logger
49
+ from zenml.utils.time_utils import utc_now
50
50
 
51
51
  logger = get_logger(__name__)
52
52
 
@@ -248,7 +248,7 @@ def wait_pod(
248
248
  Returns:
249
249
  The pod object which meets the exit condition.
250
250
  """
251
- start_time = datetime.datetime.now(datetime.timezone.utc)
251
+ start_time = utc_now()
252
252
 
253
253
  # Link to exponential back-off algorithm used here:
254
254
  # https://cloud.google.com/storage/docs/exponential-backoff
@@ -288,7 +288,7 @@ def wait_pod(
288
288
  return resp
289
289
 
290
290
  # Check if wait timed out.
291
- elapse_time = datetime.datetime.now(datetime.timezone.utc) - start_time
291
+ elapse_time = utc_now() - start_time
292
292
  if elapse_time.seconds >= timeout_sec and timeout_sec != 0:
293
293
  raise RuntimeError(
294
294
  f"Waiting for pod `{namespace}:{pod_name}` timed out after "
@@ -504,13 +504,17 @@ class KubernetesServiceConnector(ServiceConnector):
504
504
  ).decode("utf-8")
505
505
  if kube_config.ssl_ca_cert
506
506
  else None,
507
- cluster_name=kube_config.host.strip("https://").split(":")[0],
507
+ cluster_name=kube_config.host.removeprefix("https://").split(
508
+ ":"
509
+ )[0],
508
510
  insecure=kube_config.verify_ssl is False,
509
511
  )
510
512
  else:
511
513
  token: Optional[str] = None
512
514
  if kube_config.api_key:
513
- token = kube_config.api_key["authorization"].strip("Bearer ")
515
+ token = kube_config.api_key["authorization"].removeprefix(
516
+ "Bearer "
517
+ )
514
518
 
515
519
  auth_method = KubernetesAuthenticationMethods.TOKEN
516
520
  auth_config = KubernetesTokenConfig(
@@ -34,6 +34,7 @@ from zenml.integrations.whylogs.secret_schemas.whylabs_secret_schema import (
34
34
  )
35
35
  from zenml.logger import get_logger
36
36
  from zenml.stack.authentication_mixin import AuthenticationMixin
37
+ from zenml.utils.time_utils import utc_now
37
38
 
38
39
  logger = get_logger(__name__)
39
40
 
@@ -97,9 +98,7 @@ class WhylogsDataValidator(BaseDataValidator, AuthenticationMixin):
97
98
  """
98
99
  results = why.log(pandas=dataset)
99
100
  profile = results.profile()
100
- dataset_timestamp = dataset_timestamp or datetime.datetime.now(
101
- datetime.timezone.utc
102
- )
101
+ dataset_timestamp = dataset_timestamp or utc_now()
103
102
  profile.set_dataset_timestamp(dataset_timestamp=dataset_timestamp)
104
103
  return profile.view()
105
104
 
@@ -13,7 +13,6 @@
13
13
  # permissions and limitations under the License.
14
14
  """ZenML logging handler."""
15
15
 
16
- import datetime
17
16
  import os
18
17
  import re
19
18
  import sys
@@ -35,6 +34,7 @@ from zenml.logging import (
35
34
  STEP_LOGS_STORAGE_MAX_MESSAGES,
36
35
  STEP_LOGS_STORAGE_MERGE_INTERVAL_SECONDS,
37
36
  )
37
+ from zenml.utils.time_utils import utc_now
38
38
  from zenml.zen_stores.base_zen_store import BaseZenStore
39
39
 
40
40
  # Get the logger
@@ -303,9 +303,9 @@ class StepLogsStorage:
303
303
  "w",
304
304
  ) as file:
305
305
  for message in self.buffer:
306
- timestamp = datetime.datetime.now(
307
- datetime.timezone.utc
308
- ).strftime("%Y-%m-%d %H:%M:%S")
306
+ timestamp = utc_now().strftime(
307
+ "%Y-%m-%d %H:%M:%S"
308
+ )
309
309
  file.write(
310
310
  f"[{timestamp} UTC] {remove_ansi_escape_codes(message)}\n"
311
311
  )
@@ -314,9 +314,9 @@ class StepLogsStorage:
314
314
  self.logs_uri, "a"
315
315
  ) as file:
316
316
  for message in self.buffer:
317
- timestamp = datetime.datetime.now(
318
- datetime.timezone.utc
319
- ).strftime("%Y-%m-%d %H:%M:%S")
317
+ timestamp = utc_now().strftime(
318
+ "%Y-%m-%d %H:%M:%S"
319
+ )
320
320
  file.write(
321
321
  f"[{timestamp} UTC] {remove_ansi_escape_codes(message)}\n"
322
322
  )
@@ -13,7 +13,7 @@
13
13
  # permissions and limitations under the License.
14
14
  """ZenML login credentials models."""
15
15
 
16
- from datetime import datetime, timedelta, timezone
16
+ from datetime import datetime, timedelta
17
17
  from typing import Any, Dict, Optional, Union
18
18
  from urllib.parse import urlparse
19
19
  from uuid import UUID
@@ -27,6 +27,7 @@ from zenml.models.v2.misc.server_models import ServerDeploymentType
27
27
  from zenml.services.service_status import ServiceState
28
28
  from zenml.utils.enum_utils import StrEnum
29
29
  from zenml.utils.string_utils import get_human_readable_time
30
+ from zenml.utils.time_utils import to_local_tz, utc_now
30
31
 
31
32
 
32
33
  class ServerType(StrEnum):
@@ -71,7 +72,7 @@ class APIToken(BaseModel):
71
72
  expires_at = self.expires_at_with_leeway
72
73
  if not expires_at:
73
74
  return False
74
- return expires_at < datetime.now(timezone.utc)
75
+ return expires_at < utc_now(tz_aware=expires_at)
75
76
 
76
77
  model_config = ConfigDict(
77
78
  # Allow extra attributes to allow backwards compatibility
@@ -223,7 +224,7 @@ class ServerCredentials(BaseModel):
223
224
  expires_at = self.api_token.expires_at_with_leeway
224
225
  if not expires_at:
225
226
  return "never expires"
226
- if expires_at < datetime.now(timezone.utc):
227
+ if expires_at < utc_now(tz_aware=expires_at):
227
228
  return "expired at " + self.expires_at
228
229
 
229
230
  return f"valid until {self.expires_at} (in {self.expires_in})"
@@ -242,7 +243,7 @@ class ServerCredentials(BaseModel):
242
243
  return "never"
243
244
 
244
245
  # Convert the date in the local timezone
245
- local_expires_at = expires_at.astimezone()
246
+ local_expires_at = to_local_tz(expires_at)
246
247
  return local_expires_at.strftime("%Y-%m-%d %H:%M:%S %Z")
247
248
 
248
249
  @property
@@ -259,7 +260,7 @@ class ServerCredentials(BaseModel):
259
260
  return "never"
260
261
 
261
262
  # Get the time remaining until the token expires
262
- expires_in = expires_at - datetime.now(timezone.utc)
263
+ expires_in = expires_at - utc_now(tz_aware=expires_at)
263
264
  return get_human_readable_time(expires_in.total_seconds())
264
265
 
265
266
  @property
@@ -14,7 +14,7 @@
14
14
  """ZenML login credentials store support."""
15
15
 
16
16
  import os
17
- from datetime import datetime, timedelta, timezone
17
+ from datetime import timedelta
18
18
  from typing import Dict, List, Optional, Tuple, Union, cast
19
19
 
20
20
  from zenml.config.global_config import GlobalConfiguration
@@ -29,6 +29,7 @@ from zenml.login.pro.tenant.models import TenantRead
29
29
  from zenml.models import OAuthTokenResponse, ServerModel
30
30
  from zenml.utils import yaml_utils
31
31
  from zenml.utils.singleton import SingletonMetaClass
32
+ from zenml.utils.time_utils import utc_now_tz_aware
32
33
 
33
34
  logger = get_logger(__name__)
34
35
 
@@ -190,7 +191,7 @@ class CredentialsStore(metaclass=SingletonMetaClass):
190
191
  not credential.api_token.expires_at
191
192
  or credential.api_token.expires_at
192
193
  + timedelta(seconds=TOKEN_STORE_EVICTION_TIME)
193
- > datetime.now(timezone.utc)
194
+ > utc_now_tz_aware()
194
195
  )
195
196
  }
196
197
  yaml_utils.write_yaml(credentials_file, credentials_store)
@@ -477,7 +478,7 @@ class CredentialsStore(metaclass=SingletonMetaClass):
477
478
  """
478
479
  self.check_and_reload_from_file()
479
480
  if token_response.expires_in:
480
- expires_at = datetime.now(timezone.utc) + timedelta(
481
+ expires_at = utc_now_tz_aware() + timedelta(
481
482
  seconds=token_response.expires_in
482
483
  )
483
484
  # Best practice to calculate the leeway depending on the token
@@ -13,7 +13,7 @@
13
13
  # permissions and limitations under the License.
14
14
  """Models representing API keys."""
15
15
 
16
- from datetime import datetime, timedelta, timezone
16
+ from datetime import datetime, timedelta
17
17
  from typing import TYPE_CHECKING, ClassVar, List, Optional, Type, Union
18
18
  from uuid import UUID
19
19
 
@@ -35,6 +35,7 @@ from zenml.models.v2.base.base import (
35
35
  )
36
36
  from zenml.models.v2.base.filter import AnyQuery, BaseFilter
37
37
  from zenml.utils.string_utils import b64_decode, b64_encode
38
+ from zenml.utils.time_utils import utc_now
38
39
 
39
40
  if TYPE_CHECKING:
40
41
  from zenml.models.v2.base.filter import AnySchema
@@ -319,7 +320,9 @@ class APIKeyInternalResponse(APIKeyResponse):
319
320
  and self.retain_period_minutes > 0
320
321
  ):
321
322
  # check if the previous key is still valid
322
- if datetime.now(timezone.utc) - self.last_rotated < timedelta(
323
+ if utc_now(
324
+ tz_aware=self.last_rotated
325
+ ) - self.last_rotated < timedelta(
323
326
  minutes=self.retain_period_minutes
324
327
  ):
325
328
  key_hash = self.previous_key
@@ -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,
@@ -30,6 +31,7 @@ from zenml.models.v2.base.scoped import (
30
31
  WorkspaceScopedResponseMetadata,
31
32
  WorkspaceScopedResponseResources,
32
33
  )
34
+ from zenml.utils.time_utils import to_utc_timezone
33
35
 
34
36
  logger = get_logger(__name__)
35
37
 
@@ -136,6 +138,11 @@ class ScheduleResponseMetadata(WorkspaceScopedResponseMetadata):
136
138
  orchestrator_id: Optional[UUID]
137
139
  pipeline_id: Optional[UUID]
138
140
 
141
+ run_metadata: Dict[str, MetadataType] = Field(
142
+ title="Metadata associated with this schedule.",
143
+ default={},
144
+ )
145
+
139
146
 
140
147
  class ScheduleResponseResources(WorkspaceScopedResponseResources):
141
148
  """Class for all resource models associated with the schedule entity."""
@@ -176,7 +183,7 @@ class ScheduleResponse(
176
183
  if not self.start_time:
177
184
  return None
178
185
 
179
- return self.start_time.astimezone(datetime.timezone.utc).isoformat()
186
+ return to_utc_timezone(self.start_time).isoformat()
180
187
 
181
188
  @property
182
189
  def utc_end_time(self) -> Optional[str]:
@@ -188,7 +195,7 @@ class ScheduleResponse(
188
195
  if not self.end_time:
189
196
  return None
190
197
 
191
- return self.end_time.astimezone(datetime.timezone.utc).isoformat()
198
+ return to_utc_timezone(self.end_time).isoformat()
192
199
 
193
200
  # Body and metadata properties
194
201
  @property
@@ -272,6 +279,15 @@ class ScheduleResponse(
272
279
  """
273
280
  return self.get_metadata().pipeline_id
274
281
 
282
+ @property
283
+ def run_metadata(self) -> Dict[str, MetadataType]:
284
+ """The `run_metadata` property.
285
+
286
+ Returns:
287
+ the value of the property.
288
+ """
289
+ return self.get_metadata().run_metadata
290
+
275
291
 
276
292
  # ------------------ Filter Model ------------------
277
293
 
@@ -13,7 +13,6 @@
13
13
  # permissions and limitations under the License.
14
14
  """Utilities to publish pipeline and step runs."""
15
15
 
16
- from datetime import datetime, timezone
17
16
  from typing import TYPE_CHECKING, Dict, List
18
17
 
19
18
  from zenml.client import Client
@@ -25,6 +24,7 @@ from zenml.models import (
25
24
  StepRunResponse,
26
25
  StepRunUpdate,
27
26
  )
27
+ from zenml.utils.time_utils import utc_now
28
28
 
29
29
  if TYPE_CHECKING:
30
30
  from uuid import UUID
@@ -48,7 +48,7 @@ def publish_successful_step_run(
48
48
  step_run_id=step_run_id,
49
49
  step_run_update=StepRunUpdate(
50
50
  status=ExecutionStatus.COMPLETED,
51
- end_time=datetime.now(timezone.utc),
51
+ end_time=utc_now(),
52
52
  outputs=output_artifact_ids,
53
53
  ),
54
54
  )
@@ -67,7 +67,7 @@ def publish_failed_step_run(step_run_id: "UUID") -> "StepRunResponse":
67
67
  step_run_id=step_run_id,
68
68
  step_run_update=StepRunUpdate(
69
69
  status=ExecutionStatus.FAILED,
70
- end_time=datetime.now(timezone.utc),
70
+ end_time=utc_now(),
71
71
  ),
72
72
  )
73
73
 
@@ -87,7 +87,7 @@ def publish_failed_pipeline_run(
87
87
  run_id=pipeline_run_id,
88
88
  run_update=PipelineRunUpdate(
89
89
  status=ExecutionStatus.FAILED,
90
- end_time=datetime.now(timezone.utc),
90
+ end_time=utc_now(),
91
91
  ),
92
92
  )
93
93
 
@@ -16,7 +16,6 @@
16
16
  import os
17
17
  import time
18
18
  from contextlib import nullcontext
19
- from datetime import datetime, timezone
20
19
  from functools import partial
21
20
  from typing import TYPE_CHECKING, Any, Callable, Dict, Tuple
22
21
 
@@ -45,6 +44,7 @@ from zenml.orchestrators import utils as orchestrator_utils
45
44
  from zenml.orchestrators.step_runner import StepRunner
46
45
  from zenml.stack import Stack
47
46
  from zenml.utils import string_utils
47
+ from zenml.utils.time_utils import utc_now
48
48
 
49
49
  if TYPE_CHECKING:
50
50
  from zenml.step_operators import BaseStepOperator
@@ -201,7 +201,7 @@ class StepLauncher:
201
201
  f"Failed preparing step `{self._step_name}`."
202
202
  )
203
203
  step_run_request.status = ExecutionStatus.FAILED
204
- step_run_request.end_time = datetime.now(timezone.utc)
204
+ step_run_request.end_time = utc_now()
205
205
  raise
206
206
  finally:
207
207
  step_run = Client().zen_store.create_run_step(
@@ -305,7 +305,7 @@ class StepLauncher:
305
305
  The created or existing pipeline run,
306
306
  and a boolean indicating whether the run was created or reused.
307
307
  """
308
- start_time = datetime.now(timezone.utc)
308
+ start_time = utc_now()
309
309
  run_name = string_utils.format_name_template(
310
310
  name_template=self._deployment.run_name_template,
311
311
  substitutions=self._deployment.pipeline_configuration._get_full_substitutions(
@@ -13,7 +13,6 @@
13
13
  # permissions and limitations under the License.
14
14
  """Utilities for creating step runs."""
15
15
 
16
- from datetime import datetime, timezone
17
16
  from typing import Dict, List, Optional, Set, Tuple
18
17
 
19
18
  from zenml.client import Client
@@ -31,6 +30,7 @@ from zenml.models import (
31
30
  )
32
31
  from zenml.orchestrators import cache_utils, input_utils, utils
33
32
  from zenml.stack import Stack
33
+ from zenml.utils.time_utils import utc_now
34
34
 
35
35
  logger = get_logger(__name__)
36
36
 
@@ -75,7 +75,7 @@ class StepRunRequestFactory:
75
75
  pipeline_run_id=self.pipeline_run.id,
76
76
  deployment=self.deployment.id,
77
77
  status=ExecutionStatus.RUNNING,
78
- start_time=datetime.now(timezone.utc),
78
+ start_time=utc_now(),
79
79
  user=Client().active_user.id,
80
80
  workspace=Client().active_workspace.id,
81
81
  )
@@ -1,7 +1,6 @@
1
1
  """Utility functions for running pipelines."""
2
2
 
3
3
  import time
4
- from datetime import datetime, timezone
5
4
  from typing import TYPE_CHECKING, Any, Dict, List, Optional, Set, Union
6
5
  from uuid import UUID
7
6
 
@@ -25,6 +24,7 @@ from zenml.models import (
25
24
  from zenml.orchestrators.publish_utils import publish_failed_pipeline_run
26
25
  from zenml.stack import Flavor, Stack
27
26
  from zenml.utils import code_utils, notebook_utils, source_utils, string_utils
27
+ from zenml.utils.time_utils import utc_now
28
28
  from zenml.zen_stores.base_zen_store import BaseZenStore
29
29
 
30
30
  if TYPE_CHECKING:
@@ -65,7 +65,7 @@ def create_placeholder_run(
65
65
 
66
66
  if deployment.schedule:
67
67
  return None
68
- start_time = datetime.now(timezone.utc)
68
+ start_time = utc_now()
69
69
  run_request = PipelineRunRequest(
70
70
  name=string_utils.format_name_template(
71
71
  name_template=deployment.run_name_template,
@@ -55,6 +55,7 @@ from zenml.models import (
55
55
  UserResponse,
56
56
  WorkspaceResponse,
57
57
  )
58
+ from zenml.utils.time_utils import utc_now
58
59
 
59
60
  logger = get_logger(__name__)
60
61
 
@@ -794,13 +795,14 @@ class ServiceConnector(BaseModel, metaclass=ServiceConnectorMeta):
794
795
  "connector configuration is not valid: name and ID must be set"
795
796
  )
796
797
 
798
+ now = utc_now()
797
799
  model = ServiceConnectorResponse(
798
800
  id=id,
799
801
  name=name,
800
802
  body=ServiceConnectorResponseBody(
801
803
  user=user,
802
- created=datetime.now(timezone.utc),
803
- updated=datetime.now(timezone.utc),
804
+ created=now,
805
+ updated=now,
804
806
  description=description,
805
807
  connector_type=self.get_type(),
806
808
  auth_method=self.auth_method,
@@ -845,14 +847,15 @@ class ServiceConnector(BaseModel, metaclass=ServiceConnectorMeta):
845
847
  if self.expires_skew_tolerance is not None
846
848
  else SERVICE_CONNECTOR_SKEW_TOLERANCE_SECONDS
847
849
  )
848
- delta = expires_at - datetime.now(timezone.utc)
850
+ now = utc_now(tz_aware=expires_at)
851
+ delta = expires_at - now
849
852
  result = delta < timedelta(seconds=0)
850
853
 
851
854
  logger.debug(
852
855
  f"Checking if connector {self.name} has expired.\n"
853
856
  f"Expires at: {self.expires_at}\n"
854
857
  f"Expires at (+skew): {expires_at}\n"
855
- f"Current UTC time: {datetime.now(timezone.utc)}\n"
858
+ f"Current UTC time: {now}\n"
856
859
  f"Delta: {delta}\n"
857
860
  f"Result: {result}\n"
858
861
  )
zenml/stack/stack.py CHANGED
@@ -16,7 +16,7 @@
16
16
  import itertools
17
17
  import json
18
18
  import os
19
- from datetime import datetime, timezone
19
+ from datetime import datetime
20
20
  from typing import (
21
21
  TYPE_CHECKING,
22
22
  AbstractSet,
@@ -45,6 +45,7 @@ from zenml.logger import get_logger
45
45
  from zenml.metadata.metadata_types import MetadataType
46
46
  from zenml.models import StackResponse
47
47
  from zenml.utils import pagination_utils, settings_utils
48
+ from zenml.utils.time_utils import utc_now
48
49
 
49
50
  if TYPE_CHECKING:
50
51
  from zenml.alerter import BaseAlerter
@@ -732,7 +733,6 @@ class Stack:
732
733
  and not skip_default_image_builder
733
734
  and not self.image_builder
734
735
  ):
735
- from datetime import datetime
736
736
  from uuid import uuid4
737
737
 
738
738
  from zenml.image_builders import (
@@ -743,6 +743,7 @@ class Stack:
743
743
 
744
744
  flavor = LocalImageBuilderFlavor()
745
745
 
746
+ now = utc_now()
746
747
  image_builder = LocalImageBuilder(
747
748
  id=uuid4(),
748
749
  name="temporary_default",
@@ -751,8 +752,8 @@ class Stack:
751
752
  config=LocalImageBuilderConfig(),
752
753
  user=Client().active_user.id,
753
754
  workspace=Client().active_workspace.id,
754
- created=datetime.now(timezone.utc),
755
- updated=datetime.now(timezone.utc),
755
+ created=now,
756
+ updated=now,
756
757
  )
757
758
 
758
759
  self._image_builder = image_builder
@@ -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
 
@@ -26,6 +26,7 @@ from zenml.models import (
26
26
  StackDeploymentConfig,
27
27
  StackDeploymentInfo,
28
28
  )
29
+ from zenml.utils.time_utils import to_utc_timezone
29
30
 
30
31
  STACK_DEPLOYMENT_TERRAFORM = "terraform"
31
32
 
@@ -199,9 +200,7 @@ class ZenMLCloudStackDeployment(BaseModel):
199
200
  # Get all stacks created after the start date
200
201
 
201
202
  if date_start and date_start.tzinfo:
202
- date_start = date_start.astimezone(datetime.timezone.utc).replace(
203
- tzinfo=None
204
- )
203
+ date_start = to_utc_timezone(date_start).replace(tzinfo=None)
205
204
  stacks = client.list_stacks(
206
205
  created=f"gt:{str(date_start.replace(microsecond=0))}"
207
206
  if date_start
@@ -17,12 +17,12 @@ import base64
17
17
  import functools
18
18
  import random
19
19
  import string
20
- from datetime import datetime, timezone
21
20
  from typing import Any, Callable, Dict, Optional, TypeVar, cast
22
21
 
23
22
  from pydantic import BaseModel
24
23
 
25
24
  from zenml.constants import BANNED_NAME_CHARACTERS
25
+ from zenml.utils.time_utils import utc_now
26
26
 
27
27
  V = TypeVar("V", bound=Any)
28
28
 
@@ -180,7 +180,7 @@ def format_name_template(
180
180
  start_time = None
181
181
 
182
182
  if start_time is None:
183
- start_time = datetime.now(timezone.utc)
183
+ start_time = utc_now()
184
184
  substitutions.setdefault("date", start_time.strftime("%Y_%m_%d"))
185
185
  substitutions.setdefault("time", start_time.strftime("%H_%M_%S_%f"))
186
186