plexora 0.0.8__tar.gz → 0.0.9__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 (406) hide show
  1. {plexora-0.0.8/plexora.egg-info → plexora-0.0.9}/PKG-INFO +1 -1
  2. {plexora-0.0.8 → plexora-0.0.9}/plexora/connect.py +146 -129
  3. {plexora-0.0.8 → plexora-0.0.9}/plexora/server/node/app.py +18 -1
  4. {plexora-0.0.8 → plexora-0.0.9/plexora.egg-info}/PKG-INFO +1 -1
  5. {plexora-0.0.8 → plexora-0.0.9}/pyproject.toml +1 -1
  6. {plexora-0.0.8 → plexora-0.0.9}/tests/test_connect.py +68 -50
  7. {plexora-0.0.8 → plexora-0.0.9}/tests/test_node_warm_and_cache.py +28 -10
  8. {plexora-0.0.8 → plexora-0.0.9}/tests/test_remote_connect.py +10 -6
  9. {plexora-0.0.8 → plexora-0.0.9}/LICENSE +0 -0
  10. {plexora-0.0.8 → plexora-0.0.9}/MANIFEST.in +0 -0
  11. {plexora-0.0.8 → plexora-0.0.9}/README.md +0 -0
  12. {plexora-0.0.8 → plexora-0.0.9}/plexora/__init__.py +0 -0
  13. {plexora-0.0.8 → plexora-0.0.9}/plexora/__main__.py +0 -0
  14. {plexora-0.0.8 → plexora-0.0.9}/plexora/_resources.py +0 -0
  15. {plexora-0.0.8 → plexora-0.0.9}/plexora/_url.py +0 -0
  16. {plexora-0.0.8 → plexora-0.0.9}/plexora/api/__init__.py +0 -0
  17. {plexora-0.0.8 → plexora-0.0.9}/plexora/api/dataset.py +0 -0
  18. {plexora-0.0.8 → plexora-0.0.9}/plexora/api/http.py +0 -0
  19. {plexora-0.0.8 → plexora-0.0.9}/plexora/api/plugin.py +0 -0
  20. {plexora-0.0.8 → plexora-0.0.9}/plexora/api/store.py +0 -0
  21. {plexora-0.0.8 → plexora-0.0.9}/plexora/askpass.py +0 -0
  22. {plexora-0.0.8 → plexora-0.0.9}/plexora/cli.py +0 -0
  23. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/dist/354_bundle.js +0 -0
  24. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/dist/354_bundle.js.LICENSE.txt +0 -0
  25. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/dist/418_bundle.js +0 -0
  26. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/dist/418_bundle.js.LICENSE.txt +0 -0
  27. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/dist/693b935cb1f907814be9c6199a68c217.svg +0 -0
  28. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/dist/713c134ff47cd328a5b711526f151082.svg +0 -0
  29. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/dist/770_bundle.js +0 -0
  30. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/dist/ff743f408972e0e96ca9153ed5ae4c83.svg +0 -0
  31. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/dist/vendor_bundle.js +0 -0
  32. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/dist/vendor_bundle.js.LICENSE.txt +0 -0
  33. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/external/openseadragon-bin-2.4.0/LICENSE.txt +0 -0
  34. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/external/openseadragon-bin-2.4.0/canvas-overlay-hd.js +0 -0
  35. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/external/openseadragon-bin-2.4.0/changelog.txt +0 -0
  36. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/.gitattributes +0 -0
  37. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/LICENSE.txt +0 -0
  38. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/Photoshop/Toolbar.png +0 -0
  39. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/Photoshop/fullpage.psd +0 -0
  40. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/Photoshop/home.psd +0 -0
  41. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/Photoshop/next.psd +0 -0
  42. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/Photoshop/previous.psd +0 -0
  43. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/Photoshop/rotateleft.psd +0 -0
  44. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/Photoshop/rotateright.psd +0 -0
  45. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/Photoshop/zoom.psd +0 -0
  46. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/README.md +0 -0
  47. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/images/fullpage_grouphover.png +0 -0
  48. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/images/fullpage_hover.png +0 -0
  49. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/images/fullpage_pressed.png +0 -0
  50. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/images/fullpage_rest.png +0 -0
  51. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/images/home_grouphover.png +0 -0
  52. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/images/home_hover.png +0 -0
  53. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/images/home_pressed.png +0 -0
  54. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/images/home_rest.png +0 -0
  55. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/images/next_grouphover.png +0 -0
  56. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/images/next_hover.png +0 -0
  57. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/images/next_pressed.png +0 -0
  58. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/images/next_rest.png +0 -0
  59. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/images/previous_grouphover.png +0 -0
  60. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/images/previous_hover.png +0 -0
  61. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/images/previous_pressed.png +0 -0
  62. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/images/previous_rest.png +0 -0
  63. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/images/rotateleft_grouphover.png +0 -0
  64. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/images/rotateleft_hover.png +0 -0
  65. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/images/rotateleft_pressed.png +0 -0
  66. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/images/rotateleft_rest.png +0 -0
  67. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/images/rotateright_grouphover.png +0 -0
  68. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/images/rotateright_hover.png +0 -0
  69. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/images/rotateright_pressed.png +0 -0
  70. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/images/rotateright_rest.png +0 -0
  71. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/images/zoomin_grouphover.png +0 -0
  72. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/images/zoomin_hover.png +0 -0
  73. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/images/zoomin_pressed.png +0 -0
  74. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/images/zoomin_rest.png +0 -0
  75. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/images/zoomout_grouphover.png +0 -0
  76. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/images/zoomout_hover.png +0 -0
  77. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/images/zoomout_pressed.png +0 -0
  78. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/images/zoomout_rest.png +0 -0
  79. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/external/openseadragon-bin-2.4.0/openseadragon-scalebar.js +0 -0
  80. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/src/css/import.css +0 -0
  81. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/src/css/main.css +0 -0
  82. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/src/css/openProject.css +0 -0
  83. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/src/css/quickView.css +0 -0
  84. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/src/css/settings.css +0 -0
  85. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/src/css/tokens.css +0 -0
  86. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/src/css/viewer.css +0 -0
  87. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/src/img/apple-touch-icon.png +0 -0
  88. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/src/img/favicon.ico +0 -0
  89. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/src/img/logo.ai +0 -0
  90. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/src/img/logo.svg +0 -0
  91. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/src/img/logo_with_text.ai +0 -0
  92. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/src/img/logo_with_text.svg +0 -0
  93. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/src/js/main.js +0 -0
  94. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/src/js/pluginRegistry.js +0 -0
  95. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/src/js/services/appRouter.js +0 -0
  96. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/src/js/services/appStatus.js +0 -0
  97. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/src/js/services/browsePicker.js +0 -0
  98. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/src/js/services/connectionModal.js +0 -0
  99. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/src/js/services/dataLayer.js +0 -0
  100. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/src/js/services/dataLocation.js +0 -0
  101. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/src/js/services/datasetContext.js +0 -0
  102. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/src/js/services/fileLocation.js +0 -0
  103. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/src/js/services/glRenderer.js +0 -0
  104. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/src/js/services/importFormValidation.js +0 -0
  105. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/src/js/services/keyboardShortcuts.js +0 -0
  106. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/src/js/services/logTerminal.js +0 -0
  107. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/src/js/services/numericData.js +0 -0
  108. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/src/js/services/pageBoot.js +0 -0
  109. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/src/js/services/passVariablesToFrontend.js +0 -0
  110. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/src/js/services/pathPicker.js +0 -0
  111. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/src/js/services/placePicker.js +0 -0
  112. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/src/js/services/remoteGlobe.js +0 -0
  113. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/src/js/services/remoteState.js +0 -0
  114. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/src/js/services/resourceRouting.js +0 -0
  115. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/src/js/services/resourceStatus.js +0 -0
  116. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/src/js/services/sessionExpiry.js +0 -0
  117. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/src/js/services/simpleEventHandler.js +0 -0
  118. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/src/js/vendor.js +0 -0
  119. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/src/js/views/channelList.js +0 -0
  120. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/src/js/views/channelNamesUpload.js +0 -0
  121. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/src/js/views/colorSwatchPicker.js +0 -0
  122. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/src/js/views/columnClassifier.js +0 -0
  123. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/src/js/views/coordinateField.js +0 -0
  124. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/src/js/views/dataSourceField.js +0 -0
  125. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/src/js/views/imageViewer.js +0 -0
  126. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/src/js/views/miniMap.js +0 -0
  127. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/src/js/views/navbarControls.js +0 -0
  128. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/src/js/views/openProjectPage.js +0 -0
  129. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/src/js/views/popoverPortal.js +0 -0
  130. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/src/js/views/projectEdit.js +0 -0
  131. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/src/js/views/quickViewLanding.js +0 -0
  132. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/src/js/views/rainbow.js +0 -0
  133. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/src/js/views/requirementsModal.js +0 -0
  134. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/src/js/views/rgbImageViewer.js +0 -0
  135. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/src/js/views/searchableSelect.js +0 -0
  136. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/src/js/views/segmentationProgress.js +0 -0
  137. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/src/js/views/segmentationWait.js +0 -0
  138. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/src/js/views/settingsPage.js +0 -0
  139. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/src/js/views/toolLoader.js +0 -0
  140. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/src/js/views/viewerControls.js +0 -0
  141. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/src/js/views/viewerManager.js +0 -0
  142. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/src/js/views/viewerSidebar.js +0 -0
  143. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/src/js/workers/tileDecoder.js +0 -0
  144. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/src/shaders/frag.glsl +0 -0
  145. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/src/shaders/vert.glsl +0 -0
  146. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/templates/_fragment.html +0 -0
  147. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/templates/base.html +0 -0
  148. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/templates/index.html +0 -0
  149. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/templates/open_project.html +0 -0
  150. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/templates/project_columns.html +0 -0
  151. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/templates/project_edit.html +0 -0
  152. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/templates/settings.html +0 -0
  153. {plexora-0.0.8 → plexora-0.0.9}/plexora/client/templates/upload.html +0 -0
  154. {plexora-0.0.8 → plexora-0.0.9}/plexora/datasource.py +0 -0
  155. {plexora-0.0.8 → plexora-0.0.9}/plexora/jupyter.py +0 -0
  156. {plexora-0.0.8 → plexora-0.0.9}/plexora/nodes.py +0 -0
  157. {plexora-0.0.8 → plexora-0.0.9}/plexora/notebook_env.py +0 -0
  158. {plexora-0.0.8 → plexora-0.0.9}/plexora/paths.py +0 -0
  159. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/__init__.py +0 -0
  160. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/cell_explorer/__init__.py +0 -0
  161. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/cell_explorer/server/__init__.py +0 -0
  162. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/cell_explorer/server/routes.py +0 -0
  163. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/cell_explorer/server/state.py +0 -0
  164. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/cell_explorer/server/values.py +0 -0
  165. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/cell_explorer/server/variables.py +0 -0
  166. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/cell_explorer/static/cellExplorerApi.js +0 -0
  167. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/cell_explorer/static/cellExplorerColors.js +0 -0
  168. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/cell_explorer/static/cellExplorerContinuous.js +0 -0
  169. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/cell_explorer/static/cellExplorerFigureBridge.js +0 -0
  170. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/cell_explorer/static/cellExplorerLegend.js +0 -0
  171. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/cell_explorer/static/cellExplorerRoiBridge.js +0 -0
  172. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/cell_explorer/static/cellExplorerSidebarController.js +0 -0
  173. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/cell_explorer/static/cellExplorerState.js +0 -0
  174. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/cell_explorer/static/cell_explorer.css +0 -0
  175. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/cell_explorer/templates/cell_explorer/panel.html +0 -0
  176. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/figure_builder/__init__.py +0 -0
  177. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/figure_builder/server/__init__.py +0 -0
  178. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/figure_builder/server/compose.py +0 -0
  179. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/figure_builder/server/export.py +0 -0
  180. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/figure_builder/server/export_jobs.py +0 -0
  181. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/figure_builder/server/operations.py +0 -0
  182. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/figure_builder/server/pixels.py +0 -0
  183. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/figure_builder/server/provenance.py +0 -0
  184. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/figure_builder/server/render.py +0 -0
  185. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/figure_builder/server/repository.py +0 -0
  186. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/figure_builder/server/routes.py +0 -0
  187. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/figure_builder/server/schema.py +0 -0
  188. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/figure_builder/server/shapegeom.py +0 -0
  189. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/figure_builder/server/sources.py +0 -0
  190. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/figure_builder/server/strokegeom.py +0 -0
  191. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/figure_builder/server/textmetrics.py +0 -0
  192. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/figure_builder/static/figureActions.js +0 -0
  193. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/figure_builder/static/figureBuilderApi.js +0 -0
  194. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/figure_builder/static/figureCanvas.js +0 -0
  195. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/figure_builder/static/figureCaptureBoxes.js +0 -0
  196. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/figure_builder/static/figureCaptureDock.js +0 -0
  197. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/figure_builder/static/figureCaptureTool.js +0 -0
  198. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/figure_builder/static/figureChoiceField.js +0 -0
  199. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/figure_builder/static/figureColorField.js +0 -0
  200. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/figure_builder/static/figureConfirm.js +0 -0
  201. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/figure_builder/static/figureContextBar.js +0 -0
  202. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/figure_builder/static/figureContextMenu.js +0 -0
  203. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/figure_builder/static/figureDocumentState.js +0 -0
  204. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/figure_builder/static/figureExportUi.js +0 -0
  205. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/figure_builder/static/figureImagePanel.js +0 -0
  206. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/figure_builder/static/figureLibrary.js +0 -0
  207. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/figure_builder/static/figureLineDefs.js +0 -0
  208. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/figure_builder/static/figureLinePanel.js +0 -0
  209. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/figure_builder/static/figurePanelCompositor.js +0 -0
  210. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/figure_builder/static/figurePointEditor.js +0 -0
  211. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/figure_builder/static/figureQuickEdit.js +0 -0
  212. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/figure_builder/static/figureRichText.js +0 -0
  213. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/figure_builder/static/figureSceneSnapshot.js +0 -0
  214. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/figure_builder/static/figureSchema.js +0 -0
  215. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/figure_builder/static/figureShapeDefs.js +0 -0
  216. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/figure_builder/static/figureShapeDrawing.js +0 -0
  217. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/figure_builder/static/figureShapeGeometry.js +0 -0
  218. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/figure_builder/static/figureShapePanel.js +0 -0
  219. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/figure_builder/static/figureSidebarController.js +0 -0
  220. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/figure_builder/static/figureStrokeGeometry.js +0 -0
  221. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/figure_builder/static/figureTextEditor.js +0 -0
  222. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/figure_builder/static/figureTextPanel.js +0 -0
  223. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/figure_builder/static/figureViewOptions.js +0 -0
  224. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/figure_builder/static/figureWorkspace.js +0 -0
  225. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/figure_builder/static/figure_builder.css +0 -0
  226. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/figure_builder/templates/figure_builder/library.html +0 -0
  227. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/figure_builder/templates/figure_builder/workspace.html +0 -0
  228. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/figure_builder/templates/figure_builder/workspace_body.html +0 -0
  229. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/gating/__init__.py +0 -0
  230. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/gating/server/__init__.py +0 -0
  231. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/gating/server/anndata_gates.py +0 -0
  232. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/gating/server/database.py +0 -0
  233. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/gating/server/model.py +0 -0
  234. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/gating/server/routes.py +0 -0
  235. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/gating/server/tableops.py +0 -0
  236. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/gating/static/csvGatingList.js +0 -0
  237. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/gating/static/gating.css +0 -0
  238. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/gating/static/gatingApi.js +0 -0
  239. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/gating/static/gatingSidebarController.js +0 -0
  240. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/gating/templates/gating/legacy.html +0 -0
  241. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/gating/templates/gating/panel.html +0 -0
  242. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/roi/__init__.py +0 -0
  243. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/roi/server/__init__.py +0 -0
  244. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/roi/server/adapters.py +0 -0
  245. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/roi/server/geojson.py +0 -0
  246. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/roi/server/geometry.py +0 -0
  247. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/roi/server/mapping.py +0 -0
  248. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/roi/server/operations.py +0 -0
  249. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/roi/server/repository.py +0 -0
  250. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/roi/server/routes.py +0 -0
  251. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/roi/server/schema.py +0 -0
  252. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/roi/server/tableops.py +0 -0
  253. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/roi/static/roi.css +0 -0
  254. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/roi/static/roiApi.js +0 -0
  255. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/roi/static/roiFigureBridge.js +0 -0
  256. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/roi/static/roiGeometry.js +0 -0
  257. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/roi/static/roiRenderer.js +0 -0
  258. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/roi/static/roiSidebarController.js +0 -0
  259. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/roi/static/roiState.js +0 -0
  260. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/roi/static/roiTools.js +0 -0
  261. {plexora-0.0.8 → plexora-0.0.9}/plexora/plugins/roi/templates/roi/panel.html +0 -0
  262. {plexora-0.0.8 → plexora-0.0.9}/plexora/proxy.py +0 -0
  263. {plexora-0.0.8 → plexora-0.0.9}/plexora/server/models/adapters/__init__.py +0 -0
  264. {plexora-0.0.8 → plexora-0.0.9}/plexora/server/models/adapters/anndata_adapter.py +0 -0
  265. {plexora-0.0.8 → plexora-0.0.9}/plexora/server/models/adapters/base.py +0 -0
  266. {plexora-0.0.8 → plexora-0.0.9}/plexora/server/models/adapters/classify.py +0 -0
  267. {plexora-0.0.8 → plexora-0.0.9}/plexora/server/models/adapters/csv_adapter.py +0 -0
  268. {plexora-0.0.8 → plexora-0.0.9}/plexora/server/models/adapters/inspection.py +0 -0
  269. {plexora-0.0.8 → plexora-0.0.9}/plexora/server/models/adapters/spatialdata_adapter.py +0 -0
  270. {plexora-0.0.8 → plexora-0.0.9}/plexora/server/models/centroid_tiles.py +0 -0
  271. {plexora-0.0.8 → plexora-0.0.9}/plexora/server/models/data_migration.py +0 -0
  272. {plexora-0.0.8 → plexora-0.0.9}/plexora/server/models/data_model.py +0 -0
  273. {plexora-0.0.8 → plexora-0.0.9}/plexora/server/models/database_model.py +0 -0
  274. {plexora-0.0.8 → plexora-0.0.9}/plexora/server/models/nodes.py +0 -0
  275. {plexora-0.0.8 → plexora-0.0.9}/plexora/server/models/project.py +0 -0
  276. {plexora-0.0.8 → plexora-0.0.9}/plexora/server/models/recipes.py +0 -0
  277. {plexora-0.0.8 → plexora-0.0.9}/plexora/server/models/remote_sessions.py +0 -0
  278. {plexora-0.0.8 → plexora-0.0.9}/plexora/server/models/remotes.py +0 -0
  279. {plexora-0.0.8 → plexora-0.0.9}/plexora/server/models/secret_store.py +0 -0
  280. {plexora-0.0.8 → plexora-0.0.9}/plexora/server/node/api.py +0 -0
  281. {plexora-0.0.8 → plexora-0.0.9}/plexora/server/node/resources.py +0 -0
  282. {plexora-0.0.8 → plexora-0.0.9}/plexora/server/plugins.py +0 -0
  283. {plexora-0.0.8 → plexora-0.0.9}/plexora/server/providers/__init__.py +0 -0
  284. {plexora-0.0.8 → plexora-0.0.9}/plexora/server/providers/base.py +0 -0
  285. {plexora-0.0.8 → plexora-0.0.9}/plexora/server/providers/http.py +0 -0
  286. {plexora-0.0.8 → plexora-0.0.9}/plexora/server/providers/local.py +0 -0
  287. {plexora-0.0.8 → plexora-0.0.9}/plexora/server/providers/node.py +0 -0
  288. {plexora-0.0.8 → plexora-0.0.9}/plexora/server/providers/operations.py +0 -0
  289. {plexora-0.0.8 → plexora-0.0.9}/plexora/server/providers/wire.py +0 -0
  290. {plexora-0.0.8 → plexora-0.0.9}/plexora/server/routes/browse_routes.py +0 -0
  291. {plexora-0.0.8 → plexora-0.0.9}/plexora/server/routes/data_routes.py +0 -0
  292. {plexora-0.0.8 → plexora-0.0.9}/plexora/server/routes/import_routes.py +0 -0
  293. {plexora-0.0.8 → plexora-0.0.9}/plexora/server/routes/page_routes.py +0 -0
  294. {plexora-0.0.8 → plexora-0.0.9}/plexora/server/routes/project_routes.py +0 -0
  295. {plexora-0.0.8 → plexora-0.0.9}/plexora/server/routes/quick_view_routes.py +0 -0
  296. {plexora-0.0.8 → plexora-0.0.9}/plexora/server/routes/settings_routes.py +0 -0
  297. {plexora-0.0.8 → plexora-0.0.9}/plexora/server/routes/system_routes.py +0 -0
  298. {plexora-0.0.8 → plexora-0.0.9}/plexora/server/routes/tool_routes.py +0 -0
  299. {plexora-0.0.8 → plexora-0.0.9}/plexora/server/routes/transfer_routes.py +0 -0
  300. {plexora-0.0.8 → plexora-0.0.9}/plexora/server/utils/addHEColumns.py +0 -0
  301. {plexora-0.0.8 → plexora-0.0.9}/plexora/server/utils/channel_file.py +0 -0
  302. {plexora-0.0.8 → plexora-0.0.9}/plexora/server/utils/dir_listing.py +0 -0
  303. {plexora-0.0.8 → plexora-0.0.9}/plexora/server/utils/fast_png.py +0 -0
  304. {plexora-0.0.8 → plexora-0.0.9}/plexora/server/utils/file_transfer.py +0 -0
  305. {plexora-0.0.8 → plexora-0.0.9}/plexora/server/utils/fullConversion.py +0 -0
  306. {plexora-0.0.8 → plexora-0.0.9}/plexora/server/utils/native_dialog.py +0 -0
  307. {plexora-0.0.8 → plexora-0.0.9}/plexora/server/utils/pre_normalization.py +0 -0
  308. {plexora-0.0.8 → plexora-0.0.9}/plexora/server/utils/segmentation_pyramid.py +0 -0
  309. {plexora-0.0.8 → plexora-0.0.9}/plexora/server/utils/smallestenclosingcircle.py +0 -0
  310. {plexora-0.0.8 → plexora-0.0.9}/plexora/server/utils/tiffsurgeon.py +0 -0
  311. {plexora-0.0.8 → plexora-0.0.9}/plexora/server_cli.py +0 -0
  312. {plexora-0.0.8 → plexora-0.0.9}/plexora/test.py +0 -0
  313. {plexora-0.0.8 → plexora-0.0.9}/plexora.egg-info/SOURCES.txt +0 -0
  314. {plexora-0.0.8 → plexora-0.0.9}/plexora.egg-info/dependency_links.txt +0 -0
  315. {plexora-0.0.8 → plexora-0.0.9}/plexora.egg-info/entry_points.txt +0 -0
  316. {plexora-0.0.8 → plexora-0.0.9}/plexora.egg-info/requires.txt +0 -0
  317. {plexora-0.0.8 → plexora-0.0.9}/plexora.egg-info/top_level.txt +0 -0
  318. {plexora-0.0.8 → plexora-0.0.9}/setup.cfg +0 -0
  319. {plexora-0.0.8 → plexora-0.0.9}/tests/test_anndata_adapter.py +0 -0
  320. {plexora-0.0.8 → plexora-0.0.9}/tests/test_api_dataset.py +0 -0
  321. {plexora-0.0.8 → plexora-0.0.9}/tests/test_api_store.py +0 -0
  322. {plexora-0.0.8 → plexora-0.0.9}/tests/test_app_router.py +0 -0
  323. {plexora-0.0.8 → plexora-0.0.9}/tests/test_app_shell.py +0 -0
  324. {plexora-0.0.8 → plexora-0.0.9}/tests/test_auth_token.py +0 -0
  325. {plexora-0.0.8 → plexora-0.0.9}/tests/test_browse_routes.py +0 -0
  326. {plexora-0.0.8 → plexora-0.0.9}/tests/test_cell_color_layer.py +0 -0
  327. {plexora-0.0.8 → plexora-0.0.9}/tests/test_cell_mode_control.py +0 -0
  328. {plexora-0.0.8 → plexora-0.0.9}/tests/test_centroid_tiles.py +0 -0
  329. {plexora-0.0.8 → plexora-0.0.9}/tests/test_channel_names_modal.py +0 -0
  330. {plexora-0.0.8 → plexora-0.0.9}/tests/test_channel_names_upload.py +0 -0
  331. {plexora-0.0.8 → plexora-0.0.9}/tests/test_channel_overview.py +0 -0
  332. {plexora-0.0.8 → plexora-0.0.9}/tests/test_channel_rename_state.py +0 -0
  333. {plexora-0.0.8 → plexora-0.0.9}/tests/test_classify_columns.py +0 -0
  334. {plexora-0.0.8 → plexora-0.0.9}/tests/test_cli.py +0 -0
  335. {plexora-0.0.8 → plexora-0.0.9}/tests/test_column_classifier_css.py +0 -0
  336. {plexora-0.0.8 → plexora-0.0.9}/tests/test_config_store.py +0 -0
  337. {plexora-0.0.8 → plexora-0.0.9}/tests/test_connection_modal.py +0 -0
  338. {plexora-0.0.8 → plexora-0.0.9}/tests/test_csv_adapter.py +0 -0
  339. {plexora-0.0.8 → plexora-0.0.9}/tests/test_data_location.py +0 -0
  340. {plexora-0.0.8 → plexora-0.0.9}/tests/test_database_model.py +0 -0
  341. {plexora-0.0.8 → plexora-0.0.9}/tests/test_datalayer_requests.py +0 -0
  342. {plexora-0.0.8 → plexora-0.0.9}/tests/test_derive_anndata_channel_names.py +0 -0
  343. {plexora-0.0.8 → plexora-0.0.9}/tests/test_detect_data_type.py +0 -0
  344. {plexora-0.0.8 → plexora-0.0.9}/tests/test_file_location.py +0 -0
  345. {plexora-0.0.8 → plexora-0.0.9}/tests/test_file_transfer_node.py +0 -0
  346. {plexora-0.0.8 → plexora-0.0.9}/tests/test_hd_slider_domain.py +0 -0
  347. {plexora-0.0.8 → plexora-0.0.9}/tests/test_icon_names.py +0 -0
  348. {plexora-0.0.8 → plexora-0.0.9}/tests/test_jupyter_viewer.py +0 -0
  349. {plexora-0.0.8 → plexora-0.0.9}/tests/test_label_outlines.py +0 -0
  350. {plexora-0.0.8 → plexora-0.0.9}/tests/test_label_tile_lifecycle.py +0 -0
  351. {plexora-0.0.8 → plexora-0.0.9}/tests/test_marker_split.py +0 -0
  352. {plexora-0.0.8 → plexora-0.0.9}/tests/test_mask_without_table.py +0 -0
  353. {plexora-0.0.8 → plexora-0.0.9}/tests/test_metadata_columns.py +0 -0
  354. {plexora-0.0.8 → plexora-0.0.9}/tests/test_mini_map.py +0 -0
  355. {plexora-0.0.8 → plexora-0.0.9}/tests/test_nav_shortcuts.py +0 -0
  356. {plexora-0.0.8 → plexora-0.0.9}/tests/test_node_direct_routing.py +0 -0
  357. {plexora-0.0.8 → plexora-0.0.9}/tests/test_node_disconnect.py +0 -0
  358. {plexora-0.0.8 → plexora-0.0.9}/tests/test_node_dynamic.py +0 -0
  359. {plexora-0.0.8 → plexora-0.0.9}/tests/test_node_image.py +0 -0
  360. {plexora-0.0.8 → plexora-0.0.9}/tests/test_node_reconnect.py +0 -0
  361. {plexora-0.0.8 → plexora-0.0.9}/tests/test_node_routes.py +0 -0
  362. {plexora-0.0.8 → plexora-0.0.9}/tests/test_node_table.py +0 -0
  363. {plexora-0.0.8 → plexora-0.0.9}/tests/test_notebook_env.py +0 -0
  364. {plexora-0.0.8 → plexora-0.0.9}/tests/test_notebook_mode.py +0 -0
  365. {plexora-0.0.8 → plexora-0.0.9}/tests/test_optional_segmentation.py +0 -0
  366. {plexora-0.0.8 → plexora-0.0.9}/tests/test_page_assets.py +0 -0
  367. {plexora-0.0.8 → plexora-0.0.9}/tests/test_page_routes.py +0 -0
  368. {plexora-0.0.8 → plexora-0.0.9}/tests/test_path_picker.py +0 -0
  369. {plexora-0.0.8 → plexora-0.0.9}/tests/test_paths.py +0 -0
  370. {plexora-0.0.8 → plexora-0.0.9}/tests/test_plugin_boundary.py +0 -0
  371. {plexora-0.0.8 → plexora-0.0.9}/tests/test_plugin_css_boundary.py +0 -0
  372. {plexora-0.0.8 → plexora-0.0.9}/tests/test_plugins.py +0 -0
  373. {plexora-0.0.8 → plexora-0.0.9}/tests/test_popover_portal.py +0 -0
  374. {plexora-0.0.8 → plexora-0.0.9}/tests/test_project_edit_routes.py +0 -0
  375. {plexora-0.0.8 → plexora-0.0.9}/tests/test_project_record.py +0 -0
  376. {plexora-0.0.8 → plexora-0.0.9}/tests/test_quick_view_routes.py +0 -0
  377. {plexora-0.0.8 → plexora-0.0.9}/tests/test_recipes.py +0 -0
  378. {plexora-0.0.8 → plexora-0.0.9}/tests/test_reconnect.py +0 -0
  379. {plexora-0.0.8 → plexora-0.0.9}/tests/test_refresh_dataset.py +0 -0
  380. {plexora-0.0.8 → plexora-0.0.9}/tests/test_register_anndata_datasource.py +0 -0
  381. {plexora-0.0.8 → plexora-0.0.9}/tests/test_register_image_datasource.py +0 -0
  382. {plexora-0.0.8 → plexora-0.0.9}/tests/test_remote_globe.py +0 -0
  383. {plexora-0.0.8 → plexora-0.0.9}/tests/test_remote_health.py +0 -0
  384. {plexora-0.0.8 → plexora-0.0.9}/tests/test_remote_state.py +0 -0
  385. {plexora-0.0.8 → plexora-0.0.9}/tests/test_rename_channels.py +0 -0
  386. {plexora-0.0.8 → plexora-0.0.9}/tests/test_requirements_routes.py +0 -0
  387. {plexora-0.0.8 → plexora-0.0.9}/tests/test_resource_status_banner.py +0 -0
  388. {plexora-0.0.8 → plexora-0.0.9}/tests/test_segmentation_mapping.py +0 -0
  389. {plexora-0.0.8 → plexora-0.0.9}/tests/test_segmentation_mode_routes.py +0 -0
  390. {plexora-0.0.8 → plexora-0.0.9}/tests/test_segmentation_pyramid.py +0 -0
  391. {plexora-0.0.8 → plexora-0.0.9}/tests/test_segmentation_wait.py +0 -0
  392. {plexora-0.0.8 → plexora-0.0.9}/tests/test_session_expiry.py +0 -0
  393. {plexora-0.0.8 → plexora-0.0.9}/tests/test_session_walltime.py +0 -0
  394. {plexora-0.0.8 → plexora-0.0.9}/tests/test_settings_page.py +0 -0
  395. {plexora-0.0.8 → plexora-0.0.9}/tests/test_settings_remotes_page.py +0 -0
  396. {plexora-0.0.8 → plexora-0.0.9}/tests/test_shared_roots.py +0 -0
  397. {plexora-0.0.8 → plexora-0.0.9}/tests/test_spatialdata_adapter.py +0 -0
  398. {plexora-0.0.8 → plexora-0.0.9}/tests/test_tile_url.py +0 -0
  399. {plexora-0.0.8 → plexora-0.0.9}/tests/test_tool_assets.py +0 -0
  400. {plexora-0.0.8 → plexora-0.0.9}/tests/test_tool_cards.py +0 -0
  401. {plexora-0.0.8 → plexora-0.0.9}/tests/test_tool_coexistence.py +0 -0
  402. {plexora-0.0.8 → plexora-0.0.9}/tests/test_tool_switching.py +0 -0
  403. {plexora-0.0.8 → plexora-0.0.9}/tests/test_transfer_routes.py +0 -0
  404. {plexora-0.0.8 → plexora-0.0.9}/tests/test_unreachable_node.py +0 -0
  405. {plexora-0.0.8 → plexora-0.0.9}/tests/test_url_helpers.py +0 -0
  406. {plexora-0.0.8 → plexora-0.0.9}/tests/test_view_menu.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: plexora
