aignostics 0.2.231__tar.gz → 0.2.233__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.231 → aignostics-0.2.233}/PKG-INFO +14 -3
- {aignostics-0.2.231 → aignostics-0.2.233}/examples/notebook.py +1 -1
- {aignostics-0.2.231 → aignostics-0.2.233}/pyproject.toml +30 -21
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/qupath/_service.py +47 -35
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/utils/__init__.py +2 -1
- aignostics-0.2.233/src/aignostics/utils/_di.py +113 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/utils/_gui.py +6 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/wsi/_cli.py +35 -0
- aignostics-0.2.231/src/aignostics/utils/_di.py +0 -76
- {aignostics-0.2.231 → aignostics-0.2.233}/.gitignore +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/LICENSE +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/README.md +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/codegen/out/.openapi-generator/FILES +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/codegen/out/.openapi-generator/VERSION +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/codegen/out/aignx/codegen/api/public_api.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/codegen/out/aignx/codegen/api_client.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/codegen/out/aignx/codegen/api_response.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/codegen/out/aignx/codegen/configuration.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/codegen/out/aignx/codegen/exceptions.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/codegen/out/aignx/codegen/models/__init__.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/codegen/out/aignx/codegen/models/application_read_response.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/codegen/out/aignx/codegen/models/application_read_short_response.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/codegen/out/aignx/codegen/models/application_version.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/codegen/out/aignx/codegen/models/artifact_output.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/codegen/out/aignx/codegen/models/artifact_state.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/codegen/out/aignx/codegen/models/artifact_termination_reason.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/codegen/out/aignx/codegen/models/auth0_organization.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/codegen/out/aignx/codegen/models/auth0_user.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/codegen/out/aignx/codegen/models/custom_metadata_update_request.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/codegen/out/aignx/codegen/models/http_validation_error.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/codegen/out/aignx/codegen/models/input_artifact.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/codegen/out/aignx/codegen/models/input_artifact_creation_request.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/codegen/out/aignx/codegen/models/item_creation_request.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/codegen/out/aignx/codegen/models/item_output.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/codegen/out/aignx/codegen/models/item_result_read_response.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/codegen/out/aignx/codegen/models/item_state.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/codegen/out/aignx/codegen/models/item_termination_reason.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/codegen/out/aignx/codegen/models/me_read_response.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/codegen/out/aignx/codegen/models/organization_read_response.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/codegen/out/aignx/codegen/models/output_artifact.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/codegen/out/aignx/codegen/models/output_artifact_result_read_response.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/codegen/out/aignx/codegen/models/output_artifact_scope.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/codegen/out/aignx/codegen/models/output_artifact_visibility.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/codegen/out/aignx/codegen/models/run_creation_request.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/codegen/out/aignx/codegen/models/run_creation_response.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/codegen/out/aignx/codegen/models/run_item_statistics.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/codegen/out/aignx/codegen/models/run_output.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/codegen/out/aignx/codegen/models/run_read_response.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/codegen/out/aignx/codegen/models/run_state.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/codegen/out/aignx/codegen/models/run_termination_reason.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/codegen/out/aignx/codegen/models/user_read_response.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/codegen/out/aignx/codegen/models/validation_error.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/codegen/out/aignx/codegen/models/validation_error_loc_inner.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/codegen/out/aignx/codegen/models/version_read_response.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/codegen/out/aignx/codegen/rest.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/codegen/out/docs/PublicApi.md +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/dist_native_all/dist_native-macos-15-intel/extracted/aignostics.app/Contents/Frameworks/boto3/examples/cloudfront.rst +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/dist_native_all/dist_native-macos-15-intel/extracted/aignostics.app/Contents/Frameworks/boto3/examples/s3.rst +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/dist_native_all/dist_native-macos-latest/extracted/aignostics.app/Contents/Frameworks/boto3/examples/cloudfront.rst +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/dist_native_all/dist_native-macos-latest/extracted/aignostics.app/Contents/Frameworks/boto3/examples/s3.rst +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/dist_native_all/dist_native-ubuntu-24.04-arm/extracted/aignostics/_internal/boto3/examples/cloudfront.rst +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/dist_native_all/dist_native-ubuntu-24.04-arm/extracted/aignostics/_internal/boto3/examples/s3.rst +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/dist_native_all/dist_native-ubuntu-latest/extracted/aignostics/_internal/boto3/examples/cloudfront.rst +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/dist_native_all/dist_native-ubuntu-latest/extracted/aignostics/_internal/boto3/examples/s3.rst +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/dist_native_all/dist_native-windows-latest/extracted/aignostics/_internal/boto3/examples/cloudfront.rst +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/dist_native_all/dist_native-windows-latest/extracted/aignostics/_internal/boto3/examples/s3.rst +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/examples/__init__.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/examples/notebook.ipynb +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/examples/script.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/CLAUDE.md +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/__init__.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/application/CLAUDE.md +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/application/__init__.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/application/_cli.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/application/_download.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/application/_gui/_frame.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/application/_gui/_page_application_describe.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/application/_gui/_page_application_run_describe.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/application/_gui/_page_builder.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/application/_gui/_page_index.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/application/_gui/_utils.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/application/_gui/assets/.gitignore +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/application/_gui/assets/canceled.lottie +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/application/_gui/assets/done.lottie +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/application/_gui/assets/empty.lottie +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/application/_gui/assets/error.lottie +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/application/_gui/assets/error_alt.lottie +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/application/_gui/assets/home-card-1.png +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/application/_gui/assets/home-card-2.png +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/application/_gui/assets/home-card-3.png +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/application/_gui/assets/home-card-4.png +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/application/_gui/assets/home-card-5.png +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/application/_gui/assets/image-not-found.png +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/application/_gui/assets/pending.lottie +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/application/_gui/assets/processing.lottie +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/application/_gui/assets/ruo.png +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/application/_gui/assets/ruo.svg +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/application/_models.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/application/_service.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/application/_settings.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/application/_utils.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/bucket/CLAUDE.md +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/bucket/__init__.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/bucket/_cli.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/bucket/_gui.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/bucket/_service.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/bucket/_settings.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/bucket/assets/Google-Cloud-logo.png +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/bucket/assets/Google-Cloud-logo.svg +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/cli.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/constants.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/dataset/CLAUDE.md +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/dataset/__init__.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/dataset/_cli.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/dataset/_gui.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/dataset/_service.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/dataset/assets/NIH-IDC-logo.svg +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/gui/CLAUDE.md +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/gui/__init__.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/gui/_error.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/gui/_frame.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/gui/_theme.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/gui/assets/cabin-v27-latin-regular.woff2 +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/gui/assets/cat.lottie +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/gui/assets/logo.png +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/notebook/CLAUDE.md +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/notebook/__init__.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/notebook/_gui.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/notebook/_notebook.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/notebook/_service.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/notebook/assets/python.lottie +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/platform/CLAUDE.md +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/platform/__init__.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/platform/_authentication.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/platform/_cli.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/platform/_client.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/platform/_constants.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/platform/_messages.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/platform/_operation_cache.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/platform/_sdk_metadata.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/platform/_service.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/platform/_settings.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/platform/_utils.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/platform/resources/__init__.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/platform/resources/applications.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/platform/resources/runs.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/platform/resources/utils.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/qupath/CLAUDE.md +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/qupath/__init__.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/qupath/_cli.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/qupath/_gui.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/qupath/_settings.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/qupath/assets/download.lottie +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/qupath/assets/microscope.lottie +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/qupath/assets/update.lottie +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/qupath/scripts/add.groovy +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/qupath/scripts/annotate.groovy +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/qupath/scripts/inspect.groovy +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/qupath/scripts/test.groovy +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/system/CLAUDE.md +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/system/__init__.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/system/_cli.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/system/_exceptions.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/system/_gui.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/system/_service.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/system/_settings.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/system/assets/system.lottie +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/third_party/bottle.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/third_party/idc_index.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/third_party/showinfm/__init__.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/third_party/showinfm/argumentsparse.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/third_party/showinfm/constants.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/third_party/showinfm/py.typed +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/third_party/showinfm/showinfm.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/third_party/showinfm/system/__init__.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/third_party/showinfm/system/linux.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/third_party/showinfm/system/tools.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/third_party/showinfm/system/urivalidate.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/third_party/showinfm/system/windows.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/utils/CLAUDE.md +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/utils/_cli.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/utils/_console.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/utils/_constants.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/utils/_fs.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/utils/_health.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/utils/_log.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/utils/_notebook.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/utils/_process.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/utils/_sentry.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/utils/_service.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/utils/_settings.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/utils/_user_agent.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/utils/boot.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/wsi/CLAUDE.md +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/wsi/__init__.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/wsi/_gui.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/wsi/_openslide_handler.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/wsi/_pydicom_handler.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/wsi/_service.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/wsi/_utils.py +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics/wsi/assets/fallback.png +0 -0
- {aignostics-0.2.231 → aignostics-0.2.233}/src/aignostics.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: aignostics
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.233
|
|
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/
|
|
@@ -49,6 +49,7 @@ Classifier: Programming Language :: Python :: 3.13
|
|
|
49
49
|
Classifier: Programming Language :: Python :: 3.14
|
|
50
50
|
Classifier: Typing :: Typed
|
|
51
51
|
Requires-Python: <3.15,>=3.11
|
|
52
|
+
Requires-Dist: aiohttp>=3.12.14
|
|
52
53
|
Requires-Dist: boto3<2,>=1.42.4
|
|
53
54
|
Requires-Dist: certifi>=2025.11.12
|
|
54
55
|
Requires-Dist: crc32c<3,>=2.8
|
|
@@ -59,7 +60,8 @@ Requires-Dist: duckdb<=2,>=1.4.2
|
|
|
59
60
|
Requires-Dist: fastapi[all,standard]>=0.123.10
|
|
60
61
|
Requires-Dist: fastparquet>=2024.11.0; python_version < '3.14'
|
|
61
62
|
Requires-Dist: google-cloud-storage<4,>=3.6.0
|
|
62
|
-
Requires-Dist:
|
|
63
|
+
Requires-Dist: h11>=0.16.0
|
|
64
|
+
Requires-Dist: highdicom<1,>=0.26.1; python_version < '3.14'
|
|
63
65
|
Requires-Dist: html-sanitizer<3,>=2.6.0
|
|
64
66
|
Requires-Dist: httpx<1,>=0.28.1
|
|
65
67
|
Requires-Dist: humanize<5,>=4.14.0
|
|
@@ -68,11 +70,13 @@ Requires-Dist: ijson<4,>=3.4.0.post0
|
|
|
68
70
|
Requires-Dist: jsf<1,>=0.11.2
|
|
69
71
|
Requires-Dist: jsonschema[format-nongpl]<5,>=4.25.1
|
|
70
72
|
Requires-Dist: loguru<1,>=0.7.3
|
|
73
|
+
Requires-Dist: lxml>=6.0.2
|
|
71
74
|
Requires-Dist: nicegui[native]<4,>=3.4.0
|
|
72
75
|
Requires-Dist: openslide-bin<5,>=4.0.0.10
|
|
73
76
|
Requires-Dist: openslide-python<2,>=1.4.3
|
|
74
77
|
Requires-Dist: packaging<26,>=25.0
|
|
75
78
|
Requires-Dist: pandas<3,>=2.3.3
|
|
79
|
+
Requires-Dist: pillow>=11.3.0
|
|
76
80
|
Requires-Dist: platformdirs<5,>=4.3.2
|
|
77
81
|
Requires-Dist: platformdirs<5,>=4.5.1
|
|
78
82
|
Requires-Dist: procrastinate>=3.5.3
|
|
@@ -85,23 +89,30 @@ Requires-Dist: pywin32<312,>=311; sys_platform == 'win32'
|
|
|
85
89
|
Requires-Dist: pyyaml<7,>=6.0.3
|
|
86
90
|
Requires-Dist: requests-oauthlib<3,>=2.0.0
|
|
87
91
|
Requires-Dist: requests<3,>=2.32.5
|
|
92
|
+
Requires-Dist: rfc3987; sys_platform == 'never'
|
|
88
93
|
Requires-Dist: s5cmd<1,>=0.3.3
|
|
89
94
|
Requires-Dist: semver<4,>=3.0.4
|
|
90
95
|
Requires-Dist: sentry-sdk<3,>=2.47.0
|
|
91
96
|
Requires-Dist: shapely<3,>=2.1.2
|
|
97
|
+
Requires-Dist: starlette>=0.47.2
|
|
98
|
+
Requires-Dist: starlette>=0.49.1
|
|
92
99
|
Requires-Dist: tenacity<10,>=9.1.2
|
|
100
|
+
Requires-Dist: tornado>=6.5.0
|
|
93
101
|
Requires-Dist: tqdm<5,>=4.67.1
|
|
94
102
|
Requires-Dist: truststore<1,>=0.10.4
|
|
95
103
|
Requires-Dist: typer<1,>=0.20.0
|
|
96
104
|
Requires-Dist: uptime<4,>=3.0.1
|
|
97
105
|
Requires-Dist: urllib3<3,>=2.6.1
|
|
106
|
+
Requires-Dist: urllib3>=2.5.0
|
|
98
107
|
Requires-Dist: wsidicom<1,>=0.28.1
|
|
99
108
|
Provides-Extra: jupyter
|
|
109
|
+
Requires-Dist: jupyter-core>=5.8.1; extra == 'jupyter'
|
|
100
110
|
Requires-Dist: jupyter<2,>=1.1.1; extra == 'jupyter'
|
|
111
|
+
Requires-Dist: jupyterlab>=4.4.9; extra == 'jupyter'
|
|
101
112
|
Provides-Extra: marimo
|
|
102
113
|
Requires-Dist: cloudpathlib<1,>=0.23.0; extra == 'marimo'
|
|
103
114
|
Requires-Dist: ipython<10,>=9.8.0; extra == 'marimo'
|
|
104
|
-
Requires-Dist: marimo<1,>=0.18.
|
|
115
|
+
Requires-Dist: marimo<1,>=0.18.4; extra == 'marimo'
|
|
105
116
|
Requires-Dist: matplotlib<4,>=3.10.7; extra == 'marimo'
|
|
106
117
|
Requires-Dist: shapely<3,>=2.1.0; extra == 'marimo'
|
|
107
118
|
Provides-Extra: pyinstaller
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "aignostics"
|
|
3
|
-
version = "0.2.
|
|
3
|
+
version = "0.2.233"
|
|
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 = [
|
|
@@ -71,6 +71,7 @@ classifiers = [
|
|
|
71
71
|
"Natural Language :: English",
|
|
72
72
|
]
|
|
73
73
|
|
|
74
|
+
# WARNING: The upper bound of requires-python is *not* respected by uvx
|
|
74
75
|
requires-python = ">=3.11, <3.15"
|
|
75
76
|
|
|
76
77
|
dependencies = [
|
|
@@ -96,7 +97,7 @@ dependencies = [
|
|
|
96
97
|
"duckdb>=1.4.2,<=2",
|
|
97
98
|
"google-cloud-storage>=3.6.0,<4",
|
|
98
99
|
"crc32c>=2.8,<3", # TODO(Helmut): Remove and back to google_crc32c when that supports Python 3.14
|
|
99
|
-
"highdicom>=0.26.1,<1",
|
|
100
|
+
"highdicom>=0.26.1,<1; python_version < '3.14'", # transitive dependency pyjpegls not yet supporting Python 3.14
|
|
100
101
|
"html-sanitizer>=2.6.0,<3",
|
|
101
102
|
"httpx>=0.28.1,<1",
|
|
102
103
|
"idc-index-data==23.0.1",
|
|
@@ -124,15 +125,32 @@ dependencies = [
|
|
|
124
125
|
"truststore>=0.10.4,<1",
|
|
125
126
|
"urllib3>=2.6.1,<3",
|
|
126
127
|
"wsidicom>=0.28.1,<1",
|
|
128
|
+
# Transitive overrides
|
|
129
|
+
# WARNING: one cannot negate or downgrade a dependency required here. use override-dependencies for that.
|
|
130
|
+
"rfc3987; sys_platform == 'never'", # GPLv3
|
|
131
|
+
"h11>=0.16.0", # CVE-2025-43859
|
|
132
|
+
"tornado>=6.5.0", # CVE-2025-47287
|
|
133
|
+
"urllib3>=2.5.0", # CVE-2025-50181, CVE-2025-50182,
|
|
134
|
+
"pillow>=11.3.0", # CVE-2025-48379,
|
|
135
|
+
"aiohttp>=3.12.14", # CVE-2025-53643
|
|
136
|
+
"starlette>=0.47.2", # CVE-2025-54121
|
|
137
|
+
"starlette>=0.49.1", # GHSA-7f5h-v6xp-fcq8
|
|
138
|
+
"lxml>=6.0.2", # For python 3.14 pre-built wheels
|
|
127
139
|
]
|
|
128
140
|
|
|
129
141
|
[project.optional-dependencies]
|
|
130
142
|
pyinstaller = ["pyinstaller>=6.14.0,<7"]
|
|
131
|
-
jupyter = [
|
|
143
|
+
jupyter = [
|
|
144
|
+
"jupyter>=1.1.1,<2",
|
|
145
|
+
# Transitive overrides
|
|
146
|
+
# WARNING: one cannot negate or downgrade a dependency required here. use override-dependencies for that.
|
|
147
|
+
"jupyter-core>=5.8.1", # CVE-2025-30167
|
|
148
|
+
"jupyterlab>=4.4.9", # CVE-2025-59842
|
|
149
|
+
]
|
|
132
150
|
marimo = [
|
|
133
151
|
"cloudpathlib>=0.23.0,<1",
|
|
134
152
|
"ipython>=9.8.0,<10",
|
|
135
|
-
"marimo>=0.18.
|
|
153
|
+
"marimo>=0.18.4,<1",
|
|
136
154
|
"matplotlib>=3.10.7,<4",
|
|
137
155
|
"shapely>=2.1.0,<3",
|
|
138
156
|
]
|
|
@@ -185,27 +203,18 @@ dev = [
|
|
|
185
203
|
"types-pyyaml>=6.0.12.20250915,<7",
|
|
186
204
|
"types-requests>=2.32.4.20250913,<3",
|
|
187
205
|
"watchdog>=6.0.0,<7",
|
|
206
|
+
# Transitive overrides
|
|
207
|
+
# WARNING: one cannot negate or downgrade a dependency required here. use override-dependencies for that.
|
|
208
|
+
"pip>=5.3", # CVE-2025-8869
|
|
209
|
+
"uv>=0.9.7", # CVE-2025-54368, GHSA-w476-p2h3-79g9, GHSA-pqhf-p39g-3x64
|
|
210
|
+
"fonttools>=4.60.2", # CVE-2025-66034 (GHSA-768j-98cg-p3fv), dep of matplotlib
|
|
188
211
|
]
|
|
189
212
|
|
|
190
213
|
[tool.uv]
|
|
191
214
|
required-version = ">=0.9.7" # CVE-2025-54368, GHSA-w476-p2h3-79g9, GHSA-pqhf-p39g-3x64
|
|
215
|
+
# WARNING: override-dependencies is *not* respected by uvx
|
|
192
216
|
override-dependencies = [ # https://github.com/astral-sh/uv/issues/4422
|
|
193
|
-
"
|
|
194
|
-
"h11>=0.16.0", # CVE-2025-43859
|
|
195
|
-
"tornado>=6.5.0", # CVE-2025-47287
|
|
196
|
-
"jupyter-core>=5.8.1", # CVE-2025-30167
|
|
197
|
-
"urllib3>=2.5.0", # CVE-2025-50181, CVE-2025-50182,
|
|
198
|
-
"pillow>=11.3.0", # CVE-2025-48379,
|
|
199
|
-
"aiohttp>=3.12.14", # CVE-2025-53643
|
|
200
|
-
"starlette>=0.47.2", # CVE-2025-54121
|
|
201
|
-
"uv>=0.9.7", # CVE-2025-54368, GHSA-w476-p2h3-79g9, GHSA-pqhf-p39g-3x64
|
|
202
|
-
"jupyterlab>=4.4.9", # CVE-2025-59842
|
|
203
|
-
"pip>=5.3", # CVE-2025-8869
|
|
204
|
-
"starlette>=0.49.1", # GHSA-7f5h-v6xp-fcq8
|
|
205
|
-
"fonttools>=4.60.2", # CVE-2025-66034 (GHSA-768j-98cg-p3fv), dep of matplotlib
|
|
206
|
-
"pyjpegls; python_version < '3.14'", # No Python 3.14 support yet
|
|
207
|
-
"pytest>=9.0.1", # pytest-md-report depends on pytest<9 unnecessarily
|
|
208
|
-
"lxml>=6.0.2", # For python 3.14 pre-built wheels
|
|
217
|
+
"pytest>=9.0.1", # pytest-md-report depends on pytest<9 unnecessarily
|
|
209
218
|
]
|
|
210
219
|
|
|
211
220
|
[tool.uv.sources]
|
|
@@ -386,7 +395,7 @@ source = ["src/"]
|
|
|
386
395
|
|
|
387
396
|
|
|
388
397
|
[tool.bumpversion]
|
|
389
|
-
current_version = "0.2.
|
|
398
|
+
current_version = "0.2.233"
|
|
390
399
|
parse = "(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)"
|
|
391
400
|
serialize = ["{major}.{minor}.{patch}"]
|
|
392
401
|
search = "{current_version}"
|
|
@@ -42,6 +42,7 @@ QUPATH_SCRIPT_MAX_EXECUTION_TIME = 60 * 60 * 2 # seconds, maximum wait time for
|
|
|
42
42
|
|
|
43
43
|
PROJECT_FILENAME = "project.qpproj"
|
|
44
44
|
ANNOTATIONS_BATCH_SIZE = 500000
|
|
45
|
+
JSON_SUFFIX = ".json"
|
|
45
46
|
|
|
46
47
|
|
|
47
48
|
class QuPathVersion(BaseModel):
|
|
@@ -1124,40 +1125,46 @@ class Service(BaseService):
|
|
|
1124
1125
|
progress_callable(progress)
|
|
1125
1126
|
|
|
1126
1127
|
# We communicate via file I/O with the Groovy script running within QuPath
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
):
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1128
|
+
# Use delete=False to avoid Windows file locking issues - the file must be closed
|
|
1129
|
+
# before QuPath can read it, but NamedTemporaryFile keeps files locked while open on Windows
|
|
1130
|
+
paths_file = tempfile.NamedTemporaryFile(mode="w", suffix=JSON_SUFFIX, encoding="utf-8", delete=False) # noqa: SIM115
|
|
1131
|
+
output_file = tempfile.NamedTemporaryFile(mode="w", suffix=JSON_SUFFIX, encoding="utf-8", delete=False) # noqa: SIM115
|
|
1132
|
+
try:
|
|
1133
|
+
# Write paths and close file so QuPath can read it
|
|
1134
|
+
json.dump([str(path.resolve()) for path in paths], paths_file)
|
|
1135
|
+
paths_file.close()
|
|
1136
|
+
output_file.close()
|
|
1134
1137
|
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1138
|
+
pid = Service.execute_qupath(
|
|
1139
|
+
script=Service._find_groovy_script("add"),
|
|
1140
|
+
script_args=[str(project), paths_file.name, output_file.name],
|
|
1141
|
+
)
|
|
1139
1142
|
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1143
|
+
if not pid:
|
|
1144
|
+
message = "Failed to execute QuPath script for adding images."
|
|
1145
|
+
logger.error(message)
|
|
1146
|
+
raise RuntimeError(message) # noqa: TRY301
|
|
1147
|
+
|
|
1148
|
+
with Path(output_file.name).open("r", encoding="utf-8") as f:
|
|
1149
|
+
result_data = json.load(f)
|
|
1150
|
+
added_count = int(result_data.get("added_count", 0))
|
|
1151
|
+
errors = result_data.get("errors", [])
|
|
1152
|
+
for error in errors:
|
|
1153
|
+
logger.warning(f"QuPath add script error: {error}")
|
|
1154
|
+
|
|
1155
|
+
if progress_callable:
|
|
1156
|
+
progress.status = AddProgressState.COMPLETED
|
|
1157
|
+
progress_callable(progress)
|
|
1158
|
+
|
|
1159
|
+
return added_count
|
|
1160
|
+
except Exception as e:
|
|
1161
|
+
message = f"Failed to add images to QuPath project: {e!s}"
|
|
1162
|
+
logger.exception(message)
|
|
1163
|
+
raise RuntimeError(message) from e
|
|
1164
|
+
finally:
|
|
1165
|
+
# Clean up temp files
|
|
1166
|
+
Path(paths_file.name).unlink(missing_ok=True)
|
|
1167
|
+
Path(output_file.name).unlink(missing_ok=True)
|
|
1161
1168
|
|
|
1162
1169
|
@staticmethod
|
|
1163
1170
|
def annotate(
|
|
@@ -1246,9 +1253,12 @@ class Service(BaseService):
|
|
|
1246
1253
|
RuntimeError: If there is an error inspecting the project.
|
|
1247
1254
|
"""
|
|
1248
1255
|
# We communicate via file I/O with the Groovy script running within QuPath
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1256
|
+
# Use delete=False to avoid Windows file locking issues - the file must be closed
|
|
1257
|
+
# before QuPath can write to it, but NamedTemporaryFile keeps files locked while open on Windows
|
|
1258
|
+
temp_file = tempfile.NamedTemporaryFile(mode="w+", suffix=JSON_SUFFIX, encoding="utf-8", delete=False) # noqa: SIM115
|
|
1259
|
+
output_file = Path(temp_file.name).resolve()
|
|
1260
|
+
temp_file.close()
|
|
1261
|
+
try:
|
|
1252
1262
|
pid = Service.execute_qupath(
|
|
1253
1263
|
quiet=True,
|
|
1254
1264
|
project=project,
|
|
@@ -1267,3 +1277,5 @@ class Service(BaseService):
|
|
|
1267
1277
|
raise RuntimeError(message)
|
|
1268
1278
|
|
|
1269
1279
|
return QuPathProject.model_validate_json(output_file.read_text(encoding="utf-8"))
|
|
1280
|
+
finally:
|
|
1281
|
+
output_file.unlink(missing_ok=True)
|
|
@@ -22,7 +22,7 @@ from ._constants import (
|
|
|
22
22
|
__version__,
|
|
23
23
|
__version_full__,
|
|
24
24
|
)
|
|
25
|
-
from ._di import load_modules, locate_implementations, locate_subclasses
|
|
25
|
+
from ._di import discover_plugin_packages, load_modules, locate_implementations, locate_subclasses
|
|
26
26
|
from ._fs import get_user_data_directory, open_user_data_directory, sanitize_path, sanitize_path_component
|
|
27
27
|
from ._health import Health
|
|
28
28
|
from ._log import LogSettings
|
|
@@ -60,6 +60,7 @@ __all__ = [
|
|
|
60
60
|
"__version_full__",
|
|
61
61
|
"boot",
|
|
62
62
|
"console",
|
|
63
|
+
"discover_plugin_packages",
|
|
63
64
|
"get_process_info",
|
|
64
65
|
"get_user_data_directory",
|
|
65
66
|
"load_modules",
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"""Module for dynamic import and discovery of implementations and subclasses."""
|
|
2
|
+
|
|
3
|
+
import importlib
|
|
4
|
+
import pkgutil
|
|
5
|
+
from functools import lru_cache
|
|
6
|
+
from importlib.metadata import entry_points
|
|
7
|
+
from inspect import isclass
|
|
8
|
+
from typing import Any
|
|
9
|
+
|
|
10
|
+
from ._constants import __project_name__
|
|
11
|
+
|
|
12
|
+
_implementation_cache: dict[Any, list[Any]] = {}
|
|
13
|
+
_subclass_cache: dict[Any, list[Any]] = {}
|
|
14
|
+
|
|
15
|
+
# Entry point group name for aignostics plugins
|
|
16
|
+
PLUGIN_ENTRY_POINT_GROUP = "aignostics.plugins"
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@lru_cache(maxsize=1)
|
|
20
|
+
def discover_plugin_packages() -> tuple[str, ...]:
|
|
21
|
+
"""
|
|
22
|
+
Discover plugin packages using entry points.
|
|
23
|
+
|
|
24
|
+
Plugins register themselves in their pyproject.toml:
|
|
25
|
+
|
|
26
|
+
[project.entry-points."aignostics.plugins"]
|
|
27
|
+
my_plugin = "my_plugin"
|
|
28
|
+
|
|
29
|
+
Results are cached after the first call.
|
|
30
|
+
|
|
31
|
+
Returns:
|
|
32
|
+
tuple[str, ...]: Tuple of discovered plugin package names.
|
|
33
|
+
"""
|
|
34
|
+
eps = entry_points(group=PLUGIN_ENTRY_POINT_GROUP)
|
|
35
|
+
return tuple(ep.value for ep in eps)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def load_modules() -> None:
|
|
39
|
+
package = importlib.import_module(__project_name__)
|
|
40
|
+
for _, name, _ in pkgutil.iter_modules(package.__path__):
|
|
41
|
+
importlib.import_module(f"{__project_name__}.{name}")
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def locate_implementations(_class: type[Any]) -> list[Any]:
|
|
45
|
+
"""
|
|
46
|
+
Dynamically discover all instances of some class.
|
|
47
|
+
|
|
48
|
+
Searches in the main project and all plugins registered via entry points.
|
|
49
|
+
|
|
50
|
+
Args:
|
|
51
|
+
_class (type[Any]): Class to search for.
|
|
52
|
+
|
|
53
|
+
Returns:
|
|
54
|
+
list[Any]: List of discovered implementations of the given class.
|
|
55
|
+
"""
|
|
56
|
+
if _class in _implementation_cache:
|
|
57
|
+
return _implementation_cache[_class]
|
|
58
|
+
|
|
59
|
+
plugin_packages = discover_plugin_packages()
|
|
60
|
+
|
|
61
|
+
implementations = []
|
|
62
|
+
for package_name in [*plugin_packages, __project_name__]:
|
|
63
|
+
package = importlib.import_module(package_name)
|
|
64
|
+
|
|
65
|
+
for _, name, _ in pkgutil.iter_modules(package.__path__):
|
|
66
|
+
module = importlib.import_module(f"{package_name}.{name}")
|
|
67
|
+
# Check all members of the module
|
|
68
|
+
for member_name in dir(module):
|
|
69
|
+
member = getattr(module, member_name)
|
|
70
|
+
if isinstance(member, _class):
|
|
71
|
+
implementations.append(member)
|
|
72
|
+
|
|
73
|
+
_implementation_cache[_class] = implementations
|
|
74
|
+
return implementations
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def locate_subclasses(_class: type[Any]) -> list[Any]:
|
|
78
|
+
"""
|
|
79
|
+
Dynamically discover all classes that are subclasses of some type.
|
|
80
|
+
|
|
81
|
+
Searches in the main project and all plugins registered via entry points.
|
|
82
|
+
|
|
83
|
+
Args:
|
|
84
|
+
_class (type[Any]): Parent class of subclasses to search for.
|
|
85
|
+
|
|
86
|
+
Returns:
|
|
87
|
+
list[type[Any]]: List of discovered subclasses of the given class.
|
|
88
|
+
"""
|
|
89
|
+
if _class in _subclass_cache:
|
|
90
|
+
return _subclass_cache[_class]
|
|
91
|
+
|
|
92
|
+
plugin_packages = discover_plugin_packages()
|
|
93
|
+
|
|
94
|
+
subclasses = []
|
|
95
|
+
for package_name in [*plugin_packages, __project_name__]:
|
|
96
|
+
try:
|
|
97
|
+
package = importlib.import_module(package_name)
|
|
98
|
+
except ImportError:
|
|
99
|
+
continue
|
|
100
|
+
|
|
101
|
+
for _, name, _ in pkgutil.iter_modules(package.__path__):
|
|
102
|
+
try:
|
|
103
|
+
module = importlib.import_module(f"{package_name}.{name}")
|
|
104
|
+
# Check all members of the module
|
|
105
|
+
for member_name in dir(module):
|
|
106
|
+
member = getattr(module, member_name)
|
|
107
|
+
if isclass(member) and issubclass(member, _class) and member != _class:
|
|
108
|
+
subclasses.append(member)
|
|
109
|
+
except ImportError:
|
|
110
|
+
continue
|
|
111
|
+
|
|
112
|
+
_subclass_cache[_class] = subclasses
|
|
113
|
+
return subclasses
|
|
@@ -73,6 +73,12 @@ def gui_run( # noqa: PLR0913, PLR0917
|
|
|
73
73
|
native = False
|
|
74
74
|
show = True
|
|
75
75
|
|
|
76
|
+
# On Windows with python 3.14 don't use native mode due to pythonnet not yet
|
|
77
|
+
# supported
|
|
78
|
+
if native and platform.system() == "Windows" and platform.python_version_tuple() >= ("3", "14"):
|
|
79
|
+
native = False
|
|
80
|
+
show = True
|
|
81
|
+
|
|
76
82
|
gui_register_pages()
|
|
77
83
|
|
|
78
84
|
ui.run(
|
|
@@ -12,6 +12,33 @@ from aignostics.utils import console
|
|
|
12
12
|
from ._service import Service
|
|
13
13
|
from ._utils import print_slide_info, print_study_info
|
|
14
14
|
|
|
15
|
+
# Python version for highdicom compatibility check
|
|
16
|
+
_PYTHON_VERSION = f"{sys.version_info.major}.{sys.version_info.minor}"
|
|
17
|
+
_HIGHDICOM_UNSUPPORTED_VERSIONS = {"3.14"}
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def _check_highdicom_available() -> bool:
|
|
21
|
+
"""Check if highdicom is available (not supported on Python 3.14+).
|
|
22
|
+
|
|
23
|
+
Returns:
|
|
24
|
+
True if highdicom can be imported, False otherwise.
|
|
25
|
+
"""
|
|
26
|
+
try:
|
|
27
|
+
from ._pydicom_handler import PydicomHandler # noqa: PLC0415, F401
|
|
28
|
+
|
|
29
|
+
return True
|
|
30
|
+
except ImportError:
|
|
31
|
+
return False
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def _print_highdicom_unsupported_error() -> None:
|
|
35
|
+
"""Print error message when highdicom is not available."""
|
|
36
|
+
console.print(f"[red]This command requires 'highdicom' which is not available on Python {_PYTHON_VERSION}.[/red]")
|
|
37
|
+
console.print("[yellow]Please run with Python 3.13 or earlier:[/yellow]")
|
|
38
|
+
console.print("[green] uvx -p 3.13 aignostics wsi dicom <command> ...[/green]")
|
|
39
|
+
sys.exit(1)
|
|
40
|
+
|
|
41
|
+
|
|
15
42
|
cli = typer.Typer(name="wsi", help="Operations on whole slide images.")
|
|
16
43
|
|
|
17
44
|
|
|
@@ -107,6 +134,10 @@ def dicom_inspect(
|
|
|
107
134
|
summary: Annotated[bool, typer.Option(help="Show only summary information")] = False,
|
|
108
135
|
) -> None: # pylint: disable=W0613
|
|
109
136
|
"""Inspect DICOM files at any hierarchy level."""
|
|
137
|
+
if not _check_highdicom_available():
|
|
138
|
+
_print_highdicom_unsupported_error()
|
|
139
|
+
return
|
|
140
|
+
|
|
110
141
|
from ._pydicom_handler import PydicomHandler # noqa: PLC0415
|
|
111
142
|
|
|
112
143
|
try:
|
|
@@ -139,6 +170,10 @@ def dicom_geojson_import(
|
|
|
139
170
|
geojson_path: Annotated[Path, typer.Argument(help="Path to the GeoJSON file", exists=True)],
|
|
140
171
|
) -> None: # pylint: disable=W0613
|
|
141
172
|
"""Import GeoJSON annotations into DICOM ANN instance."""
|
|
173
|
+
if not _check_highdicom_available():
|
|
174
|
+
_print_highdicom_unsupported_error()
|
|
175
|
+
return
|
|
176
|
+
|
|
142
177
|
from ._pydicom_handler import PydicomHandler # noqa: PLC0415
|
|
143
178
|
|
|
144
179
|
try:
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
"""Module for dynamic import and discovery of implementations and subclasses."""
|
|
2
|
-
|
|
3
|
-
import importlib
|
|
4
|
-
import pkgutil
|
|
5
|
-
from inspect import isclass
|
|
6
|
-
from typing import Any
|
|
7
|
-
|
|
8
|
-
from ._constants import __project_name__
|
|
9
|
-
|
|
10
|
-
_implementation_cache: dict[Any, list[Any]] = {}
|
|
11
|
-
_subclass_cache: dict[Any, list[Any]] = {}
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
def load_modules() -> None:
|
|
15
|
-
package = importlib.import_module(__project_name__)
|
|
16
|
-
for _, name, _ in pkgutil.iter_modules(package.__path__):
|
|
17
|
-
importlib.import_module(f"{__project_name__}.{name}")
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
def locate_implementations(_class: type[Any]) -> list[Any]:
|
|
21
|
-
"""
|
|
22
|
-
Dynamically discover all instances of some class.
|
|
23
|
-
|
|
24
|
-
Args:
|
|
25
|
-
_class (type[Any]): Class to search for.
|
|
26
|
-
|
|
27
|
-
Returns:
|
|
28
|
-
list[Any]: List of discovered implementations of the given class.
|
|
29
|
-
"""
|
|
30
|
-
if _class in _implementation_cache:
|
|
31
|
-
return _implementation_cache[_class]
|
|
32
|
-
|
|
33
|
-
implementations = []
|
|
34
|
-
package = importlib.import_module(__project_name__)
|
|
35
|
-
|
|
36
|
-
for _, name, _ in pkgutil.iter_modules(package.__path__):
|
|
37
|
-
module = importlib.import_module(f"{__project_name__}.{name}")
|
|
38
|
-
# Check all members of the module
|
|
39
|
-
for member_name in dir(module):
|
|
40
|
-
member = getattr(module, member_name)
|
|
41
|
-
if isinstance(member, _class):
|
|
42
|
-
implementations.append(member)
|
|
43
|
-
|
|
44
|
-
_implementation_cache[_class] = implementations
|
|
45
|
-
return implementations
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
def locate_subclasses(_class: type[Any]) -> list[Any]:
|
|
49
|
-
"""
|
|
50
|
-
Dynamically discover all classes that are subclasses of some type.
|
|
51
|
-
|
|
52
|
-
Args:
|
|
53
|
-
_class (type[Any]): Parent class of subclasses to search for.
|
|
54
|
-
|
|
55
|
-
Returns:
|
|
56
|
-
list[type[Any]]: List of discovered subclasses of the given class.
|
|
57
|
-
"""
|
|
58
|
-
if _class in _subclass_cache:
|
|
59
|
-
return _subclass_cache[_class]
|
|
60
|
-
|
|
61
|
-
subclasses = []
|
|
62
|
-
package = importlib.import_module(__project_name__)
|
|
63
|
-
|
|
64
|
-
for _, name, _ in pkgutil.iter_modules(package.__path__):
|
|
65
|
-
try:
|
|
66
|
-
module = importlib.import_module(f"{__project_name__}.{name}")
|
|
67
|
-
# Check all members of the module
|
|
68
|
-
for member_name in dir(module):
|
|
69
|
-
member = getattr(module, member_name)
|
|
70
|
-
if isclass(member) and issubclass(member, _class) and member != _class:
|
|
71
|
-
subclasses.append(member)
|
|
72
|
-
except ImportError:
|
|
73
|
-
continue
|
|
74
|
-
|
|
75
|
-
_subclass_cache[_class] = subclasses
|
|
76
|
-
return subclasses
|
|
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.231 → aignostics-0.2.233}/codegen/out/aignx/codegen/models/application_version.py
RENAMED
|
File without changes
|
{aignostics-0.2.231 → aignostics-0.2.233}/codegen/out/aignx/codegen/models/artifact_output.py
RENAMED
|
File without changes
|
{aignostics-0.2.231 → aignostics-0.2.233}/codegen/out/aignx/codegen/models/artifact_state.py
RENAMED
|
File without changes
|
|
File without changes
|
{aignostics-0.2.231 → aignostics-0.2.233}/codegen/out/aignx/codegen/models/auth0_organization.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{aignostics-0.2.231 → aignostics-0.2.233}/codegen/out/aignx/codegen/models/http_validation_error.py
RENAMED
|
File without changes
|
{aignostics-0.2.231 → aignostics-0.2.233}/codegen/out/aignx/codegen/models/input_artifact.py
RENAMED
|
File without changes
|
|
File without changes
|
{aignostics-0.2.231 → aignostics-0.2.233}/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.231 → aignostics-0.2.233}/codegen/out/aignx/codegen/models/me_read_response.py
RENAMED
|
File without changes
|
|
File without changes
|
{aignostics-0.2.231 → aignostics-0.2.233}/codegen/out/aignx/codegen/models/output_artifact.py
RENAMED
|
File without changes
|
|
File without changes
|
{aignostics-0.2.231 → aignostics-0.2.233}/codegen/out/aignx/codegen/models/output_artifact_scope.py
RENAMED
|
File without changes
|
|
File without changes
|