zenml-nightly 0.73.0.dev20250127__py3-none-any.whl → 0.73.0.dev20250129__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 +1 -1
- zenml/cli/code_repository.py +69 -1
- zenml/client.py +58 -19
- zenml/config/schedule.py +47 -10
- zenml/constants.py +2 -0
- zenml/entrypoints/base_entrypoint_configuration.py +46 -3
- zenml/exceptions.py +4 -0
- zenml/integrations/github/code_repositories/github_code_repository.py +20 -8
- zenml/integrations/gitlab/code_repositories/gitlab_code_repository.py +9 -3
- zenml/logger.py +15 -2
- zenml/models/v2/base/scoped.py +3 -2
- zenml/models/v2/core/pipeline_run.py +6 -6
- zenml/models/v2/core/schedule.py +42 -21
- zenml/pipelines/build_utils.py +43 -7
- zenml/pipelines/pipeline_definition.py +2 -1
- zenml/stack/flavor.py +27 -1
- zenml/stack/stack_component.py +3 -9
- zenml/utils/code_repository_utils.py +9 -2
- zenml/utils/code_utils.py +17 -13
- zenml/utils/dashboard_utils.py +24 -3
- zenml/utils/deprecation_utils.py +4 -2
- zenml/utils/pipeline_docker_image_builder.py +1 -4
- zenml/zen_stores/schemas/code_repository_schemas.py +3 -0
- {zenml_nightly-0.73.0.dev20250127.dist-info → zenml_nightly-0.73.0.dev20250129.dist-info}/METADATA +1 -1
- {zenml_nightly-0.73.0.dev20250127.dist-info → zenml_nightly-0.73.0.dev20250129.dist-info}/RECORD +28 -28
- {zenml_nightly-0.73.0.dev20250127.dist-info → zenml_nightly-0.73.0.dev20250129.dist-info}/LICENSE +0 -0
- {zenml_nightly-0.73.0.dev20250127.dist-info → zenml_nightly-0.73.0.dev20250129.dist-info}/WHEEL +0 -0
- {zenml_nightly-0.73.0.dev20250127.dist-info → zenml_nightly-0.73.0.dev20250129.dist-info}/entry_points.txt +0 -0
zenml/models/v2/core/schedule.py
CHANGED
@@ -13,11 +13,11 @@
|
|
13
13
|
# permissions and limitations under the License.
|
14
14
|
"""Models representing schedules."""
|
15
15
|
|
16
|
-
import datetime
|
16
|
+
from datetime import datetime, timedelta, timezone
|
17
17
|
from typing import Dict, Optional, Union
|
18
18
|
from uuid import UUID
|
19
19
|
|
20
|
-
from pydantic import Field, model_validator
|
20
|
+
from pydantic import Field, field_validator, model_validator
|
21
21
|
|
22
22
|
from zenml.constants import STR_FIELD_MAX_LENGTH
|
23
23
|
from zenml.logger import get_logger
|
@@ -46,15 +46,36 @@ class ScheduleRequest(WorkspaceScopedRequest):
|
|
46
46
|
active: bool
|
47
47
|
|
48
48
|
cron_expression: Optional[str] = None
|
49
|
-
start_time: Optional[datetime
|
50
|
-
end_time: Optional[datetime
|
51
|
-
interval_second: Optional[
|
49
|
+
start_time: Optional[datetime] = None
|
50
|
+
end_time: Optional[datetime] = None
|
51
|
+
interval_second: Optional[timedelta] = None
|
52
52
|
catchup: bool = False
|
53
|
-
run_once_start_time: Optional[datetime
|
53
|
+
run_once_start_time: Optional[datetime] = None
|
54
54
|
|
55
55
|
orchestrator_id: Optional[UUID]
|
56
56
|
pipeline_id: Optional[UUID]
|
57
57
|
|
58
|
+
@field_validator(
|
59
|
+
"start_time", "end_time", "run_once_start_time", mode="after"
|
60
|
+
)
|
61
|
+
@classmethod
|
62
|
+
def _ensure_tzunaware_utc(
|
63
|
+
cls, value: Optional[datetime]
|
64
|
+
) -> Optional[datetime]:
|
65
|
+
"""Ensures that all datetimes are timezone unaware and in UTC time.
|
66
|
+
|
67
|
+
Args:
|
68
|
+
value: The datetime.
|
69
|
+
|
70
|
+
Returns:
|
71
|
+
The datetime in UTC time without timezone.
|
72
|
+
"""
|
73
|
+
if value and value.tzinfo:
|
74
|
+
value = value.astimezone(timezone.utc)
|
75
|
+
value = value.replace(tzinfo=None)
|
76
|
+
|
77
|
+
return value
|
78
|
+
|
58
79
|
@model_validator(mode="after")
|
59
80
|
def _ensure_cron_or_periodic_schedule_configured(
|
60
81
|
self,
|
@@ -108,11 +129,11 @@ class ScheduleUpdate(BaseUpdate):
|
|
108
129
|
name: Optional[str] = None
|
109
130
|
active: Optional[bool] = None
|
110
131
|
cron_expression: Optional[str] = None
|
111
|
-
start_time: Optional[datetime
|
112
|
-
end_time: Optional[datetime
|
113
|
-
interval_second: Optional[
|
132
|
+
start_time: Optional[datetime] = None
|
133
|
+
end_time: Optional[datetime] = None
|
134
|
+
interval_second: Optional[timedelta] = None
|
114
135
|
catchup: Optional[bool] = None
|
115
|
-
run_once_start_time: Optional[datetime
|
136
|
+
run_once_start_time: Optional[datetime] = None
|
116
137
|
orchestrator_id: Optional[UUID] = None
|
117
138
|
pipeline_id: Optional[UUID] = None
|
118
139
|
|
@@ -125,11 +146,11 @@ class ScheduleResponseBody(WorkspaceScopedResponseBody):
|
|
125
146
|
|
126
147
|
active: bool
|
127
148
|
cron_expression: Optional[str] = None
|
128
|
-
start_time: Optional[datetime
|
129
|
-
end_time: Optional[datetime
|
130
|
-
interval_second: Optional[
|
149
|
+
start_time: Optional[datetime] = None
|
150
|
+
end_time: Optional[datetime] = None
|
151
|
+
interval_second: Optional[timedelta] = None
|
131
152
|
catchup: bool = False
|
132
|
-
run_once_start_time: Optional[datetime
|
153
|
+
run_once_start_time: Optional[datetime] = None
|
133
154
|
|
134
155
|
|
135
156
|
class ScheduleResponseMetadata(WorkspaceScopedResponseMetadata):
|
@@ -217,7 +238,7 @@ class ScheduleResponse(
|
|
217
238
|
return self.get_body().cron_expression
|
218
239
|
|
219
240
|
@property
|
220
|
-
def start_time(self) -> Optional[datetime
|
241
|
+
def start_time(self) -> Optional[datetime]:
|
221
242
|
"""The `start_time` property.
|
222
243
|
|
223
244
|
Returns:
|
@@ -226,7 +247,7 @@ class ScheduleResponse(
|
|
226
247
|
return self.get_body().start_time
|
227
248
|
|
228
249
|
@property
|
229
|
-
def end_time(self) -> Optional[datetime
|
250
|
+
def end_time(self) -> Optional[datetime]:
|
230
251
|
"""The `end_time` property.
|
231
252
|
|
232
253
|
Returns:
|
@@ -235,7 +256,7 @@ class ScheduleResponse(
|
|
235
256
|
return self.get_body().end_time
|
236
257
|
|
237
258
|
@property
|
238
|
-
def run_once_start_time(self) -> Optional[datetime
|
259
|
+
def run_once_start_time(self) -> Optional[datetime]:
|
239
260
|
"""The `run_once_start_time` property.
|
240
261
|
|
241
262
|
Returns:
|
@@ -244,7 +265,7 @@ class ScheduleResponse(
|
|
244
265
|
return self.get_body().run_once_start_time
|
245
266
|
|
246
267
|
@property
|
247
|
-
def interval_second(self) -> Optional[
|
268
|
+
def interval_second(self) -> Optional[timedelta]:
|
248
269
|
"""The `interval_second` property.
|
249
270
|
|
250
271
|
Returns:
|
@@ -313,10 +334,10 @@ class ScheduleFilter(WorkspaceScopedFilter):
|
|
313
334
|
default=None,
|
314
335
|
description="The cron expression, describing the schedule",
|
315
336
|
)
|
316
|
-
start_time: Optional[Union[datetime
|
337
|
+
start_time: Optional[Union[datetime, str]] = Field(
|
317
338
|
default=None, description="Start time", union_mode="left_to_right"
|
318
339
|
)
|
319
|
-
end_time: Optional[Union[datetime
|
340
|
+
end_time: Optional[Union[datetime, str]] = Field(
|
320
341
|
default=None, description="End time", union_mode="left_to_right"
|
321
342
|
)
|
322
343
|
interval_second: Optional[Optional[float]] = Field(
|
@@ -332,7 +353,7 @@ class ScheduleFilter(WorkspaceScopedFilter):
|
|
332
353
|
default=None,
|
333
354
|
description="Name of the schedule",
|
334
355
|
)
|
335
|
-
run_once_start_time: Optional[Union[datetime
|
356
|
+
run_once_start_time: Optional[Union[datetime, str]] = Field(
|
336
357
|
default=None,
|
337
358
|
description="The time at which the schedule should run once",
|
338
359
|
union_mode="left_to_right",
|
zenml/pipelines/build_utils.py
CHANGED
@@ -30,7 +30,6 @@ from zenml.code_repositories import BaseCodeRepository
|
|
30
30
|
from zenml.logger import get_logger
|
31
31
|
from zenml.models import (
|
32
32
|
BuildItem,
|
33
|
-
CodeReferenceRequest,
|
34
33
|
PipelineBuildBase,
|
35
34
|
PipelineBuildRequest,
|
36
35
|
PipelineBuildResponse,
|
@@ -362,6 +361,7 @@ def create_pipeline_build(
|
|
362
361
|
item_key = checksums[checksum]
|
363
362
|
image_name_or_digest = images[item_key].image
|
364
363
|
contains_code = images[item_key].contains_code
|
364
|
+
requires_code_download = images[item_key].requires_code_download
|
365
365
|
dockerfile = images[item_key].dockerfile
|
366
366
|
requirements = images[item_key].requirements
|
367
367
|
else:
|
@@ -373,7 +373,7 @@ def create_pipeline_build(
|
|
373
373
|
include_files = build_config.should_include_files(
|
374
374
|
code_repository=code_repository,
|
375
375
|
)
|
376
|
-
|
376
|
+
requires_code_download = build_config.should_download_files(
|
377
377
|
code_repository=code_repository,
|
378
378
|
)
|
379
379
|
pass_code_repo = (
|
@@ -391,7 +391,6 @@ def create_pipeline_build(
|
|
391
391
|
tag=tag,
|
392
392
|
stack=stack,
|
393
393
|
include_files=include_files,
|
394
|
-
download_files=download_files,
|
395
394
|
entrypoint=build_config.entrypoint,
|
396
395
|
extra_files=build_config.extra_files,
|
397
396
|
code_repository=code_repository if pass_code_repo else None,
|
@@ -404,7 +403,7 @@ def create_pipeline_build(
|
|
404
403
|
requirements=requirements,
|
405
404
|
settings_checksum=checksum,
|
406
405
|
contains_code=contains_code,
|
407
|
-
requires_code_download=
|
406
|
+
requires_code_download=requires_code_download,
|
408
407
|
)
|
409
408
|
checksums[checksum] = combined_key
|
410
409
|
|
@@ -537,6 +536,14 @@ def verify_local_repository_context(
|
|
537
536
|
)
|
538
537
|
code_repository = BaseCodeRepository.from_model(model)
|
539
538
|
|
539
|
+
if will_download_from_code_repository(
|
540
|
+
deployment=deployment, local_repo_context=local_repo_context
|
541
|
+
):
|
542
|
+
logger.info(
|
543
|
+
"Using code repository `%s` to download code for this run.",
|
544
|
+
model.name,
|
545
|
+
)
|
546
|
+
|
540
547
|
return code_repository
|
541
548
|
|
542
549
|
|
@@ -695,14 +702,15 @@ def compute_stack_checksum(stack: StackResponse) -> str:
|
|
695
702
|
def should_upload_code(
|
696
703
|
deployment: PipelineDeploymentBase,
|
697
704
|
build: Optional[PipelineBuildResponse],
|
698
|
-
|
705
|
+
can_download_from_code_repository: bool,
|
699
706
|
) -> bool:
|
700
707
|
"""Checks whether the current code should be uploaded for the deployment.
|
701
708
|
|
702
709
|
Args:
|
703
710
|
deployment: The deployment.
|
704
711
|
build: The build for the deployment.
|
705
|
-
|
712
|
+
can_download_from_code_repository: Whether the code can be downloaded
|
713
|
+
from a code repository.
|
706
714
|
|
707
715
|
Returns:
|
708
716
|
Whether the current code should be uploaded for the deployment.
|
@@ -718,7 +726,7 @@ def should_upload_code(
|
|
718
726
|
docker_settings = step.config.docker_settings
|
719
727
|
|
720
728
|
if (
|
721
|
-
|
729
|
+
can_download_from_code_repository
|
722
730
|
and docker_settings.allow_download_from_code_repository
|
723
731
|
):
|
724
732
|
# No upload needed for this step
|
@@ -728,3 +736,31 @@ def should_upload_code(
|
|
728
736
|
return True
|
729
737
|
|
730
738
|
return False
|
739
|
+
|
740
|
+
|
741
|
+
def will_download_from_code_repository(
|
742
|
+
deployment: PipelineDeploymentBase,
|
743
|
+
local_repo_context: "LocalRepositoryContext",
|
744
|
+
) -> bool:
|
745
|
+
"""Checks whether a code repository will be used to download code.
|
746
|
+
|
747
|
+
Args:
|
748
|
+
deployment: The deployment.
|
749
|
+
local_repo_context: The local repository context.
|
750
|
+
|
751
|
+
Returns:
|
752
|
+
Whether a code repository will be used to download code.
|
753
|
+
"""
|
754
|
+
if not build_required(deployment=deployment):
|
755
|
+
return False
|
756
|
+
|
757
|
+
if local_repo_context.has_local_changes:
|
758
|
+
return False
|
759
|
+
|
760
|
+
for step in deployment.step_configurations.values():
|
761
|
+
docker_settings = step.config.docker_settings
|
762
|
+
|
763
|
+
if docker_settings.allow_download_from_code_repository:
|
764
|
+
return True
|
765
|
+
|
766
|
+
return False
|
@@ -701,6 +701,7 @@ To avoid this consider setting pipeline parameters only in one place (config or
|
|
701
701
|
code_repository = build_utils.verify_local_repository_context(
|
702
702
|
deployment=deployment, local_repo_context=local_repo_context
|
703
703
|
)
|
704
|
+
can_download_from_code_repository = code_repository is not None
|
704
705
|
|
705
706
|
if prevent_build_reuse:
|
706
707
|
logger.warning(
|
@@ -737,7 +738,7 @@ To avoid this consider setting pipeline parameters only in one place (config or
|
|
737
738
|
if build_utils.should_upload_code(
|
738
739
|
deployment=deployment,
|
739
740
|
build=build_model,
|
740
|
-
|
741
|
+
can_download_from_code_repository=can_download_from_code_repository,
|
741
742
|
):
|
742
743
|
code_archive = code_utils.CodeArchive(
|
743
744
|
root=source_utils.get_source_root()
|
zenml/stack/flavor.py
CHANGED
@@ -13,11 +13,13 @@
|
|
13
13
|
# permissions and limitations under the License.
|
14
14
|
"""Base ZenML Flavor implementation."""
|
15
15
|
|
16
|
+
import os
|
16
17
|
from abc import abstractmethod
|
17
18
|
from typing import Any, Dict, Optional, Type, cast
|
18
19
|
|
19
20
|
from zenml.client import Client
|
20
21
|
from zenml.enums import StackComponentType
|
22
|
+
from zenml.exceptions import CustomFlavorImportError
|
21
23
|
from zenml.models import (
|
22
24
|
FlavorRequest,
|
23
25
|
FlavorResponse,
|
@@ -126,10 +128,34 @@ class Flavor:
|
|
126
128
|
Args:
|
127
129
|
flavor_model: The model to load from.
|
128
130
|
|
131
|
+
Raises:
|
132
|
+
CustomFlavorImportError: If the custom flavor can't be imported.
|
133
|
+
ImportError: If the flavor can't be imported.
|
134
|
+
|
129
135
|
Returns:
|
130
136
|
The loaded flavor.
|
131
137
|
"""
|
132
|
-
|
138
|
+
try:
|
139
|
+
flavor = source_utils.load(flavor_model.source)()
|
140
|
+
except (ModuleNotFoundError, ImportError, NotImplementedError) as err:
|
141
|
+
if flavor_model.is_custom:
|
142
|
+
flavor_module, _ = flavor_model.source.rsplit(".")
|
143
|
+
expected_file_path = os.path.join(
|
144
|
+
source_utils.get_source_root(),
|
145
|
+
flavor_module.replace(".", os.path.sep),
|
146
|
+
)
|
147
|
+
raise CustomFlavorImportError(
|
148
|
+
f"Couldn't import custom flavor {flavor_model.name}: "
|
149
|
+
f"{err}. Make sure the custom flavor class "
|
150
|
+
f"`{flavor_model.source}` is importable. If it is part of "
|
151
|
+
"a library, make sure it is installed. If "
|
152
|
+
"it is a local code file, make sure it exists at "
|
153
|
+
f"`{expected_file_path}.py`."
|
154
|
+
)
|
155
|
+
else:
|
156
|
+
raise ImportError(
|
157
|
+
f"Couldn't import flavor {flavor_model.name}: {err}"
|
158
|
+
)
|
133
159
|
return cast(Flavor, flavor)
|
134
160
|
|
135
161
|
def to_model(
|
zenml/stack/stack_component.py
CHANGED
@@ -402,16 +402,10 @@ class StackComponent:
|
|
402
402
|
Raises:
|
403
403
|
ImportError: If the flavor can't be imported.
|
404
404
|
"""
|
405
|
-
|
406
|
-
|
407
|
-
try:
|
408
|
-
from zenml.stack import Flavor
|
405
|
+
from zenml.stack import Flavor
|
409
406
|
|
410
|
-
|
411
|
-
|
412
|
-
raise ImportError(
|
413
|
-
f"Couldn't import flavor {flavor_model.name}: {err}"
|
414
|
-
)
|
407
|
+
flavor_model = component_model.flavor
|
408
|
+
flavor = Flavor.from_model(flavor_model)
|
415
409
|
|
416
410
|
configuration = flavor.config_class(**component_model.configuration)
|
417
411
|
|
@@ -109,9 +109,16 @@ def find_active_code_repository(
|
|
109
109
|
for model in depaginate(list_method=Client().list_code_repositories):
|
110
110
|
try:
|
111
111
|
repo = BaseCodeRepository.from_model(model)
|
112
|
-
except
|
112
|
+
except ImportError:
|
113
113
|
logger.debug(
|
114
|
-
"Failed to
|
114
|
+
"Failed to import code repository class.", exc_info=True
|
115
|
+
)
|
116
|
+
continue
|
117
|
+
except Exception as e:
|
118
|
+
logger.warning(
|
119
|
+
"Failed to instantiate or login to code repository `%s`: %s",
|
120
|
+
model.name,
|
121
|
+
e,
|
115
122
|
)
|
116
123
|
continue
|
117
124
|
|
zenml/utils/code_utils.py
CHANGED
@@ -249,16 +249,7 @@ def download_and_extract_code(code_path: str, extract_dir: str) -> None:
|
|
249
249
|
Args:
|
250
250
|
code_path: Path where the code is uploaded.
|
251
251
|
extract_dir: Directory where to code should be extracted to.
|
252
|
-
|
253
|
-
Raises:
|
254
|
-
RuntimeError: If the code is stored in an artifact store which is
|
255
|
-
not active.
|
256
252
|
"""
|
257
|
-
artifact_store = Client().active_stack.artifact_store
|
258
|
-
|
259
|
-
if not code_path.startswith(artifact_store.path):
|
260
|
-
raise RuntimeError("Code stored in different artifact store.")
|
261
|
-
|
262
253
|
download_path = os.path.basename(code_path)
|
263
254
|
fileio.copy(code_path, download_path)
|
264
255
|
|
@@ -266,17 +257,30 @@ def download_and_extract_code(code_path: str, extract_dir: str) -> None:
|
|
266
257
|
os.remove(download_path)
|
267
258
|
|
268
259
|
|
269
|
-
def download_code_from_artifact_store(
|
260
|
+
def download_code_from_artifact_store(
|
261
|
+
code_path: str, artifact_store: "BaseArtifactStore"
|
262
|
+
) -> None:
|
270
263
|
"""Download code from the artifact store.
|
271
264
|
|
272
265
|
Args:
|
273
266
|
code_path: Path where the code is stored.
|
267
|
+
artifact_store: The artifact store to use for the download.
|
268
|
+
|
269
|
+
Raises:
|
270
|
+
RuntimeError: If the code is stored in an artifact store which is
|
271
|
+
not active.
|
274
272
|
"""
|
275
273
|
logger.info("Downloading code from artifact store path `%s`.", code_path)
|
276
274
|
|
277
|
-
|
278
|
-
|
279
|
-
|
275
|
+
if not code_path.startswith(artifact_store.path):
|
276
|
+
raise RuntimeError(
|
277
|
+
"The code is not stored in the artifact store "
|
278
|
+
f"{artifact_store.name} that was passed to download it."
|
279
|
+
)
|
280
|
+
|
281
|
+
# Make sure we register the artifact store filesystem here so the
|
282
|
+
# fileio.copy call will pick up the right credentials
|
283
|
+
artifact_store._register()
|
280
284
|
|
281
285
|
extract_dir = os.path.abspath("code")
|
282
286
|
os.makedirs(extract_dir)
|
zenml/utils/dashboard_utils.py
CHANGED
@@ -13,6 +13,7 @@
|
|
13
13
|
# permissions and limitations under the License.
|
14
14
|
"""Utility class to help with interacting with the dashboard."""
|
15
15
|
|
16
|
+
import os
|
16
17
|
from typing import Optional
|
17
18
|
from uuid import UUID
|
18
19
|
|
@@ -156,9 +157,27 @@ def show_dashboard(url: str) -> None:
|
|
156
157
|
display(IFrame(src=url, width="100%", height=720))
|
157
158
|
|
158
159
|
elif environment in (EnvironmentType.NATIVE, EnvironmentType.WSL):
|
159
|
-
|
160
|
+
open_dashboard = True
|
161
|
+
|
162
|
+
if constants.ENV_AUTO_OPEN_DASHBOARD in os.environ:
|
163
|
+
logger.warning(
|
164
|
+
"The `%s` environment variable is deprecated, use the `%s` "
|
165
|
+
"environment variable instead.",
|
166
|
+
constants.ENV_AUTO_OPEN_DASHBOARD,
|
167
|
+
constants.ENV_ZENML_AUTO_OPEN_DASHBOARD,
|
168
|
+
)
|
169
|
+
|
170
|
+
if not constants.handle_bool_env_var(
|
160
171
|
constants.ENV_AUTO_OPEN_DASHBOARD, default=True
|
161
172
|
):
|
173
|
+
open_dashboard = False
|
174
|
+
|
175
|
+
if not constants.handle_bool_env_var(
|
176
|
+
constants.ENV_ZENML_AUTO_OPEN_DASHBOARD, default=True
|
177
|
+
):
|
178
|
+
open_dashboard = False
|
179
|
+
|
180
|
+
if open_dashboard:
|
162
181
|
try:
|
163
182
|
import webbrowser
|
164
183
|
|
@@ -169,14 +188,16 @@ def show_dashboard(url: str) -> None:
|
|
169
188
|
logger.info(
|
170
189
|
"Automatically opening the dashboard in your "
|
171
190
|
"browser. To disable this, set the env variable "
|
172
|
-
"
|
191
|
+
"`%s=false`.",
|
192
|
+
constants.ENV_ZENML_AUTO_OPEN_DASHBOARD,
|
173
193
|
)
|
174
194
|
except Exception as e:
|
175
195
|
logger.error(e)
|
176
196
|
else:
|
177
197
|
logger.info(
|
178
198
|
"To open the dashboard in a browser automatically, "
|
179
|
-
"set the env variable
|
199
|
+
"set the env variable `%s=true`.",
|
200
|
+
constants.ENV_ZENML_AUTO_OPEN_DASHBOARD,
|
180
201
|
)
|
181
202
|
|
182
203
|
else:
|
zenml/utils/deprecation_utils.py
CHANGED
@@ -132,14 +132,16 @@ def deprecate_pydantic_attributes(
|
|
132
132
|
if replacement_attribute is None:
|
133
133
|
_warn(
|
134
134
|
message=f"The attribute `{deprecated_attribute}` of class "
|
135
|
-
f"`{cls.__name__}` will be
|
135
|
+
f"`{cls.__name__}` is deprecated and will be removed in "
|
136
|
+
"the future.",
|
136
137
|
attribute=deprecated_attribute,
|
137
138
|
)
|
138
139
|
continue
|
139
140
|
|
140
141
|
_warn(
|
141
142
|
message=f"The attribute `{deprecated_attribute}` of class "
|
142
|
-
f"`{cls.__name__}` will be
|
143
|
+
f"`{cls.__name__}` is deprecated and will be removed in the "
|
144
|
+
"future. Use the "
|
143
145
|
f"attribute `{replacement_attribute}` instead.",
|
144
146
|
attribute=deprecated_attribute,
|
145
147
|
)
|
@@ -78,7 +78,6 @@ class PipelineDockerImageBuilder:
|
|
78
78
|
tag: str,
|
79
79
|
stack: "Stack",
|
80
80
|
include_files: bool,
|
81
|
-
download_files: bool,
|
82
81
|
entrypoint: Optional[str] = None,
|
83
82
|
extra_files: Optional[Dict[str, str]] = None,
|
84
83
|
code_repository: Optional["BaseCodeRepository"] = None,
|
@@ -93,7 +92,6 @@ class PipelineDockerImageBuilder:
|
|
93
92
|
tag: The tag to use for the image.
|
94
93
|
stack: The stack on which the pipeline will be deployed.
|
95
94
|
include_files: Whether to include files in the build context.
|
96
|
-
download_files: Whether to download files in the build context.
|
97
95
|
entrypoint: Entrypoint to use for the final image. If left empty,
|
98
96
|
no entrypoint will be included in the image.
|
99
97
|
extra_files: Extra files to add to the build context. Keys are the
|
@@ -165,7 +163,6 @@ class PipelineDockerImageBuilder:
|
|
165
163
|
docker_settings.apt_packages,
|
166
164
|
docker_settings.environment,
|
167
165
|
include_files,
|
168
|
-
download_files,
|
169
166
|
entrypoint,
|
170
167
|
extra_files,
|
171
168
|
]
|
@@ -590,7 +587,7 @@ class PipelineDockerImageBuilder:
|
|
590
587
|
f"ENV {ENV_ZENML_LOGGING_COLORS_DISABLED}={str(handle_bool_env_var(ENV_ZENML_LOGGING_COLORS_DISABLED, False))}"
|
591
588
|
)
|
592
589
|
for key, value in docker_settings.environment.items():
|
593
|
-
lines.append(f"ENV {key.upper()}={value}")
|
590
|
+
lines.append(f"ENV {key.upper()}='{value}'")
|
594
591
|
|
595
592
|
if apt_packages:
|
596
593
|
apt_packages = " ".join(f"'{p}'" for p in apt_packages)
|