3
- Version: 0.0.8
3
+ Version: 0.0.9
4
4
  Summary: OpenSeadragon-based cellular image viewing and analysis tool.
5
5
  License-Expression: LicenseRef-Plexora-Academic-1.0
6
6
  Requires-Python: <3.14,>=3.12
@@ -222,7 +222,12 @@ def normalize_remote_command(remote_command):
222
222
  #: has Plexora is asking for the current one, and a plain install would report
223
223
  #: "already satisfied" and leave last year's copy in place -- which is the
224
224
  #: exact failure the option exists to end.
225
- PIP_ARGUMENTS = ("install", "--upgrade", "plexora")
225
+ #: `--progress-bar off` because the install rides the launch's ssh, which asks
226
+ #: for a pty (`-t`) -- and pip with a pty redraws its download bar with
227
+ #: carriage returns, which a line-based log renders as one line growing to
228
+ #: kilobytes. The per-package Collecting/Installing lines still come through,
229
+ #: and they are the progress worth showing.
230
+ PIP_ARGUMENTS = ("install", "--progress-bar", "off", "--upgrade", "plexora")
226
231
 
227
232
  #: What conda does to a subprocess's output unless told not to: buffers it and
228
233
  #: prints the lot when the child exits. Correct for a script whose output is a
@@ -346,23 +351,35 @@ def parse_installed_version(lines):
346
351
  return None
