aignostics 0.2.36__tar.gz → 0.2.39__tar.gz
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.
- {aignostics-0.2.36 → aignostics-0.2.39}/PKG-INFO +1 -1
- {aignostics-0.2.36 → aignostics-0.2.39}/examples/notebook.py +1 -1
- {aignostics-0.2.36 → aignostics-0.2.39}/pyproject.toml +2 -2
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/__init__.py +3 -1
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/application/_cli.py +1 -1
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/application/_service.py +5 -5
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/bucket/_cli.py +0 -11
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/bucket/_service.py +4 -4
- aignostics-0.2.39/src/aignostics/bucket/_settings.py +86 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/constants.py +1 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/notebook/_notebook.py +2 -3
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/platform/_service.py +2 -2
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/platform/_settings.py +29 -11
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/qupath/_cli.py +0 -27
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/qupath/_service.py +14 -9
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/utils/_settings.py +7 -1
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/wsi/_service.py +6 -7
- aignostics-0.2.36/src/aignostics/bucket/_settings.py +0 -53
- {aignostics-0.2.36 → aignostics-0.2.39}/.gitignore +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/LICENSE +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/README.md +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/codegen/out/.openapi-generator/FILES +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/codegen/out/.openapi-generator/VERSION +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/codegen/out/aignx/codegen/api/public_api.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/codegen/out/aignx/codegen/api_client.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/codegen/out/aignx/codegen/api_response.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/codegen/out/aignx/codegen/configuration.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/codegen/out/aignx/codegen/exceptions.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/codegen/out/aignx/codegen/models/__init__.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/codegen/out/aignx/codegen/models/application_read_response.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/codegen/out/aignx/codegen/models/application_run_status.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/codegen/out/aignx/codegen/models/application_version_read_response.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/codegen/out/aignx/codegen/models/http_validation_error.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/codegen/out/aignx/codegen/models/input_artifact_creation_request.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/codegen/out/aignx/codegen/models/input_artifact_read_response.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/codegen/out/aignx/codegen/models/item_creation_request.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/codegen/out/aignx/codegen/models/item_result_read_response.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/codegen/out/aignx/codegen/models/item_status.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/codegen/out/aignx/codegen/models/output_artifact_read_response.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/codegen/out/aignx/codegen/models/output_artifact_result_read_response.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/codegen/out/aignx/codegen/models/output_artifact_scope.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/codegen/out/aignx/codegen/models/payload_input_artifact.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/codegen/out/aignx/codegen/models/payload_item.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/codegen/out/aignx/codegen/models/payload_output_artifact.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/codegen/out/aignx/codegen/models/run_creation_request.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/codegen/out/aignx/codegen/models/run_creation_response.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/codegen/out/aignx/codegen/models/run_read_response.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/codegen/out/aignx/codegen/models/transfer_urls.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/codegen/out/aignx/codegen/models/user_payload.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/codegen/out/aignx/codegen/models/validation_error.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/codegen/out/aignx/codegen/models/validation_error_loc_inner.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/codegen/out/aignx/codegen/rest.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/codegen/out/docs/PublicApi.md +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/examples/__init__.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/examples/e2e.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/examples/notebook.ipynb +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/examples/script.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/application/__init__.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/application/_gui/_frame.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/application/_gui/_page_application_describe.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/application/_gui/_page_application_run_describe.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/application/_gui/_page_builder.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/application/_gui/_page_index.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/application/_gui/_utils.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/application/_gui/assets/canceled.lottie +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/application/_gui/assets/done.lottie +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/application/_gui/assets/empty.lottie +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/application/_gui/assets/error.lottie +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/application/_gui/assets/error_alt.lottie +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/application/_gui/assets/home-card-1.png +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/application/_gui/assets/home-card-2.png +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/application/_gui/assets/home-card-3.png +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/application/_gui/assets/home-card-4.png +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/application/_gui/assets/home-card-5.png +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/application/_gui/assets/image-not-found.png +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/application/_gui/assets/pending.lottie +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/application/_gui/assets/pending_alt.lottie +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/application/_gui/assets/ruo.png +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/application/_gui/assets/ruo.svg +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/application/_settings.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/application/_utils.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/bucket/__init__.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/bucket/_gui.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/bucket/assets/Google-Cloud-logo.png +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/bucket/assets/Google-Cloud-logo.svg +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/cli.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/dataset/__init__.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/dataset/_cli.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/dataset/_gui.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/dataset/_idc_index.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/dataset/_service.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/dataset/assets/NIH-IDC-logo.svg +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/gui/__init__.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/gui/_frame.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/gui/_theme.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/gui/assets/cabin-v27-latin-regular.woff2 +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/gui/assets/logo.png +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/notebook/__init__.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/notebook/_gui.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/notebook/_service.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/notebook/assets/python.lottie +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/platform/__init__.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/platform/_authentication.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/platform/_client.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/platform/_constants.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/platform/_messages.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/platform/_utils.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/platform/resources/__init__.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/platform/resources/applications.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/platform/resources/runs.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/platform/resources/utils.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/qupath/__init__.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/qupath/_gui.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/qupath/_settings.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/qupath/annotate.groovy +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/qupath/assets/download.lottie +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/qupath/assets/microscope.lottie +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/qupath/assets/update.lottie +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/system/__init__.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/system/_cli.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/system/_exceptions.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/system/_gui.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/system/_service.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/system/_settings.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/system/assets/system.lottie +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/utils/.vendored/bottle.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/utils/__init__.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/utils/_cli.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/utils/_console.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/utils/_constants.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/utils/_di.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/utils/_fs.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/utils/_gui.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/utils/_health.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/utils/_log.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/utils/_logfire.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/utils/_notebook.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/utils/_process.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/utils/_sentry.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/utils/_service.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/utils/boot.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/wsi/__init__.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/wsi/_cli.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/wsi/_gui.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/wsi/_openslide_handler.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/wsi/_pydicom_handler.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/wsi/_utils.py +0 -0
- {aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/wsi/assets/fallback.png +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: aignostics
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.39
|
|
4
4
|
Summary: 🔬 Python SDK providing access to the Aignostics Platform. Includes Aignostics Launchpad (Desktop Application), Aignostics CLI (Command-Line Interface), example notebooks, and Aignostics Client Library.
|
|
5
5
|
Project-URL: Homepage, https://aignostics.readthedocs.io/en/latest/
|
|
6
6
|
Project-URL: Documentation, https://aignostics.readthedocs.io/en/latest/
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "aignostics"
|
|
3
|
-
version = "0.2.
|
|
3
|
+
version = "0.2.39"
|
|
4
4
|
description = "🔬 Python SDK providing access to the Aignostics Platform. Includes Aignostics Launchpad (Desktop Application), Aignostics CLI (Command-Line Interface), example notebooks, and Aignostics Client Library."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
authors = [
|
|
@@ -356,7 +356,7 @@ source = ["src/"]
|
|
|
356
356
|
|
|
357
357
|
|
|
358
358
|
[tool.bumpversion]
|
|
359
|
-
current_version = "0.2.
|
|
359
|
+
current_version = "0.2.39"
|
|
360
360
|
parse = "(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)"
|
|
361
361
|
serialize = ["{major}.{minor}.{patch}"]
|
|
362
362
|
search = "{current_version}"
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import os
|
|
4
4
|
|
|
5
|
-
from .constants import MODULES_TO_INSTRUMENT
|
|
5
|
+
from .constants import MODULES_TO_INSTRUMENT, WSI_SUPPORTED_FILE_EXTENSIONS
|
|
6
6
|
from .utils.boot import boot
|
|
7
7
|
|
|
8
8
|
# Add scheme to HTTP proxy environment variables if missing
|
|
@@ -12,3 +12,5 @@ for proxy_var in ["HTTP_PROXY", "HTTPS_PROXY"]:
|
|
|
12
12
|
os.environ[proxy_var] = f"http://{proxy_url}"
|
|
13
13
|
|
|
14
14
|
boot(modules_to_instrument=MODULES_TO_INSTRUMENT)
|
|
15
|
+
|
|
16
|
+
__all__ = ["WSI_SUPPORTED_FILE_EXTENSIONS"]
|
|
@@ -300,7 +300,7 @@ def run_prepare(
|
|
|
300
300
|
) -> None:
|
|
301
301
|
"""Prepare metadata CSV file required for submitting a run.
|
|
302
302
|
|
|
303
|
-
(1) Scans source_directory for whole slide images
|
|
303
|
+
(1) Scans source_directory for whole slide images.
|
|
304
304
|
(2) Extracts metadata from whole slide images such as width, height, mpp.
|
|
305
305
|
(3) Creates CSV file with columns as required by the given application version.
|
|
306
306
|
(4) Optionally applies mappings to amend the metadata CSV file for columns
|
|
@@ -15,6 +15,7 @@ import requests
|
|
|
15
15
|
from pydantic import BaseModel, computed_field
|
|
16
16
|
|
|
17
17
|
from aignostics.bucket import Service as BucketService
|
|
18
|
+
from aignostics.constants import WSI_SUPPORTED_FILE_EXTENSIONS
|
|
18
19
|
from aignostics.platform import (
|
|
19
20
|
LIST_APPLICATION_RUNS_MAX_PAGE_SIZE,
|
|
20
21
|
ApiException,
|
|
@@ -154,13 +155,13 @@ class Service(BaseService):
|
|
|
154
155
|
"""Initialize service."""
|
|
155
156
|
super().__init__(Settings) # automatically loads and validates the settings
|
|
156
157
|
|
|
157
|
-
def info(self) -> dict[str, Any]:
|
|
158
|
+
def info(self) -> dict[str, Any]:
|
|
158
159
|
"""Determine info of this service.
|
|
159
160
|
|
|
160
161
|
Returns:
|
|
161
162
|
dict[str,Any]: The info of this service.
|
|
162
163
|
"""
|
|
163
|
-
return {}
|
|
164
|
+
return {"settings": self._settings.model_dump()}
|
|
164
165
|
|
|
165
166
|
def health(self) -> Health: # noqa: PLR6301
|
|
166
167
|
"""Determine health of this service.
|
|
@@ -350,7 +351,7 @@ class Service(BaseService):
|
|
|
350
351
|
"""Generate metadata from the source directory.
|
|
351
352
|
|
|
352
353
|
Steps:
|
|
353
|
-
1. Recursively files ending with
|
|
354
|
+
1. Recursively files ending with supported extensions in the source directory
|
|
354
355
|
2. Creates a dict with the following columns
|
|
355
356
|
- reference (str): The reference of the file, by default equivalent to the absolute file name
|
|
356
357
|
- source (str): The absolute filename
|
|
@@ -385,10 +386,9 @@ class Service(BaseService):
|
|
|
385
386
|
application_version = Service().application_version(application_version_id, use_latest_if_no_version_given=True) # noqa: F841
|
|
386
387
|
|
|
387
388
|
metadata = []
|
|
388
|
-
file_extensions = [".tiff", ".tif", ".svs", ".dcm"]
|
|
389
389
|
|
|
390
390
|
try:
|
|
391
|
-
for extension in
|
|
391
|
+
for extension in list(WSI_SUPPORTED_FILE_EXTENSIONS):
|
|
392
392
|
for file_path in source_directory.glob(f"**/*{extension}"):
|
|
393
393
|
# Generate CRC32C checksum with google_crc32c and encode as base64
|
|
394
394
|
hash_sum = google_crc32c.Checksum() # type: ignore[no-untyped-call]
|
|
@@ -59,11 +59,9 @@ def upload(
|
|
|
59
59
|
|
|
60
60
|
console.print(f"Uploading {source} to bucket...")
|
|
61
61
|
|
|
62
|
-
# Create a counter for total bytes
|
|
63
62
|
total_bytes = 0
|
|
64
63
|
files_count = 0
|
|
65
64
|
|
|
66
|
-
# First, calculate total size and count files
|
|
67
65
|
if source.is_file():
|
|
68
66
|
total_bytes = source.stat().st_size
|
|
69
67
|
files_count = 1
|
|
@@ -75,14 +73,9 @@ def upload(
|
|
|
75
73
|
|
|
76
74
|
console.print(f"Found {files_count} files with total size of {humanize.naturalsize(total_bytes)}")
|
|
77
75
|
|
|
78
|
-
# Generate base prefix with placeholders replaced
|
|
79
76
|
username = psutil.Process().username()
|
|
80
77
|
timestamp = datetime.datetime.now(tz=datetime.UTC).strftime("%Y%m%d_%H%M%S")
|
|
81
|
-
|
|
82
|
-
# Replace placeholders in the destination_prefix
|
|
83
78
|
base_prefix = destination_prefix.format(username=username, timestamp=timestamp)
|
|
84
|
-
|
|
85
|
-
# Remove leading/trailing slashes for consistency
|
|
86
79
|
base_prefix = base_prefix.strip("/")
|
|
87
80
|
|
|
88
81
|
with Progress(
|
|
@@ -98,18 +91,14 @@ def upload(
|
|
|
98
91
|
TransferSpeedColumn(),
|
|
99
92
|
TextColumn("[progress.description]{task.description}"),
|
|
100
93
|
) as progress:
|
|
101
|
-
# Create a task for overall progress
|
|
102
94
|
task = progress.add_task(f"Uploading to {base_prefix}/...", total=total_bytes)
|
|
103
95
|
|
|
104
|
-
# Callback function to update progress
|
|
105
96
|
def update_progress(bytes_uploaded: int, file: Path) -> None:
|
|
106
97
|
relpath = file.relative_to(source)
|
|
107
98
|
progress.update(task, advance=bytes_uploaded, description=f"{relpath}")
|
|
108
99
|
|
|
109
|
-
# Upload with progress reporting
|
|
110
100
|
results = Service().upload(source, base_prefix, update_progress)
|
|
111
101
|
|
|
112
|
-
# Print results summary
|
|
113
102
|
if results["success"]:
|
|
114
103
|
console.print(f"[green]Successfully uploaded {len(results['success'])} files:[/green]")
|
|
115
104
|
for key in results["success"]:
|
|
@@ -28,13 +28,13 @@ class Service(BaseService):
|
|
|
28
28
|
"""Initialize service."""
|
|
29
29
|
super().__init__(Settings)
|
|
30
30
|
|
|
31
|
-
def info(self) -> dict[str, Any]:
|
|
31
|
+
def info(self) -> dict[str, Any]:
|
|
32
32
|
"""Determine info of this service.
|
|
33
33
|
|
|
34
34
|
Returns:
|
|
35
35
|
dict[str,Any]: The info of this service.
|
|
36
36
|
"""
|
|
37
|
-
return {}
|
|
37
|
+
return {"settings": self._settings.model_dump()}
|
|
38
38
|
|
|
39
39
|
def health(self) -> Health: # noqa: PLR6301
|
|
40
40
|
"""Determine health of this service.
|
|
@@ -97,7 +97,7 @@ class Service(BaseService):
|
|
|
97
97
|
url = self._get_s3_client().generate_presigned_url(
|
|
98
98
|
ClientMethod="put_object",
|
|
99
99
|
Params={"Bucket": self._settings.name if bucket_name is None else bucket_name, "Key": object_key},
|
|
100
|
-
ExpiresIn=
|
|
100
|
+
ExpiresIn=self._settings.upload_signed_url_expiration_seconds,
|
|
101
101
|
)
|
|
102
102
|
return cast("str", url)
|
|
103
103
|
|
|
@@ -163,7 +163,7 @@ class Service(BaseService):
|
|
|
163
163
|
url = self._get_s3_client().generate_presigned_url(
|
|
164
164
|
ClientMethod="get_object",
|
|
165
165
|
Params={"Bucket": self._settings.name if bucket_name is None else bucket_name, "Key": object_key},
|
|
166
|
-
ExpiresIn=
|
|
166
|
+
ExpiresIn=self._settings.download_signed_url_expiration_seconds,
|
|
167
167
|
)
|
|
168
168
|
return cast("str", url)
|
|
169
169
|
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"""Settings of the bucket module."""
|
|
2
|
+
|
|
3
|
+
from enum import StrEnum
|
|
4
|
+
from typing import Annotated
|
|
5
|
+
|
|
6
|
+
from pydantic import Field, PlainSerializer, SecretStr
|
|
7
|
+
from pydantic_settings import SettingsConfigDict
|
|
8
|
+
|
|
9
|
+
from ..utils import OpaqueSettings, __env_file__, __project_name__ # noqa: TID252
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class BucketProtocol(StrEnum):
|
|
13
|
+
GS = "gs"
|
|
14
|
+
S3 = "s3"
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class Settings(OpaqueSettings):
|
|
18
|
+
"""Settings."""
|
|
19
|
+
|
|
20
|
+
model_config = SettingsConfigDict(
|
|
21
|
+
env_prefix=f"{__project_name__.upper()}_BUCKET_",
|
|
22
|
+
extra="ignore",
|
|
23
|
+
env_file=__env_file__,
|
|
24
|
+
env_file_encoding="utf-8",
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
protocol: Annotated[
|
|
28
|
+
BucketProtocol,
|
|
29
|
+
Field(
|
|
30
|
+
description=("Protocol to access the cloud bucket, default is gs"),
|
|
31
|
+
default="gs",
|
|
32
|
+
),
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
name: Annotated[
|
|
36
|
+
str,
|
|
37
|
+
Field(description=("Name of the cloud bucket")),
|
|
38
|
+
]
|
|
39
|
+
|
|
40
|
+
region_name: Annotated[
|
|
41
|
+
str,
|
|
42
|
+
Field(description=("Region of the cloud bucket"), default="EUROPE-WEST3"),
|
|
43
|
+
]
|
|
44
|
+
|
|
45
|
+
hmac_access_key_id: Annotated[
|
|
46
|
+
SecretStr,
|
|
47
|
+
PlainSerializer(func=OpaqueSettings.serialize_sensitive_info, return_type=str, when_used="always"),
|
|
48
|
+
Field(description=("HMAC access key ID of the cloud bucket")),
|
|
49
|
+
]
|
|
50
|
+
|
|
51
|
+
hmac_secret_access_key: Annotated[
|
|
52
|
+
SecretStr,
|
|
53
|
+
PlainSerializer(func=OpaqueSettings.serialize_sensitive_info, return_type=str, when_used="always"),
|
|
54
|
+
Field(description=("HMAC secret access key of the cloud bucket")),
|
|
55
|
+
]
|
|
56
|
+
|
|
57
|
+
upload_signed_url_expiration_seconds: Annotated[
|
|
58
|
+
int,
|
|
59
|
+
Field(
|
|
60
|
+
description=("Expiration time for signed URLs created and used by the Python SDK to upload to the bucket."),
|
|
61
|
+
default=2
|
|
62
|
+
* 60
|
|
63
|
+
* 60, # The Python SDK creates the signed upload URLs immediately before uploading, so 2h is sufficient.
|
|
64
|
+
ge=60, # Minimum expiration time is 60 seconds, see https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-presigned-url.html
|
|
65
|
+
le=7
|
|
66
|
+
* 24
|
|
67
|
+
* 60
|
|
68
|
+
* 60, # Limit to 7 days as this is the max e.g. at AWS, see https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-presigned-url.html
|
|
69
|
+
),
|
|
70
|
+
]
|
|
71
|
+
|
|
72
|
+
download_signed_url_expiration_seconds: Annotated[
|
|
73
|
+
int,
|
|
74
|
+
Field(
|
|
75
|
+
description=(
|
|
76
|
+
"Expiration time of the signed URLs provided by the Python SDK to the platform on submitting "
|
|
77
|
+
"application runs."
|
|
78
|
+
),
|
|
79
|
+
default=7 * 24 * 60 * 60, # The platform queues application runs, so we set a gracious default of 7d.
|
|
80
|
+
ge=60, # Minimum expiration time is 60 seconds, see https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-presigned-url.html
|
|
81
|
+
le=7
|
|
82
|
+
* 24
|
|
83
|
+
* 60
|
|
84
|
+
* 60, # Limit to 7 days as this is the max e.g. at AWS, see https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-presigned-url.html
|
|
85
|
+
),
|
|
86
|
+
]
|
|
@@ -12,3 +12,4 @@ NOTEBOOK_APP = Path(__file__).parent.parent.parent / "examples" / "notebook.py"
|
|
|
12
12
|
# Project specific configuration
|
|
13
13
|
os.environ["MATPLOTLIB"] = "false"
|
|
14
14
|
os.environ["NICEGUI_STORAGE_PATH"] = str(Path.home().resolve() / ".aignostics" / ".nicegui")
|
|
15
|
+
WSI_SUPPORTED_FILE_EXTENSIONS = {".dcm", ".tiff", ".tif", ".svs"}
|
|
@@ -27,7 +27,7 @@ def _():
|
|
|
27
27
|
import matplotlib.pyplot as plt
|
|
28
28
|
from cloudpathlib import GSPath
|
|
29
29
|
from dotenv import load_dotenv
|
|
30
|
-
from aignostics import dataset
|
|
30
|
+
from aignostics import dataset, WSI_SUPPORTED_FILE_EXTENSIONS
|
|
31
31
|
from wsidicom import WsiDicom
|
|
32
32
|
|
|
33
33
|
mo.sidebar([
|
|
@@ -44,7 +44,6 @@ def _():
|
|
|
44
44
|
orientation="vertical",
|
|
45
45
|
),
|
|
46
46
|
])
|
|
47
|
-
return Path, WsiDicom, dataset, mo, plt
|
|
48
47
|
|
|
49
48
|
|
|
50
49
|
@app.cell
|
|
@@ -55,7 +54,7 @@ def _(Path, mo):
|
|
|
55
54
|
mo.vstack([
|
|
56
55
|
mo.ui.file_browser(
|
|
57
56
|
Path(query_params["results_folder"]),
|
|
58
|
-
filetypes=
|
|
57
|
+
filetypes=list(WSI_SUPPORTED_FILE_EXTENSIONS),
|
|
59
58
|
multiple=True,
|
|
60
59
|
restrict_navigation=True,
|
|
61
60
|
)
|
|
@@ -24,13 +24,13 @@ class Service(BaseService):
|
|
|
24
24
|
"""Initialize service."""
|
|
25
25
|
super().__init__(Settings) # automatically loads and validates the settings
|
|
26
26
|
|
|
27
|
-
def info(self) -> dict[str, Any]:
|
|
27
|
+
def info(self) -> dict[str, Any]:
|
|
28
28
|
"""Determine info of this service.
|
|
29
29
|
|
|
30
30
|
Returns:
|
|
31
31
|
dict[str,Any]: The info of this service.
|
|
32
32
|
"""
|
|
33
|
-
return {}
|
|
33
|
+
return {"settings": self._settings.model_dump()}
|
|
34
34
|
|
|
35
35
|
def _determine_api_public_health(self) -> Health:
|
|
36
36
|
"""Determine healthiness and reachability of Aignostics Platform API.
|
|
@@ -6,7 +6,15 @@ from pathlib import Path
|
|
|
6
6
|
from typing import Annotated, TypeVar
|
|
7
7
|
|
|
8
8
|
import appdirs
|
|
9
|
-
from pydantic import
|
|
9
|
+
from pydantic import (
|
|
10
|
+
Field,
|
|
11
|
+
FieldSerializationInfo,
|
|
12
|
+
PlainSerializer,
|
|
13
|
+
SecretStr,
|
|
14
|
+
computed_field,
|
|
15
|
+
field_serializer,
|
|
16
|
+
model_validator,
|
|
17
|
+
)
|
|
10
18
|
from pydantic_settings import BaseSettings, SettingsConfigDict
|
|
11
19
|
|
|
12
20
|
from aignostics.utils import OpaqueSettings, __project_name__, load_settings
|
|
@@ -47,22 +55,22 @@ class Settings(OpaqueSettings):
|
|
|
47
55
|
client credentials, token storage, and other SDK behaviors.
|
|
48
56
|
|
|
49
57
|
Attributes:
|
|
50
|
-
client_id_device (SecretStr): Client ID for device authorization flow.
|
|
51
|
-
client_id_interactive (SecretStr): Client ID for interactive authorization flow.
|
|
52
58
|
api_root (str): Base URL of the Aignostics API.
|
|
53
|
-
scope (str): OAuth scopes required by the SDK.
|
|
54
|
-
scope_elements (list[str]): OAuth scopes split into individual elements.
|
|
55
59
|
audience (str): OAuth audience claim.
|
|
60
|
+
authorization_backoff_seconds (int): Backoff time for authorization retries in seconds.
|
|
56
61
|
authorization_base_url (str): Authorization endpoint for OAuth flows.
|
|
57
|
-
|
|
58
|
-
|
|
62
|
+
cache_dir (str): Directory for caching tokens and other data.
|
|
63
|
+
client_id_device (SecretStr): Client ID for device authorization flow.
|
|
64
|
+
client_id_interactive (SecretStr): Client ID for interactive authorization flow.
|
|
59
65
|
device_url (str): Device authorization endpoint for device flow.
|
|
60
66
|
jws_json_url (str): URL for JWS key set.
|
|
67
|
+
redirect_uri (str): Redirect URI for OAuth authorization code flow.
|
|
61
68
|
refresh_token (SecretStr | None): OAuth refresh token if available.
|
|
62
|
-
cache_dir (str): Directory for caching tokens and other data.
|
|
63
|
-
token_file (Path): Path to the token storage file.
|
|
64
69
|
request_timeout_seconds (int): Timeout for API requests in seconds.
|
|
65
|
-
|
|
70
|
+
scope (str): OAuth scopes required by the SDK.
|
|
71
|
+
scope_elements (list[str]): OAuth scopes split into individual elements.
|
|
72
|
+
token_file (Path): Path to the token storage file.
|
|
73
|
+
token_url (str): Token endpoint for OAuth flows.
|
|
66
74
|
"""
|
|
67
75
|
|
|
68
76
|
model_config = SettingsConfigDict(
|
|
@@ -117,7 +125,13 @@ class Settings(OpaqueSettings):
|
|
|
117
125
|
device_url: str
|
|
118
126
|
jws_json_url: str
|
|
119
127
|
|
|
120
|
-
refresh_token:
|
|
128
|
+
refresh_token: Annotated[
|
|
129
|
+
SecretStr | None,
|
|
130
|
+
PlainSerializer(
|
|
131
|
+
func=OpaqueSettings.serialize_sensitive_info, return_type=str, when_used="always"
|
|
132
|
+
), # allow to unhide sensitive info from CLI or if user presents valid token via API
|
|
133
|
+
Field(description="Refresh token for OAuth authentication", min_length=10, max_length=1000, default=None),
|
|
134
|
+
] = None
|
|
121
135
|
|
|
122
136
|
cache_dir: str = appdirs.user_cache_dir(__project_name__)
|
|
123
137
|
|
|
@@ -131,6 +145,10 @@ class Settings(OpaqueSettings):
|
|
|
131
145
|
"""
|
|
132
146
|
return Path(self.cache_dir) / ".token"
|
|
133
147
|
|
|
148
|
+
@field_serializer("token_file")
|
|
149
|
+
def serialize_token_file(self, token_file: Path, _info: FieldSerializationInfo) -> str: # noqa: PLR6301
|
|
150
|
+
return str(token_file.resolve())
|
|
151
|
+
|
|
134
152
|
request_timeout_seconds: int = 30
|
|
135
153
|
authorization_backoff_seconds: int = 3
|
|
136
154
|
|
|
@@ -172,33 +172,6 @@ def launch(
|
|
|
172
172
|
sys.exit(1)
|
|
173
173
|
|
|
174
174
|
|
|
175
|
-
@cli.command()
|
|
176
|
-
def info() -> None:
|
|
177
|
-
"""Get info about QuPath installation."""
|
|
178
|
-
if not Service().is_qupath_installed():
|
|
179
|
-
console.print("QuPath is not installed. Use 'uvx aignostics qupath install' to install it.", style="warning")
|
|
180
|
-
sys.exit(2)
|
|
181
|
-
try:
|
|
182
|
-
console.print_json(data=Service().info())
|
|
183
|
-
except Exception as e:
|
|
184
|
-
message = f"Failed to get QuPath info: {e!s}."
|
|
185
|
-
logger.exception(message)
|
|
186
|
-
console.print(message, style="error")
|
|
187
|
-
sys.exit(1)
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
@cli.command()
|
|
191
|
-
def settings() -> None:
|
|
192
|
-
"""Show settings configured for Paquo based QuPath integration."""
|
|
193
|
-
console.print_json(data=Service().get_paquo_settings())
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
@cli.command()
|
|
197
|
-
def defaults() -> None:
|
|
198
|
-
"""Show default settings of Paquo based QuPath integration."""
|
|
199
|
-
console.print_json(data=Service().get_paquo_defaults())
|
|
200
|
-
|
|
201
|
-
|
|
202
175
|
@cli.command()
|
|
203
176
|
def uninstall(
|
|
204
177
|
version: Annotated[
|
|
@@ -25,6 +25,7 @@ import requests
|
|
|
25
25
|
from packaging.version import Version
|
|
26
26
|
from pydantic import BaseModel, computed_field
|
|
27
27
|
|
|
28
|
+
from aignostics import WSI_SUPPORTED_FILE_EXTENSIONS
|
|
28
29
|
from aignostics.utils import BaseService, Health, __project_name__, get_logger
|
|
29
30
|
|
|
30
31
|
from ._settings import Settings
|
|
@@ -35,7 +36,6 @@ QUPATH_VERSION = "0.6.0-rc5"
|
|
|
35
36
|
DOWNLOAD_CHUNK_SIZE = 10 * 1024 * 1024
|
|
36
37
|
LAUNCH_MAX_WAIT_TIME = 60 # seconds, maximum wait time for QuPath to start
|
|
37
38
|
|
|
38
|
-
IMAGE_SUFFIXES = {".dcm", ".tiff", ".tif", ".svs"}
|
|
39
39
|
PROJECT_FILENAME = "project.qpproj"
|
|
40
40
|
ANNOTATIONS_BATCH_SIZE = 500000
|
|
41
41
|
|
|
@@ -152,17 +152,22 @@ class Service(BaseService):
|
|
|
152
152
|
Returns:
|
|
153
153
|
dict[str,Any]: The info of this service.
|
|
154
154
|
"""
|
|
155
|
-
|
|
155
|
+
settings = self._settings.model_dump()
|
|
156
|
+
settings.update({
|
|
157
|
+
"paquo": {
|
|
158
|
+
"current": self.get_paquo_settings(),
|
|
159
|
+
"defaults": self.get_paquo_defaults(),
|
|
160
|
+
},
|
|
161
|
+
})
|
|
162
|
+
app_path = Service.find_qupath()
|
|
156
163
|
version = Service.get_version()
|
|
157
164
|
return {
|
|
158
|
-
"
|
|
159
|
-
"
|
|
165
|
+
"app": {
|
|
166
|
+
"path": str(app_path) if app_path else None,
|
|
160
167
|
"version": dict(version) if version else None,
|
|
168
|
+
"expected_version": Service.get_expected_version(),
|
|
161
169
|
},
|
|
162
|
-
"
|
|
163
|
-
"settings": self.get_paquo_settings(),
|
|
164
|
-
"defaults": self.get_paquo_defaults(),
|
|
165
|
-
},
|
|
170
|
+
"settings": settings,
|
|
166
171
|
}
|
|
167
172
|
|
|
168
173
|
def health(self) -> Health:
|
|
@@ -1085,7 +1090,7 @@ class Service(BaseService):
|
|
|
1085
1090
|
progress.status = AddProgressState.FINDING_IMAGES
|
|
1086
1091
|
progress_callable(progress)
|
|
1087
1092
|
|
|
1088
|
-
supported_extensions =
|
|
1093
|
+
supported_extensions = WSI_SUPPORTED_FILE_EXTENSIONS
|
|
1089
1094
|
|
|
1090
1095
|
def is_supported_image(file_path: Path) -> bool:
|
|
1091
1096
|
return file_path.is_file() and file_path.suffix.lower() in supported_extensions
|
|
@@ -34,10 +34,16 @@ class OpaqueSettings(BaseSettings):
|
|
|
34
34
|
def serialize_sensitive_info(input_value: SecretStr, info: FieldSerializationInfo) -> str | None:
|
|
35
35
|
if not input_value:
|
|
36
36
|
return None
|
|
37
|
-
if info.context.get(UNHIDE_SENSITIVE_INFO, False):
|
|
37
|
+
if info.context and info.context.get(UNHIDE_SENSITIVE_INFO, False):
|
|
38
38
|
return input_value.get_secret_value()
|
|
39
39
|
return str(input_value)
|
|
40
40
|
|
|
41
|
+
@staticmethod
|
|
42
|
+
def serialize_path_resolve(input_value: Path, _info: FieldSerializationInfo) -> str | None:
|
|
43
|
+
if not input_value:
|
|
44
|
+
return None
|
|
45
|
+
return str(input_value.resolve())
|
|
46
|
+
|
|
41
47
|
|
|
42
48
|
def load_settings(settings_class: type[T]) -> T:
|
|
43
49
|
"""
|
|
@@ -6,14 +6,13 @@ from typing import Any
|
|
|
6
6
|
|
|
7
7
|
import requests
|
|
8
8
|
|
|
9
|
+
from aignostics import WSI_SUPPORTED_FILE_EXTENSIONS
|
|
9
10
|
from aignostics.utils import BaseService, Health, get_logger
|
|
10
11
|
|
|
11
12
|
logger = get_logger(__name__)
|
|
12
13
|
|
|
13
14
|
TIMEOUT = 60 # 1 minutes
|
|
14
15
|
|
|
15
|
-
FILE_TYPES_SUPPORTED = {".dcm", ".tiff", ".tif", ".svs"}
|
|
16
|
-
|
|
17
16
|
|
|
18
17
|
class Service(BaseService):
|
|
19
18
|
"""Service of the application module."""
|
|
@@ -47,7 +46,7 @@ class Service(BaseService):
|
|
|
47
46
|
PIL.Image.Image: Thumbnail of the image.
|
|
48
47
|
|
|
49
48
|
Raises:
|
|
50
|
-
ValueError: If the file type is not supported
|
|
49
|
+
ValueError: If the file type is not supported.
|
|
51
50
|
RuntimeError: If there is an error generating the thumbnail.
|
|
52
51
|
"""
|
|
53
52
|
from ._openslide_handler import OpenSlideHandler # noqa: PLC0415
|
|
@@ -56,8 +55,8 @@ class Service(BaseService):
|
|
|
56
55
|
message = f"File does not exist: {path}"
|
|
57
56
|
logger.warning(message)
|
|
58
57
|
raise ValueError(message)
|
|
59
|
-
if path.suffix.lower() not in
|
|
60
|
-
message = f"Unsupported file type: {path.suffix}. Supported types are
|
|
58
|
+
if path.suffix.lower() not in WSI_SUPPORTED_FILE_EXTENSIONS:
|
|
59
|
+
message = f"Unsupported file type: {path.suffix}. Supported types are {WSI_SUPPORTED_FILE_EXTENSIONS!s}"
|
|
61
60
|
logger.warning(message)
|
|
62
61
|
raise ValueError(message)
|
|
63
62
|
try:
|
|
@@ -106,8 +105,8 @@ class Service(BaseService):
|
|
|
106
105
|
message = f"File does not exist: {path}"
|
|
107
106
|
logger.warning(message)
|
|
108
107
|
raise ValueError(message)
|
|
109
|
-
if path.suffix.lower() not in
|
|
110
|
-
message = f"Unsupported file type: {path.suffix}. Supported types are .
|
|
108
|
+
if path.suffix.lower() not in WSI_SUPPORTED_FILE_EXTENSIONS:
|
|
109
|
+
message = f"Unsupported file type: {path.suffix}. Supported types are {WSI_SUPPORTED_FILE_EXTENSIONS}."
|
|
111
110
|
logger.warning(message)
|
|
112
111
|
raise ValueError(message)
|
|
113
112
|
try:
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
"""Settings of the bucket module."""
|
|
2
|
-
|
|
3
|
-
from enum import StrEnum
|
|
4
|
-
from typing import Annotated
|
|
5
|
-
|
|
6
|
-
from pydantic import Field, SecretStr
|
|
7
|
-
from pydantic_settings import SettingsConfigDict
|
|
8
|
-
|
|
9
|
-
from ..utils import OpaqueSettings, __env_file__, __project_name__ # noqa: TID252
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
class BucketProtocol(StrEnum):
|
|
13
|
-
GS = "gs"
|
|
14
|
-
S3 = "s3"
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
class Settings(OpaqueSettings):
|
|
18
|
-
"""Settings."""
|
|
19
|
-
|
|
20
|
-
model_config = SettingsConfigDict(
|
|
21
|
-
env_prefix=f"{__project_name__.upper()}_BUCKET_",
|
|
22
|
-
extra="ignore",
|
|
23
|
-
env_file=__env_file__,
|
|
24
|
-
env_file_encoding="utf-8",
|
|
25
|
-
)
|
|
26
|
-
|
|
27
|
-
protocol: Annotated[
|
|
28
|
-
BucketProtocol,
|
|
29
|
-
Field(
|
|
30
|
-
description=("Protocol to access the cloud bucket, default is gs"),
|
|
31
|
-
default="gs",
|
|
32
|
-
),
|
|
33
|
-
]
|
|
34
|
-
|
|
35
|
-
name: Annotated[
|
|
36
|
-
str,
|
|
37
|
-
Field(description=("Name of the cloud bucket")),
|
|
38
|
-
]
|
|
39
|
-
|
|
40
|
-
region_name: Annotated[
|
|
41
|
-
str,
|
|
42
|
-
Field(description=("Region of the cloud bucket"), default="EUROPE-WEST3"),
|
|
43
|
-
]
|
|
44
|
-
|
|
45
|
-
hmac_access_key_id: Annotated[
|
|
46
|
-
SecretStr,
|
|
47
|
-
Field(description=("HMAC access key ID of the cloud bucket")),
|
|
48
|
-
]
|
|
49
|
-
|
|
50
|
-
hmac_secret_access_key: Annotated[
|
|
51
|
-
SecretStr,
|
|
52
|
-
Field(description=("HMAC secret access key of the cloud bucket")),
|
|
53
|
-
]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{aignostics-0.2.36 → aignostics-0.2.39}/codegen/out/aignx/codegen/models/application_run_status.py
RENAMED
|
File without changes
|
|
File without changes
|
{aignostics-0.2.36 → aignostics-0.2.39}/codegen/out/aignx/codegen/models/http_validation_error.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{aignostics-0.2.36 → aignostics-0.2.39}/codegen/out/aignx/codegen/models/item_creation_request.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{aignostics-0.2.36 → aignostics-0.2.39}/codegen/out/aignx/codegen/models/output_artifact_scope.py
RENAMED
|
File without changes
|
{aignostics-0.2.36 → aignostics-0.2.39}/codegen/out/aignx/codegen/models/payload_input_artifact.py
RENAMED
|
File without changes
|
|
File without changes
|
{aignostics-0.2.36 → aignostics-0.2.39}/codegen/out/aignx/codegen/models/payload_output_artifact.py
RENAMED
|
File without changes
|
{aignostics-0.2.36 → aignostics-0.2.39}/codegen/out/aignx/codegen/models/run_creation_request.py
RENAMED
|
File without changes
|
{aignostics-0.2.36 → aignostics-0.2.39}/codegen/out/aignx/codegen/models/run_creation_response.py
RENAMED
|
File without changes
|
{aignostics-0.2.36 → aignostics-0.2.39}/codegen/out/aignx/codegen/models/run_read_response.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{aignostics-0.2.36 → aignostics-0.2.39}/codegen/out/aignx/codegen/models/validation_error.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/application/_gui/assets/canceled.lottie
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/application/_gui/assets/error_alt.lottie
RENAMED
|
File without changes
|
{aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/application/_gui/assets/home-card-1.png
RENAMED
|
File without changes
|
{aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/application/_gui/assets/home-card-2.png
RENAMED
|
File without changes
|
{aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/application/_gui/assets/home-card-3.png
RENAMED
|
File without changes
|
{aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/application/_gui/assets/home-card-4.png
RENAMED
|
File without changes
|
{aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/application/_gui/assets/home-card-5.png
RENAMED
|
File without changes
|
{aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/application/_gui/assets/image-not-found.png
RENAMED
|
File without changes
|
{aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/application/_gui/assets/pending.lottie
RENAMED
|
File without changes
|
{aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/application/_gui/assets/pending_alt.lottie
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{aignostics-0.2.36 → aignostics-0.2.39}/src/aignostics/gui/assets/cabin-v27-latin-regular.woff2
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|