diff --git a/optuna_dashboard/artifact/__init__.py b/optuna_dashboard/artifact/__init__.py index 06cf2721..d804424b 100644 --- a/optuna_dashboard/artifact/__init__.py +++ b/optuna_dashboard/artifact/__init__.py @@ -3,49 +3,39 @@ from __future__ import annotations import json import mimetypes import os.path -from typing import Any -from typing import BinaryIO -from typing import Optional +from typing import TYPE_CHECKING import uuid from bottle import Bottle from bottle import response import optuna -from optuna.storages import BaseStorage -try: - from typing import Protocol +if TYPE_CHECKING: + from typing import Any + from typing import Optional from typing import TypedDict -except ImportError: - from typing_extensions import Protocol # type: ignore - from typing_extensions import TypedDict # type: ignore + + from optuna.storages import BaseStorage + + from .backend import ArtifactBackend + + ArtifactMeta = TypedDict( + "ArtifactMeta", + { + "artifact_id": str, + "mimetype": str, + "encoding": str, + "filename": str, + }, + ) ARTIFACTS_ATTR_PREFIX = "dashboard:artifacts:" -ArtifactMeta = TypedDict( - "ArtifactMeta", - { - "artifact_id": str, - "mimetype": str, - "encoding": str, - "filename": str, - }, -) - - -class ArtifactBackend(Protocol): - def open(self, artifact_id: str) -> BinaryIO: - ... - - def write(self, artifact_id: str, content_body: BinaryIO) -> None: - ... - - def register_artifact_route( - app: Bottle, storage: BaseStorage, artifact_backend: ArtifactBackend + app: Bottle, storage: BaseStorage, artifact_backend: Optional[ArtifactBackend] ) -> None: @app.get("/artifacts//") def proxy_artifact(trial_id: int, artifact_id: str) -> bytes: @@ -59,6 +49,15 @@ def register_artifact_route( body = f.read() return body + @app.delete("/artifacts/") + def delete_artifact(artifact_id: str) -> bytes: + if artifact_backend is None: + response.status = 400 # Bad Request + return b"Cannot access to the artifacts." + artifact_backend.remove(artifact_id) + response.status = 204 + return b"" + def upload_artifact( backend: ArtifactBackend, diff --git a/optuna_dashboard/artifact/backend.py b/optuna_dashboard/artifact/backend.py new file mode 100644 index 00000000..5845b0f9 --- /dev/null +++ b/optuna_dashboard/artifact/backend.py @@ -0,0 +1,20 @@ +from __future__ import annotations + +from typing import BinaryIO + + +try: + from typing import Protocol +except ImportError: + from typing_extensions import Protocol # type: ignore + + +class ArtifactBackend(Protocol): + def open(self, artifact_id: str) -> BinaryIO: + ... + + def write(self, artifact_id: str, content_body: BinaryIO) -> None: + ... + + def remove(self, artifact_id: str) -> None: + ... diff --git a/optuna_dashboard/artifact/file_system.py b/optuna_dashboard/artifact/file_system.py index 97d74ef8..e4674b62 100644 --- a/optuna_dashboard/artifact/file_system.py +++ b/optuna_dashboard/artifact/file_system.py @@ -4,7 +4,7 @@ import os from typing import BinaryIO from typing import TYPE_CHECKING -from . import ArtifactBackend +from .backend import ArtifactBackend class FileSystemBackend: @@ -20,6 +20,10 @@ class FileSystemBackend: with open(filepath, "wb") as f: f.write(content_body.read()) + def remove(self, artifact_id: str) -> None: + filepath = os.path.join(self._base_path, artifact_id) + os.remove(filepath) + if TYPE_CHECKING: # A mypy-runtime assertion to ensure that LocalArtifactBackend