347
352
 
348
353
 
349
- def install_ssh_argv(target, install_line, *, jump=None, ssh_opts=()):
350
- """The ssh that installs Plexora over there and exits.
354
+ #: Printed by the remote shell between the install and the launch. The two
355
+ #: run in ONE ssh -- `pip … && echo … && srun …` -- so the only way to know
356
+ #: pip finished (rather than printed its last routine line) is to say so
357
+ #: ourselves. `&&` is also the failure story: a pip that exits non-zero
358
+ #: short-circuits the chain, the marker never appears, the ssh ends, and
359
+ #: nothing was launched from the half-upgraded environment.
360
+ INSTALL_DONE_MARK = "PLEXORA_INSTALL_DONE"
351
361
 
352
- No `-t`, unlike every other ssh here. The pty those ask for exists so the
353
- remote gets a SIGHUP when this end goes away, which matters for a process
354
- meant to outlive the call and not at all for one we wait on -- and it
355
- costs something here: pip draws a progress bar with carriage returns when
356
- it thinks it has a terminal, and the log this feeds is line-based, so a
357
- download would arrive as one line growing to a few kilobytes. Without a
358
- pty pip prints plain lines instead. Prompts are unaffected: the askpass
359
- relay is what answers them, and it needs no terminal by design.
362
+
363
+ def parse_install_done(line):
364
+ """Matcher for the marker line. True on the marker, None otherwise."""
365
+ return True if line.strip() == INSTALL_DONE_MARK else None
366
+
367
+
368
+ def install_prefixed(install_line, launch_line):
369
+ """One remote command: install, say so, then launch.
370
+
371
+ One command because it is one login. The install used to be its own ssh,
372
+ which was one extra authentication -- and at a site that confirms every
373
+ login on somebody's phone, "connect" buzzed it twice. Chaining also puts
374
+ the install literally immediately before the run, in the same shell, so
375
+ nothing can start from the copy the upgrade was replacing.
376
+
377
+ Under a scheduler the chain still runs the install on the LOGIN node --
378
+ it precedes the `srun` in the same command -- which is where it belongs:
379
+ the environment is on a shared filesystem, and the allocation should not
380
+ be spent watching pip download wheels.
360
381
  """
361
- argv = ["ssh", *_ssh_options(ssh_opts)]
362
- if jump:
363
- argv += ["-J", jump]
364
- argv += [target, install_line]
365
- return argv
382
+ return f"{install_line} && echo {INSTALL_DONE_MARK} && {launch_line}"
366
383
 
367
384
 
368
385
  def remote_command_line(remote_command, port, *, bind_node=False, datasource=None,
@@ -823,24 +840,6 @@ class _Watched:
823
840
  def tail(self, count=6):
824
841
  return self.lines[-count:]
825
842
 
826
- def wait_for_exit(self, deadline):
827
- """Block until this process ends. Its exit code, or None if it did not.
828
-
829
- The one watcher here that is waited ON rather than merely watched: an
830
- install has to have finished before the launch that depends on it
831
- starts. `drain` before returning, for the same reason every other
832
- reader of `lines` calls it -- the pump thread is still working through
833
- what the shell wrote on its way out, and that is where the reason for
834
- a non-zero exit lives.
835
- """
836
- while _now() < deadline:
837
- code = self.process.poll()
838
- if code is not None:
839
- self.drain()
840
- return code
841
- _sleep(0.2)
842
- return self.process.poll()
843
-
844
843
  def stop(self):
845
844
  if self.process.poll() is not None:
846
845
  return
@@ -1087,14 +1086,13 @@ def _missing_command_hint(remote_command, watched):
1087
1086
 
1088
1087
 
1089
1088
  class _BareInstall:
1090
- """The four things `_install_plexora` needs, for a caller with no session.
1089
+ """What `_begin_install`/`_await_install` read, for a caller with no session.
1091
1090
 
1092
1091
  `connect_node` drives one ssh by hand -- it predates `NodeSession` and is
1093
- what `plexora connect --node` still runs -- so there is no object there to
1092
+ what `plexora node connect` still runs -- so there is no object there to
1094
1093
  read `target` and `remote_command` off. This is that object and nothing
1095
- more: its `watchers` list exists so the install's watcher can be taken
1096
- back out of it, and its `_phase` is a no-op because a terminal has the
1097
- echoed lines and no progress list to update.
1094
+ more; its `_phase` is a no-op because a terminal has the echoed lines and
1095
+ no progress list to update.
1098
1096
  """
