zenml-nightly 0.58.0.dev20240529__py3-none-any.whl → 0.58.1.dev20240610__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.
- CONTRIBUTING.md +1 -1
- README.md +3 -3
- RELEASE_NOTES.md +37 -1
- zenml/VERSION +1 -1
- zenml/artifacts/utils.py +19 -3
- zenml/cli/__init__.py +28 -22
- zenml/cli/base.py +17 -6
- zenml/cli/pipeline.py +18 -3
- zenml/cli/server.py +1 -1
- zenml/cli/stack.py +1 -1
- zenml/client.py +24 -4
- zenml/config/docker_settings.py +3 -0
- zenml/config/global_config.py +1 -1
- zenml/config/secret_reference_mixin.py +1 -1
- zenml/environment.py +1 -1
- zenml/integrations/huggingface/materializers/huggingface_tokenizer_materializer.py +11 -12
- zenml/integrations/kaniko/flavors/kaniko_image_builder_flavor.py +2 -44
- zenml/integrations/kubernetes/flavors/kubernetes_orchestrator_flavor.py +4 -1
- zenml/integrations/kubernetes/orchestrators/kubernetes_orchestrator.py +4 -16
- zenml/integrations/kubernetes/orchestrators/kubernetes_orchestrator_entrypoint.py +2 -1
- zenml/integrations/kubernetes/orchestrators/manifest_utils.py +15 -15
- zenml/integrations/s3/flavors/s3_artifact_store_flavor.py +0 -38
- zenml/integrations/spark/flavors/spark_step_operator_flavor.py +1 -38
- zenml/materializers/base_materializer.py +3 -3
- zenml/materializers/cloudpickle_materializer.py +1 -1
- zenml/orchestrators/base_orchestrator.py +1 -1
- zenml/orchestrators/local_docker/local_docker_orchestrator.py +1 -37
- zenml/orchestrators/step_runner.py +2 -2
- zenml/stack/flavor.py +3 -1
- zenml/stack/stack.py +2 -2
- zenml/stack/stack_component.py +42 -2
- zenml/steps/base_step.py +1 -1
- zenml/steps/entrypoint_function_utils.py +2 -2
- zenml/steps/utils.py +1 -1
- zenml/utils/dashboard_utils.py +1 -1
- zenml/utils/pipeline_docker_image_builder.py +23 -3
- zenml/utils/source_utils.py +32 -7
- zenml/zen_server/auth.py +2 -2
- zenml/zen_server/dashboard/assets/{404-DIgYOHj5.js → 404-D5p6PIdn.js} +1 -1
- zenml/zen_server/dashboard/assets/{@radix-BrEjOMvl.js → @radix-C9DBgJhe.js} +9 -9
- zenml/zen_server/dashboard/assets/@react-router-DYovave8.js +29 -0
- zenml/zen_server/dashboard/assets/@reactflow-C26Olbza.css +1 -0
- zenml/zen_server/dashboard/assets/@reactflow-CegZ5GV3.js +17 -0
- zenml/zen_server/dashboard/assets/@tanstack-CEbkxrhX.js +30 -0
- zenml/zen_server/dashboard/assets/{AwarenessChannel-CqRB1HO9.js → AwarenessChannel-DDpU6zHx.js} +1 -1
- zenml/zen_server/dashboard/assets/{Cards-DuJ8uYGM.js → Cards-wfOUm_Ae.js} +1 -1
- zenml/zen_server/dashboard/assets/CodeSnippet-iinvcx17.js +9 -0
- zenml/zen_server/dashboard/assets/Commands-DGnWeAWF.js +1 -0
- zenml/zen_server/dashboard/assets/{CopyButton-BOFZCr5Z.js → CopyButton-eUfW9370.js} +2 -2
- zenml/zen_server/dashboard/assets/{CsvVizualization-D4QRvdDk.js → CsvVizualization-CoIkmrjr.js} +7 -7
- zenml/zen_server/dashboard/assets/{DisplayDate-BoCi3-Ng.js → DisplayDate-BdguISQF.js} +1 -1
- zenml/zen_server/dashboard/assets/{EmptyState-CPJglRv0.js → EmptyState-BkooiGtL.js} +1 -1
- zenml/zen_server/dashboard/assets/{Error-C9i5GdiH.js → Error-CDMUBgpN.js} +1 -1
- zenml/zen_server/dashboard/assets/{Helpbox-CnuWjxcc.js → Helpbox-BV73V0J6.js} +1 -1
- zenml/zen_server/dashboard/assets/Infobox-DG7zmtut.js +1 -0
- zenml/zen_server/dashboard/assets/{InlineAvatar-DE_1-SDN.js → InlineAvatar-BiKh3XC5.js} +1 -1
- zenml/zen_server/dashboard/assets/{MarkdownVisualization-CMOybYJS.js → MarkdownVisualization-DsB2QZiK.js} +1 -1
- zenml/zen_server/dashboard/assets/{PageHeader-D7r1Jb6H.js → PageHeader-D-u0obgg.js} +1 -1
- zenml/zen_server/dashboard/assets/{Pagination-0-Hv-4DJ.js → Pagination-ZYqHJ5gE.js} +1 -1
- zenml/zen_server/dashboard/assets/{PasswordChecker-C2ImqlTr.js → PasswordChecker-DSLBp7Vl.js} +1 -1
- zenml/zen_server/dashboard/assets/{SetPassword-074iDZCm.js → SetPassword-Dq6iUfpW.js} +1 -1
- zenml/zen_server/dashboard/assets/{SuccessStep-DEeKB0Wq.js → SuccessStep-BHhPYxz9.js} +1 -1
- zenml/zen_server/dashboard/assets/{UpdatePasswordSchemas-4be5el9x.js → UpdatePasswordSchemas-4FyPPBY9.js} +1 -1
- zenml/zen_server/dashboard/assets/{aws-BaCucHs5.js → aws-t0gKCj_R.js} +1 -1
- zenml/zen_server/dashboard/assets/{check-circle-GxOo3117.js → check-circle-BVvhm5dy.js} +1 -1
- zenml/zen_server/dashboard/assets/{chevron-down-tsuIW52H.js → chevron-down-zcvCWmyP.js} +1 -1
- zenml/zen_server/dashboard/assets/{chevron-right-double-Dfr12EKG.js → chevron-right-double-CJ50E9Gr.js} +1 -1
- zenml/zen_server/dashboard/assets/{cloud-only-lInATL8-.js → cloud-only-DsILLhXk.js} +1 -1
- zenml/zen_server/dashboard/assets/{copy-B8yRmO5i.js → copy-BRhQz3j-.js} +1 -1
- zenml/zen_server/dashboard/assets/{database-BiV4iNgr.js → database-CRRnyFWh.js} +1 -1
- zenml/zen_server/dashboard/assets/{docker-EYFTGVBw.js → docker-BAonhm6G.js} +1 -1
- zenml/zen_server/dashboard/assets/{file-text-Bp-4kjON.js → file-text-CbVERUON.js} +1 -1
- zenml/zen_server/dashboard/assets/{help-hEyYkC3q.js → help-B8rqCvqn.js} +1 -1
- zenml/zen_server/dashboard/assets/index-BhYPVFKa.js +55 -0
- zenml/zen_server/dashboard/assets/index-CRZ5qzG3.css +1 -0
- zenml/zen_server/dashboard/assets/index.esm-F7nqy9zY.js +1 -0
- zenml/zen_server/dashboard/assets/{login-mutation-BfEeVmSl.js → login-mutation-CDARn8rx.js} +1 -1
- zenml/zen_server/dashboard/assets/{not-found-an_3Z-Ep.js → not-found-D1_I0ubu.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-NlxFzoaz.js → page-7IP7WH5_.js} +1 -1
- zenml/zen_server/dashboard/assets/page-B5Y_HW80.js +1 -0
- zenml/zen_server/dashboard/assets/{page-Ba5l9-eg.js → page-BQT1Zxsp.js} +1 -1
- zenml/zen_server/dashboard/assets/page-BR7WTzLa.js +1 -0
- zenml/zen_server/dashboard/assets/page-BmuIfr11.js +1 -0
- zenml/zen_server/dashboard/assets/{page-C6Xn5o3F.js → page-Bwrw_wb_.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-GXA0bsIT.js → page-ByiUk9rA.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-68OLHx44.js → page-C9lMl0g8.js} +2 -2
- zenml/zen_server/dashboard/assets/{page-NTQrxRsu.js → page-CK0iF8U_.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-Cea5XeRB.js → page-CQTaUp7q.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-ZJ5Cy_-x.js → page-Ca8Zw2SO.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-B90yVxNb.js → page-CaDkuI7b.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-C1Jl09zF.js → page-DB_mi8or.js} +1 -1
- zenml/zen_server/dashboard/assets/page-DDY5j-6S.js +1 -0
- zenml/zen_server/dashboard/assets/page-DIz9_5Du.js +2 -0
- zenml/zen_server/dashboard/assets/page-DPrgvGj6.js +9 -0
- zenml/zen_server/dashboard/assets/{page-C0opS_t4.js → page-D_Vj_UH1.js} +1 -1
- zenml/zen_server/dashboard/assets/page-QPP3iIQH.js +1 -0
- zenml/zen_server/dashboard/assets/{page-Bjj9GHVF.js → page-bpP11sGS.js} +1 -1
- zenml/zen_server/dashboard/assets/page-xA0WcjLa.js +1 -0
- zenml/zen_server/dashboard/assets/{page-DVAcOIuw.js → page-zYQJvPVh.js} +1 -1
- zenml/zen_server/dashboard/assets/{play-circle-DsngbHkK.js → play-circle-DK5QMJyp.js} +1 -1
- zenml/zen_server/dashboard/assets/{terminal-Cb3ce-nr.js → terminal-B2ovgWuz.js} +1 -1
- zenml/zen_server/dashboard/assets/{update-server-settings-mutation-CdcOI8-c.js → update-server-settings-mutation-SaWcyAnk.js} +1 -1
- zenml/zen_server/dashboard/assets/{url-DLJUVIKc.js → url-ZKNs861m.js} +1 -1
- zenml/zen_server/dashboard/assets/zod-DrZvVLjd.js +1 -0
- zenml/zen_server/dashboard/index.html +8 -8
- zenml/zen_server/dashboard_legacy/asset-manifest.json +4 -4
- zenml/zen_server/dashboard_legacy/index.html +1 -1
- zenml/zen_server/dashboard_legacy/{precache-manifest.05e51e85bd64770b2708d408a88d7028.js → precache-manifest.8e59f98d08e9c4c7cb3ef9f0bab7093f.js} +4 -4
- zenml/zen_server/dashboard_legacy/service-worker.js +1 -1
- zenml/zen_server/dashboard_legacy/static/js/main.a238a4d2.chunk.js +2 -0
- zenml/zen_server/dashboard_legacy/static/js/main.a238a4d2.chunk.js.map +1 -0
- zenml/zen_server/deploy/helm/Chart.yaml +1 -1
- zenml/zen_server/deploy/helm/README.md +3 -3
- zenml/zen_server/deploy/helm/values.yaml +7 -7
- zenml/zen_server/jwt.py +11 -11
- zenml/zen_server/routers/auth_endpoints.py +17 -0
- zenml/zen_server/routers/steps_endpoints.py +11 -3
- zenml/zen_stores/migrations/versions/0.58.1_release.py +23 -0
- zenml/zen_stores/rest_zen_store.py +17 -1
- {zenml_nightly-0.58.0.dev20240529.dist-info → zenml_nightly-0.58.1.dev20240610.dist-info}/METADATA +4 -3
- {zenml_nightly-0.58.0.dev20240529.dist-info → zenml_nightly-0.58.1.dev20240610.dist-info}/RECORD +124 -123
- zenml/zen_server/dashboard/assets/@react-router-CCpyfPW-.js +0 -29
- zenml/zen_server/dashboard/assets/@reactflow-CF_wPv-n.js +0 -17
- zenml/zen_server/dashboard/assets/@reactflow-lOPj8ZwY.css +0 -1
- zenml/zen_server/dashboard/assets/@tanstack-GFKzItNf.js +0 -30
- zenml/zen_server/dashboard/assets/CodeSnippet-CBFcxTGW.js +0 -9
- zenml/zen_server/dashboard/assets/Commands-BQb0_PAa.js +0 -1
- zenml/zen_server/dashboard/assets/Infobox-DV6YqO5N.js +0 -1
- zenml/zen_server/dashboard/assets/index-D4zsM9tz.css +0 -1
- zenml/zen_server/dashboard/assets/index-DKgtNG83.js +0 -56
- zenml/zen_server/dashboard/assets/index.esm-DNxbrOmx.js +0 -1
- zenml/zen_server/dashboard/assets/page-0AGNIDYi.js +0 -1
- zenml/zen_server/dashboard/assets/page-6Gp_NCQL.js +0 -14
- zenml/zen_server/dashboard/assets/page-BiyORkbM.js +0 -1
- zenml/zen_server/dashboard/assets/page-BnrWbXYJ.js +0 -2
- zenml/zen_server/dashboard/assets/page-CUqLUGbU.js +0 -1
- zenml/zen_server/dashboard/assets/page-CWpGAjSi.js +0 -1
- zenml/zen_server/dashboard/assets/page-DFQa6C6e.js +0 -1
- zenml/zen_server/dashboard/assets/page-Dn87PjPv.js +0 -1
- zenml/zen_server/dashboard/assets/zod-DueGCdzx.js +0 -1
- zenml/zen_server/dashboard_legacy/static/js/main.41d438ec.chunk.js +0 -2
- zenml/zen_server/dashboard_legacy/static/js/main.41d438ec.chunk.js.map +0 -1
- {zenml_nightly-0.58.0.dev20240529.dist-info → zenml_nightly-0.58.1.dev20240610.dist-info}/LICENSE +0 -0
- {zenml_nightly-0.58.0.dev20240529.dist-info → zenml_nightly-0.58.1.dev20240610.dist-info}/WHEEL +0 -0
- {zenml_nightly-0.58.0.dev20240529.dist-info → zenml_nightly-0.58.1.dev20240610.dist-info}/entry_points.txt +0 -0
@@ -44,7 +44,9 @@ class KubernetesOrchestratorSettings(BaseSettings):
|
|
44
44
|
step_pod_service_account_name: Name of the service account to use for the
|
45
45
|
step pods. If not provided, the default service account will be used.
|
46
46
|
privileged: If the container should be run in privileged mode.
|
47
|
-
pod_settings: Pod settings to apply.
|
47
|
+
pod_settings: Pod settings to apply to pods executing the steps.
|
48
|
+
orchestrator_pod_settings: Pod settings to apply to the pod which is
|
49
|
+
launching the actual steps.
|
48
50
|
"""
|
49
51
|
|
50
52
|
synchronous: bool = True
|
@@ -53,6 +55,7 @@ class KubernetesOrchestratorSettings(BaseSettings):
|
|
53
55
|
step_pod_service_account_name: Optional[str] = None
|
54
56
|
privileged: bool = False
|
55
57
|
pod_settings: Optional[KubernetesPodSettings] = None
|
58
|
+
orchestrator_pod_settings: Optional[KubernetesPodSettings] = None
|
56
59
|
|
57
60
|
|
58
61
|
class KubernetesOrchestratorConfig( # type: ignore[misc] # https://github.com/pydantic/pydantic/issues/4173
|
@@ -391,20 +391,6 @@ class KubernetesOrchestrator(ContainerizedOrchestrator):
|
|
391
391
|
# Authorize pod to run Kubernetes commands inside the cluster.
|
392
392
|
service_account_name = self._get_service_account_name(settings)
|
393
393
|
|
394
|
-
if settings.pod_settings:
|
395
|
-
# Remove all settings that specify on which pod to run for the
|
396
|
-
# orchestrator pod. These settings should only be used
|
397
|
-
# for the pods executing the actual steps.
|
398
|
-
pod_settings = settings.pod_settings.copy(
|
399
|
-
update={
|
400
|
-
"resources": {},
|
401
|
-
"node_selectors": {},
|
402
|
-
"affinity": {},
|
403
|
-
"tolerations": [],
|
404
|
-
}
|
405
|
-
)
|
406
|
-
settings = settings.copy(update={"pod_settings": pod_settings})
|
407
|
-
|
408
394
|
# Schedule as CRON job if CRON schedule is given.
|
409
395
|
if deployment.schedule:
|
410
396
|
if not deployment.schedule.cron_expression:
|
@@ -423,7 +409,8 @@ class KubernetesOrchestrator(ContainerizedOrchestrator):
|
|
423
409
|
command=command,
|
424
410
|
args=args,
|
425
411
|
service_account_name=service_account_name,
|
426
|
-
|
412
|
+
privileged=False,
|
413
|
+
pod_settings=settings.orchestrator_pod_settings,
|
427
414
|
env=environment,
|
428
415
|
mount_local_stores=self.config.is_local,
|
429
416
|
)
|
@@ -446,8 +433,9 @@ class KubernetesOrchestrator(ContainerizedOrchestrator):
|
|
446
433
|
image_name=image,
|
447
434
|
command=command,
|
448
435
|
args=args,
|
436
|
+
privileged=False,
|
437
|
+
pod_settings=settings.orchestrator_pod_settings,
|
449
438
|
service_account_name=service_account_name,
|
450
|
-
settings=settings,
|
451
439
|
env=environment,
|
452
440
|
mount_local_stores=self.config.is_local,
|
453
441
|
)
|
@@ -116,7 +116,8 @@ def main() -> None:
|
|
116
116
|
command=step_command,
|
117
117
|
args=step_args,
|
118
118
|
env=env,
|
119
|
-
|
119
|
+
privileged=settings.privileged,
|
120
|
+
pod_settings=settings.pod_settings,
|
120
121
|
service_account_name=settings.step_pod_service_account_name
|
121
122
|
or settings.service_account_name,
|
122
123
|
mount_local_stores=mount_local_stores,
|
@@ -25,9 +25,6 @@ from zenml.constants import ENV_ZENML_ENABLE_REPO_INIT_WARNINGS
|
|
25
25
|
from zenml.integrations.airflow.orchestrators.dag_generator import (
|
26
26
|
ENV_ZENML_LOCAL_STORES_PATH,
|
27
27
|
)
|
28
|
-
from zenml.integrations.kubernetes.flavors import (
|
29
|
-
KubernetesOrchestratorSettings,
|
30
|
-
)
|
31
28
|
from zenml.integrations.kubernetes.pod_settings import KubernetesPodSettings
|
32
29
|
|
33
30
|
|
@@ -100,7 +97,8 @@ def build_pod_manifest(
|
|
100
97
|
image_name: str,
|
101
98
|
command: List[str],
|
102
99
|
args: List[str],
|
103
|
-
|
100
|
+
privileged: bool,
|
101
|
+
pod_settings: Optional[KubernetesPodSettings] = None,
|
104
102
|
service_account_name: Optional[str] = None,
|
105
103
|
env: Optional[Dict[str, str]] = None,
|
106
104
|
mount_local_stores: bool = False,
|
@@ -114,7 +112,8 @@ def build_pod_manifest(
|
|
114
112
|
image_name: Name of the Docker image.
|
115
113
|
command: Command to execute the entrypoint in the pod.
|
116
114
|
args: Arguments provided to the entrypoint command.
|
117
|
-
|
115
|
+
privileged: Whether to run the container in privileged mode.
|
116
|
+
pod_settings: Optional settings for the pod.
|
118
117
|
service_account_name: Optional name of a service account.
|
119
118
|
Can be used to assign certain roles to a pod, e.g., to allow it to
|
120
119
|
run Kubernetes commands from within the cluster.
|
@@ -128,9 +127,7 @@ def build_pod_manifest(
|
|
128
127
|
env = env.copy() if env else {}
|
129
128
|
env.setdefault(ENV_ZENML_ENABLE_REPO_INIT_WARNINGS, "False")
|
130
129
|
|
131
|
-
security_context = k8s_client.V1SecurityContext(
|
132
|
-
privileged=settings.privileged
|
133
|
-
)
|
130
|
+
security_context = k8s_client.V1SecurityContext(privileged=privileged)
|
134
131
|
container_spec = k8s_client.V1Container(
|
135
132
|
name="main",
|
136
133
|
image=image_name,
|
@@ -151,8 +148,8 @@ def build_pod_manifest(
|
|
151
148
|
if service_account_name is not None:
|
152
149
|
pod_spec.service_account_name = service_account_name
|
153
150
|
|
154
|
-
if
|
155
|
-
add_pod_settings(pod_spec,
|
151
|
+
if pod_settings:
|
152
|
+
add_pod_settings(pod_spec, pod_settings)
|
156
153
|
|
157
154
|
pod_metadata = k8s_client.V1ObjectMeta(
|
158
155
|
name=pod_name,
|
@@ -162,8 +159,8 @@ def build_pod_manifest(
|
|
162
159
|
},
|
163
160
|
)
|
164
161
|
|
165
|
-
if
|
166
|
-
pod_metadata.annotations =
|
162
|
+
if pod_settings and pod_settings.annotations:
|
163
|
+
pod_metadata.annotations = pod_settings.annotations
|
167
164
|
|
168
165
|
pod_manifest = k8s_client.V1Pod(
|
169
166
|
kind="Pod",
|
@@ -224,7 +221,8 @@ def build_cron_job_manifest(
|
|
224
221
|
image_name: str,
|
225
222
|
command: List[str],
|
226
223
|
args: List[str],
|
227
|
-
|
224
|
+
privileged: bool,
|
225
|
+
pod_settings: Optional[KubernetesPodSettings] = None,
|
228
226
|
service_account_name: Optional[str] = None,
|
229
227
|
env: Optional[Dict[str, str]] = None,
|
230
228
|
mount_local_stores: bool = False,
|
@@ -239,7 +237,8 @@ def build_cron_job_manifest(
|
|
239
237
|
image_name: Name of the Docker image.
|
240
238
|
command: Command to execute the entrypoint in the pod.
|
241
239
|
args: Arguments provided to the entrypoint command.
|
242
|
-
|
240
|
+
privileged: Whether to run the container in privileged mode.
|
241
|
+
pod_settings: Optional settings for the pod.
|
243
242
|
service_account_name: Optional name of a service account.
|
244
243
|
Can be used to assign certain roles to a pod, e.g., to allow it to
|
245
244
|
run Kubernetes commands from within the cluster.
|
@@ -257,7 +256,8 @@ def build_cron_job_manifest(
|
|
257
256
|
image_name=image_name,
|
258
257
|
command=command,
|
259
258
|
args=args,
|
260
|
-
|
259
|
+
privileged=privileged,
|
260
|
+
pod_settings=pod_settings,
|
261
261
|
service_account_name=service_account_name,
|
262
262
|
env=env,
|
263
263
|
mount_local_stores=mount_local_stores,
|
@@ -13,7 +13,6 @@
|
|
13
13
|
# permissions and limitations under the License.
|
14
14
|
"""Amazon S3 artifact store flavor."""
|
15
15
|
|
16
|
-
import json
|
17
16
|
import re
|
18
17
|
from typing import (
|
19
18
|
TYPE_CHECKING,
|
@@ -23,7 +22,6 @@ from typing import (
|
|
23
22
|
Optional,
|
24
23
|
Set,
|
25
24
|
Type,
|
26
|
-
Union,
|
27
25
|
)
|
28
26
|
|
29
27
|
from pydantic import validator
|
@@ -72,42 +70,6 @@ class S3ArtifactStoreConfig(
|
|
72
70
|
config_kwargs: Optional[Dict[str, Any]] = None
|
73
71
|
s3_additional_kwargs: Optional[Dict[str, Any]] = None
|
74
72
|
|
75
|
-
@validator(
|
76
|
-
"client_kwargs", "config_kwargs", "s3_additional_kwargs", pre=True
|
77
|
-
)
|
78
|
-
def _convert_json_string(
|
79
|
-
cls, value: Union[None, str, Dict[str, Any]]
|
80
|
-
) -> Optional[Dict[str, Any]]:
|
81
|
-
"""Converts potential JSON strings passed via the CLI to dictionaries.
|
82
|
-
|
83
|
-
Args:
|
84
|
-
value: The value to convert.
|
85
|
-
|
86
|
-
Returns:
|
87
|
-
The converted value.
|
88
|
-
|
89
|
-
Raises:
|
90
|
-
TypeError: If the value is not a `str`, `Dict` or `None`.
|
91
|
-
ValueError: If the value is an invalid json string or a json string
|
92
|
-
that does not decode into a dictionary.
|
93
|
-
"""
|
94
|
-
if isinstance(value, str):
|
95
|
-
try:
|
96
|
-
dict_ = json.loads(value)
|
97
|
-
except json.JSONDecodeError as e:
|
98
|
-
raise ValueError(f"Invalid json string '{value}'") from e
|
99
|
-
|
100
|
-
if not isinstance(dict_, Dict):
|
101
|
-
raise ValueError(
|
102
|
-
f"Json string '{value}' did not decode into a dictionary."
|
103
|
-
)
|
104
|
-
|
105
|
-
return dict_
|
106
|
-
elif isinstance(value, Dict) or value is None:
|
107
|
-
return value
|
108
|
-
else:
|
109
|
-
raise TypeError(f"{value} is not a json string or a dictionary.")
|
110
|
-
|
111
73
|
@validator("client_kwargs")
|
112
74
|
def _validate_client_kwargs(
|
113
75
|
cls, value: Optional[Dict[str, Any]]
|
@@ -13,10 +13,7 @@
|
|
13
13
|
# permissions and limitations under the License.
|
14
14
|
"""Spark step operator flavor."""
|
15
15
|
|
16
|
-
import
|
17
|
-
from typing import TYPE_CHECKING, Any, Dict, Optional, Type, Union
|
18
|
-
|
19
|
-
from pydantic import validator
|
16
|
+
from typing import TYPE_CHECKING, Any, Dict, Optional, Type
|
20
17
|
|
21
18
|
from zenml.config.base_settings import BaseSettings
|
22
19
|
from zenml.step_operators.base_step_operator import (
|
@@ -45,40 +42,6 @@ class SparkStepOperatorSettings(BaseSettings):
|
|
45
42
|
deploy_mode: str = "cluster"
|
46
43
|
submit_kwargs: Optional[Dict[str, Any]] = None
|
47
44
|
|
48
|
-
@validator("submit_kwargs", pre=True)
|
49
|
-
def _convert_json_string(
|
50
|
-
cls, value: Union[None, str, Dict[str, Any]]
|
51
|
-
) -> Optional[Dict[str, Any]]:
|
52
|
-
"""Converts potential JSON strings passed via the CLI to dictionaries.
|
53
|
-
|
54
|
-
Args:
|
55
|
-
value: The value to convert.
|
56
|
-
|
57
|
-
Returns:
|
58
|
-
The converted value.
|
59
|
-
|
60
|
-
Raises:
|
61
|
-
TypeError: If the value is not a `str`, `Dict` or `None`.
|
62
|
-
ValueError: If the value is an invalid json string or a json string
|
63
|
-
that does not decode into a dictionary.
|
64
|
-
"""
|
65
|
-
if isinstance(value, str):
|
66
|
-
try:
|
67
|
-
dict_ = json.loads(value)
|
68
|
-
except json.JSONDecodeError as e:
|
69
|
-
raise ValueError(f"Invalid json string '{value}'") from e
|
70
|
-
|
71
|
-
if not isinstance(dict_, Dict):
|
72
|
-
raise ValueError(
|
73
|
-
f"Json string '{value}' did not decode into a dictionary."
|
74
|
-
)
|
75
|
-
|
76
|
-
return dict_
|
77
|
-
elif isinstance(value, Dict) or value is None:
|
78
|
-
return value
|
79
|
-
else:
|
80
|
-
raise TypeError(f"{value} is not a json string or a dictionary.")
|
81
|
-
|
82
45
|
|
83
46
|
class SparkStepOperatorConfig( # type: ignore[misc] # https://github.com/pydantic/pydantic/issues/4173
|
84
47
|
BaseStepOperatorConfig, SparkStepOperatorSettings
|
@@ -65,7 +65,7 @@ class BaseMaterializerMeta(type):
|
|
65
65
|
f"Invalid materializer class '{name}'. When creating a "
|
66
66
|
f"custom materializer, make sure to specify at least one "
|
67
67
|
f"type in its ASSOCIATED_TYPES class variable.",
|
68
|
-
url="https://docs.zenml.io/
|
68
|
+
url="https://docs.zenml.io/how-to/handle-data-artifacts/handle-custom-data-types",
|
69
69
|
)
|
70
70
|
|
71
71
|
# Validate associated artifact type.
|
@@ -80,7 +80,7 @@ class BaseMaterializerMeta(type):
|
|
80
80
|
f"custom materializer, make sure to specify a valid "
|
81
81
|
f"artifact type in its ASSOCIATED_ARTIFACT_TYPE class "
|
82
82
|
f"variable.",
|
83
|
-
url="https://docs.zenml.io/
|
83
|
+
url="https://docs.zenml.io/how-to/handle-data-artifacts/handle-custom-data-types",
|
84
84
|
)
|
85
85
|
|
86
86
|
# Validate associated data types.
|
@@ -89,7 +89,7 @@ class BaseMaterializerMeta(type):
|
|
89
89
|
raise MaterializerInterfaceError(
|
90
90
|
f"Associated type {associated_type} for materializer "
|
91
91
|
f"{name} is not a class.",
|
92
|
-
url="https://docs.zenml.io/
|
92
|
+
url="https://docs.zenml.io/how-to/handle-data-artifacts/handle-custom-data-types",
|
93
93
|
)
|
94
94
|
|
95
95
|
# Register the materializer.
|
@@ -102,7 +102,7 @@ class CloudpickleMaterializer(BaseMaterializer):
|
|
102
102
|
"the artifacts cannot be loaded when running with a different "
|
103
103
|
"Python version. Please consider implementing a custom "
|
104
104
|
f"materializer for type `{type(data)}` according to the "
|
105
|
-
"instructions at https://docs.zenml.io/
|
105
|
+
"instructions at https://docs.zenml.io/how-to/handle-data-artifacts/handle-custom-data-types"
|
106
106
|
)
|
107
107
|
|
108
108
|
# save python version for validation on loading
|
@@ -51,7 +51,7 @@ class BaseOrchestratorConfig(StackComponentConfig):
|
|
51
51
|
"The 'custom_docker_base_image_name' field has been "
|
52
52
|
"deprecated. To use a custom base container image with your "
|
53
53
|
"orchestrators, please use the DockerSettings in your "
|
54
|
-
"pipeline (see https://docs.zenml.io/
|
54
|
+
"pipeline (see https://docs.zenml.io/how-to/customize-docker-builds)."
|
55
55
|
)
|
56
56
|
|
57
57
|
return values
|
@@ -14,15 +14,13 @@
|
|
14
14
|
"""Implementation of the ZenML local Docker orchestrator."""
|
15
15
|
|
16
16
|
import copy
|
17
|
-
import json
|
18
17
|
import os
|
19
18
|
import sys
|
20
19
|
import time
|
21
|
-
from typing import TYPE_CHECKING, Any, Dict, Optional, Type,
|
20
|
+
from typing import TYPE_CHECKING, Any, Dict, Optional, Type, cast
|
22
21
|
from uuid import uuid4
|
23
22
|
|
24
23
|
from docker.errors import ContainerError
|
25
|
-
from pydantic import validator
|
26
24
|
|
27
25
|
from zenml.config.base_settings import BaseSettings
|
28
26
|
from zenml.config.global_config import GlobalConfiguration
|
@@ -207,40 +205,6 @@ class LocalDockerOrchestratorSettings(BaseSettings):
|
|
207
205
|
|
208
206
|
run_args: Dict[str, Any] = {}
|
209
207
|
|
210
|
-
@validator("run_args", pre=True)
|
211
|
-
def _convert_json_string(
|
212
|
-
cls, value: Union[None, str, Dict[str, Any]]
|
213
|
-
) -> Optional[Dict[str, Any]]:
|
214
|
-
"""Converts potential JSON strings passed via the CLI to dictionaries.
|
215
|
-
|
216
|
-
Args:
|
217
|
-
value: The value to convert.
|
218
|
-
|
219
|
-
Returns:
|
220
|
-
The converted value.
|
221
|
-
|
222
|
-
Raises:
|
223
|
-
TypeError: If the value is not a `str`, `Dict` or `None`.
|
224
|
-
ValueError: If the value is an invalid json string or a json string
|
225
|
-
that does not decode into a dictionary.
|
226
|
-
"""
|
227
|
-
if isinstance(value, str):
|
228
|
-
try:
|
229
|
-
dict_ = json.loads(value)
|
230
|
-
except json.JSONDecodeError as e:
|
231
|
-
raise ValueError(f"Invalid json string '{value}'") from e
|
232
|
-
|
233
|
-
if not isinstance(dict_, Dict):
|
234
|
-
raise ValueError(
|
235
|
-
f"Json string '{value}' did not decode into a dictionary."
|
236
|
-
)
|
237
|
-
|
238
|
-
return dict_
|
239
|
-
elif isinstance(value, Dict) or value is None:
|
240
|
-
return value
|
241
|
-
else:
|
242
|
-
raise TypeError(f"{value} is not a json string or a dictionary.")
|
243
|
-
|
244
208
|
|
245
209
|
class LocalDockerOrchestratorConfig( # type: ignore[misc] # https://github.com/pydantic/pydantic/issues/4173
|
246
210
|
BaseOrchestratorConfig, LocalDockerOrchestratorSettings
|
@@ -348,7 +348,7 @@ class StepRunner:
|
|
348
348
|
"is deprecated and will be removed in a future release. "
|
349
349
|
f"Please adjust your '{step_name}' step to instead import "
|
350
350
|
"the `StepContext` inside your step, as shown here: "
|
351
|
-
"https://docs.zenml.io/
|
351
|
+
"https://docs.zenml.io/how-to/track-metrics-metadata/fetch-metadata-within-steps"
|
352
352
|
)
|
353
353
|
function_params[arg] = get_step_context()
|
354
354
|
elif arg in input_artifacts:
|
@@ -409,7 +409,7 @@ class StepRunner:
|
|
409
409
|
"is deprecated and will be removed in a future release. "
|
410
410
|
f"Please adjust your '{step_name}' hook to instead import "
|
411
411
|
"the `StepContext` inside your hook, as shown here: "
|
412
|
-
"https://docs.zenml.io/
|
412
|
+
"https://docs.zenml.io/how-to/track-metrics-metadata/fetch-metadata-within-steps"
|
413
413
|
)
|
414
414
|
function_params[arg] = get_step_context()
|
415
415
|
|
zenml/stack/flavor.py
CHANGED
@@ -206,7 +206,9 @@ class Flavor:
|
|
206
206
|
name = self.name.replace("_", "-")
|
207
207
|
docs_component_name = component_name or name
|
208
208
|
base = f"https://docs.zenml.io/v/{__version__}"
|
209
|
-
return
|
209
|
+
return (
|
210
|
+
f"{base}/stack-components/{component_type}/{docs_component_name}"
|
211
|
+
)
|
210
212
|
|
211
213
|
def generate_default_sdk_docs_url(self) -> str:
|
212
214
|
"""Generate SDK docs url for a flavor.
|
zenml/stack/stack.py
CHANGED
@@ -801,7 +801,7 @@ class Stack:
|
|
801
801
|
f"Additionally, we are also providing a variety of "
|
802
802
|
f" deployment recipes for popular Kubernetes-based "
|
803
803
|
f"integrations such as Kubeflow, Tekton, and Seldon etc."
|
804
|
-
f"Check out https://docs.zenml.io/
|
804
|
+
f"Check out https://docs.zenml.io/how-to/stack-deployment/deploy-a-stack-using-mlstacks"
|
805
805
|
f"for more information."
|
806
806
|
)
|
807
807
|
|
@@ -811,7 +811,7 @@ class Stack:
|
|
811
811
|
"and step operators require a remote "
|
812
812
|
"ZenML server. To run a pipeline with this stack you need to "
|
813
813
|
"connect to a remote ZenML server first. Check out "
|
814
|
-
"https://docs.zenml.io/
|
814
|
+
"https://docs.zenml.io/getting-started/deploying-zenml "
|
815
815
|
"for more information on how to deploy ZenML."
|
816
816
|
)
|
817
817
|
|
zenml/stack/stack_component.py
CHANGED
@@ -13,12 +13,16 @@
|
|
13
13
|
# permissions and limitations under the License.
|
14
14
|
"""Implementation of the ZenML Stack Component class."""
|
15
15
|
|
16
|
+
import json
|
16
17
|
from abc import ABC
|
18
|
+
from collections.abc import Mapping, Sequence
|
17
19
|
from datetime import datetime
|
20
|
+
from inspect import isclass
|
18
21
|
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Set, Type, Union
|
19
22
|
from uuid import UUID
|
20
23
|
|
21
|
-
from pydantic import BaseModel, Extra
|
24
|
+
from pydantic import BaseModel, Extra, root_validator
|
25
|
+
from pydantic.typing import get_origin
|
22
26
|
|
23
27
|
from zenml.config.build_configuration import BuildConfiguration
|
24
28
|
from zenml.config.step_configurations import Step
|
@@ -93,7 +97,7 @@ class StackComponentConfig(BaseModel, ABC):
|
|
93
97
|
"in sensitive information as secrets. Check out the "
|
94
98
|
"documentation on how to configure your stack "
|
95
99
|
"components with secrets here: "
|
96
|
-
"https://docs.zenml.io/
|
100
|
+
"https://docs.zenml.io/getting-started/deploying-zenml/manage-the-deployed-services/secret-management"
|
97
101
|
)
|
98
102
|
continue
|
99
103
|
|
@@ -242,6 +246,42 @@ class StackComponentConfig(BaseModel, ABC):
|
|
242
246
|
# (see https://github.com/python/mypy/issues/13319).
|
243
247
|
__getattribute__ = __custom_getattribute__
|
244
248
|
|
249
|
+
@root_validator(pre=True)
|
250
|
+
def _convert_json_strings(cls, values: Dict[str, Any]) -> Any:
|
251
|
+
"""Converts potential JSON strings.
|
252
|
+
|
253
|
+
Args:
|
254
|
+
values: The model values.
|
255
|
+
|
256
|
+
Returns:
|
257
|
+
The potentially converted values.
|
258
|
+
|
259
|
+
Raises:
|
260
|
+
ValueError: If any of the values is an invalid JSON string.
|
261
|
+
"""
|
262
|
+
for key, field in cls.__fields__.items():
|
263
|
+
value = values.get(key, None)
|
264
|
+
|
265
|
+
if isinstance(value, str):
|
266
|
+
if get_origin(field.outer_type_) in {
|
267
|
+
dict,
|
268
|
+
list,
|
269
|
+
Mapping,
|
270
|
+
Sequence,
|
271
|
+
}:
|
272
|
+
try:
|
273
|
+
values[key] = json.loads(value)
|
274
|
+
except json.JSONDecodeError as e:
|
275
|
+
raise ValueError(
|
276
|
+
f"Invalid json string '{value}'"
|
277
|
+
) from e
|
278
|
+
elif isclass(field.type_) and issubclass(
|
279
|
+
field.type_, BaseModel
|
280
|
+
):
|
281
|
+
values[key] = field.type_.parse_raw(value).dict()
|
282
|
+
|
283
|
+
return values
|
284
|
+
|
245
285
|
class Config:
|
246
286
|
"""Pydantic configuration class."""
|
247
287
|
|
zenml/steps/base_step.py
CHANGED
@@ -1233,7 +1233,7 @@ To avoid this consider setting step parameters only in one place (config or code
|
|
1233
1233
|
logger.warning(
|
1234
1234
|
"The `BaseParameters` class to define step parameters is "
|
1235
1235
|
"deprecated. Check out our docs "
|
1236
|
-
"https://docs.zenml.io/
|
1236
|
+
"https://docs.zenml.io/how-to/use-configuration-files/how-to-use-config "
|
1237
1237
|
"for information on how to parameterize your steps. As a quick "
|
1238
1238
|
"fix to get rid of this warning, make sure your parameter class "
|
1239
1239
|
"inherits from `pydantic.BaseModel` instead of the "
|
@@ -115,7 +115,7 @@ class StepArtifact:
|
|
115
115
|
"you're trying to unpack the return value of your step but the "
|
116
116
|
"step only returns a single artifact. For more information on how "
|
117
117
|
"to add type annotations to your step to indicate multiple "
|
118
|
-
"artifacts visit https://docs.zenml.io/
|
118
|
+
"artifacts visit https://docs.zenml.io/how-to/build-pipelines/step-output-typing-and-annotation#type-annotations."
|
119
119
|
)
|
120
120
|
|
121
121
|
|
@@ -214,7 +214,7 @@ class EntrypointFunctionDefinition(NamedTuple):
|
|
214
214
|
f"'{key}' is not JSON serializable and can not be passed as "
|
215
215
|
"a parameter. This input can either be provided by the "
|
216
216
|
"output of another step or as an external artifact: "
|
217
|
-
"https://docs.zenml.io/user-guide/
|
217
|
+
"https://docs.zenml.io/user-guide/starter-guide/manage-artifacts#managing-artifacts-not-produced-by-zenml-pipelines"
|
218
218
|
)
|
219
219
|
|
220
220
|
try:
|
zenml/steps/utils.py
CHANGED
@@ -110,7 +110,7 @@ def parse_return_type_annotations(
|
|
110
110
|
"Using the `Output` class to define the outputs of your steps is "
|
111
111
|
"deprecated. You should instead use the standard Python way of "
|
112
112
|
"type annotating your functions. Check out our documentation "
|
113
|
-
"https://docs.zenml.io/
|
113
|
+
"https://docs.zenml.io/how-to/build-pipelines/step-output-typing-and-annotation "
|
114
114
|
"for more information on how to assign custom names to your step "
|
115
115
|
"outputs."
|
116
116
|
)
|
zenml/utils/dashboard_utils.py
CHANGED
@@ -20,6 +20,7 @@ import sys
|
|
20
20
|
from collections import defaultdict
|
21
21
|
from typing import (
|
22
22
|
TYPE_CHECKING,
|
23
|
+
Any,
|
23
24
|
DefaultDict,
|
24
25
|
Dict,
|
25
26
|
List,
|
@@ -65,6 +66,15 @@ DEFAULT_DOCKER_PARENT_IMAGE = (
|
|
65
66
|
f"py{sys.version_info.major}.{sys.version_info.minor}"
|
66
67
|
)
|
67
68
|
|
69
|
+
PIP_DEFAULT_ARGS = {
|
70
|
+
"no-cache-dir": None,
|
71
|
+
"default-timeout": 60,
|
72
|
+
}
|
73
|
+
UV_DEFAULT_ARGS = {
|
74
|
+
"no-cache-dir": None,
|
75
|
+
"system": None,
|
76
|
+
}
|
77
|
+
|
68
78
|
|
69
79
|
class PipelineDockerImageBuilder:
|
70
80
|
"""Builds Docker images to run a ZenML pipeline."""
|
@@ -636,22 +646,32 @@ class PipelineDockerImageBuilder:
|
|
636
646
|
docker_settings.python_package_installer
|
637
647
|
== PythonPackageInstaller.PIP
|
638
648
|
):
|
639
|
-
install_command = "pip install
|
649
|
+
install_command = "pip install"
|
650
|
+
default_installer_args: Dict[str, Any] = PIP_DEFAULT_ARGS
|
640
651
|
elif (
|
641
652
|
docker_settings.python_package_installer
|
642
653
|
== PythonPackageInstaller.UV
|
643
654
|
):
|
644
655
|
lines.append("RUN pip install uv")
|
645
|
-
install_command = "uv pip install
|
656
|
+
install_command = "uv pip install"
|
657
|
+
default_installer_args = UV_DEFAULT_ARGS
|
646
658
|
else:
|
647
659
|
raise ValueError("Unsupported python package installer.")
|
648
660
|
|
661
|
+
installer_args = {
|
662
|
+
**default_installer_args,
|
663
|
+
**docker_settings.python_package_installer_args,
|
664
|
+
}
|
665
|
+
installer_args_string = " ".join(
|
666
|
+
f"--{key}" if value is None else f"--{key}={value}"
|
667
|
+
for key, value in installer_args.items()
|
668
|
+
)
|
649
669
|
for file, _, options in requirements_files:
|
650
670
|
lines.append(f"COPY {file} .")
|
651
671
|
option_string = " ".join(options)
|
652
672
|
|
653
673
|
lines.append(
|
654
|
-
f"RUN {install_command}
|
674
|
+
f"RUN {install_command} {installer_args_string}"
|
655
675
|
f"{option_string} -r {file}"
|
656
676
|
)
|
657
677
|
|