zenml-nightly 0.82.1.dev20250521__py3-none-any.whl → 0.82.1.dev20250524__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/client.py +6 -2
- zenml/config/build_configuration.py +7 -0
- zenml/config/docker_settings.py +25 -0
- zenml/config/server_config.py +7 -0
- zenml/constants.py +1 -0
- zenml/enums.py +1 -0
- zenml/environment.py +12 -0
- zenml/integrations/gcp/__init__.py +1 -1
- zenml/integrations/gcp/service_connectors/gcp_service_connector.py +12 -11
- zenml/integrations/hyperai/orchestrators/hyperai_orchestrator.py +1 -1
- zenml/integrations/kubernetes/orchestrators/kube_utils.py +16 -12
- zenml/materializers/built_in_materializer.py +9 -3
- zenml/zen_server/cloud_utils.py +45 -21
- zenml/zen_server/routers/actions_endpoints.py +6 -6
- zenml/zen_server/routers/artifact_endpoint.py +6 -6
- zenml/zen_server/routers/artifact_version_endpoints.py +11 -11
- zenml/zen_server/routers/auth_endpoints.py +4 -3
- zenml/zen_server/routers/code_repositories_endpoints.py +6 -6
- zenml/zen_server/routers/devices_endpoints.py +6 -6
- zenml/zen_server/routers/event_source_endpoints.py +6 -6
- zenml/zen_server/routers/flavors_endpoints.py +7 -7
- zenml/zen_server/routers/logs_endpoints.py +2 -2
- zenml/zen_server/routers/model_versions_endpoints.py +13 -13
- zenml/zen_server/routers/models_endpoints.py +6 -6
- zenml/zen_server/routers/pipeline_builds_endpoints.py +5 -5
- zenml/zen_server/routers/pipeline_deployments_endpoints.py +6 -6
- zenml/zen_server/routers/pipelines_endpoints.py +7 -7
- zenml/zen_server/routers/plugin_endpoints.py +3 -3
- zenml/zen_server/routers/projects_endpoints.py +7 -7
- zenml/zen_server/routers/run_metadata_endpoints.py +2 -2
- zenml/zen_server/routers/run_templates_endpoints.py +7 -7
- zenml/zen_server/routers/runs_endpoints.py +11 -11
- zenml/zen_server/routers/schedule_endpoints.py +6 -6
- zenml/zen_server/routers/secrets_endpoints.py +8 -8
- zenml/zen_server/routers/server_endpoints.py +13 -9
- zenml/zen_server/routers/service_accounts_endpoints.py +12 -12
- zenml/zen_server/routers/service_connectors_endpoints.py +13 -13
- zenml/zen_server/routers/service_endpoints.py +6 -6
- zenml/zen_server/routers/stack_components_endpoints.py +18 -9
- zenml/zen_server/routers/stack_deployment_endpoints.py +4 -4
- zenml/zen_server/routers/stacks_endpoints.py +6 -6
- zenml/zen_server/routers/steps_endpoints.py +8 -8
- zenml/zen_server/routers/tag_resource_endpoints.py +5 -5
- zenml/zen_server/routers/tags_endpoints.py +6 -6
- zenml/zen_server/routers/triggers_endpoints.py +9 -9
- zenml/zen_server/routers/users_endpoints.py +12 -12
- zenml/zen_server/routers/webhook_endpoints.py +2 -2
- zenml/zen_server/utils.py +72 -33
- zenml/zen_server/zen_server_api.py +211 -55
- zenml/zen_stores/rest_zen_store.py +40 -11
- zenml/zen_stores/sql_zen_store.py +79 -2
- {zenml_nightly-0.82.1.dev20250521.dist-info → zenml_nightly-0.82.1.dev20250524.dist-info}/METADATA +1 -1
- {zenml_nightly-0.82.1.dev20250521.dist-info → zenml_nightly-0.82.1.dev20250524.dist-info}/RECORD +57 -57
- {zenml_nightly-0.82.1.dev20250521.dist-info → zenml_nightly-0.82.1.dev20250524.dist-info}/LICENSE +0 -0
- {zenml_nightly-0.82.1.dev20250521.dist-info → zenml_nightly-0.82.1.dev20250524.dist-info}/WHEEL +0 -0
- {zenml_nightly-0.82.1.dev20250521.dist-info → zenml_nightly-0.82.1.dev20250524.dist-info}/entry_points.txt +0 -0
zenml/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.82.1.
|
1
|
+
0.82.1.dev20250524
|
zenml/client.py
CHANGED
@@ -2024,7 +2024,9 @@ class Client(metaclass=ClientMetaClass):
|
|
2024
2024
|
name=name,
|
2025
2025
|
type=component_type,
|
2026
2026
|
flavor=flavor,
|
2027
|
-
configuration=
|
2027
|
+
configuration=validated_config.model_dump(
|
2028
|
+
mode="json", exclude_unset=True
|
2029
|
+
),
|
2028
2030
|
labels=labels,
|
2029
2031
|
)
|
2030
2032
|
|
@@ -2112,7 +2114,9 @@ class Client(metaclass=ClientMetaClass):
|
|
2112
2114
|
assert validated_config is not None
|
2113
2115
|
warn_if_config_server_mismatch(validated_config)
|
2114
2116
|
|
2115
|
-
update_model.configuration =
|
2117
|
+
update_model.configuration = validated_config.model_dump(
|
2118
|
+
mode="json", exclude_unset=True
|
2119
|
+
)
|
2116
2120
|
|
2117
2121
|
if labels is not None:
|
2118
2122
|
existing_labels = component.labels or {}
|
@@ -108,6 +108,13 @@ class BuildConfiguration(BaseModel):
|
|
108
108
|
)
|
109
109
|
if digest:
|
110
110
|
hash_.update(digest.encode())
|
111
|
+
elif self.settings.skip_build:
|
112
|
+
# If the user has specified to skip the build, the image being
|
113
|
+
# used for the run is whatever they set for `parent_image`.
|
114
|
+
# In this case, the bevavior depends on the orchestrators image
|
115
|
+
# pull policy, and whether there is any caching involved. This
|
116
|
+
# is out of our control here, so we don't log any warning.
|
117
|
+
pass
|
111
118
|
else:
|
112
119
|
logger.warning(
|
113
120
|
"Unable to fetch parent image digest for image `%s`. "
|
zenml/config/docker_settings.py
CHANGED
@@ -386,6 +386,31 @@ class DockerSettings(BaseSettings):
|
|
386
386
|
|
387
387
|
return self
|
388
388
|
|
389
|
+
@model_validator(mode="before")
|
390
|
+
@classmethod
|
391
|
+
@before_validator_handler
|
392
|
+
def _warn_about_future_default_installer(
|
393
|
+
cls, data: Dict[str, Any]
|
394
|
+
) -> Dict[str, Any]:
|
395
|
+
"""Warns about the future change of default package installer from pip to uv.
|
396
|
+
|
397
|
+
Args:
|
398
|
+
data: The model data.
|
399
|
+
|
400
|
+
Returns:
|
401
|
+
The validated settings values.
|
402
|
+
"""
|
403
|
+
if "python_package_installer" not in data:
|
404
|
+
logger.warning(
|
405
|
+
"In a future release, the default Python package installer "
|
406
|
+
"used by ZenML to build container images for your "
|
407
|
+
"containerized pipelines will change from 'pip' to 'uv'. "
|
408
|
+
"To maintain current behavior, you can explicitly set "
|
409
|
+
"`python_package_installer=PythonPackageInstaller.PIP` "
|
410
|
+
"in your DockerSettings."
|
411
|
+
)
|
412
|
+
return data
|
413
|
+
|
389
414
|
model_config = ConfigDict(
|
390
415
|
# public attributes are immutable
|
391
416
|
frozen=True,
|
zenml/config/server_config.py
CHANGED
@@ -45,6 +45,7 @@ from zenml.constants import (
|
|
45
45
|
DEFAULT_ZENML_SERVER_MAX_REQUEST_BODY_SIZE_IN_BYTES,
|
46
46
|
DEFAULT_ZENML_SERVER_NAME,
|
47
47
|
DEFAULT_ZENML_SERVER_PIPELINE_RUN_AUTH_WINDOW,
|
48
|
+
DEFAULT_ZENML_SERVER_REQUEST_TIMEOUT,
|
48
49
|
DEFAULT_ZENML_SERVER_SECURE_HEADERS_CACHE,
|
49
50
|
DEFAULT_ZENML_SERVER_SECURE_HEADERS_CONTENT,
|
50
51
|
DEFAULT_ZENML_SERVER_SECURE_HEADERS_CSP,
|
@@ -252,6 +253,11 @@ class ServerConfiguration(BaseModel):
|
|
252
253
|
used.
|
253
254
|
file_download_size_limit: The maximum size of the file download in
|
254
255
|
bytes. If not specified, the default value of 2GB will be used.
|
256
|
+
thread_pool_size: The size of the thread pool for handling requests. If
|
257
|
+
not specified, the default value of 40 will be used.
|
258
|
+
server_request_timeout: The timeout for server requests in seconds. If
|
259
|
+
not specified, the default value of 20 seconds will be used. This
|
260
|
+
value should be lower than the client's request timeout.
|
255
261
|
"""
|
256
262
|
|
257
263
|
deployment_type: ServerDeploymentType = ServerDeploymentType.OTHER
|
@@ -348,6 +354,7 @@ class ServerConfiguration(BaseModel):
|
|
348
354
|
auto_activate: bool = False
|
349
355
|
|
350
356
|
thread_pool_size: int = DEFAULT_ZENML_SERVER_THREAD_POOL_SIZE
|
357
|
+
server_request_timeout: int = DEFAULT_ZENML_SERVER_REQUEST_TIMEOUT
|
351
358
|
|
352
359
|
max_request_body_size_in_bytes: int = (
|
353
360
|
DEFAULT_ZENML_SERVER_MAX_REQUEST_BODY_SIZE_IN_BYTES
|
zenml/constants.py
CHANGED
@@ -282,6 +282,7 @@ DEFAULT_ZENML_SERVER_MAX_DEVICE_AUTH_ATTEMPTS = 3
|
|
282
282
|
DEFAULT_ZENML_SERVER_DEVICE_AUTH_TIMEOUT = 60 * 5 # 5 minutes
|
283
283
|
DEFAULT_ZENML_SERVER_DEVICE_AUTH_POLLING = 5 # seconds
|
284
284
|
DEFAULT_HTTP_TIMEOUT = 30
|
285
|
+
DEFAULT_ZENML_SERVER_REQUEST_TIMEOUT = 20 # seconds
|
285
286
|
SERVICE_CONNECTOR_VERIFY_REQUEST_TIMEOUT = 120 # seconds
|
286
287
|
ZENML_API_KEY_PREFIX = "ZENKEY_"
|
287
288
|
DEFAULT_ZENML_SERVER_PIPELINE_RUN_AUTH_WINDOW = 60 * 48 # 48 hours
|
zenml/enums.py
CHANGED
@@ -314,6 +314,7 @@ class EnvironmentType(StrEnum):
|
|
314
314
|
LIGHTNING_AI_STUDIO = "lightning_ai_studio"
|
315
315
|
GITHUB_CODESPACES = "github_codespaces"
|
316
316
|
VSCODE_REMOTE_CONTAINER = "vscode_remote_container"
|
317
|
+
ZENML_CODESPACE = "zenml_codespace"
|
317
318
|
|
318
319
|
|
319
320
|
class ModelStages(StrEnum):
|
zenml/environment.py
CHANGED
@@ -79,6 +79,8 @@ def get_environment() -> str:
|
|
79
79
|
return EnvironmentType.GENERIC_CI
|
80
80
|
elif Environment.in_github_codespaces():
|
81
81
|
return EnvironmentType.GITHUB_CODESPACES
|
82
|
+
elif Environment.in_zenml_codespace():
|
83
|
+
return EnvironmentType.ZENML_CODESPACE
|
82
84
|
elif Environment.in_vscode_remote_container():
|
83
85
|
return EnvironmentType.VSCODE_REMOTE_CONTAINER
|
84
86
|
elif Environment.in_lightning_ai_studio():
|
@@ -254,6 +256,16 @@ class Environment(metaclass=SingletonMetaClass):
|
|
254
256
|
or "GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN" in os.environ
|
255
257
|
)
|
256
258
|
|
259
|
+
@staticmethod
|
260
|
+
def in_zenml_codespace() -> bool:
|
261
|
+
"""If the current Python process is running in ZenML Codespaces.
|
262
|
+
|
263
|
+
Returns:
|
264
|
+
`True` if the current Python process is running in ZenML Codespaces,
|
265
|
+
`False` otherwise.
|
266
|
+
"""
|
267
|
+
return os.environ.get("ZENML_ENVIRONMENT") == "codespace"
|
268
|
+
|
257
269
|
@staticmethod
|
258
270
|
def in_vscode_remote_container() -> bool:
|
259
271
|
"""If the current Python process is running in a VS Code Remote Container.
|
@@ -78,7 +78,7 @@ from zenml.service_connectors.service_connector import (
|
|
78
78
|
from zenml.utils.enum_utils import StrEnum
|
79
79
|
from zenml.utils.pydantic_utils import before_validator_handler
|
80
80
|
from zenml.utils.secret_utils import PlainSerializedSecretStr
|
81
|
-
from zenml.utils.time_utils import utc_now
|
81
|
+
from zenml.utils.time_utils import to_utc_timezone, utc_now
|
82
82
|
|
83
83
|
logger = get_logger(__name__)
|
84
84
|
|
@@ -1200,14 +1200,13 @@ class GCPServiceConnector(ServiceConnector):
|
|
1200
1200
|
elif auth_method == GCPAuthenticationMethods.OAUTH2_TOKEN:
|
1201
1201
|
assert isinstance(cfg, GCPOAuth2TokenConfig)
|
1202
1202
|
|
1203
|
-
expires_at = self.expires_at
|
1204
|
-
if expires_at:
|
1205
|
-
# Remove the UTC timezone
|
1206
|
-
expires_at = expires_at.replace(tzinfo=None)
|
1207
|
-
|
1208
1203
|
credentials = gcp_credentials.Credentials(
|
1209
1204
|
token=cfg.token.get_secret_value(),
|
1210
|
-
expiry
|
1205
|
+
# Currently GCP expects the expiry to be a timezone-naive
|
1206
|
+
# UTC datetime.
|
1207
|
+
expiry=to_utc_timezone(self.expires_at).replace(tzinfo=None)
|
1208
|
+
if self.expires_at
|
1209
|
+
else None,
|
1211
1210
|
scopes=scopes,
|
1212
1211
|
)
|
1213
1212
|
|
@@ -1303,10 +1302,12 @@ class GCPServiceConnector(ServiceConnector):
|
|
1303
1302
|
)
|
1304
1303
|
|
1305
1304
|
if credentials.expiry:
|
1306
|
-
|
1307
|
-
|
1308
|
-
|
1309
|
-
|
1305
|
+
expires_at = credentials.expiry
|
1306
|
+
|
1307
|
+
if expires_at:
|
1308
|
+
# Add the UTC timezone to the expiration time, if it's not already
|
1309
|
+
# set
|
1310
|
+
expires_at = to_utc_timezone(expires_at)
|
1310
1311
|
|
1311
1312
|
return credentials, expires_at
|
1312
1313
|
|
@@ -425,7 +425,7 @@ class HyperAIOrchestrator(ContainerizedOrchestrator):
|
|
425
425
|
with tempfile.NamedTemporaryFile(mode="w", delete=True) as f:
|
426
426
|
# Define bash line and command line
|
427
427
|
bash_line = "#!/bin/bash\n"
|
428
|
-
command_line =
|
428
|
+
command_line = rf'cd {directory_name} && echo {ENV_ZENML_HYPERAI_RUN_ID}="{deployment_id}_$(date +\%s)" > .env && docker compose up -d'
|
429
429
|
|
430
430
|
# Write script to temporary file
|
431
431
|
with f.file as f_:
|
@@ -270,18 +270,22 @@ def wait_pod(
|
|
270
270
|
# Stream logs to `zenml.logger.info()`.
|
271
271
|
# TODO: can we do this without parsing all logs every time?
|
272
272
|
if stream_logs and pod_is_not_pending(resp):
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
273
|
+
try:
|
274
|
+
response = core_api.read_namespaced_pod_log(
|
275
|
+
name=pod_name,
|
276
|
+
namespace=namespace,
|
277
|
+
_preload_content=False,
|
278
|
+
)
|
279
|
+
except ApiException as e:
|
280
|
+
logger.error(f"Error reading pod logs: {e}. Retrying...")
|
281
|
+
else:
|
282
|
+
raw_data = response.data
|
283
|
+
decoded_log = raw_data.decode("utf-8", errors="replace")
|
284
|
+
logs = decoded_log.splitlines()
|
285
|
+
if len(logs) > logged_lines:
|
286
|
+
for line in logs[logged_lines:]:
|
287
|
+
logger.info(line)
|
288
|
+
logged_lines = len(logs)
|
285
289
|
|
286
290
|
# Raise an error if the pod failed.
|
287
291
|
if pod_failed(resp):
|
@@ -352,7 +352,9 @@ class BuiltInContainerMaterializer(BaseMaterializer):
|
|
352
352
|
):
|
353
353
|
type_ = find_type_by_str(type_str)
|
354
354
|
materializer_class = materializer_registry[type_]
|
355
|
-
materializer = materializer_class(
|
355
|
+
materializer = materializer_class(
|
356
|
+
uri=path_, artifact_store=self.artifact_store
|
357
|
+
)
|
356
358
|
element = materializer.load(type_)
|
357
359
|
outputs.append(element)
|
358
360
|
|
@@ -364,7 +366,9 @@ class BuiltInContainerMaterializer(BaseMaterializer):
|
|
364
366
|
materializer_class = source_utils.load(
|
365
367
|
entry["materializer"]
|
366
368
|
)
|
367
|
-
materializer = materializer_class(
|
369
|
+
materializer = materializer_class(
|
370
|
+
uri=path_, artifact_store=self.artifact_store
|
371
|
+
)
|
368
372
|
element = materializer.load(type_)
|
369
373
|
outputs.append(element)
|
370
374
|
|
@@ -427,7 +431,9 @@ class BuiltInContainerMaterializer(BaseMaterializer):
|
|
427
431
|
self.artifact_store.mkdir(element_path)
|
428
432
|
type_ = type(element)
|
429
433
|
materializer_class = materializer_registry[type_]
|
430
|
-
materializer = materializer_class(
|
434
|
+
materializer = materializer_class(
|
435
|
+
uri=element_path, artifact_store=self.artifact_store
|
436
|
+
)
|
431
437
|
materializers.append(materializer)
|
432
438
|
metadata.append(
|
433
439
|
{
|
zenml/zen_server/cloud_utils.py
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
"""Utils concerning anything concerning the cloud control plane backend."""
|
2
2
|
|
3
|
+
import logging
|
4
|
+
import threading
|
5
|
+
import time
|
3
6
|
from datetime import datetime, timedelta
|
4
7
|
from threading import RLock
|
5
8
|
from typing import Any, Dict, Optional
|
@@ -12,9 +15,12 @@ from zenml.exceptions import (
|
|
12
15
|
IllegalOperationError,
|
13
16
|
SubscriptionUpgradeRequiredError,
|
14
17
|
)
|
18
|
+
from zenml.logger import get_logger
|
15
19
|
from zenml.utils.time_utils import utc_now
|
16
20
|
from zenml.zen_server.utils import get_zenml_headers, server_config
|
17
21
|
|
22
|
+
logger = get_logger(__name__)
|
23
|
+
|
18
24
|
_cloud_connection: Optional["ZenMLCloudConnection"] = None
|
19
25
|
|
20
26
|
|
@@ -56,16 +62,16 @@ class ZenMLCloudConnection:
|
|
56
62
|
"""
|
57
63
|
url = self._config.api_url + endpoint
|
58
64
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
65
|
+
if logger.isEnabledFor(logging.DEBUG):
|
66
|
+
# Get the request ID from the current thread object
|
67
|
+
request_id = threading.current_thread().name
|
68
|
+
logger.debug(
|
69
|
+
f"[{request_id}] RBAC STATS - {method} {endpoint} started"
|
70
|
+
)
|
71
|
+
start_time = time.time()
|
72
|
+
|
73
|
+
status_code: Optional[int] = None
|
74
|
+
try:
|
69
75
|
response = self.session.request(
|
70
76
|
method=method,
|
71
77
|
url=url,
|
@@ -73,18 +79,36 @@ class ZenMLCloudConnection:
|
|
73
79
|
json=data,
|
74
80
|
timeout=self._config.http_timeout,
|
75
81
|
)
|
82
|
+
if response.status_code == 401:
|
83
|
+
# Refresh the auth token and try again
|
84
|
+
self._reset_login()
|
85
|
+
response = self.session.request(
|
86
|
+
method=method,
|
87
|
+
url=url,
|
88
|
+
params=params,
|
89
|
+
json=data,
|
90
|
+
timeout=self._config.http_timeout,
|
91
|
+
)
|
76
92
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
93
|
+
status_code = response.status_code
|
94
|
+
try:
|
95
|
+
response.raise_for_status()
|
96
|
+
except requests.HTTPError as e:
|
97
|
+
if response.status_code == 402:
|
98
|
+
raise SubscriptionUpgradeRequiredError(response.json())
|
99
|
+
elif response.status_code == 403:
|
100
|
+
raise IllegalOperationError(response.json())
|
101
|
+
else:
|
102
|
+
raise RuntimeError(
|
103
|
+
f"Failed while trying to contact the central zenml pro "
|
104
|
+
f"service: {e}"
|
105
|
+
)
|
106
|
+
finally:
|
107
|
+
if logger.isEnabledFor(logging.DEBUG):
|
108
|
+
duration = (time.time() - start_time) * 1000
|
109
|
+
logger.debug(
|
110
|
+
f"[{request_id}] RBAC STATS - {status_code} {method} "
|
111
|
+
f"{endpoint} completed in {duration:.2f}ms"
|
88
112
|
)
|
89
113
|
|
90
114
|
return response
|
@@ -44,7 +44,7 @@ from zenml.zen_server.rbac.utils import (
|
|
44
44
|
verify_permission_for_model,
|
45
45
|
)
|
46
46
|
from zenml.zen_server.utils import (
|
47
|
-
|
47
|
+
async_fastapi_endpoint_wrapper,
|
48
48
|
make_dependable,
|
49
49
|
plugin_flavor_registry,
|
50
50
|
zen_store,
|
@@ -61,7 +61,7 @@ router = APIRouter(
|
|
61
61
|
"",
|
62
62
|
responses={401: error_response, 404: error_response, 422: error_response},
|
63
63
|
)
|
64
|
-
@
|
64
|
+
@async_fastapi_endpoint_wrapper
|
65
65
|
def list_actions(
|
66
66
|
action_filter_model: ActionFilter = Depends(make_dependable(ActionFilter)),
|
67
67
|
hydrate: bool = False,
|
@@ -132,7 +132,7 @@ def list_actions(
|
|
132
132
|
"/{action_id}",
|
133
133
|
responses={401: error_response, 404: error_response, 422: error_response},
|
134
134
|
)
|
135
|
-
@
|
135
|
+
@async_fastapi_endpoint_wrapper
|
136
136
|
def get_action(
|
137
137
|
action_id: UUID,
|
138
138
|
hydrate: bool = True,
|
@@ -179,7 +179,7 @@ def get_action(
|
|
179
179
|
"",
|
180
180
|
responses={401: error_response, 409: error_response, 422: error_response},
|
181
181
|
)
|
182
|
-
@
|
182
|
+
@async_fastapi_endpoint_wrapper
|
183
183
|
def create_action(
|
184
184
|
action: ActionRequest,
|
185
185
|
_: AuthContext = Security(authorize),
|
@@ -225,7 +225,7 @@ def create_action(
|
|
225
225
|
"/{action_id}",
|
226
226
|
responses={401: error_response, 404: error_response, 422: error_response},
|
227
227
|
)
|
228
|
-
@
|
228
|
+
@async_fastapi_endpoint_wrapper
|
229
229
|
def update_action(
|
230
230
|
action_id: UUID,
|
231
231
|
action_update: ActionUpdate,
|
@@ -280,7 +280,7 @@ def update_action(
|
|
280
280
|
"/{action_id}",
|
281
281
|
responses={401: error_response, 404: error_response, 422: error_response},
|
282
282
|
)
|
283
|
-
@
|
283
|
+
@async_fastapi_endpoint_wrapper
|
284
284
|
def delete_action(
|
285
285
|
action_id: UUID,
|
286
286
|
force: bool = False,
|
@@ -36,7 +36,7 @@ from zenml.zen_server.rbac.endpoint_utils import (
|
|
36
36
|
)
|
37
37
|
from zenml.zen_server.rbac.models import ResourceType
|
38
38
|
from zenml.zen_server.utils import (
|
39
|
-
|
39
|
+
async_fastapi_endpoint_wrapper,
|
40
40
|
make_dependable,
|
41
41
|
zen_store,
|
42
42
|
)
|
@@ -52,7 +52,7 @@ artifact_router = APIRouter(
|
|
52
52
|
"",
|
53
53
|
responses={401: error_response, 404: error_response, 422: error_response},
|
54
54
|
)
|
55
|
-
@
|
55
|
+
@async_fastapi_endpoint_wrapper
|
56
56
|
def list_artifacts(
|
57
57
|
artifact_filter_model: ArtifactFilter = Depends(
|
58
58
|
make_dependable(ArtifactFilter)
|
@@ -83,7 +83,7 @@ def list_artifacts(
|
|
83
83
|
"",
|
84
84
|
responses={401: error_response, 409: error_response, 422: error_response},
|
85
85
|
)
|
86
|
-
@
|
86
|
+
@async_fastapi_endpoint_wrapper
|
87
87
|
def create_artifact(
|
88
88
|
artifact: ArtifactRequest,
|
89
89
|
_: AuthContext = Security(authorize),
|
@@ -106,7 +106,7 @@ def create_artifact(
|
|
106
106
|
"/{artifact_id}",
|
107
107
|
responses={401: error_response, 404: error_response, 422: error_response},
|
108
108
|
)
|
109
|
-
@
|
109
|
+
@async_fastapi_endpoint_wrapper
|
110
110
|
def get_artifact(
|
111
111
|
artifact_id: UUID,
|
112
112
|
hydrate: bool = True,
|
@@ -133,7 +133,7 @@ def get_artifact(
|
|
133
133
|
"/{artifact_id}",
|
134
134
|
responses={401: error_response, 404: error_response, 422: error_response},
|
135
135
|
)
|
136
|
-
@
|
136
|
+
@async_fastapi_endpoint_wrapper
|
137
137
|
def update_artifact(
|
138
138
|
artifact_id: UUID,
|
139
139
|
artifact_update: ArtifactUpdate,
|
@@ -160,7 +160,7 @@ def update_artifact(
|
|
160
160
|
"/{artifact_id}",
|
161
161
|
responses={401: error_response, 404: error_response, 422: error_response},
|
162
162
|
)
|
163
|
-
@
|
163
|
+
@async_fastapi_endpoint_wrapper
|
164
164
|
def delete_artifact(
|
165
165
|
artifact_id: UUID,
|
166
166
|
_: AuthContext = Security(authorize),
|
@@ -66,7 +66,7 @@ from zenml.zen_server.rbac.utils import (
|
|
66
66
|
get_allowed_resource_ids,
|
67
67
|
)
|
68
68
|
from zenml.zen_server.utils import (
|
69
|
-
|
69
|
+
async_fastapi_endpoint_wrapper,
|
70
70
|
make_dependable,
|
71
71
|
set_filter_project_scope,
|
72
72
|
zen_store,
|
@@ -83,7 +83,7 @@ artifact_version_router = APIRouter(
|
|
83
83
|
"",
|
84
84
|
responses={401: error_response, 404: error_response, 422: error_response},
|
85
85
|
)
|
86
|
-
@
|
86
|
+
@async_fastapi_endpoint_wrapper
|
87
87
|
def list_artifact_versions(
|
88
88
|
artifact_version_filter_model: ArtifactVersionFilter = Depends(
|
89
89
|
make_dependable(ArtifactVersionFilter)
|
@@ -127,7 +127,7 @@ def list_artifact_versions(
|
|
127
127
|
"",
|
128
128
|
responses={401: error_response, 409: error_response, 422: error_response},
|
129
129
|
)
|
130
|
-
@
|
130
|
+
@async_fastapi_endpoint_wrapper
|
131
131
|
def create_artifact_version(
|
132
132
|
artifact_version: ArtifactVersionRequest,
|
133
133
|
_: AuthContext = Security(authorize),
|
@@ -150,7 +150,7 @@ def create_artifact_version(
|
|
150
150
|
BATCH,
|
151
151
|
responses={401: error_response, 409: error_response, 422: error_response},
|
152
152
|
)
|
153
|
-
@
|
153
|
+
@async_fastapi_endpoint_wrapper
|
154
154
|
def batch_create_artifact_version(
|
155
155
|
artifact_versions: List[ArtifactVersionRequest],
|
156
156
|
_: AuthContext = Security(authorize),
|
@@ -173,7 +173,7 @@ def batch_create_artifact_version(
|
|
173
173
|
"/{artifact_version_id}",
|
174
174
|
responses={401: error_response, 404: error_response, 422: error_response},
|
175
175
|
)
|
176
|
-
@
|
176
|
+
@async_fastapi_endpoint_wrapper
|
177
177
|
def get_artifact_version(
|
178
178
|
artifact_version_id: UUID,
|
179
179
|
hydrate: bool = True,
|
@@ -200,7 +200,7 @@ def get_artifact_version(
|
|
200
200
|
"/{artifact_version_id}",
|
201
201
|
responses={401: error_response, 404: error_response, 422: error_response},
|
202
202
|
)
|
203
|
-
@
|
203
|
+
@async_fastapi_endpoint_wrapper
|
204
204
|
def update_artifact_version(
|
205
205
|
artifact_version_id: UUID,
|
206
206
|
artifact_version_update: ArtifactVersionUpdate,
|
@@ -227,7 +227,7 @@ def update_artifact_version(
|
|
227
227
|
"/{artifact_version_id}",
|
228
228
|
responses={401: error_response, 404: error_response, 422: error_response},
|
229
229
|
)
|
230
|
-
@
|
230
|
+
@async_fastapi_endpoint_wrapper
|
231
231
|
def delete_artifact_version(
|
232
232
|
artifact_version_id: UUID,
|
233
233
|
_: AuthContext = Security(authorize),
|
@@ -248,7 +248,7 @@ def delete_artifact_version(
|
|
248
248
|
"",
|
249
249
|
responses={401: error_response, 404: error_response, 422: error_response},
|
250
250
|
)
|
251
|
-
@
|
251
|
+
@async_fastapi_endpoint_wrapper
|
252
252
|
def prune_artifact_versions(
|
253
253
|
project_name_or_id: Union[str, UUID],
|
254
254
|
only_versions: bool = True,
|
@@ -275,7 +275,7 @@ def prune_artifact_versions(
|
|
275
275
|
"/{artifact_version_id}" + VISUALIZE,
|
276
276
|
responses={401: error_response, 404: error_response, 422: error_response},
|
277
277
|
)
|
278
|
-
@
|
278
|
+
@async_fastapi_endpoint_wrapper
|
279
279
|
def get_artifact_visualization(
|
280
280
|
artifact_version_id: UUID,
|
281
281
|
index: int = 0,
|
@@ -303,7 +303,7 @@ def get_artifact_visualization(
|
|
303
303
|
"/{artifact_version_id}" + DOWNLOAD_TOKEN,
|
304
304
|
responses={401: error_response, 404: error_response, 422: error_response},
|
305
305
|
)
|
306
|
-
@
|
306
|
+
@async_fastapi_endpoint_wrapper
|
307
307
|
def get_artifact_download_token(
|
308
308
|
artifact_version_id: UUID,
|
309
309
|
_: AuthContext = Security(authorize),
|
@@ -334,7 +334,7 @@ def get_artifact_download_token(
|
|
334
334
|
"/{artifact_version_id}" + DATA,
|
335
335
|
responses={401: error_response, 404: error_response, 422: error_response},
|
336
336
|
)
|
337
|
-
@
|
337
|
+
@async_fastapi_endpoint_wrapper
|
338
338
|
def download_artifact_data(
|
339
339
|
artifact_version_id: UUID, token: str
|
340
340
|
) -> FileResponse:
|
@@ -71,8 +71,8 @@ from zenml.zen_server.rbac.utils import (
|
|
71
71
|
verify_permission_for_model,
|
72
72
|
)
|
73
73
|
from zenml.zen_server.utils import (
|
74
|
+
async_fastapi_endpoint_wrapper,
|
74
75
|
get_ip_location,
|
75
|
-
handle_exceptions,
|
76
76
|
server_config,
|
77
77
|
zen_store,
|
78
78
|
)
|
@@ -222,11 +222,11 @@ class OAuthLoginRequestForm:
|
|
222
222
|
LOGIN,
|
223
223
|
response_model=Union[OAuthTokenResponse, OAuthRedirectResponse],
|
224
224
|
)
|
225
|
+
@async_fastapi_endpoint_wrapper
|
225
226
|
@rate_limit_requests(
|
226
227
|
day_limit=server_config().login_rate_limit_day,
|
227
228
|
minute_limit=server_config().login_rate_limit_minute,
|
228
229
|
)
|
229
|
-
@handle_exceptions
|
230
230
|
def token(
|
231
231
|
request: Request,
|
232
232
|
response: Response,
|
@@ -341,6 +341,7 @@ def logout(
|
|
341
341
|
DEVICE_AUTHORIZATION,
|
342
342
|
response_model=OAuthDeviceAuthorizationResponse,
|
343
343
|
)
|
344
|
+
@async_fastapi_endpoint_wrapper
|
344
345
|
def device_authorization(
|
345
346
|
request: Request,
|
346
347
|
client_id: UUID = Form(...),
|
@@ -471,7 +472,7 @@ def device_authorization(
|
|
471
472
|
API_TOKEN,
|
472
473
|
response_model=str,
|
473
474
|
)
|
474
|
-
@
|
475
|
+
@async_fastapi_endpoint_wrapper
|
475
476
|
def api_token(
|
476
477
|
token_type: APITokenType = APITokenType.GENERIC,
|
477
478
|
expires_in: Optional[int] = None,
|