1099
1097
 
1100
1098
  def __init__(self, target, remote_command, jump, ssh_opts, echo):
@@ -1103,7 +1101,6 @@ class _BareInstall:
1103
1101
  self.jump = jump
1104
1102
  self.ssh_opts = ssh_opts
1105
1103
  self.echo = echo
1106
- self.watchers = []
1107
1104
  self.install_log = []
1108
1105
  self.installed_version = None
1109
1106
 
@@ -1118,63 +1115,53 @@ class _BareInstall:
1118
1115
  return watched
1119
1116
 
1120
1117
 
1121
- def _install_plexora(session):
1122
- """Install or update Plexora on the far side, before anything is launched.
1123
-
1124
- Shared by both session shapes because it is the same act for both: one
1125
- ssh, run to completion, whose output is the connection's own log. It runs
1126
- BEFORE the launch and not beside it, which is the whole point of the
1127
- option -- a viewer started from the copy that was already there, while an
1128
- upgrade downloads alongside it, is the version the user asked to stop
1129
- running.
1130
-
1131
- Under a scheduler it still runs on the target -- the login node -- rather
1132
- than inside the job. The environment being written to is on a filesystem
1133
- both machines share, so the compute node gets the same result; and doing
1134
- it here means the install is not spending an allocation, and not standing
1135
- between somebody and the announce that says their job finally started.
1136
-
1137
- The watcher is taken back out of `session.watchers` when it exits. That
1138
- list is what `alive` is computed from -- `all(w.alive for w in ...)` --
1139
- so an exited process left in it would report the whole connection dead the
1140
- moment the install succeeded. Its output has already been echoed and is
1141
- kept here, which is the part anybody wants afterwards.
1142
- """
1118
+ def _begin_install(session):
1119
+ """Announce the install and hand back the pip line the launch is chained to."""
1143
1120
  line = install_command_line(session.remote_command)
