Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 5
Chore/papi 4760 stop using download url#507
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -10,7 +10,7 @@ | ||
| import requests | ||
| from loguru import logger | ||
| from aignostics.platform import ItemOutput, ItemState, Run, generate_signed_url | ||
| from aignostics.platform import ItemOutput, ItemState, OutputArtifactElement, Run, generate_signed_url | ||
| from aignostics.utils import sanitize_path_component | ||
| from ._models import DownloadProgress, DownloadProgressState | ||
| @@ -146,6 +146,44 @@ def update_progress( | ||
| download_progress_queue.put_nowait(progress) | ||
| def _resolve_artifact_url( | ||
| artifact: OutputArtifactElement, | ||
| run_id: str, | ||
| get_artifact_download_url: Callable[[str, str], str] | None, | ||
| ) -> str | None: | ||
| """Resolve the download URL for an artifact. | ||
| Tries the new file endpoint first (via get_artifact_download_url), then falls back to | ||
| the deprecated download_url field on the artifact if the endpoint fails. | ||
| Args: | ||
| artifact: The artifact object with optional output_artifact_id and download_url. | ||
| run_id: The run ID, passed to get_artifact_download_url. | ||
| get_artifact_download_url: Callable for the new endpoint, or None to skip. | ||
| Returns: | ||
| str | None: The resolved download URL, or None if unavailable. | ||
| Raises: | ||
| Exception: Re-raises if the new endpoint fails and no fallback download_url exists. | ||
| """ | ||
| if get_artifact_download_url and artifact.output_artifact_id: | ||
| try: | ||
| return get_artifact_download_url(run_id, artifact.output_artifact_id) | ||
| except Exception as e: | ||
| fallback_url: str | None = getattr(artifact, "download_url", None) | ||
| if fallback_url: | ||
| logger.warning( | ||
| "Failed to resolve download URL via file endpoint for artifact {} ({}). " | ||
| "Falling back to deprecated download_url field.", | ||
| artifact.output_artifact_id, | ||
| e, | ||
| ) | ||
| return fallback_url | ||
| raise | ||
| return getattr(artifact, "download_url", None) | ||
| def download_available_items( # noqa: PLR0913, PLR0917 | ||
| progress: DownloadProgress, | ||
| application_run: Run, | ||
| @@ -154,6 +192,7 @@ def download_available_items( # noqa: PLR0913, PLR0917 | ||
| create_subdirectory_per_item: bool = False, | ||
| download_progress_queue: Any | None = None, # noqa: ANN401 | ||
| download_progress_callable: Callable | None = None, # type: ignore[type-arg] | ||
| get_artifact_download_url: Callable[[str, str], str] | None = None, | ||
| ) -> None: | ||
| """Download items that are available and not yet downloaded. | ||
| @@ -165,6 +204,9 @@ def download_available_items( # noqa: PLR0913, PLR0917 | ||
| create_subdirectory_per_item (bool): Whether to create a subdirectory for each item. | ||
| download_progress_queue (Queue | None): Queue for GUI progress updates. | ||
| download_progress_callable (Callable | None): Callback for CLI progress updates. | ||
| get_artifact_download_url (Callable[[str, str], str] | None): Callback that takes | ||
| (run_id, artifact_id) and returns a presigned download URL. If None, falls back | ||
| to artifact.download_url (deprecated). | ||
| """ | ||
| items = list(application_run.results()) | ||
| progress.item_count = len(items) | ||
| @@ -201,9 +243,16 @@ def download_available_items( # noqa: PLR0913, PLR0917 | ||
| progress.artifact = artifact | ||
| update_progress(progress, download_progress_callable, download_progress_queue) | ||
| # Resolve artifact download URL via the new file endpoint, with fallback | ||
| artifact_url = _resolve_artifact_url(artifact, application_run.run_id, get_artifact_download_url) | ||
| if not artifact_url: | ||
| logger.warning("No download URL available for artifact {}", artifact.output_artifact_id) | ||
| continue | ||
nahua-aignx marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| download_item_artifact( | ||
| progress, | ||
| artifact, | ||
| artifact_url, | ||
| item_directory, | ||
| item.external_id if not create_subdirectory_per_item else "", | ||
| download_progress_queue, | ||
| @@ -216,6 +265,7 @@ def download_available_items( # noqa: PLR0913, PLR0917 | ||
| def download_item_artifact( # noqa: PLR0913, PLR0917 | ||
| progress: DownloadProgress, | ||
| artifact: Any, # noqa: ANN401 | ||
| artifact_download_url: str, | ||
| destination_directory: Path, | ||
| prefix: str = "", | ||
| download_progress_queue: Any | None = None, # noqa: ANN401 | ||
| @@ -226,6 +276,7 @@ def download_item_artifact( # noqa: PLR0913, PLR0917 | ||
| Args: | ||
| progress (DownloadProgress): Progress tracking object for GUI or CLI updates. | ||
| artifact (Any): The artifact to download. | ||
| artifact_download_url (str): The presigned URL to download the artifact from. | ||
| destination_directory (Path): Directory to save the file. | ||
| prefix (str): Prefix for the file name, if needed. | ||
| download_progress_queue (Queue | None): Queue for GUI progress updates. | ||
| @@ -260,7 +311,7 @@ def download_item_artifact( # noqa: PLR0913, PLR0917 | ||
| download_file_with_progress( | ||
| progress, | ||
| artifact.download_url, | ||
| artifact_download_url, | ||
| artifact_path, | ||
| metadata_checksum, | ||
| download_progress_queue, | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -14,8 +14,9 @@ | ||
| ui, # noq | ||
| ) | ||
| from nicegui import run as nicegui_run | ||
| from nicegui.events import ClickEventArguments | ||
| from aignostics.platform import ItemOutput, ItemResult, ItemState, RunState | ||
| from aignostics.platform import ItemOutput, ItemResult, ItemState, Run, RunState | ||
| from aignostics.third_party.showinfm.showinfm import show_in_file_manager | ||
| from aignostics.utils import GUILocalFilePicker, get_user_data_directory | ||
| @@ -338,9 +339,9 @@ async def start_download() -> None: | ||
| # Activate the timer now that download is starting | ||
| progress_timer.activate() | ||
| download_button.disable() | ||
| download_button.props(add="loading") | ||
| try: | ||
| download_button.disable() | ||
| download_button.props(add="loading") | ||
| results_folder = await nicegui_run.cpu_bound( | ||
| Service.application_run_download_static, | ||
| run_id=run.run_id, | ||
| @@ -364,19 +365,24 @@ async def start_download() -> None: | ||
| else: | ||
| ui.notify("Download completed.", type="positive") | ||
| show_in_file_manager(str(results_folder)) | ||
| except ValueError as e: | ||
| except Exception as e: | ||
nahua-aignx marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| logger.exception( | ||
| "Download failed for run {} (qupath_project={}, marimo={}, folder={})", | ||
| run.run_id, | ||
| current_qupath_project, | ||
| current_marimo, | ||
| current_folder, | ||
| ) | ||
| ui.notify(f"Download failed: {e}", type="negative", multi_line=True) | ||
| finally: | ||
| progress_timer.deactivate() | ||
| progress_state["queue"] = None | ||
| return | ||
| progress_timer.deactivate() | ||
| progress_state["queue"] = None | ||
| download_button.props(remove="loading") | ||
| download_button.enable() | ||
| download_item_status.set_visibility(False) | ||
| download_item_progress.set_visibility(False) | ||
| download_artifact_status.set_visibility(False) | ||
| download_artifact_progress.set_visibility(False) | ||
| download_button.props(remove="loading") | ||
| download_button.enable() | ||
| download_item_status.set_visibility(False) | ||
| download_item_progress.set_visibility(False) | ||
| download_artifact_status.set_visibility(False) | ||
| download_artifact_progress.set_visibility(False) | ||
| ui.separator() | ||
| with ui.row(align_items="end").classes("w-full justify-end"): | ||
| @@ -781,29 +787,85 @@ def render_item(item: ItemResult) -> None: # noqa: C901, PLR0912, PLR0915 | ||
| icon=mime_type_to_icon(mime_type), | ||
| group="artifacts", | ||
| ).classes("w-full"): | ||
| if artifact.download_url: | ||
| url = artifact.download_url | ||
| if artifact.output_artifact_id: | ||
| artifact_id = artifact.output_artifact_id | ||
| title = artifact.name | ||
| metadata = artifact.metadata | ||
| with ui.button_group(): | ||
| if mime_type == "image/tiff": | ||
| ui.button( | ||
| preview_button = ui.button( | ||
| "Preview", | ||
| icon=mime_type_to_icon(mime_type), | ||
| on_click=lambda _, url=url, title=title: tiff_dialog_open(title, url), | ||
| ) | ||
| async def _preview_tiff( | ||
| _: ClickEventArguments, | ||
| aid: str = artifact_id, | ||
| t: str = title, | ||
| _run: Run = run, | ||
| _btn: ui.button = preview_button, | ||
| ) -> None: | ||
| try: | ||
| _btn.props(add="loading") | ||
| url = await nicegui_run.io_bound( | ||
| _run.get_artifact_download_url, aid | ||
| ) | ||
| tiff_dialog_open(t, url) | ||
| except Exception as e: | ||
| ui.notify(f"Failed to resolve preview URL: {e}", type="warning") | ||
| finally: | ||
| _btn.props(remove="loading") | ||
| preview_button.on_click(_preview_tiff) | ||
| if mime_type == "text/csv": | ||
| ui.button( | ||
| preview_button = ui.button( | ||
| "Preview", | ||
| icon=mime_type_to_icon(mime_type), | ||
| on_click=lambda _, url=url, title=title: csv_dialog_open(title, url), | ||
| ) | ||
| if url: | ||
| ui.button( | ||
| text="Download", | ||
| icon="cloud_download", | ||
| on_click=lambda _, url=url: webbrowser.open(url), | ||
| ) | ||
| async def _preview_csv( | ||
| _: ClickEventArguments, | ||
| aid: str = artifact_id, | ||
| t: str = title, | ||
| _run: Run = run, | ||
| _btn: ui.button = preview_button, | ||
| ) -> None: | ||
| try: | ||
| _btn.props(add="loading") | ||
| url = await nicegui_run.io_bound( | ||
| _run.get_artifact_download_url, aid | ||
| ) | ||
| csv_dialog_open(t, url) | ||
| except Exception as e: | ||
| ui.notify(f"Failed to resolve preview URL: {e}", type="warning") | ||
| finally: | ||
| _btn.props(remove="loading") | ||
| preview_button.on_click(_preview_csv) | ||
| artifact_dl_button = ui.button( | ||
| text="Download", | ||
| icon="cloud_download", | ||
| ) | ||
| async def _download_artifact( | ||
| _: ClickEventArguments, | ||
| aid: str = artifact_id, | ||
| _run: Run = run, | ||
| _btn: ui.button = artifact_dl_button, | ||
| ) -> None: | ||
| try: | ||
| _btn.props(add="loading") | ||
| url = await nicegui_run.io_bound(_run.get_artifact_download_url, aid) | ||
| webbrowser.open(url) | ||
| except Exception as e: | ||
| ui.notify(f"Failed to resolve download URL: {e}", type="warning") | ||
| finally: | ||
| _btn.props(remove="loading") | ||
| artifact_dl_button.on_click(_download_artifact) | ||
| if metadata: | ||
| ui.button( | ||
| text="Schema", | ||
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.