zenml-nightly 0.70.0.dev20241126__py3-none-any.whl → 0.70.0.dev20241128__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/artifact_stores/base_artifact_store.py +2 -2
- zenml/artifacts/utils.py +1 -1
- zenml/cli/__init__.py +3 -0
- zenml/cli/login.py +26 -0
- zenml/integrations/__init__.py +1 -0
- zenml/integrations/aws/orchestrators/sagemaker_orchestrator.py +14 -6
- zenml/integrations/constants.py +1 -0
- zenml/integrations/kubernetes/orchestrators/kube_utils.py +46 -2
- zenml/integrations/kubernetes/orchestrators/kubernetes_orchestrator.py +13 -2
- zenml/integrations/kubernetes/orchestrators/kubernetes_orchestrator_entrypoint.py +3 -1
- zenml/integrations/kubernetes/orchestrators/manifest_utils.py +3 -2
- zenml/integrations/kubernetes/step_operators/kubernetes_step_operator.py +3 -1
- zenml/integrations/modal/__init__.py +46 -0
- zenml/integrations/modal/flavors/__init__.py +26 -0
- zenml/integrations/modal/flavors/modal_step_operator_flavor.py +125 -0
- zenml/integrations/modal/step_operators/__init__.py +22 -0
- zenml/integrations/modal/step_operators/modal_step_operator.py +242 -0
- zenml/io/filesystem.py +2 -2
- zenml/io/local_filesystem.py +3 -3
- zenml/model/model.py +0 -82
- zenml/orchestrators/step_run_utils.py +8 -3
- zenml/orchestrators/step_runner.py +1 -1
- zenml/orchestrators/utils.py +24 -2
- zenml/steps/entrypoint_function_utils.py +3 -1
- zenml/zen_server/cloud_utils.py +3 -1
- zenml/zen_server/rbac/endpoint_utils.py +6 -4
- zenml/zen_server/rbac/models.py +3 -2
- zenml/zen_server/rbac/utils.py +4 -7
- zenml/zen_server/routers/users_endpoints.py +35 -37
- zenml/zen_server/routers/workspaces_endpoints.py +25 -36
- zenml/zen_stores/sql_zen_store.py +13 -0
- {zenml_nightly-0.70.0.dev20241126.dist-info → zenml_nightly-0.70.0.dev20241128.dist-info}/METADATA +1 -1
- {zenml_nightly-0.70.0.dev20241126.dist-info → zenml_nightly-0.70.0.dev20241128.dist-info}/RECORD +37 -33
- zenml/utils/cloud_utils.py +0 -40
- {zenml_nightly-0.70.0.dev20241126.dist-info → zenml_nightly-0.70.0.dev20241128.dist-info}/LICENSE +0 -0
- {zenml_nightly-0.70.0.dev20241126.dist-info → zenml_nightly-0.70.0.dev20241128.dist-info}/WHEEL +0 -0
- {zenml_nightly-0.70.0.dev20241126.dist-info → zenml_nightly-0.70.0.dev20241128.dist-info}/entry_points.txt +0 -0
zenml/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.70.0.
|
1
|
+
0.70.0.dev20241128
|
@@ -267,11 +267,11 @@ class BaseArtifactStore(StackComponent):
|
|
267
267
|
|
268
268
|
# --- User interface ---
|
269
269
|
@abstractmethod
|
270
|
-
def open(self,
|
270
|
+
def open(self, path: PathType, mode: str = "r") -> Any:
|
271
271
|
"""Open a file at the given path.
|
272
272
|
|
273
273
|
Args:
|
274
|
-
|
274
|
+
path: The path of the file to open.
|
275
275
|
mode: The mode to open the file.
|
276
276
|
|
277
277
|
Returns:
|
zenml/artifacts/utils.py
CHANGED
@@ -575,7 +575,7 @@ def download_artifact_files_from_response(
|
|
575
575
|
)
|
576
576
|
file_path = str(Path(artifact.uri) / file_str)
|
577
577
|
with artifact_store.open(
|
578
|
-
|
578
|
+
file_path, mode="rb"
|
579
579
|
) as store_file:
|
580
580
|
# Use a loop to read and write chunks of the file
|
581
581
|
# instead of reading the entire file into memory
|
zenml/cli/__init__.py
CHANGED
@@ -2242,6 +2242,9 @@ export ZENML_STORE_URL=https://...
|
|
2242
2242
|
export ZENML_STORE_API_KEY=<API_KEY>
|
2243
2243
|
```
|
2244
2244
|
|
2245
|
+
You don't need to run `zenml login` after setting these two environment
|
2246
|
+
variables and can start interacting with your server right away.
|
2247
|
+
|
2245
2248
|
To see all the service accounts you've created and their API keys, use the
|
2246
2249
|
following commands:
|
2247
2250
|
|
zenml/cli/login.py
CHANGED
@@ -14,6 +14,7 @@
|
|
14
14
|
"""CLI for managing ZenML server deployments."""
|
15
15
|
|
16
16
|
import ipaddress
|
17
|
+
import os
|
17
18
|
import re
|
18
19
|
import sys
|
19
20
|
import time
|
@@ -413,6 +414,27 @@ def connect_to_pro_server(
|
|
413
414
|
cli_utils.declare(f"Connected to ZenML Pro server: {server.name}.")
|
414
415
|
|
415
416
|
|
417
|
+
def _fail_if_authentication_environment_variables_set() -> None:
|
418
|
+
"""Fail if any of the authentication environment variables are set."""
|
419
|
+
environment_variables = [
|
420
|
+
"ZENML_STORE_URL",
|
421
|
+
"ZENML_STORE_API_KEY",
|
422
|
+
"ZENML_STORE_USERNAME",
|
423
|
+
"ZENML_STORE_PASSWORD",
|
424
|
+
]
|
425
|
+
|
426
|
+
if any(env_var in os.environ for env_var in environment_variables):
|
427
|
+
cli_utils.error(
|
428
|
+
"You're running to login/logout while having one of the "
|
429
|
+
f"{environment_variables} environment variables set. "
|
430
|
+
"If you want to use those environment variables to authenticate "
|
431
|
+
"to your ZenML server, there is no need to login/logout, you can "
|
432
|
+
"start interacting with your server right away. If you want to use "
|
433
|
+
"the `zenml login` command for authentication, please unset these "
|
434
|
+
"environment variables first."
|
435
|
+
)
|
436
|
+
|
437
|
+
|
416
438
|
@cli.command(
|
417
439
|
"login",
|
418
440
|
help=(
|
@@ -670,6 +692,8 @@ def login(
|
|
670
692
|
dashboard on a public domain. Primarily used for accessing the
|
671
693
|
dashboard in Colab.
|
672
694
|
"""
|
695
|
+
_fail_if_authentication_environment_variables_set()
|
696
|
+
|
673
697
|
if local:
|
674
698
|
if api_key:
|
675
699
|
cli_utils.error(
|
@@ -849,6 +873,8 @@ def logout(
|
|
849
873
|
"""
|
850
874
|
from zenml.login.credentials_store import get_credentials_store
|
851
875
|
|
876
|
+
_fail_if_authentication_environment_variables_set()
|
877
|
+
|
852
878
|
credentials_store = get_credentials_store()
|
853
879
|
gc = GlobalConfiguration()
|
854
880
|
store_cfg = gc.store_configuration
|
zenml/integrations/__init__.py
CHANGED
@@ -48,6 +48,7 @@ from zenml.integrations.lightgbm import LightGBMIntegration # noqa
|
|
48
48
|
|
49
49
|
# from zenml.integrations.llama_index import LlamaIndexIntegration # noqa
|
50
50
|
from zenml.integrations.mlflow import MlflowIntegration # noqa
|
51
|
+
from zenml.integrations.modal import ModalIntegration # noqa
|
51
52
|
from zenml.integrations.neptune import NeptuneIntegration # noqa
|
52
53
|
from zenml.integrations.neural_prophet import NeuralProphetIntegration # noqa
|
53
54
|
from zenml.integrations.numpy import NumpyIntegration # noqa
|
@@ -305,8 +305,21 @@ class SagemakerOrchestrator(ContainerizedOrchestrator):
|
|
305
305
|
# Retrieve Executor arguments provided in the Step settings.
|
306
306
|
if use_training_step:
|
307
307
|
args_for_step_executor = step_settings.estimator_args or {}
|
308
|
+
args_for_step_executor.setdefault(
|
309
|
+
"volume_size", step_settings.volume_size_in_gb
|
310
|
+
)
|
311
|
+
args_for_step_executor.setdefault(
|
312
|
+
"max_run", step_settings.max_runtime_in_seconds
|
313
|
+
)
|
308
314
|
else:
|
309
315
|
args_for_step_executor = step_settings.processor_args or {}
|
316
|
+
args_for_step_executor.setdefault(
|
317
|
+
"volume_size_in_gb", step_settings.volume_size_in_gb
|
318
|
+
)
|
319
|
+
args_for_step_executor.setdefault(
|
320
|
+
"max_runtime_in_seconds",
|
321
|
+
step_settings.max_runtime_in_seconds,
|
322
|
+
)
|
310
323
|
|
311
324
|
# Set default values from configured orchestrator Component to
|
312
325
|
# arguments to be used when they are not present in processor_args.
|
@@ -314,12 +327,7 @@ class SagemakerOrchestrator(ContainerizedOrchestrator):
|
|
314
327
|
"role",
|
315
328
|
step_settings.execution_role or self.config.execution_role,
|
316
329
|
)
|
317
|
-
|
318
|
-
"volume_size_in_gb", step_settings.volume_size_in_gb
|
319
|
-
)
|
320
|
-
args_for_step_executor.setdefault(
|
321
|
-
"max_runtime_in_seconds", step_settings.max_runtime_in_seconds
|
322
|
-
)
|
330
|
+
|
323
331
|
tags = step_settings.tags
|
324
332
|
args_for_step_executor.setdefault(
|
325
333
|
"tags",
|
zenml/integrations/constants.py
CHANGED
@@ -94,18 +94,62 @@ def load_kube_config(
|
|
94
94
|
k8s_config.load_kube_config(context=context)
|
95
95
|
|
96
96
|
|
97
|
-
def
|
97
|
+
def calculate_max_pod_name_length_for_namespace(namespace: str) -> int:
|
98
|
+
"""Calculate the max pod length for a certain namespace.
|
99
|
+
|
100
|
+
Args:
|
101
|
+
namespace: The namespace in which the pod will be created.
|
102
|
+
|
103
|
+
Returns:
|
104
|
+
The maximum pod name length.
|
105
|
+
"""
|
106
|
+
# Kubernetes allows Pod names to have 253 characters. However, when
|
107
|
+
# creating a pod they try to create a log file which is called
|
108
|
+
# <NAMESPACE>_<POD_NAME>_<UUID>, which adds additional characters and
|
109
|
+
# runs into filesystem limitations for filename lengths (255). We therefore
|
110
|
+
# subtract the length of a UUID (36), the two underscores and the
|
111
|
+
# namespace length from the max filename length.
|
112
|
+
return 255 - 38 - len(namespace)
|
113
|
+
|
114
|
+
|
115
|
+
def sanitize_pod_name(pod_name: str, namespace: str) -> str:
|
98
116
|
"""Sanitize pod names so they conform to Kubernetes pod naming convention.
|
99
117
|
|
100
118
|
Args:
|
101
119
|
pod_name: Arbitrary input pod name.
|
120
|
+
namespace: Namespace in which the Pod will be created.
|
102
121
|
|
103
122
|
Returns:
|
104
123
|
Sanitized pod name.
|
105
124
|
"""
|
125
|
+
# https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#dns-subdomain-names
|
106
126
|
pod_name = re.sub(r"[^a-z0-9-]", "-", pod_name.lower())
|
107
127
|
pod_name = re.sub(r"^[-]+", "", pod_name)
|
108
|
-
|
128
|
+
pod_name = re.sub(r"[-]+$", "", pod_name)
|
129
|
+
pod_name = re.sub(r"[-]+", "-", pod_name)
|
130
|
+
|
131
|
+
allowed_length = calculate_max_pod_name_length_for_namespace(
|
132
|
+
namespace=namespace
|
133
|
+
)
|
134
|
+
return pod_name[:allowed_length]
|
135
|
+
|
136
|
+
|
137
|
+
def sanitize_label(label: str) -> str:
|
138
|
+
"""Sanitize a label for a Kubernetes resource.
|
139
|
+
|
140
|
+
Args:
|
141
|
+
label: The label to sanitize.
|
142
|
+
|
143
|
+
Returns:
|
144
|
+
The sanitized label.
|
145
|
+
"""
|
146
|
+
# https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#rfc-1035-label-names
|
147
|
+
label = re.sub(r"[^a-z0-9-]", "-", label.lower())
|
148
|
+
label = re.sub(r"^[-]+", "", label)
|
149
|
+
label = re.sub(r"[-]+$", "", label)
|
150
|
+
label = re.sub(r"[-]+", "-", label)
|
151
|
+
|
152
|
+
return label[:63]
|
109
153
|
|
110
154
|
|
111
155
|
def pod_is_not_pending(pod: k8s_client.V1Pod) -> bool:
|
@@ -395,8 +395,19 @@ class KubernetesOrchestrator(ContainerizedOrchestrator):
|
|
395
395
|
)
|
396
396
|
|
397
397
|
pipeline_name = deployment.pipeline_configuration.name
|
398
|
-
|
399
|
-
|
398
|
+
|
399
|
+
# We already make sure the orchestrator run name has the correct length
|
400
|
+
# to make sure we don't cut off the randomized suffix later when
|
401
|
+
# sanitizing the pod name. This avoids any pod naming collisions.
|
402
|
+
max_length = kube_utils.calculate_max_pod_name_length_for_namespace(
|
403
|
+
namespace=self.config.kubernetes_namespace
|
404
|
+
)
|
405
|
+
orchestrator_run_name = get_orchestrator_run_name(
|
406
|
+
pipeline_name, max_length=max_length
|
407
|
+
)
|
408
|
+
pod_name = kube_utils.sanitize_pod_name(
|
409
|
+
orchestrator_run_name, namespace=self.config.kubernetes_namespace
|
410
|
+
)
|
400
411
|
|
401
412
|
assert stack.container_registry
|
402
413
|
|
@@ -90,7 +90,9 @@ def main() -> None:
|
|
90
90
|
"""
|
91
91
|
# Define Kubernetes pod name.
|
92
92
|
pod_name = f"{orchestrator_run_id}-{step_name}"
|
93
|
-
pod_name = kube_utils.sanitize_pod_name(
|
93
|
+
pod_name = kube_utils.sanitize_pod_name(
|
94
|
+
pod_name, namespace=args.kubernetes_namespace
|
95
|
+
)
|
94
96
|
|
95
97
|
image = KubernetesOrchestrator.get_image(
|
96
98
|
deployment=deployment_config, step_name=step_name
|
@@ -25,6 +25,7 @@ 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.orchestrators import kube_utils
|
28
29
|
from zenml.integrations.kubernetes.pod_settings import KubernetesPodSettings
|
29
30
|
|
30
31
|
|
@@ -167,8 +168,8 @@ def build_pod_manifest(
|
|
167
168
|
# Add run_name and pipeline_name to the labels
|
168
169
|
labels.update(
|
169
170
|
{
|
170
|
-
"run": run_name,
|
171
|
-
"pipeline": pipeline_name,
|
171
|
+
"run": kube_utils.sanitize_label(run_name),
|
172
|
+
"pipeline": kube_utils.sanitize_label(pipeline_name),
|
172
173
|
}
|
173
174
|
)
|
174
175
|
|
@@ -197,7 +197,9 @@ class KubernetesStepOperator(BaseStepOperator):
|
|
197
197
|
)
|
198
198
|
|
199
199
|
pod_name = f"{info.run_name}_{info.pipeline_step_name}"
|
200
|
-
pod_name = kube_utils.sanitize_pod_name(
|
200
|
+
pod_name = kube_utils.sanitize_pod_name(
|
201
|
+
pod_name, namespace=self.config.kubernetes_namespace
|
202
|
+
)
|
201
203
|
|
202
204
|
command = entrypoint_command[:3]
|
203
205
|
args = entrypoint_command[3:]
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# Copyright (c) ZenML GmbH 2024. All Rights Reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at:
|
6
|
+
#
|
7
|
+
# https://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
12
|
+
# or implied. See the License for the specific language governing
|
13
|
+
# permissions and limitations under the License.
|
14
|
+
"""Modal integration for cloud-native step execution.
|
15
|
+
|
16
|
+
The Modal integration sub-module provides a step operator flavor that allows
|
17
|
+
executing steps on Modal's cloud infrastructure.
|
18
|
+
"""
|
19
|
+
from typing import List, Type
|
20
|
+
|
21
|
+
from zenml.integrations.constants import MODAL
|
22
|
+
from zenml.integrations.integration import Integration
|
23
|
+
from zenml.stack import Flavor
|
24
|
+
|
25
|
+
MODAL_STEP_OPERATOR_FLAVOR = "modal"
|
26
|
+
|
27
|
+
|
28
|
+
class ModalIntegration(Integration):
|
29
|
+
"""Definition of Modal integration for ZenML."""
|
30
|
+
|
31
|
+
NAME = MODAL
|
32
|
+
REQUIREMENTS = ["modal>=0.64.49,<1"]
|
33
|
+
|
34
|
+
@classmethod
|
35
|
+
def flavors(cls) -> List[Type[Flavor]]:
|
36
|
+
"""Declare the stack component flavors for the Modal integration.
|
37
|
+
|
38
|
+
Returns:
|
39
|
+
List of new stack component flavors.
|
40
|
+
"""
|
41
|
+
from zenml.integrations.modal.flavors import ModalStepOperatorFlavor
|
42
|
+
|
43
|
+
return [ModalStepOperatorFlavor]
|
44
|
+
|
45
|
+
|
46
|
+
ModalIntegration.check_installation()
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# Copyright (c) ZenML GmbH 2024. All Rights Reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at:
|
6
|
+
#
|
7
|
+
# https://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
12
|
+
# or implied. See the License for the specific language governing
|
13
|
+
# permissions and limitations under the License.
|
14
|
+
"""Modal integration flavors."""
|
15
|
+
|
16
|
+
from zenml.integrations.modal.flavors.modal_step_operator_flavor import (
|
17
|
+
ModalStepOperatorConfig,
|
18
|
+
ModalStepOperatorFlavor,
|
19
|
+
ModalStepOperatorSettings,
|
20
|
+
)
|
21
|
+
|
22
|
+
__all__ = [
|
23
|
+
"ModalStepOperatorConfig",
|
24
|
+
"ModalStepOperatorFlavor",
|
25
|
+
"ModalStepOperatorSettings",
|
26
|
+
]
|
@@ -0,0 +1,125 @@
|
|
1
|
+
# Copyright (c) ZenML GmbH 2024. All Rights Reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at:
|
6
|
+
#
|
7
|
+
# https://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
12
|
+
# or implied. See the License for the specific language governing
|
13
|
+
# permissions and limitations under the License.
|
14
|
+
"""Modal step operator flavor."""
|
15
|
+
|
16
|
+
from typing import TYPE_CHECKING, Optional, Type
|
17
|
+
|
18
|
+
from zenml.config.base_settings import BaseSettings
|
19
|
+
from zenml.integrations.modal import MODAL_STEP_OPERATOR_FLAVOR
|
20
|
+
from zenml.step_operators import BaseStepOperatorConfig, BaseStepOperatorFlavor
|
21
|
+
|
22
|
+
if TYPE_CHECKING:
|
23
|
+
from zenml.integrations.modal.step_operators import ModalStepOperator
|
24
|
+
|
25
|
+
|
26
|
+
class ModalStepOperatorSettings(BaseSettings):
|
27
|
+
"""Settings for the Modal step operator.
|
28
|
+
|
29
|
+
Specifying the region and cloud provider is only available for Enterprise
|
30
|
+
and Team plan customers.
|
31
|
+
|
32
|
+
Certain combinations of settings are not available. It is suggested to err
|
33
|
+
on the side of looser settings rather than more restrictive ones to avoid
|
34
|
+
pipeline execution failures. In the case of failures, however, Modal
|
35
|
+
provides detailed error messages that can help identify what is
|
36
|
+
incompatible. See more in the Modal docs at https://modal.com/docs/guide/region-selection.
|
37
|
+
|
38
|
+
Attributes:
|
39
|
+
gpu: The type of GPU to use for the step execution.
|
40
|
+
region: The region to use for the step execution.
|
41
|
+
cloud: The cloud provider to use for the step execution.
|
42
|
+
"""
|
43
|
+
|
44
|
+
gpu: Optional[str] = None
|
45
|
+
region: Optional[str] = None
|
46
|
+
cloud: Optional[str] = None
|
47
|
+
|
48
|
+
|
49
|
+
class ModalStepOperatorConfig(
|
50
|
+
BaseStepOperatorConfig, ModalStepOperatorSettings
|
51
|
+
):
|
52
|
+
"""Configuration for the Modal step operator."""
|
53
|
+
|
54
|
+
@property
|
55
|
+
def is_remote(self) -> bool:
|
56
|
+
"""Checks if this stack component is running remotely.
|
57
|
+
|
58
|
+
This designation is used to determine if the stack component can be
|
59
|
+
used with a local ZenML database or if it requires a remote ZenML
|
60
|
+
server.
|
61
|
+
|
62
|
+
Returns:
|
63
|
+
True if this config is for a remote component, False otherwise.
|
64
|
+
"""
|
65
|
+
return True
|
66
|
+
|
67
|
+
|
68
|
+
class ModalStepOperatorFlavor(BaseStepOperatorFlavor):
|
69
|
+
"""Modal step operator flavor."""
|
70
|
+
|
71
|
+
@property
|
72
|
+
def name(self) -> str:
|
73
|
+
"""Name of the flavor.
|
74
|
+
|
75
|
+
Returns:
|
76
|
+
The name of the flavor.
|
77
|
+
"""
|
78
|
+
return MODAL_STEP_OPERATOR_FLAVOR
|
79
|
+
|
80
|
+
@property
|
81
|
+
def docs_url(self) -> Optional[str]:
|
82
|
+
"""A url to point at docs explaining this flavor.
|
83
|
+
|
84
|
+
Returns:
|
85
|
+
A flavor docs url.
|
86
|
+
"""
|
87
|
+
return self.generate_default_docs_url()
|
88
|
+
|
89
|
+
@property
|
90
|
+
def sdk_docs_url(self) -> Optional[str]:
|
91
|
+
"""A url to point at SDK docs explaining this flavor.
|
92
|
+
|
93
|
+
Returns:
|
94
|
+
A flavor SDK docs url.
|
95
|
+
"""
|
96
|
+
return self.generate_default_sdk_docs_url()
|
97
|
+
|
98
|
+
@property
|
99
|
+
def logo_url(self) -> str:
|
100
|
+
"""A url to represent the flavor in the dashboard.
|
101
|
+
|
102
|
+
Returns:
|
103
|
+
The flavor logo.
|
104
|
+
"""
|
105
|
+
return "https://public-flavor-logos.s3.eu-central-1.amazonaws.com/step_operator/modal.png"
|
106
|
+
|
107
|
+
@property
|
108
|
+
def config_class(self) -> Type[ModalStepOperatorConfig]:
|
109
|
+
"""Returns `ModalStepOperatorConfig` config class.
|
110
|
+
|
111
|
+
Returns:
|
112
|
+
The config class.
|
113
|
+
"""
|
114
|
+
return ModalStepOperatorConfig
|
115
|
+
|
116
|
+
@property
|
117
|
+
def implementation_class(self) -> Type["ModalStepOperator"]:
|
118
|
+
"""Implementation class for this flavor.
|
119
|
+
|
120
|
+
Returns:
|
121
|
+
The implementation class.
|
122
|
+
"""
|
123
|
+
from zenml.integrations.modal.step_operators import ModalStepOperator
|
124
|
+
|
125
|
+
return ModalStepOperator
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# Copyright (c) ZenML GmbH 2024. All Rights Reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at:
|
6
|
+
#
|
7
|
+
# https://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
12
|
+
# or implied. See the License for the specific language governing
|
13
|
+
# permissions and limitations under the License.
|
14
|
+
"""Modal step operator."""
|
15
|
+
|
16
|
+
from zenml.integrations.modal.step_operators.modal_step_operator import (
|
17
|
+
ModalStepOperator,
|
18
|
+
)
|
19
|
+
|
20
|
+
__all__ = [
|
21
|
+
"ModalStepOperator",
|
22
|
+
]
|