1144
1121
  environment = environment_label(session.remote_command)
1145
1122
  session._phase("installing")
1146
1123
  session.echo(f" Installing Plexora on {session.target}"
1147
1124
  + (f" in {environment}" if environment else "")
1148
- + "; this can take a few minutes.")
1149
- watched = session._spawn(
1150
- install_ssh_argv(session.target, line, jump=session.jump,
1151
- ssh_opts=session.ssh_opts),
1152
- "install",
1153
- )
1154
- try:
1155
- code = watched.wait_for_exit(_now() + INSTALL_TIMEOUT)
1156
- finally:
1157
- watched.stop()
1158
- if watched in session.watchers:
1159
- session.watchers.remove(watched)
1160
- if watched in _ACTIVE:
1161
- _ACTIVE.remove(watched)
1162
- session.install_log = list(watched.lines)
1125
+ + " before launching it; this can take a few minutes.")
1126
+ return line
1163
1127
 
1164
- if code is None:
1165
- raise ConnectError(
1166
- f"Installing Plexora on {session.target} did not finish within "
1167
- f"{INSTALL_TIMEOUT:g}s.\n"
1168
- + "\n".join(f" {text}" for text in watched.tail())
1169
- + "\n\nThe environment may be half-upgraded. Run it by hand over "
1170
- "there to see where it stopped:\n"
1171
- f" {line}\n"
1172
- "Or turn “Install or update Plexora” off and connect to the "
1173
- "copy that is already installed."
1174
- )
1175
- if code != 0:
1176
- raise ConnectError(_install_failure(session, line, watched, code))
1177
1128
 
