aignostics 0.2.142__tar.gz → 0.2.146__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.
Files changed (167) hide show
  1. {aignostics-0.2.142 → aignostics-0.2.146}/PKG-INFO +2 -3
  2. {aignostics-0.2.142 → aignostics-0.2.146}/examples/notebook.py +1 -1
  3. {aignostics-0.2.142 → aignostics-0.2.146}/pyproject.toml +4 -4
  4. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/application/_cli.py +19 -6
  5. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/application/_gui/_page_application_run_describe.py +44 -2
  6. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/application/_service.py +32 -1
  7. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/dataset/_service.py +3 -1
  8. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/gui/_frame.py +3 -1
  9. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/notebook/_service.py +3 -1
  10. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/platform/_settings.py +2 -2
  11. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/platform/resources/runs.py +8 -0
  12. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/qupath/_service.py +13 -3
  13. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/third_party/idc_index.py +7 -3
  14. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/utils/__init__.py +2 -1
  15. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/utils/_fs.py +2 -2
  16. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/utils/_gui.py +1 -1
  17. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/utils/_log.py +2 -2
  18. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/utils/_process.py +3 -0
  19. {aignostics-0.2.142 → aignostics-0.2.146}/.gitignore +0 -0
  20. {aignostics-0.2.142 → aignostics-0.2.146}/LICENSE +0 -0
  21. {aignostics-0.2.142 → aignostics-0.2.146}/README.md +0 -0
  22. {aignostics-0.2.142 → aignostics-0.2.146}/codegen/out/.openapi-generator/FILES +0 -0
  23. {aignostics-0.2.142 → aignostics-0.2.146}/codegen/out/.openapi-generator/VERSION +0 -0
  24. {aignostics-0.2.142 → aignostics-0.2.146}/codegen/out/aignx/codegen/api/public_api.py +0 -0
  25. {aignostics-0.2.142 → aignostics-0.2.146}/codegen/out/aignx/codegen/api_client.py +0 -0
  26. {aignostics-0.2.142 → aignostics-0.2.146}/codegen/out/aignx/codegen/api_response.py +0 -0
  27. {aignostics-0.2.142 → aignostics-0.2.146}/codegen/out/aignx/codegen/configuration.py +0 -0
  28. {aignostics-0.2.142 → aignostics-0.2.146}/codegen/out/aignx/codegen/exceptions.py +0 -0
  29. {aignostics-0.2.142 → aignostics-0.2.146}/codegen/out/aignx/codegen/models/__init__.py +0 -0
  30. {aignostics-0.2.142 → aignostics-0.2.146}/codegen/out/aignx/codegen/models/application_read_response.py +0 -0
  31. {aignostics-0.2.142 → aignostics-0.2.146}/codegen/out/aignx/codegen/models/application_run_status.py +0 -0
  32. {aignostics-0.2.142 → aignostics-0.2.146}/codegen/out/aignx/codegen/models/application_version_read_response.py +0 -0
  33. {aignostics-0.2.142 → aignostics-0.2.146}/codegen/out/aignx/codegen/models/http_validation_error.py +0 -0
  34. {aignostics-0.2.142 → aignostics-0.2.146}/codegen/out/aignx/codegen/models/input_artifact_creation_request.py +0 -0
  35. {aignostics-0.2.142 → aignostics-0.2.146}/codegen/out/aignx/codegen/models/input_artifact_read_response.py +0 -0
  36. {aignostics-0.2.142 → aignostics-0.2.146}/codegen/out/aignx/codegen/models/item_creation_request.py +0 -0
  37. {aignostics-0.2.142 → aignostics-0.2.146}/codegen/out/aignx/codegen/models/item_result_read_response.py +0 -0
  38. {aignostics-0.2.142 → aignostics-0.2.146}/codegen/out/aignx/codegen/models/item_status.py +0 -0
  39. {aignostics-0.2.142 → aignostics-0.2.146}/codegen/out/aignx/codegen/models/me_read_response.py +0 -0
  40. {aignostics-0.2.142 → aignostics-0.2.146}/codegen/out/aignx/codegen/models/organization_read_response.py +0 -0
  41. {aignostics-0.2.142 → aignostics-0.2.146}/codegen/out/aignx/codegen/models/output_artifact_read_response.py +0 -0
  42. {aignostics-0.2.142 → aignostics-0.2.146}/codegen/out/aignx/codegen/models/output_artifact_result_read_response.py +0 -0
  43. {aignostics-0.2.142 → aignostics-0.2.146}/codegen/out/aignx/codegen/models/output_artifact_scope.py +0 -0
  44. {aignostics-0.2.142 → aignostics-0.2.146}/codegen/out/aignx/codegen/models/payload_input_artifact.py +0 -0
  45. {aignostics-0.2.142 → aignostics-0.2.146}/codegen/out/aignx/codegen/models/payload_item.py +0 -0
  46. {aignostics-0.2.142 → aignostics-0.2.146}/codegen/out/aignx/codegen/models/payload_output_artifact.py +0 -0
  47. {aignostics-0.2.142 → aignostics-0.2.146}/codegen/out/aignx/codegen/models/run_creation_request.py +0 -0
  48. {aignostics-0.2.142 → aignostics-0.2.146}/codegen/out/aignx/codegen/models/run_creation_response.py +0 -0
  49. {aignostics-0.2.142 → aignostics-0.2.146}/codegen/out/aignx/codegen/models/run_read_response.py +0 -0
  50. {aignostics-0.2.142 → aignostics-0.2.146}/codegen/out/aignx/codegen/models/transfer_urls.py +0 -0
  51. {aignostics-0.2.142 → aignostics-0.2.146}/codegen/out/aignx/codegen/models/user_payload.py +0 -0
  52. {aignostics-0.2.142 → aignostics-0.2.146}/codegen/out/aignx/codegen/models/user_read_response.py +0 -0
  53. {aignostics-0.2.142 → aignostics-0.2.146}/codegen/out/aignx/codegen/models/validation_error.py +0 -0
  54. {aignostics-0.2.142 → aignostics-0.2.146}/codegen/out/aignx/codegen/models/validation_error_loc_inner.py +0 -0
  55. {aignostics-0.2.142 → aignostics-0.2.146}/codegen/out/aignx/codegen/rest.py +0 -0
  56. {aignostics-0.2.142 → aignostics-0.2.146}/codegen/out/docs/PublicApi.md +0 -0
  57. {aignostics-0.2.142 → aignostics-0.2.146}/dist_native_all/dist_native-macos-13/extracted/aignostics.app/Contents/Frameworks/boto3/examples/cloudfront.rst +0 -0
  58. {aignostics-0.2.142 → aignostics-0.2.146}/dist_native_all/dist_native-macos-13/extracted/aignostics.app/Contents/Frameworks/boto3/examples/s3.rst +0 -0
  59. {aignostics-0.2.142 → aignostics-0.2.146}/dist_native_all/dist_native-macos-latest/extracted/aignostics.app/Contents/Frameworks/boto3/examples/cloudfront.rst +0 -0
  60. {aignostics-0.2.142 → aignostics-0.2.146}/dist_native_all/dist_native-macos-latest/extracted/aignostics.app/Contents/Frameworks/boto3/examples/s3.rst +0 -0
  61. {aignostics-0.2.142 → aignostics-0.2.146}/dist_native_all/dist_native-ubuntu-24.04-arm/extracted/aignostics/_internal/boto3/examples/cloudfront.rst +0 -0
  62. {aignostics-0.2.142 → aignostics-0.2.146}/dist_native_all/dist_native-ubuntu-24.04-arm/extracted/aignostics/_internal/boto3/examples/s3.rst +0 -0
  63. {aignostics-0.2.142 → aignostics-0.2.146}/dist_native_all/dist_native-ubuntu-latest/extracted/aignostics/_internal/boto3/examples/cloudfront.rst +0 -0
  64. {aignostics-0.2.142 → aignostics-0.2.146}/dist_native_all/dist_native-ubuntu-latest/extracted/aignostics/_internal/boto3/examples/s3.rst +0 -0
  65. {aignostics-0.2.142 → aignostics-0.2.146}/dist_native_all/dist_native-windows-latest/extracted/aignostics/_internal/boto3/examples/cloudfront.rst +0 -0
  66. {aignostics-0.2.142 → aignostics-0.2.146}/dist_native_all/dist_native-windows-latest/extracted/aignostics/_internal/boto3/examples/s3.rst +0 -0
  67. {aignostics-0.2.142 → aignostics-0.2.146}/examples/__init__.py +0 -0
  68. {aignostics-0.2.142 → aignostics-0.2.146}/examples/notebook.ipynb +0 -0
  69. {aignostics-0.2.142 → aignostics-0.2.146}/examples/script.py +0 -0
  70. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/__init__.py +0 -0
  71. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/application/__init__.py +0 -0
  72. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/application/_gui/_frame.py +0 -0
  73. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/application/_gui/_page_application_describe.py +0 -0
  74. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/application/_gui/_page_builder.py +0 -0
  75. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/application/_gui/_page_index.py +0 -0
  76. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/application/_gui/_utils.py +0 -0
  77. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/application/_gui/assets/.gitignore +0 -0
  78. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/application/_gui/assets/canceled.lottie +0 -0
  79. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/application/_gui/assets/done.lottie +0 -0
  80. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/application/_gui/assets/empty.lottie +0 -0
  81. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/application/_gui/assets/error.lottie +0 -0
  82. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/application/_gui/assets/error_alt.lottie +0 -0
  83. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/application/_gui/assets/home-card-1.png +0 -0
  84. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/application/_gui/assets/home-card-2.png +0 -0
  85. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/application/_gui/assets/home-card-3.png +0 -0
  86. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/application/_gui/assets/home-card-4.png +0 -0
  87. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/application/_gui/assets/home-card-5.png +0 -0
  88. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/application/_gui/assets/image-not-found.png +0 -0
  89. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/application/_gui/assets/pending.lottie +0 -0
  90. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/application/_gui/assets/pending_alt.lottie +0 -0
  91. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/application/_gui/assets/ruo.png +0 -0
  92. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/application/_gui/assets/ruo.svg +0 -0
  93. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/application/_settings.py +0 -0
  94. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/application/_utils.py +0 -0
  95. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/bucket/__init__.py +0 -0
  96. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/bucket/_cli.py +0 -0
  97. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/bucket/_gui.py +0 -0
  98. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/bucket/_service.py +0 -0
  99. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/bucket/_settings.py +0 -0
  100. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/bucket/assets/Google-Cloud-logo.png +0 -0
  101. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/bucket/assets/Google-Cloud-logo.svg +0 -0
  102. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/cli.py +0 -0
  103. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/constants.py +0 -0
  104. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/dataset/__init__.py +0 -0
  105. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/dataset/_cli.py +0 -0
  106. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/dataset/_gui.py +0 -0
  107. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/dataset/assets/NIH-IDC-logo.svg +0 -0
  108. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/gui/__init__.py +0 -0
  109. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/gui/_error.py +0 -0
  110. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/gui/_theme.py +0 -0
  111. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/gui/assets/cabin-v27-latin-regular.woff2 +0 -0
  112. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/gui/assets/cat.lottie +0 -0
  113. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/gui/assets/logo.png +0 -0
  114. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/notebook/__init__.py +0 -0
  115. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/notebook/_gui.py +0 -0
  116. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/notebook/_notebook.py +0 -0
  117. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/notebook/assets/python.lottie +0 -0
  118. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/platform/__init__.py +0 -0
  119. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/platform/_authentication.py +0 -0
  120. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/platform/_cli.py +0 -0
  121. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/platform/_client.py +0 -0
  122. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/platform/_constants.py +0 -0
  123. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/platform/_messages.py +0 -0
  124. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/platform/_service.py +0 -0
  125. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/platform/_utils.py +0 -0
  126. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/platform/resources/__init__.py +0 -0
  127. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/platform/resources/applications.py +0 -0
  128. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/platform/resources/utils.py +0 -0
  129. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/qupath/__init__.py +0 -0
  130. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/qupath/_cli.py +0 -0
  131. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/qupath/_gui.py +0 -0
  132. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/qupath/_settings.py +0 -0
  133. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/qupath/assets/download.lottie +0 -0
  134. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/qupath/assets/microscope.lottie +0 -0
  135. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/qupath/assets/update.lottie +0 -0
  136. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/qupath/scripts/add.groovy +0 -0
  137. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/qupath/scripts/annotate.groovy +0 -0
  138. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/qupath/scripts/inspect.groovy +0 -0
  139. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/qupath/scripts/test.groovy +0 -0
  140. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/system/__init__.py +0 -0
  141. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/system/_cli.py +0 -0
  142. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/system/_exceptions.py +0 -0
  143. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/system/_gui.py +0 -0
  144. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/system/_service.py +0 -0
  145. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/system/_settings.py +0 -0
  146. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/system/assets/system.lottie +0 -0
  147. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/third_party/bottle.py +0 -0
  148. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/utils/_cli.py +0 -0
  149. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/utils/_console.py +0 -0
  150. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/utils/_constants.py +0 -0
  151. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/utils/_di.py +0 -0
  152. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/utils/_health.py +0 -0
  153. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/utils/_logfire.py +0 -0
  154. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/utils/_notebook.py +0 -0
  155. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/utils/_sentry.py +0 -0
  156. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/utils/_service.py +0 -0
  157. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/utils/_settings.py +0 -0
  158. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/utils/boot.py +0 -0
  159. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/wsi/__init__.py +0 -0
  160. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/wsi/_cli.py +0 -0
  161. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/wsi/_gui.py +0 -0
  162. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/wsi/_openslide_handler.py +0 -0
  163. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/wsi/_pydicom_handler.py +0 -0
  164. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/wsi/_service.py +0 -0
  165. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/wsi/_utils.py +0 -0
  166. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics/wsi/assets/fallback.png +0 -0
  167. {aignostics-0.2.142 → aignostics-0.2.146}/src/aignostics.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aignostics
