zenml-nightly 0.58.2.dev20240623__py3-none-any.whl → 0.61.0.dev20240712__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.
- README.md +30 -9
- RELEASE_NOTES.md +240 -0
- zenml/VERSION +1 -1
- zenml/actions/base_action.py +177 -174
- zenml/actions/pipeline_run/pipeline_run_action.py +28 -23
- zenml/analytics/enums.py +3 -0
- zenml/artifact_stores/base_artifact_store.py +7 -1
- zenml/artifacts/utils.py +13 -10
- zenml/cli/__init__.py +28 -0
- zenml/cli/artifact.py +1 -2
- zenml/cli/integration.py +9 -8
- zenml/cli/server.py +6 -0
- zenml/cli/service_connectors.py +1 -0
- zenml/cli/stack.py +946 -39
- zenml/cli/stack_components.py +7 -0
- zenml/cli/text_utils.py +35 -1
- zenml/cli/utils.py +127 -10
- zenml/client.py +257 -72
- zenml/config/compiler.py +10 -9
- zenml/config/docker_settings.py +33 -14
- zenml/constants.py +11 -2
- zenml/container_registries/base_container_registry.py +1 -0
- zenml/enums.py +7 -0
- zenml/event_hub/base_event_hub.py +5 -5
- zenml/event_hub/event_hub.py +20 -14
- zenml/event_sources/base_event.py +0 -11
- zenml/event_sources/base_event_source.py +7 -0
- zenml/event_sources/webhooks/base_webhook_event_source.py +1 -4
- zenml/exceptions.py +4 -0
- zenml/hooks/hook_validators.py +2 -3
- zenml/integrations/aws/__init__.py +1 -0
- zenml/integrations/azure/__init__.py +1 -0
- zenml/integrations/bitbucket/plugins/event_sources/bitbucket_webhook_event_source.py +3 -3
- zenml/integrations/deepchecks/__init__.py +1 -0
- zenml/integrations/discord/__init__.py +1 -0
- zenml/integrations/evidently/__init__.py +1 -0
- zenml/integrations/facets/__init__.py +1 -0
- zenml/integrations/feast/__init__.py +1 -0
- zenml/integrations/gcp/__init__.py +3 -1
- zenml/integrations/gcp/google_credentials_mixin.py +1 -1
- zenml/integrations/gcp/service_connectors/gcp_service_connector.py +320 -64
- zenml/integrations/huggingface/__init__.py +1 -0
- zenml/integrations/integration.py +24 -0
- zenml/integrations/kubeflow/__init__.py +3 -0
- zenml/integrations/kubeflow/flavors/kubeflow_orchestrator_flavor.py +1 -1
- zenml/integrations/kubeflow/orchestrators/kubeflow_orchestrator.py +0 -1
- zenml/integrations/kubernetes/__init__.py +3 -1
- zenml/integrations/kubernetes/orchestrators/kube_utils.py +4 -1
- zenml/integrations/label_studio/annotators/label_studio_annotator.py +1 -0
- zenml/integrations/langchain/__init__.py +1 -0
- zenml/integrations/mlflow/__init__.py +4 -2
- zenml/integrations/neural_prophet/__init__.py +1 -0
- zenml/integrations/polars/__init__.py +1 -0
- zenml/integrations/prodigy/__init__.py +1 -0
- zenml/integrations/pycaret/__init__.py +6 -0
- zenml/integrations/registry.py +37 -0
- zenml/integrations/s3/artifact_stores/s3_artifact_store.py +93 -9
- zenml/integrations/seldon/__init__.py +1 -0
- zenml/integrations/seldon/model_deployers/seldon_model_deployer.py +1 -0
- zenml/integrations/skypilot/flavors/skypilot_orchestrator_base_vm_config.py +2 -2
- zenml/integrations/skypilot/orchestrators/skypilot_base_vm_orchestrator.py +1 -1
- zenml/integrations/skypilot/orchestrators/skypilot_orchestrator_entrypoint.py +2 -2
- zenml/integrations/skypilot_aws/__init__.py +2 -1
- zenml/integrations/skypilot_azure/__init__.py +1 -1
- zenml/integrations/skypilot_gcp/__init__.py +1 -1
- zenml/integrations/skypilot_lambda/__init__.py +1 -1
- zenml/integrations/skypilot_lambda/flavors/skypilot_orchestrator_lambda_vm_flavor.py +1 -1
- zenml/integrations/slack/__init__.py +1 -0
- zenml/integrations/tekton/__init__.py +1 -0
- zenml/integrations/tensorboard/__init__.py +0 -1
- zenml/integrations/tensorflow/__init__.py +18 -6
- zenml/integrations/wandb/__init__.py +1 -0
- zenml/logging/step_logging.py +54 -51
- zenml/models/__init__.py +28 -0
- zenml/models/v2/core/action.py +276 -0
- zenml/models/v2/core/component.py +18 -0
- zenml/models/v2/core/model.py +1 -2
- zenml/models/v2/core/service_connector.py +17 -0
- zenml/models/v2/core/stack.py +31 -0
- zenml/models/v2/core/trigger.py +182 -141
- zenml/models/v2/misc/full_stack.py +97 -0
- zenml/models/v2/misc/stack_deployment.py +86 -0
- zenml/new/pipelines/pipeline.py +14 -4
- zenml/new/pipelines/pipeline_decorator.py +1 -2
- zenml/new/pipelines/run_utils.py +1 -12
- zenml/new/steps/step_decorator.py +2 -3
- zenml/orchestrators/input_utils.py +3 -6
- zenml/pipelines/base_pipeline.py +0 -2
- zenml/pipelines/pipeline_decorator.py +1 -2
- zenml/stack/stack.py +3 -6
- zenml/stack/stack_component.py +4 -0
- zenml/stack_deployments/__init__.py +14 -0
- zenml/stack_deployments/aws_stack_deployment.py +254 -0
- zenml/stack_deployments/gcp_stack_deployment.py +260 -0
- zenml/stack_deployments/stack_deployment.py +208 -0
- zenml/stack_deployments/utils.py +44 -0
- zenml/steps/base_step.py +1 -2
- zenml/steps/step_decorator.py +1 -2
- zenml/types.py +10 -1
- zenml/utils/function_utils.py +1 -1
- zenml/utils/pagination_utils.py +7 -5
- zenml/utils/pipeline_docker_image_builder.py +117 -73
- zenml/utils/pydantic_utils.py +6 -5
- zenml/zen_server/cloud_utils.py +18 -3
- zenml/zen_server/dashboard/assets/{404-CDPQCl4D.js → 404-DpJaNHKF.js} +1 -1
- zenml/zen_server/dashboard/assets/@radix-CFOkMR_E.js +85 -0
- zenml/zen_server/dashboard/assets/{@react-router-DYovave8.js → @react-router-CO-OsFwI.js} +2 -2
- zenml/zen_server/dashboard/assets/{@reactflow-CHBapDaj.js → @reactflow-DJfzkHO1.js} +2 -2
- zenml/zen_server/dashboard/assets/@tanstack-DYiOyJUL.js +22 -0
- zenml/zen_server/dashboard/assets/AwarenessChannel-BYDLT2xC.js +1 -0
- zenml/zen_server/dashboard/assets/{CodeSnippet-BidtnWOi.js → CodeSnippet-BkOuRmyq.js} +2 -2
- zenml/zen_server/dashboard/assets/Commands-ZvWR1BRs.js +1 -0
- zenml/zen_server/dashboard/assets/CopyButton-DVwLkafa.js +2 -0
- zenml/zen_server/dashboard/assets/{CsvVizualization-BOuez-fG.js → CsvVizualization-C2IiqX4I.js} +7 -7
- zenml/zen_server/dashboard/assets/DisplayDate-DYgIjlDF.js +1 -0
- zenml/zen_server/dashboard/assets/EmptyState-BMLnFVlB.js +1 -0
- zenml/zen_server/dashboard/assets/Error-CqX0VqW_.js +1 -0
- zenml/zen_server/dashboard/assets/ExecutionStatus-BoLUXR9t.js +1 -0
- zenml/zen_server/dashboard/assets/Helpbox-LFydyVwh.js +1 -0
- zenml/zen_server/dashboard/assets/Infobox-DnENC0sh.js +1 -0
- zenml/zen_server/dashboard/assets/InlineAvatar-CbJtYr0t.js +1 -0
- zenml/zen_server/dashboard/assets/{MarkdownVisualization-DsB2QZiK.js → MarkdownVisualization-xp3hhULl.js} +2 -2
- zenml/zen_server/dashboard/assets/Pagination-DEbVUupy.js +1 -0
- zenml/zen_server/dashboard/assets/PasswordChecker-DUveqlva.js +1 -0
- zenml/zen_server/dashboard/assets/SetPassword-BYBdbQDo.js +1 -0
- zenml/zen_server/dashboard/assets/SuccessStep-Nx743hll.js +1 -0
- zenml/zen_server/dashboard/assets/{UpdatePasswordSchemas-DnM-c11H.js → UpdatePasswordSchemas-DF9gSzE0.js} +1 -1
- zenml/zen_server/dashboard/assets/{aws-t0gKCj_R.js → aws-BgKTfTfx.js} +1 -1
- zenml/zen_server/dashboard/assets/{check-circle-BVvhm5dy.js → check-circle-i56092KI.js} +1 -1
- zenml/zen_server/dashboard/assets/{chevron-down-zcvCWmyP.js → chevron-down-D_ZlKMqH.js} +1 -1
- zenml/zen_server/dashboard/assets/{chevron-right-double-CJ50E9Gr.js → chevron-right-double-BiEMg7rd.js} +1 -1
- zenml/zen_server/dashboard/assets/cloud-only-DVbIeckv.js +1 -0
- zenml/zen_server/dashboard/assets/{copy-BRhQz3j-.js → copy-BXNk6BjL.js} +1 -1
- zenml/zen_server/dashboard/assets/{database-CRRnyFWh.js → database-1xWSgZfO.js} +1 -1
- zenml/zen_server/dashboard/assets/{docker-BAonhm6G.js → docker-CQMVm_4d.js} +1 -1
- zenml/zen_server/dashboard/assets/{file-text-CbVERUON.js → file-text-CqD_iu6l.js} +1 -1
- zenml/zen_server/dashboard/assets/{help-B8rqCvqn.js → help-bu_DgLKI.js} +1 -1
- zenml/zen_server/dashboard/assets/index-C_CrU4vI.js +1 -0
- zenml/zen_server/dashboard/assets/index-DK1ynKjA.js +55 -0
- zenml/zen_server/dashboard/assets/index-inApY3KQ.css +1 -0
- zenml/zen_server/dashboard/assets/index-rK_Wuy2W.js +1 -0
- zenml/zen_server/dashboard/assets/index.esm-Corw4lXQ.js +1 -0
- zenml/zen_server/dashboard/assets/{login-mutation-wzzl23C6.js → login-mutation-BUnVASxp.js} +1 -1
- zenml/zen_server/dashboard/assets/not-found-B4VnX8gK.js +1 -0
- zenml/zen_server/dashboard/assets/package-CsUhPmou.js +1 -0
- zenml/zen_server/dashboard/assets/{page-BmkSiYeQ.js → page-3efNCDeb.js} +2 -2
- zenml/zen_server/dashboard/assets/page-7zTHbhhI.js +1 -0
- zenml/zen_server/dashboard/assets/page-BEs6jK71.js +1 -0
- zenml/zen_server/dashboard/assets/page-BpSqIf4B.js +1 -0
- zenml/zen_server/dashboard/assets/{page-AQKopn_4.js → page-Bx6o0ARS.js} +1 -1
- zenml/zen_server/dashboard/assets/page-C43QGHTt.js +9 -0
- zenml/zen_server/dashboard/assets/page-CR0OG7ss.js +1 -0
- zenml/zen_server/dashboard/assets/page-CRTJ0UuR.js +1 -0
- zenml/zen_server/dashboard/assets/page-CUZIGO-3.js +1 -0
- zenml/zen_server/dashboard/assets/page-CaopxiU1.js +1 -0
- zenml/zen_server/dashboard/assets/{page-CuT1SUik.js → page-Cx67M0QT.js} +1 -1
- zenml/zen_server/dashboard/assets/page-D7Z399xy.js +1 -0
- zenml/zen_server/dashboard/assets/page-D93kd7Xj.js +1 -0
- zenml/zen_server/dashboard/assets/{page-BzVZGExK.js → page-DKlIdAe5.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-Bi5AI0S7.js → page-DMOYZppS.js} +1 -1
- zenml/zen_server/dashboard/assets/page-DMsSn3dv.js +2 -0
- zenml/zen_server/dashboard/assets/{page-BW6Ket3a.js → page-Dc_7KMQE.js} +1 -1
- zenml/zen_server/dashboard/assets/page-DvCvroOM.js +1 -0
- zenml/zen_server/dashboard/assets/page-Hus2pr9T.js +1 -0
- zenml/zen_server/dashboard/assets/page-JyfeDUfu.js +1 -0
- zenml/zen_server/dashboard/assets/{page-yN4rZ-ZS.js → page-Sxn82W-5.js} +1 -1
- zenml/zen_server/dashboard/assets/page-TKXERe16.js +1 -0
- zenml/zen_server/dashboard/assets/page-Xu8JEjSU.js +1 -0
- zenml/zen_server/dashboard/assets/{play-circle-DK5QMJyp.js → play-circle-CNtZKDnW.js} +1 -1
- zenml/zen_server/dashboard/assets/plus-DOeLmm7C.js +1 -0
- zenml/zen_server/dashboard/assets/{terminal-B2ovgWuz.js → terminal-By9cErXc.js} +1 -1
- zenml/zen_server/dashboard/assets/{update-server-settings-mutation-0Wgz8pUE.js → update-server-settings-mutation-CR8e3Sir.js} +1 -1
- zenml/zen_server/dashboard/assets/{url-6_xv0WJS.js → url-DuQMeqYA.js} +1 -1
- zenml/zen_server/dashboard/assets/{zod-DrZvVLjd.js → zod-BhoGpZ63.js} +1 -1
- zenml/zen_server/dashboard/index.html +7 -7
- 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.f4abc5b7cfa7d90c1caf5521918e29a8.js → precache-manifest.c8c57fb0d2132b1d3c2119e776b7dfb3.js} +4 -4
- zenml/zen_server/dashboard_legacy/service-worker.js +1 -1
- zenml/zen_server/dashboard_legacy/static/js/{main.ac2f17d0.chunk.js → main.382439a7.chunk.js} +2 -2
- zenml/zen_server/dashboard_legacy/static/js/{main.ac2f17d0.chunk.js.map → main.382439a7.chunk.js.map} +1 -1
- zenml/zen_server/deploy/helm/Chart.yaml +1 -1
- zenml/zen_server/deploy/helm/README.md +2 -2
- zenml/zen_server/feature_gate/zenml_cloud_feature_gate.py +11 -5
- zenml/zen_server/pipeline_deployment/utils.py +57 -44
- zenml/zen_server/rbac/models.py +1 -0
- zenml/zen_server/rbac/utils.py +22 -1
- zenml/zen_server/rbac/zenml_cloud_rbac.py +11 -5
- zenml/zen_server/routers/actions_endpoints.py +324 -0
- zenml/zen_server/routers/stack_deployment_endpoints.py +158 -0
- zenml/zen_server/routers/triggers_endpoints.py +30 -158
- zenml/zen_server/routers/workspaces_endpoints.py +64 -0
- zenml/zen_server/zen_server_api.py +4 -0
- zenml/zen_stores/migrations/utils.py +1 -1
- zenml/zen_stores/migrations/versions/0.60.0_release.py +23 -0
- zenml/zen_stores/migrations/versions/0.61.0_release.py +23 -0
- zenml/zen_stores/migrations/versions/0d707865f404_adding_labels_to_stacks.py +30 -0
- zenml/zen_stores/migrations/versions/25155145c545_separate_actions_and_triggers.py +228 -0
- zenml/zen_stores/rest_zen_store.py +248 -8
- zenml/zen_stores/schemas/__init__.py +2 -0
- zenml/zen_stores/schemas/action_schemas.py +192 -0
- zenml/zen_stores/schemas/stack_schemas.py +10 -0
- zenml/zen_stores/schemas/step_run_schemas.py +27 -11
- zenml/zen_stores/schemas/trigger_schemas.py +43 -50
- zenml/zen_stores/schemas/user_schemas.py +10 -2
- zenml/zen_stores/schemas/workspace_schemas.py +5 -0
- zenml/zen_stores/sql_zen_store.py +540 -36
- zenml/zen_stores/zen_store_interface.py +165 -0
- {zenml_nightly-0.58.2.dev20240623.dist-info → zenml_nightly-0.61.0.dev20240712.dist-info}/METADATA +33 -11
- {zenml_nightly-0.58.2.dev20240623.dist-info → zenml_nightly-0.61.0.dev20240712.dist-info}/RECORD +213 -193
- zenml/zen_server/dashboard/assets/@radix-C9DBgJhe.js +0 -77
- zenml/zen_server/dashboard/assets/@tanstack-CEbkxrhX.js +0 -30
- zenml/zen_server/dashboard/assets/AwarenessChannel-nXGpmj_f.js +0 -1
- zenml/zen_server/dashboard/assets/Cards-nwsvQLVS.js +0 -1
- zenml/zen_server/dashboard/assets/Commands-DuIWKg_Q.js +0 -1
- zenml/zen_server/dashboard/assets/CopyButton-B_YSm-Ds.js +0 -2
- zenml/zen_server/dashboard/assets/DisplayDate-BdguISQF.js +0 -1
- zenml/zen_server/dashboard/assets/EmptyState-BkooiGtL.js +0 -1
- zenml/zen_server/dashboard/assets/Error-B6M0dPph.js +0 -1
- zenml/zen_server/dashboard/assets/Helpbox-BQoqCm04.js +0 -1
- zenml/zen_server/dashboard/assets/Infobox-Ce9mefqU.js +0 -1
- zenml/zen_server/dashboard/assets/InlineAvatar-DGf3dVhV.js +0 -1
- zenml/zen_server/dashboard/assets/PageHeader-DGaemzjc.js +0 -1
- zenml/zen_server/dashboard/assets/Pagination-DVYfBCCc.js +0 -1
- zenml/zen_server/dashboard/assets/PasswordChecker-DSLBp7Vl.js +0 -1
- zenml/zen_server/dashboard/assets/SetPassword-B5s7DJug.js +0 -1
- zenml/zen_server/dashboard/assets/SuccessStep-ZzczaM7g.js +0 -1
- zenml/zen_server/dashboard/assets/cloud-only-Ba_ShBR5.js +0 -1
- zenml/zen_server/dashboard/assets/index-CWJ3xbIf.css +0 -1
- zenml/zen_server/dashboard/assets/index-QORVVTMN.js +0 -55
- zenml/zen_server/dashboard/assets/index.esm-F7nqy9zY.js +0 -1
- zenml/zen_server/dashboard/assets/not-found-Dh2la7kh.js +0 -1
- zenml/zen_server/dashboard/assets/page-B-5jAKoO.js +0 -1
- zenml/zen_server/dashboard/assets/page-B-vWk8a6.js +0 -1
- zenml/zen_server/dashboard/assets/page-B0BrqfS8.js +0 -1
- zenml/zen_server/dashboard/assets/page-BQxVFlUl.js +0 -1
- zenml/zen_server/dashboard/assets/page-ByrHy6Ss.js +0 -1
- zenml/zen_server/dashboard/assets/page-CPtY4Kv_.js +0 -1
- zenml/zen_server/dashboard/assets/page-CmmukLsl.js +0 -1
- zenml/zen_server/dashboard/assets/page-D2D-7qyr.js +0 -9
- zenml/zen_server/dashboard/assets/page-DAQQyLxT.js +0 -1
- zenml/zen_server/dashboard/assets/page-DHkUMl_E.js +0 -1
- zenml/zen_server/dashboard/assets/page-DZCbwOEs.js +0 -2
- zenml/zen_server/dashboard/assets/page-DdaIt20-.js +0 -1
- zenml/zen_server/dashboard/assets/page-LqLs24Ot.js +0 -1
- zenml/zen_server/dashboard/assets/page-lebv0c7C.js +0 -1
- {zenml_nightly-0.58.2.dev20240623.dist-info → zenml_nightly-0.61.0.dev20240712.dist-info}/LICENSE +0 -0
- {zenml_nightly-0.58.2.dev20240623.dist-info → zenml_nightly-0.61.0.dev20240712.dist-info}/WHEEL +0 -0
- {zenml_nightly-0.58.2.dev20240623.dist-info → zenml_nightly-0.61.0.dev20240712.dist-info}/entry_points.txt +0 -0
@@ -31,6 +31,9 @@ class KubeflowIntegration(Integration):
|
|
31
31
|
|
32
32
|
NAME = KUBEFLOW
|
33
33
|
REQUIREMENTS = ["kfp>=2.6.0", "kfp-kubernetes>=1.1.0"] # Only 1.x version that supports pyyaml 6
|
34
|
+
REQUIREMENTS_IGNORED_ON_UNINSTALL = [
|
35
|
+
"kfp", # it is used by GCP as well
|
36
|
+
]
|
34
37
|
|
35
38
|
@classmethod
|
36
39
|
def flavors(cls) -> List[Type[Flavor]]:
|
@@ -149,7 +149,7 @@ class KubeflowOrchestratorConfig(
|
|
149
149
|
|
150
150
|
kubeflow_hostname: Optional[str] = None
|
151
151
|
kubeflow_namespace: str = "kubeflow"
|
152
|
-
kubernetes_context: Optional[str] # TODO: Potential setting
|
152
|
+
kubernetes_context: Optional[str] = None # TODO: Potential setting
|
153
153
|
|
154
154
|
@model_validator(mode="before")
|
155
155
|
@classmethod
|
@@ -31,7 +31,9 @@ class KubernetesIntegration(Integration):
|
|
31
31
|
|
32
32
|
NAME = KUBERNETES
|
33
33
|
REQUIREMENTS = ["kubernetes>=21.7,<26"]
|
34
|
-
|
34
|
+
REQUIREMENTS_IGNORED_ON_UNINSTALL = [
|
35
|
+
"kfp", # it is used by many others
|
36
|
+
]
|
35
37
|
@classmethod
|
36
38
|
def flavors(cls) -> List[Type[Flavor]]:
|
37
39
|
"""Declare the stack component flavors for the Kubernetes integration.
|
@@ -225,8 +225,11 @@ def wait_pod(
|
|
225
225
|
response = core_api.read_namespaced_pod_log(
|
226
226
|
name=pod_name,
|
227
227
|
namespace=namespace,
|
228
|
+
_preload_content=False,
|
228
229
|
)
|
229
|
-
|
230
|
+
raw_data = response.data
|
231
|
+
decoded_log = raw_data.decode("utf-8", errors="replace")
|
232
|
+
logs = decoded_log.splitlines()
|
230
233
|
if len(logs) > logged_lines:
|
231
234
|
for line in logs[logged_lines:]:
|
232
235
|
logger.info(line)
|
@@ -33,7 +33,7 @@ class MlflowIntegration(Integration):
|
|
33
33
|
NAME = MLFLOW
|
34
34
|
|
35
35
|
REQUIREMENTS = [
|
36
|
-
"mlflow>=2.1.1,<=2.
|
36
|
+
"mlflow>=2.1.1,<=2.14.1",
|
37
37
|
"mlserver>=1.3.3",
|
38
38
|
"mlserver-mlflow>=1.3.3",
|
39
39
|
# TODO: remove this requirement once rapidjson is fixed
|
@@ -45,9 +45,11 @@ class MlflowIntegration(Integration):
|
|
45
45
|
# This downgrades pydantic to v1 even though mlflow does not have
|
46
46
|
# any issues with v2. This is why we have to pin it here so a downgrade
|
47
47
|
# will not happen.
|
48
|
-
"pydantic>=2.7.0,<2.8.0"
|
48
|
+
"pydantic>=2.7.0,<2.8.0",
|
49
49
|
]
|
50
50
|
|
51
|
+
REQUIREMENTS_IGNORED_ON_UNINSTALL = ["python-rapidjson", "pydantic"]
|
52
|
+
|
51
53
|
@classmethod
|
52
54
|
def activate(cls) -> None:
|
53
55
|
"""Activate the MLflow integration."""
|
zenml/integrations/registry.py
CHANGED
@@ -124,6 +124,43 @@ class IntegrationRegistry(object):
|
|
124
124
|
)
|
125
125
|
]
|
126
126
|
|
127
|
+
def select_uninstall_requirements(
|
128
|
+
self,
|
129
|
+
integration_name: Optional[str] = None,
|
130
|
+
target_os: Optional[str] = None,
|
131
|
+
) -> List[str]:
|
132
|
+
"""Select the uninstall requirements for a given integration or all integrations.
|
133
|
+
|
134
|
+
Args:
|
135
|
+
integration_name: Name of the integration to check.
|
136
|
+
target_os: Target OS for the requirements.
|
137
|
+
|
138
|
+
Returns:
|
139
|
+
List of requirements for the integration uninstall.
|
140
|
+
|
141
|
+
Raises:
|
142
|
+
KeyError: If the integration is not found.
|
143
|
+
"""
|
144
|
+
if integration_name:
|
145
|
+
if integration_name in self.list_integration_names:
|
146
|
+
return self._integrations[
|
147
|
+
integration_name
|
148
|
+
].get_uninstall_requirements(target_os=target_os)
|
149
|
+
else:
|
150
|
+
raise KeyError(
|
151
|
+
f"Version {integration_name} does not exist. "
|
152
|
+
f"Currently the following integrations are implemented. "
|
153
|
+
f"{self.list_integration_names}"
|
154
|
+
)
|
155
|
+
else:
|
156
|
+
return [
|
157
|
+
requirement
|
158
|
+
for name in self.list_integration_names
|
159
|
+
for requirement in self._integrations[
|
160
|
+
name
|
161
|
+
].get_uninstall_requirements(target_os=target_os)
|
162
|
+
]
|
163
|
+
|
127
164
|
def is_installed(self, integration_name: Optional[str] = None) -> bool:
|
128
165
|
"""Checks if all requirements for an integration are installed.
|
129
166
|
|
@@ -26,6 +26,7 @@ from typing import (
|
|
26
26
|
)
|
27
27
|
|
28
28
|
import s3fs
|
29
|
+
from fsspec.asyn import FSTimeoutError, sync, sync_wrapper
|
29
30
|
|
30
31
|
from zenml.artifact_stores import BaseArtifactStore
|
31
32
|
from zenml.integrations.s3.flavors.s3_artifact_store_flavor import (
|
@@ -38,10 +39,77 @@ from zenml.stack.authentication_mixin import AuthenticationMixin
|
|
38
39
|
PathType = Union[bytes, str]
|
39
40
|
|
40
41
|
|
42
|
+
class ZenMLS3Filesystem(s3fs.S3FileSystem): # type: ignore[misc]
|
43
|
+
"""Modified s3fs.S3FileSystem to disable caching.
|
44
|
+
|
45
|
+
The original s3fs.S3FileSystem caches all class instances based on the
|
46
|
+
constructor input arguments and it never releases them. This is problematic
|
47
|
+
in the context of the ZenML server, because the server is a long-running
|
48
|
+
process that instantiates many S3 filesystems with different credentials,
|
49
|
+
especially when the credentials are generated by service connectors.
|
50
|
+
|
51
|
+
The caching behavior of s3fs causes the server to slowly consume more and
|
52
|
+
more memory over time until it crashes. This class disables the caching
|
53
|
+
behavior of s3fs by setting the `cachable` attribute to `False`.
|
54
|
+
|
55
|
+
In addition to disabling instance caching, this class also provides a
|
56
|
+
correct cleanup implementation by overriding the `close_session` method
|
57
|
+
the S3 aiobotocore client. The original one provided by s3fs was causing
|
58
|
+
memory leaks by creating a new event loop in the destructor instead of
|
59
|
+
using the existing one.
|
60
|
+
|
61
|
+
A `close` method is also provided to allow for synchronous on-demand cleanup
|
62
|
+
of the S3 client.
|
63
|
+
"""
|
64
|
+
|
65
|
+
cachable = False
|
66
|
+
|
67
|
+
async def _close(self) -> None:
|
68
|
+
"""Close the S3 client."""
|
69
|
+
if self._s3creator is not None: # type: ignore[has-type]
|
70
|
+
await self._s3creator.__aexit__(None, None, None) # type: ignore[has-type]
|
71
|
+
self._s3creator = None
|
72
|
+
self._s3 = None
|
73
|
+
|
74
|
+
close = sync_wrapper(_close)
|
75
|
+
|
76
|
+
@staticmethod
|
77
|
+
def close_session(loop: Any, s3: Any) -> None:
|
78
|
+
"""Close the S3 client session.
|
79
|
+
|
80
|
+
Args:
|
81
|
+
loop: The event loop to use for closing the session.
|
82
|
+
s3: The S3 client to close.
|
83
|
+
"""
|
84
|
+
# IMPORTANT: This method is a copy of the original close_session method
|
85
|
+
# from s3fs.S3FileSystem. The only difference is that it uses the
|
86
|
+
# provided event loop instead of creating a new one.
|
87
|
+
if loop is not None and loop.is_running():
|
88
|
+
try:
|
89
|
+
# NOTE: this is the line in the original method that causes
|
90
|
+
# the memory leak
|
91
|
+
# loop = asyncio.get_event_loop()
|
92
|
+
loop.create_task(s3.__aexit__(None, None, None))
|
93
|
+
return
|
94
|
+
except RuntimeError:
|
95
|
+
pass
|
96
|
+
try:
|
97
|
+
sync(loop, s3.__aexit__, None, None, None, timeout=0.1)
|
98
|
+
return
|
99
|
+
except FSTimeoutError:
|
100
|
+
pass
|
101
|
+
try:
|
102
|
+
# close the actual socket
|
103
|
+
s3._client._endpoint.http_session._connector._close()
|
104
|
+
except AttributeError:
|
105
|
+
# but during shutdown, it may have gone
|
106
|
+
pass
|
107
|
+
|
108
|
+
|
41
109
|
class S3ArtifactStore(BaseArtifactStore, AuthenticationMixin):
|
42
110
|
"""Artifact Store for S3 based artifacts."""
|
43
111
|
|
44
|
-
_filesystem: Optional[
|
112
|
+
_filesystem: Optional[ZenMLS3Filesystem] = None
|
45
113
|
|
46
114
|
@property
|
47
115
|
def config(self) -> S3ArtifactStoreConfig:
|
@@ -54,7 +122,7 @@ class S3ArtifactStore(BaseArtifactStore, AuthenticationMixin):
|
|
54
122
|
|
55
123
|
def get_credentials(
|
56
124
|
self,
|
57
|
-
) -> Tuple[Optional[str], Optional[str], Optional[str]]:
|
125
|
+
) -> Tuple[Optional[str], Optional[str], Optional[str], Optional[str]]:
|
58
126
|
"""Gets authentication credentials.
|
59
127
|
|
60
128
|
If an authentication secret is configured, the secret values are
|
@@ -62,8 +130,8 @@ class S3ArtifactStore(BaseArtifactStore, AuthenticationMixin):
|
|
62
130
|
attributes.
|
63
131
|
|
64
132
|
Returns:
|
65
|
-
Tuple (key, secret, token) of credentials used to
|
66
|
-
the S3 filesystem.
|
133
|
+
Tuple (key, secret, token, region) of credentials used to
|
134
|
+
authenticate with the S3 filesystem.
|
67
135
|
|
68
136
|
Raises:
|
69
137
|
RuntimeError: If the AWS connector behaves unexpectedly.
|
@@ -83,6 +151,7 @@ class S3ArtifactStore(BaseArtifactStore, AuthenticationMixin):
|
|
83
151
|
credentials.access_key,
|
84
152
|
credentials.secret_key,
|
85
153
|
credentials.token,
|
154
|
+
client.meta.region_name,
|
86
155
|
)
|
87
156
|
|
88
157
|
secret = self.get_typed_authentication_secret(
|
@@ -93,12 +162,13 @@ class S3ArtifactStore(BaseArtifactStore, AuthenticationMixin):
|
|
93
162
|
secret.aws_access_key_id,
|
94
163
|
secret.aws_secret_access_key,
|
95
164
|
secret.aws_session_token,
|
165
|
+
None,
|
96
166
|
)
|
97
167
|
else:
|
98
|
-
return self.config.key, self.config.secret, self.config.token
|
168
|
+
return self.config.key, self.config.secret, self.config.token, None
|
99
169
|
|
100
170
|
@property
|
101
|
-
def filesystem(self) ->
|
171
|
+
def filesystem(self) -> ZenMLS3Filesystem:
|
102
172
|
"""The s3 filesystem to access this artifact store.
|
103
173
|
|
104
174
|
Returns:
|
@@ -108,18 +178,32 @@ class S3ArtifactStore(BaseArtifactStore, AuthenticationMixin):
|
|
108
178
|
if self._filesystem and not self.connector_has_expired():
|
109
179
|
return self._filesystem
|
110
180
|
|
111
|
-
key, secret, token = self.get_credentials()
|
181
|
+
key, secret, token, region = self.get_credentials()
|
182
|
+
|
183
|
+
# Use the region from the connector if available, otherwise some
|
184
|
+
# remote workloads (e.g. Sagemaker) might not work correctly because
|
185
|
+
# they look for the bucket in the wrong region
|
186
|
+
client_kwargs = {}
|
187
|
+
if region:
|
188
|
+
client_kwargs["region_name"] = region
|
189
|
+
if self.config.client_kwargs:
|
190
|
+
client_kwargs.update(self.config.client_kwargs)
|
112
191
|
|
113
|
-
self._filesystem =
|
192
|
+
self._filesystem = ZenMLS3Filesystem(
|
114
193
|
key=key,
|
115
194
|
secret=secret,
|
116
195
|
token=token,
|
117
|
-
client_kwargs=
|
196
|
+
client_kwargs=client_kwargs,
|
118
197
|
config_kwargs=self.config.config_kwargs,
|
119
198
|
s3_additional_kwargs=self.config.s3_additional_kwargs,
|
120
199
|
)
|
121
200
|
return self._filesystem
|
122
201
|
|
202
|
+
def cleanup(self) -> None:
|
203
|
+
"""Close the filesystem."""
|
204
|
+
if self._filesystem:
|
205
|
+
self._filesystem.close()
|
206
|
+
|
123
207
|
def open(self, path: PathType, mode: str = "r") -> Any:
|
124
208
|
"""Open a file at the given path.
|
125
209
|
|
@@ -43,7 +43,7 @@ class SkypilotBaseOrchestratorSettings(BaseSettings):
|
|
43
43
|
`{'tpu_vm': True, 'runtime_version': 'tpu-vm-base'}` for TPUs.
|
44
44
|
use_spot: whether to use spot instances. If None, defaults to
|
45
45
|
False.
|
46
|
-
|
46
|
+
job_recovery: the spot recovery strategy to use for the managed
|
47
47
|
spot to recover the cluster from preemption. Refer to
|
48
48
|
`recovery_strategy module <https://github.com/skypilot-org/skypilot/blob/master/sky/spot/recovery_strategy.py>`__ # pylint: disable=line-too-long
|
49
49
|
for more details.
|
@@ -103,7 +103,7 @@ class SkypilotBaseOrchestratorSettings(BaseSettings):
|
|
103
103
|
)
|
104
104
|
accelerator_args: Optional[Dict[str, str]] = None
|
105
105
|
use_spot: Optional[bool] = None
|
106
|
-
|
106
|
+
job_recovery: Optional[str] = None
|
107
107
|
region: Optional[str] = None
|
108
108
|
zone: Optional[str] = None
|
109
109
|
image_id: Union[Dict[str, str], str, None] = Field(
|
@@ -303,7 +303,7 @@ class SkypilotBaseOrchestrator(ContainerizedOrchestrator):
|
|
303
303
|
accelerators=settings.accelerators,
|
304
304
|
accelerator_args=settings.accelerator_args,
|
305
305
|
use_spot=settings.use_spot,
|
306
|
-
|
306
|
+
job_recovery=settings.job_recovery,
|
307
307
|
region=settings.region,
|
308
308
|
zone=settings.zone,
|
309
309
|
image_id=settings.image_id,
|
@@ -136,7 +136,7 @@ def main() -> None:
|
|
136
136
|
settings.disk_size, # Assuming disk_size is part of the settings
|
137
137
|
settings.disk_tier, # Assuming disk_tier is part of the settings
|
138
138
|
settings.use_spot,
|
139
|
-
settings.
|
139
|
+
settings.job_recovery,
|
140
140
|
settings.region,
|
141
141
|
settings.zone,
|
142
142
|
accelerators_hashable,
|
@@ -213,7 +213,7 @@ def main() -> None:
|
|
213
213
|
accelerators=settings.accelerators,
|
214
214
|
accelerator_args=settings.accelerator_args,
|
215
215
|
use_spot=settings.use_spot,
|
216
|
-
|
216
|
+
job_recovery=settings.job_recovery,
|
217
217
|
region=settings.region,
|
218
218
|
zone=settings.zone,
|
219
219
|
image_id=settings.image_id,
|
@@ -31,7 +31,8 @@ class SkypilotAWSIntegration(Integration):
|
|
31
31
|
"""Definition of Skypilot AWS Integration for ZenML."""
|
32
32
|
|
33
33
|
NAME = SKYPILOT_AWS
|
34
|
-
|
34
|
+
# all 0.6.x versions of skypilot[aws] are compatible
|
35
|
+
REQUIREMENTS = ["skypilot[aws]~=0.6.0"]
|
35
36
|
APT_PACKAGES = ["openssh-client", "rsync"]
|
36
37
|
|
37
38
|
@classmethod
|
@@ -33,7 +33,7 @@ class SkypilotAzureIntegration(Integration):
|
|
33
33
|
"""Definition of Skypilot (Azure) Integration for ZenML."""
|
34
34
|
|
35
35
|
NAME = SKYPILOT_AZURE
|
36
|
-
REQUIREMENTS = ["skypilot[azure]
|
36
|
+
REQUIREMENTS = ["skypilot[azure]~=0.6.0"]
|
37
37
|
APT_PACKAGES = ["openssh-client", "rsync"]
|
38
38
|
|
39
39
|
@classmethod
|
@@ -31,7 +31,7 @@ class SkypilotGCPIntegration(Integration):
|
|
31
31
|
"""Definition of Skypilot (GCP) Integration for ZenML."""
|
32
32
|
|
33
33
|
NAME = SKYPILOT_GCP
|
34
|
-
REQUIREMENTS = ["skypilot[gcp]
|
34
|
+
REQUIREMENTS = ["skypilot[gcp]~=0.6.0"]
|
35
35
|
APT_PACKAGES = ["openssh-client", "rsync"]
|
36
36
|
|
37
37
|
@classmethod
|
@@ -31,7 +31,7 @@ class SkypilotLambdaIntegration(Integration):
|
|
31
31
|
"""Definition of Skypilot Lambda Integration for ZenML."""
|
32
32
|
|
33
33
|
NAME = SKYPILOT_LAMBDA
|
34
|
-
REQUIREMENTS = ["skypilot[lambda]<=0.
|
34
|
+
REQUIREMENTS = ["skypilot[lambda]<=0.6.0"]
|
35
35
|
|
36
36
|
@classmethod
|
37
37
|
def flavors(cls) -> List[Type[Flavor]]:
|
@@ -40,7 +40,7 @@ class SkypilotLambdaOrchestratorSettings(SkypilotBaseOrchestratorSettings):
|
|
40
40
|
|
41
41
|
_UNSUPPORTED_FEATURES = {
|
42
42
|
"use_spot": "Spot instances not supported for Lambda orchestrator.",
|
43
|
-
"
|
43
|
+
"job_recovery": "Job recovery not supported for Lambda orchestrator.",
|
44
44
|
"image_id": "Custom image IDs not supported for Lambda orchestrator.",
|
45
45
|
# Add other unsupported features as needed
|
46
46
|
}
|
@@ -13,7 +13,6 @@
|
|
13
13
|
# permissions and limitations under the License.
|
14
14
|
"""Initialization for TensorBoard integration."""
|
15
15
|
|
16
|
-
import sys
|
17
16
|
from typing import List, Optional
|
18
17
|
from zenml.integrations.constants import TENSORBOARD
|
19
18
|
from zenml.integrations.integration import Integration
|
@@ -18,6 +18,9 @@ import sys
|
|
18
18
|
from typing import List, Optional
|
19
19
|
from zenml.integrations.constants import TENSORFLOW
|
20
20
|
from zenml.integrations.integration import Integration
|
21
|
+
from zenml.logger import get_logger
|
22
|
+
|
23
|
+
logger = get_logger(__name__)
|
21
24
|
|
22
25
|
|
23
26
|
class TensorflowIntegration(Integration):
|
@@ -25,20 +28,27 @@ class TensorflowIntegration(Integration):
|
|
25
28
|
|
26
29
|
NAME = TENSORFLOW
|
27
30
|
REQUIREMENTS = []
|
31
|
+
REQUIREMENTS_IGNORED_ON_UNINSTALL = ["typing-extensions"]
|
28
32
|
|
29
33
|
@classmethod
|
30
34
|
def activate(cls) -> None:
|
31
35
|
"""Activates the integration."""
|
32
36
|
# need to import this explicitly to load the Tensorflow file IO support
|
33
37
|
# for S3 and other file systems
|
34
|
-
if (
|
35
|
-
not platform.system() == "Darwin"
|
36
|
-
or not platform.machine() == "arm64"
|
37
|
-
):
|
38
|
+
if not platform.system() == "Darwin" or not platform.machine() == "arm64":
|
38
39
|
import tensorflow_io # type: ignore
|
39
40
|
|
40
41
|
from zenml.integrations.tensorflow import materializers # noqa
|
41
42
|
|
43
|
+
if sys.version_info.minor == 8:
|
44
|
+
logger.warning(
|
45
|
+
"Python 3.8 with TensorFlow is not fully "
|
46
|
+
"compatible with Pydantic 2 requirements. "
|
47
|
+
"Consider upgrading to a higher Python "
|
48
|
+
"version if you would like to use the "
|
49
|
+
"Tensorflow integration."
|
50
|
+
)
|
51
|
+
|
42
52
|
@classmethod
|
43
53
|
def get_requirements(cls, target_os: Optional[str] = None) -> List[str]:
|
44
54
|
"""Defines platform specific requirements for the integration.
|
@@ -52,13 +62,15 @@ class TensorflowIntegration(Integration):
|
|
52
62
|
target_os = target_os or platform.system()
|
53
63
|
if target_os == "Darwin" and platform.machine() == "arm64":
|
54
64
|
requirements = [
|
55
|
-
|
65
|
+
"tensorflow-macos>=2.12,<=2.15",
|
56
66
|
]
|
57
67
|
else:
|
58
68
|
requirements = [
|
59
|
-
|
69
|
+
"tensorflow>=2.12,<=2.15",
|
60
70
|
"tensorflow_io>=0.24.0",
|
61
71
|
]
|
72
|
+
if sys.version_info.minor == 8:
|
73
|
+
requirements.append("typing-extensions>=4.6.1")
|
62
74
|
return requirements
|
63
75
|
|
64
76
|
|