1129
+ def _await_install(session, watched, line):
1130
+ """Block until the chained install prints its marker, or explain why not.
1131
+
1132
+ `watched` is the connection's own primary ssh -- install and launch are
1133
+ one process now -- so unlike the old separate-ssh install there is no
1134
+ watcher to clean up afterwards: a marker means the same process is now
1135
+ busy launching, and a death before the marker means the connection failed
1136
+ and the watcher's exit is the correct thing for `alive` to report.
1137
+ """
1138
+ event = watched.events["installed"]
1139
+ deadline = _now() + INSTALL_TIMEOUT
1140
+ # `found`, not the event alone: the pump sets every event when the stream
1141
+ # ends, precisely so waiters do not hang on an announce that is never
1142
+ # coming -- so a set event proves the process finished talking, and only
1143
+ # `found` proves the marker was in what it said.
1144
+ while not watched.found.get("installed"):
1145
+ event.wait(0.2)
1146
+ if watched.found.get("installed"):
1147
+ break
1148
+ if not watched.alive:
1149
+ watched.drain()
1150
+ session.install_log = list(watched.lines)
1151
+ code = watched.process.poll()
1152
+ raise ConnectError(_install_failure(session, line, watched, code))
1153
+ if _now() > deadline:
1154
+ raise ConnectError(
1155
+ f"Installing Plexora on {session.target} did not finish within "
1156
+ f"{INSTALL_TIMEOUT:g}s.\n"
1157
+ + "\n".join(f" {text}" for text in watched.tail())
1158
+ + "\n\nThe environment may be half-upgraded. Run it by hand "
1159
+ "over there to see where it stopped:\n"
1160
+ f" {line}\n"
1161
+ "Or turn “Install or update Plexora” off and connect to the "
1162
+ "copy that is already installed."
1163
+ )
1164
+ session.install_log = list(watched.lines)
1178
1165
  version = parse_installed_version(watched.lines)