3
- Version: 0.2.142
3
+ Version: 0.2.146
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/
@@ -48,8 +48,7 @@ Classifier: Programming Language :: Python :: 3.12
48
48
  Classifier: Programming Language :: Python :: 3.13
49
49
  Classifier: Typing :: Typed
50
50
  Requires-Python: <4.0,>=3.11
51
- Requires-Dist: appdirs>=1.4.4
52
- Requires-Dist: boto3>=1.40.10
51
+ Requires-Dist: boto3>=1.40.11
53
52
  Requires-Dist: certifi>=2025.8.3
54
53
  Requires-Dist: dicom-validator>=0.7.1
55
54
  Requires-Dist: dicomweb-client[gcp]>=0.59.2
@@ -2,7 +2,7 @@
2
2
  # requires-python = ">=3.13"
3
3
  # dependencies = [
4
4
  # "marimo",
5
- # "aignostics==0.2.142",
5
+ # "aignostics==0.2.146",
6
6
  # ]
7
7
  # ///
8
8
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "aignostics"
3
- version = "0.2.142"
3
+ version = "0.2.146"
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 = [
@@ -96,8 +96,8 @@ dependencies = [
96
96
  "typer>=0.16.0",
97
97
  "uptime>=3.0.1",
98
98
  # Custom
99
- "appdirs>=1.4.4",
100
- "boto3>=1.40.10",
99
+ "platformdirs>=4.3.8",
100
+ "boto3>=1.40.11",
101
101
  "certifi>=2025.8.3",
102
102
  "dicom-validator>=0.7.1",
103
103
  "dicomweb-client[gcp]>=0.59.2",
@@ -358,7 +358,7 @@ source = ["src/"]
358
358
 
359
359
 
360
360
  [tool.bumpversion]
361
- current_version = "0.2.142"
361
+ current_version = "0.2.146"
362
362
  parse = "(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)"
363
363
  serialize = ["{major}.{minor}.{patch}"]
364
364
  search = "{current_version}"
@@ -819,9 +819,22 @@ def result_download( # noqa: PLR0913, PLR0917
819
819
  sys.exit(1)
820
820
 
821
821
 
822
- # TODO(Helmut): Implement result delete when available in platform
823
- @result_app.command("delete")
824
- def result_delete() -> None:
825
- """Delete results of a run."""
826
- console.print(MESSAGE_NOT_YET_IMPLEMENTED)
827
- sys.exit(1)
822
+ @run_app.command("delete")
823
+ def run_delete(
824
+ run_id: Annotated[str, typer.Argument(..., help="Id of the run to delete")],
825
+ ) -> None:
826
+ """Delete run."""
827
+ logger.debug("Deleting run with ID '%s'", run_id)
828
+
829
+ try:
830
+ Service().application_run_delete(run_id)
831
+ logger.info("Deleted run with ID '%s'.", run_id)
832
+ console.print(f"Run with ID '{run_id}' has been deleted.")
833
+ except NotFoundException:
834
+ logger.warning("Run with ID '%s' not found.", run_id)
835
+ console.print(f"[warning]Warning:[/warning] Run with ID '{run_id}' not found.")
836
+ sys.exit(2)
837
+ except Exception as e:
838
+ logger.exception("Failed to delete run with ID '%s'", run_id)
839
+ console.print(f"[bold red]Error:[/bold red] Failed to delete run with ID '{run_id}': {e}")
840
+ sys.exit(1)
@@ -97,6 +97,30 @@ async def _page_application_run_describe(application_run_id: str) -> None: # no
97
97
  ui.notify(f"Failed to cancel application run: {e}.", type="warning")
98
98
  return False
99
99
 
100
+ async def _delete(run_id: str) -> bool:
101
+ """Delete the application run and navigate to the main page.
102
+
103
+ Args:
104
+ run_id (str): The ID of the run to cancel.
105
+
106
+ Returns:
107
+ bool: True if the run was cancelled, False otherwise.
108
+ """
109
+ ui.notify(f"Deleting application run with id '{run_id}' ...", type="info")
110
+ try:
111
+ delete_button.disable()
112
+ delete_button.props(add="loading")
113
+ await nicegui_run.io_bound(service.application_run_delete, run_id)
114
+ delete_button.props(remove="loading")
115
+ ui.navigate.to("/")
116
+ ui.notify("Application run deleted!", type="positive")
117
+ return True
118
+ except Exception as e: # noqa: BLE001
119
+ delete_button.enable()
120
+ delete_button.props(remove="loading")
121
+ ui.notify(f"Failed to delete application run: {e}.", type="warning")
122
+ return False
123
+
100
124
  @ui.refreshable
101
125
  def download_run_dialog_content(qupath_project: bool = False, marimo: bool = False) -> None: # noqa: C901, PLR0915
102
126
  if qupath_project:
@@ -407,14 +431,15 @@ async def _page_application_run_describe(application_run_id: str) -> None: # no
407
431
  if run_data: # noqa: PLR1702
408
432
  with ui.row().classes("w-full justify-center"):
409
433
  with ui.expansion(text=f"Run {run.application_run_id}"):
410
- ui.markdown(
434
+ ui.code(
411
435
  f"""
412
436
  * Run ID: {run_data.application_run_id}
413
437
  * Application Version: {run_data.application_version_id}
414
438
  * Triggered On: {run_data.triggered_at.astimezone().strftime("%m-%d %H:%M")}
415
439
  * Triggered by: {run_data.triggered_by}
416
440
  * Organization: {run_data.organization_id}
417
- """
441
+ """,
442
+ language="markdown",
418
443
  )
419
444
  ui.space()
420
445
  with ui.row().classes("justify-end"):
@@ -448,6 +473,7 @@ async def _page_application_run_describe(application_run_id: str) -> None: # no
448
473
  .props("push")
449
474
  ):
450
475
  ui.tooltip("Open results in Python Notebook served by Marimo")
476
+
451
477
  if run_data.status.value == ApplicationRunStatus.RUNNING:
452
478
  cancel_button = ui.button(
453
479
  "Cancel",
@@ -456,6 +482,22 @@ async def _page_application_run_describe(application_run_id: str) -> None: # no
456
482
  icon="cancel",
457
483
  ).mark("BUTTON_APPLICATION_RUN_CANCEL")
458
484
 
485
+ if run_data.status.value in {
486
+ ApplicationRunStatus.CANCELED_USER,
487
+ ApplicationRunStatus.CANCELED_SYSTEM,
488
+ ApplicationRunStatus.COMPLETED,
489
+ ApplicationRunStatus.COMPLETED_WITH_ERROR,
490
+ ApplicationRunStatus.REJECTED,
491
+ ApplicationRunStatus.RUNNING,
492
+ ApplicationRunStatus.SCHEDULED,
493
+ }:
494
+ delete_button = ui.button(
495
+ "Delete",
496
+ color="red",
497
+ on_click=lambda: _delete(run.application_run_id),
498
+ icon="delete",
499
+ ).mark("BUTTON_APPLICATION_RUN_DELETE")
500
+
459
501
  with ui.list().classes("full-width"):
460
502
  results = list(run.results())
461
503
  if not results:
@@ -775,7 +775,7 @@ class Service(BaseService):
775
775
 
776
776
  Raises:
777
777
  NotFoundException: If the application run with the given ID is not found.
778
- ValueError: If the run ID is invalid or the run cannot be canceled given its current status.
778
+ ValueError: If the run ID is invalid or the run cannot be canceled given its current state.
779
779
  RuntimeError: If canceling the run fails unexpectedly.
780
780
  """
781
781
  try:
@@ -793,6 +793,37 @@ class Service(BaseService):
793
793
  logger.exception(message)
794
794
  raise RuntimeError(message) from e
795
795
 
796
+ def application_run_delete(self, run_id: str) -> None:
797
+ """Delete a run by its ID.
798
+
799
+ Args:
800
+ run_id: The ID of the run to delete
801
+
802
+ Raises:
803
+ Exception: If the client cannot be created.
804
+
805
+ Raises:
806
+ NotFoundException: If the application run with the given ID is not found.
807
+ ValueError: If the run ID is invalid or the run cannot be deleted given its current state.
808
+ RuntimeError: If deleting the run fails unexpectedly.
809
+ """
810
+ try:
811
+ logger.debug("Deleting application run with ID '%s'", run_id)
812
+ self.application_run(run_id).delete()
813
+ logger.debug("Deleted application run with ID '%s'", run_id)
814
+ except ValueError as e:
815
+ message = f"Failed to delete application run with ID '{run_id}': ValueError {e}"
816
+ logger.warning(message)
817
+ raise ValueError(message) from e
818
+ except NotFoundException as e:
819
+ message = f"Application run with ID '{run_id}' not found: {e}"
820
+ logger.warning(message)
821
+ raise NotFoundException(message) from e
822
+ except Exception as e:
823
+ message = f"Failed to delete application run with ID '{run_id}': {e}"
824
+ logger.exception(message)
825
+ raise RuntimeError(message) from e
826
+
796
827
  @staticmethod
797
828
  def application_run_download_static( # noqa: PLR0913, PLR0917
798
829
  run_id: str,
@@ -10,7 +10,7 @@ from multiprocessing import Queue
10
10
  from pathlib import Path
11
11
  from typing import Any
12
12
 
13
- from aignostics.utils import BaseService, Health, get_logger
13
+ from aignostics.utils import SUBPROCESS_CREATION_FLAGS, BaseService, Health, get_logger
14
14
 
15
15
  logger = get_logger(__name__)
16
16
 
@@ -248,6 +248,7 @@ client.download_from_selection(
248
248
  stderr=subprocess.PIPE,
249
249
  text=True,
250
250
  bufsize=1,
251
+ creationflags=SUBPROCESS_CREATION_FLAGS,
251
252
  )
252
253
  else:
253
254
  logger.debug(
@@ -259,6 +260,7 @@ client.download_from_selection(
259
260
  stderr=subprocess.PIPE,
260
261
  text=True,
261
262
  bufsize=1,
263
+ creationflags=SUBPROCESS_CREATION_FLAGS,
262
264
  )
263
265
 
264
266
  # Register process for cleanup
@@ -2,6 +2,7 @@
2
2
 
3
3
  import contextlib
4
4
  import platform
5
+ import sys
5
6
  from collections.abc import Generator
6
7
  from contextlib import contextmanager
7
8
  from importlib.util import find_spec
@@ -307,9 +308,10 @@ def frame( # noqa: C901, PLR0915
307
308
  ui.tooltip("Check Platform Status")
308
309
  ui.space()
309
310
  with ui.row():
311
+ flavor = " (native)" if getattr(sys, "frozen", False) else ""
310
312
  ui.html(
311
313
  '🔬<a style="color: black; text-decoration: underline" target="_blank" href="https://github.com/aignostics/python-sdk/">'
312
- f"Aignostics Python SDK v{__version__}</a>"
314
+ f"Aignostics Python SDK v{__version__}{flavor}</a>"
313
315
  ' - built with love in <a style="color: black; text-decoration: underline" target="_blank"'
314
316
  ' href="https://www.aignostics.com/company/about">Berlin</A> 🐻'
315
317
  ).style("color: black")
@@ -8,7 +8,7 @@ from threading import Event, Thread
8
8
  from typing import Any
9
9
 
10
10
  from aignostics.constants import NOTEBOOK_DEFAULT
11
- from aignostics.utils import BaseService, Health, get_logger, get_user_data_directory
11
+ from aignostics.utils import SUBPROCESS_CREATION_FLAGS, BaseService, Health, get_logger, get_user_data_directory
12
12
 
13
13
  logger = get_logger(__name__)
14
14
 
@@ -104,6 +104,7 @@ class _Runner:
104
104
  encoding="utf-8",
105
105
  errors="replace",
106
106
  bufsize=1,
107
+ creationflags=SUBPROCESS_CREATION_FLAGS,
107
108
  )
108
109
  else:
109
110
  self._marimo_server = Popen( # noqa: S603
@@ -124,6 +125,7 @@ class _Runner:
124
125
  encoding="utf-8",
125
126
  errors="replace",
126
127
  bufsize=1,
128
+ creationflags=SUBPROCESS_CREATION_FLAGS,
127
129
  )
128
130
 
129
131
  # Start a thread to monitor the subprocess output
@@ -6,7 +6,7 @@ from pathlib import Path
6
6
  from typing import Annotated, TypeVar
7
7
  from urllib.parse import urlparse
8
8
 
9
- import appdirs
9
+ import platformdirs
10
10
  from pydantic import (
11
11
  Field,
12
12
  FieldSerializationInfo,
@@ -180,7 +180,7 @@ class Settings(OpaqueSettings):
180
180
  Field(description="Refresh token for OAuth authentication", min_length=10, max_length=1000, default=None),
181
181
  ] = None
182
182
 
183
- cache_dir: str = appdirs.user_cache_dir(__project_name__)
183
+ cache_dir: str = platformdirs.user_cache_dir(__project_name__)
184
184
 
185
185
  @computed_field # type: ignore[prop-decorator]
186
186
  @property
@@ -114,6 +114,14 @@ class ApplicationRun:
114
114
  """
115
115
  self._api.cancel_application_run_v1_runs_application_run_id_cancel_post(self.application_run_id)
116
116
 
117
+ def delete(self) -> None:
118
+ """Delete the application run.
119
+
120
+ Raises:
121
+ Exception: If the API request fails.
122
+ """
123
+ self._api.delete_application_run_results_v1_runs_application_run_id_results_delete(self.application_run_id)
124
+
117
125
  def results(self) -> t.Iterator[ItemResultData]:
118
126
  """Retrieves the results of all items in the run.
119
127
 
@@ -17,15 +17,22 @@ from pathlib import Path
17
17
  from typing import Any
18
18
  from urllib.parse import urlparse, urlsplit
19
19
 
20
- import appdirs
21
20
  import ijson
21
+ import platformdirs
22
22
  import psutil
23
23
  import requests
24
24
  from packaging.version import Version
25
25
  from psutil import Process, wait_procs
26
26
  from pydantic import BaseModel, computed_field
27
27
 
28
- from aignostics.utils import UNHIDE_SENSITIVE_INFO, BaseService, Health, __project_name__, get_logger
28
+ from aignostics.utils import (
29
+ SUBPROCESS_CREATION_FLAGS,
30
+ UNHIDE_SENSITIVE_INFO,
31
+ BaseService,
32
+ Health,
33
+ __project_name__,
34
+ get_logger,
35
+ )
29
36
 
30
37
  from ._settings import Settings
31
38
 
@@ -333,6 +340,7 @@ class Service(BaseService):
333
340
  text=True,
334
341
  check=True,
335
342
  timeout=QUPATH_LAUNCH_MAX_WAIT_TIME,
343
+ creationflags=SUBPROCESS_CREATION_FLAGS,
336
344
  )
337
345
 
338
346
  output = result.stdout.strip()
@@ -449,7 +457,7 @@ class Service(BaseService):
449
457
  Returns:
450
458
  Path: The directory QuPath will be installed into.
451
459
  """
452
- return Path(appdirs.user_data_dir(__project_name__)).resolve()
460
+ return Path(platformdirs.user_data_dir(__project_name__)).resolve()
453
461
 
454
462
  @staticmethod
455
463
  def _download_qupath( # noqa: C901, PLR0912, PLR0913, PLR0915, PLR0917
@@ -702,6 +710,7 @@ class Service(BaseService):
702
710
  command,
703
711
  capture_output=True,
704
712
  check=True,
713
+ creationflags=SUBPROCESS_CREATION_FLAGS,
705
714
  )
706
715
  except subprocess.CalledProcessError as e:
707
716
  stderr_output = e.stderr.decode("utf-8", errors="replace") if e.stderr else ""
@@ -735,6 +744,7 @@ class Service(BaseService):
735
744
  command,
736
745
  capture_output=True,
737
746
  check=True,
747
+ creationflags=SUBPROCESS_CREATION_FLAGS,
738
748
  )
739
749
  except subprocess.CalledProcessError as e:
740
750
  stderr_output = e.stderr.decode("utf-8", errors="replace") if e.stderr else ""
@@ -52,7 +52,7 @@ import requests
52
52
  from packaging.version import Version
53
53
  from tqdm import tqdm
54
54
 
55
- from aignostics.utils import get_logger
55
+ from aignostics.utils import get_logger, SUBPROCESS_CREATION_FLAGS
56
56
 
57
57
  aws_endpoint_url = "https://s3.amazonaws.com"
58
58
  gcp_endpoint_url = "https://storage.googleapis.com"
@@ -427,6 +427,7 @@ class IDCClient:
427
427
  capture_output=True,
428
428
  text=True,
429
429
  check=True,
430
+ creationflags=SUBPROCESS_CREATION_FLAGS,
430
431
  )
431
432
  if result.stderr and result.stdout.startswith("ERROR"):
432
433
  logger.error("Failed to download IDC clinical data.")
@@ -712,6 +713,7 @@ class IDCClient:
712
713
  ],
713
714
  stdout=subprocess.PIPE,
714
715
  check=False,
716
+ creationflags=SUBPROCESS_CREATION_FLAGS,
715
717
  )
716
718
  output = result.stdout.decode("utf-8")
717
719
 
@@ -1135,7 +1137,8 @@ class IDCClient:
1135
1137
  merged_df.s3_url.values[0],
1136
1138
  ]
1137
1139
  process = subprocess.run(
1138
- cmd, capture_output=True, text=True, check=False
1140
+ cmd, capture_output=True, text=True, check=False,
1141
+ creationflags=SUBPROCESS_CREATION_FLAGS,
1139
1142
  )
1140
1143
  if process.stderr and process.stdout.startswith("ERROR"):
1141
1144
  logger.debug(
@@ -1473,7 +1476,8 @@ class IDCClient:
1473
1476
  ]
1474
1477
 
1475
1478
  process = subprocess.run(
1476
- dry_run_cmd, stdout=subprocess.PIPE, text=True, check=False
1479
+ dry_run_cmd, stdout=subprocess.PIPE, text=True, check=False,
1480
+ creationflags=SUBPROCESS_CREATION_FLAGS,
1477
1481
  )
1478
1482
 
1479
1483
  if process.stdout:
@@ -21,12 +21,13 @@ from ._di import load_modules, locate_implementations, locate_subclasses
21
21
  from ._fs import get_user_data_directory, open_user_data_directory, sanitize_path, sanitize_path_component
22
22
  from ._health import Health
23
23
  from ._log import LogSettings, get_logger
24
- from ._process import ProcessInfo, get_process_info
24
+ from ._process import SUBPROCESS_CREATION_FLAGS, ProcessInfo, get_process_info
25
25
  from ._service import BaseService
26
26
  from ._settings import UNHIDE_SENSITIVE_INFO, OpaqueSettings, load_settings, strip_to_none_before_validator
27
27
  from .boot import boot
28
28
 
29
29
  __all__ = [
30
+ "SUBPROCESS_CREATION_FLAGS",
30
31
  "UNHIDE_SENSITIVE_INFO",
31
32
  "BaseService",
32
33
  "Health",
@@ -3,7 +3,7 @@
3
3
  import platform
4
4
  from pathlib import Path, PureWindowsPath
5
5
 
6
- import appdirs
6
+ import platformdirs
7
7
  from showinfm.showinfm import show_in_file_manager
8
8
 
9
9
  from ._constants import __is_running_in_read_only_environment__, __project_name__
@@ -89,7 +89,7 @@ def get_user_data_directory(scope: str | None = None) -> Path:
89
89
  Returns:
90
90
  Path: The data directory path.
91
91
  """
92
- directory = Path(appdirs.user_data_dir(__project_name__))
92
+ directory = Path(platformdirs.user_data_dir(__project_name__))
93
93
  if scope:
94
94
  directory /= scope
95
95
  if not __is_running_in_read_only_environment__:
@@ -9,7 +9,7 @@ from ._log import get_logger
9
9
 
10
10
  logger = get_logger(__name__)
11
11
 
12
- WINDOW_SIZE = (1200, 768) # Default window size for the GUI
12
+ WINDOW_SIZE = (1280, 768) # Default window size for the GUI
13
13
 
14
14
 
15
15
  class BasePageBuilder(ABC):
@@ -8,8 +8,8 @@ from logging import Handler
8
8
  from pathlib import Path
9
9
  from typing import Annotated, Literal
10
10
 
11
- import appdirs
12
11
  import click
12
+ import platformdirs
13
13
  from pydantic import Field, ValidationInfo, field_validator
14
14
  from pydantic_settings import BaseSettings, SettingsConfigDict
15
15
  from rich.console import Console
@@ -100,7 +100,7 @@ class LogSettings(BaseSettings):
100
100
  description="Name of the log file",
101
101
  default="/dev/stdout"
102
102
  if __is_running_in_read_only_environment__
103
- else appdirs.user_data_dir(__project_name__) + f"/{__project_name__}.log",
103
+ else platformdirs.user_data_dir(__project_name__) + f"/{__project_name__}.log",
104
104
  ),
105
105
  ]
106
106
  console_enabled: Annotated[
@@ -1,9 +1,12 @@
1
1
  """Process related utilities."""
2
2
 
3
+ import subprocess
3
4
  from pathlib import Path
4
5
 
5
6
  from pydantic import BaseModel
6
7
 
8
+ SUBPROCESS_CREATION_FLAGS = getattr(subprocess, "CREATE_NO_WINDOW", 0)
9
+
7
10
 
8
11
  class ParentProcessInfo(BaseModel):
9
12
  """Information about a parent process."""
File without changes
File without changes
File without changes