1179
1166
  session.installed_version = version
1180
1167
  session.echo(f" Plexora {version} is installed on {session.target}."
@@ -1311,9 +1298,9 @@ class Session:
1311
1298
  #: one -- the viewer still opens.
1312
1299
  self.data_nodes = []
1313
1300
  self.node_errors = []
1314
- #: What the install said, and which version it left behind. Kept after
1315
- #: the process it came from has been taken back out of `watchers` --
1316
- #: see `_install_plexora` for why it cannot stay there.
1301
+ #: What the install said, and which version it left behind. A copy of
1302
+ #: the primary's lines up to the marker -- the install rides the same
1303
+ #: ssh as the launch (see `install_prefixed`).
1317
1304
  self.install_log = []
1318
1305
  self.installed_version = None
1319
1306
 
@@ -1340,12 +1327,11 @@ class Session:
1340
1327
  def log(self, count=40):
1341
1328
  """Every ssh's recent output, labelled, oldest first.
1342
1329
 
1343
- The install first and from its own store, because by the time anybody
1344
- reads this the process it came from has exited and been taken out of
1345
- `watchers` -- and it is the half of the log somebody diagnosing a
1346
- failed connection is most likely to be after.
1330
+ Install output needs no special handling any more: the install rides
1331
+ the primary ssh itself, so its lines are in that watcher's tail like
1332
+ everything else the connection printed.
1347
1333
  """
1348
- lines = [f"[install] {line}" for line in self.install_log[-count:]]
1334
+ lines = []
1349
1335
  for watched in self.watchers:
1350
1336
  lines += [f"[{watched.label}] {line}" for line in watched.tail(count)]
1351
1337
  return lines
@@ -1463,32 +1449,45 @@ class Session:
1463
1449
  matchers["node"] = parse_node_announce
1464
1450
 
1465
1451
  try:
1466
- # Before the local node and before any launch: this is the step
1467
- # whose whole purpose is that what starts afterwards is the
1468
- # version it just installed.
1469
- if self.install:
1470
- _install_plexora(self)
1452
+ # The install rides the SAME ssh as the launch, chained ahead of
1453
+ # it -- one login instead of two, and at a Duo site one buzz of
1454
+ # the phone instead of two. `&&` is what keeps the promise the
1455
+ # separate-ssh version made: a failed install launches nothing.
1456
+ install_line = _begin_install(self) if self.install else None
1457
+ if install_line:
1458
+ matchers["installed"] = parse_install_done
1471
1459
 
1472
1460
  local_node = None
1473
1461
  if self.local_node:
1474
1462
  local_node = self._start_local_node(local_node_serve_port)
1475
1463
 
1476
1464
  if self.srun is None:
1465
+ line = (install_prefixed(install_line, launch)
1466
+ if install_line else launch)
1477
1467
  self.primary = self._spawn(
1478
1468
  direct_ssh_argv(self.target, self.local_port,
1479
- self.remote_port, launch, jump=self.jump,
1469
+ self.remote_port, line, jump=self.jump,
1480
1470
  ssh_opts=self.ssh_opts,
1481
1471
  forwards=forwards, reverse=reverse),
1482
1472
  "ssh", matchers,
1483
1473
  )
1474
+ if install_line:
1475
+ _await_install(self, self.primary, install_line)
1476
+ # The install spent none of the connection's own budget.
1477
+ deadline = _now() + self.timeout
1484
1478
  self._phase("starting")
1485
1479
  else:
1480
+ remote = srun_command_line(self.srun, launch)
1481
+ if install_line:
1482
+ remote = install_prefixed(install_line, remote)
1486
1483
  self.primary = self._spawn(
1487
- job_ssh_argv(self.target,
1488
- srun_command_line(self.srun, launch),
1484
+ job_ssh_argv(self.target, remote,
1489
1485
  jump=self.jump, ssh_opts=self.ssh_opts),
1490
1486
  "job", matchers,
1491
1487
  )
1488
+ if install_line:
1489
+ _await_install(self, self.primary, install_line)
1490
+ deadline = _now() + self.timeout
1492
1491
  self._phase("waiting_for_job")
1493
1492
  self.node, self.node_port = _wait_for_announce(
1494
1493
  self.primary, deadline, echo=self.echo)
@@ -1830,7 +1829,7 @@ class NodeSession:
1830
1829
  return bool(self.watchers) and all(w.alive for w in self.watchers)
1831
1830
 
1832
1831
  def log(self, count=40):
1833
- lines = [f"[install] {line}" for line in self.install_log[-count:]]
1832
+ lines = []
1834
1833
  for watched in self.watchers:
1835
1834
  lines += [f"[{watched.label}] {line}" for line in watched.tail(count)]
1836
1835
  return lines
@@ -1871,30 +1870,44 @@ class NodeSession:
1871
1870
  host=bind)
1872
1871
  matchers = {"node": parse_node_announce}
1873
1872
 
1874
- # Ahead of the deadline, not inside it: `self.timeout` is how long a
1875
- # node may take to answer, and an install that ate half of it would
1876
- # leave a node that was starting normally being called dead.
1877
- if self.install:
1878
- _install_plexora(self)
1879
- deadline = _now() + self.timeout
1873
+ # The install is chained ahead of the launch in the SAME ssh -- one
1874
+ # login, one Duo prompt -- and it has its own budget: `self.timeout`
1875
+ # is how long a node may take to answer, and an install that ate half
1876
+ # of it would leave a node that was starting normally being called
1877
+ # dead. The deadline is therefore taken after the marker.
1878
+ install_line = _begin_install(self) if self.install else None
1879
+ if install_line:
1880
+ matchers["installed"] = parse_install_done
1880
1881
 
1881
1882
  if self.srun is None:
1882
- self._phase("tunneling")
1883
+ if not install_line:
1884
+ self._phase("tunneling")
1885
+ line = (install_prefixed(install_line, launch)
1886
+ if install_line else launch)
1883
1887
  self.primary = self._spawn(
1884
1888
  direct_ssh_argv(self.target, self.local_port, self.remote_port,
1885
- launch, jump=self.jump, ssh_opts=self.ssh_opts),
1889
+ line, jump=self.jump, ssh_opts=self.ssh_opts),
1886
1890
  "node", matchers)
1891
+ if install_line:
1892
+ _await_install(self, self.primary, install_line)
1893
+ self._phase("tunneling")
1887
1894
  else:
1888
1895
  # No forward on this one: at the moment it opens, the job has not
1889
1896
  # been allocated and there is no host to point a forward at. The
1890
1897
  # announce is what names it, and the tunnel follows.
1891
- self._phase("waiting_for_job")
1892
- self.echo(" asking the scheduler for a node to serve the data "
1893
- "from; this can wait in the queue.")
1898
+ remote = srun_command_line(self.srun, launch)
1899
+ if install_line:
1900
+ remote = install_prefixed(install_line, remote)
1894
1901
  self.primary = self._spawn(
1895
- job_ssh_argv(self.target, srun_command_line(self.srun, launch),
1902
+ job_ssh_argv(self.target, remote,
1896
1903
  jump=self.jump, ssh_opts=self.ssh_opts),
1897
1904
  "job", matchers)
1905
+ if install_line:
1906
+ _await_install(self, self.primary, install_line)
1907
+ self._phase("waiting_for_job")
1908
+ self.echo(" asking the scheduler for a node to serve the data "
1909
+ "from; this can wait in the queue.")
1910
+ deadline = _now() + self.timeout
1898
1911
 
1899
1912
  announced = _wait_for_node(self.primary, deadline, echo=self.echo)
1900
1913
  if not announced:
@@ -2133,21 +2146,25 @@ def connect_node(target, serve, *, name=None,
2133
2146
  local, remote = pick_ports(local_port, remote_port)
2134
2147
  name = name or f"{split_target(target)[1]}-node"
2135
2148
 
2136
- if install:
2137
- # A stand-in with the four attributes `_install_plexora` reads. This
2138
- # function drives its ssh by hand rather than through a session object,
2139
- # and giving it one just to install would be a bigger change than the
2140
- # shim it would replace.
2141
- _install_plexora(_BareInstall(target, remote_command, jump, ssh_opts,
2142
- echo))
2143
-
2144
2149
  launch = node_command_line(remote_command, remote, serve,
2145
2150
  allow_origin=allow_origin, plugins=plugins)
2151
+ matchers = {"node": parse_node_announce}
2152
+ shim = install_line = None
2153
+ if install:
2154
+ # A stand-in with the attributes `_begin_install`/`_await_install`
2155
+ # read. This function drives its ssh by hand rather than through a
2156
+ # session object, and giving it one just to install would be a bigger
2157
+ # change than the shim it replaces.
2158
+ shim = _BareInstall(target, remote_command, jump, ssh_opts, echo)
2159
+ install_line = _begin_install(shim)
2160
+ launch = install_prefixed(install_line, launch)
2161
+ matchers["installed"] = parse_install_done
2146
2162
  argv = direct_ssh_argv(target, local, remote, launch, jump=jump,
2147
2163
  ssh_opts=ssh_opts)
2148
2164
  echo(f"$ {' '.join(argv)}")
2149
- watched = _Watched(argv, "node", echo=echo,
2150
- matchers={"node": parse_node_announce})
2165
+ watched = _Watched(argv, "node", echo=echo, matchers=matchers)
2166
+ if install_line:
2167
+ _await_install(shim, watched, install_line)
2151
2168
  _ACTIVE.append(watched)
2152
2169
  deadline = _now() + timeout
2153
2170
 
@@ -361,6 +361,19 @@ def warm_resources(registry, log=print):
361
361
  across a node restart -- so fitting them here would be twenty seconds of
362
362
  work for an answer nobody is going to ask this node for.
363
363
 
364
+ **And deliberately not the window SCANS.** An earlier version computed
365
+ every channel's quantization window here, on the reasoning that a first
366
+ zoom should not pay for it. Each window is a full-resolution read of a
367
+ whole channel plane, and a node restored from its manifest can be serving
368
+ several whole slides -- so on a cluster filesystem that reasoning turned
369
+ into the node reading a hundred gigabytes, by itself, starting seconds
370
+ after it announced, and answering nothing -- not even /health -- while it
371
+ did. Watched live, twice, on two clusters: the panel said "Not answering"
372
+ about a machine that was busy doing work nobody had asked for yet. Windows
373
+ are seeded from the persistent store when the last job already paid for
374
+ them -- a JSON read -- and are otherwise computed on demand, one channel
375
+ at a time, when a request actually needs that channel.
376
+
364
377
  Sequential, and on one background thread. The reads contend for the same
365
378
  file, so racing them wins nothing, and the readers-writer lock means a real
366
379
  request can interleave rather than queue behind the whole warm.
@@ -380,8 +393,12 @@ def warm_resources(registry, log=print):
380
393
  continue
381
394
  overview = resource.opened_overview
382
395
  for index in range(len(overview) if overview is not None else 0):
396
+ stored = node_api._stored_window(resource, index)
397
+ if stored is None:
398
+ continue
383
399
  with node_api._reading(resource):
384
- node_api._quantization(resource, index)
400
+ node_api._cached(resource, ("qwindow", index),
401
+ lambda window=stored: window)
385
402
  except Exception as exc: # pragma: no cover - unreadable at warm time
386
403
  # Never fatal. A resource that cannot be warmed is one that
387
404
  # will report its own failure when something asks for it, and
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: plexora
3
- Version: 0.0.8
3
+ Version: 0.0.9
4
4
  Summary: OpenSeadragon-based cellular image viewing and analysis tool.
5
5
  License-Expression: LicenseRef-Plexora-Academic-1.0
6
6
  Requires-Python: <3.14,>=3.12
@@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta"
6
6
 
7
7
  [project]
8
8
  name = "plexora"
9
- version = "0.0.8"
9
+ version = "0.0.9"
10
10
  description = "OpenSeadragon-based cellular image viewing and analysis tool."
11
11
  readme = "README.md"
12
12
  requires-python = ">=3.12,<3.14"