histomicsui 1.4.7.dev46__tar.gz → 1.4.7.dev49__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 (178) hide show
  1. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/.circleci/config.yml +1 -1
  2. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/.git-blame-ignore-revs +2 -0
  3. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/.pre-commit-config.yaml +10 -3
  4. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/PKG-INFO +1 -1
  5. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/__init__.py +18 -11
  6. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/handlers.py +16 -10
  7. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/models/aperio.py +8 -5
  8. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/models/case.py +11 -7
  9. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/models/cohort.py +3 -2
  10. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/models/image.py +18 -10
  11. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/models/meta.py +14 -11
  12. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/models/pathology.py +2 -1
  13. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/models/slide.py +8 -5
  14. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/rest/aperio.py +11 -11
  15. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/rest/hui_resource.py +13 -11
  16. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/rest/image_browse_resource.py +5 -4
  17. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/rest/system.py +24 -17
  18. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/rest/tcga.py +107 -98
  19. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui.egg-info/PKG-INFO +1 -1
  20. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui.egg-info/SOURCES.txt +1 -1
  21. histomicsui-1.4.7.dev49/ruff.toml +69 -0
  22. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/tests/datastore.py +1 -1
  23. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/tests/test_hui_rest.py +17 -17
  24. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/tests/test_image_browse_endpoints.py +1 -1
  25. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/tests/test_tcga.py +122 -120
  26. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/tests/test_web_client.py +12 -12
  27. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/tox.ini +6 -2
  28. histomicsui-1.4.7.dev46/.travis.yml +0 -24
  29. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/.editorconfig +0 -0
  30. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/.gitignore +0 -0
  31. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/LICENSE +0 -0
  32. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/MANIFEST.in +0 -0
  33. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/NOTICE +0 -0
  34. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/README.rst +0 -0
  35. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/codecov.yml +0 -0
  36. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/docs/config_options.rst +0 -0
  37. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/docs/controls.rst +0 -0
  38. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/docs/images/difference.gif +0 -0
  39. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/docs/images/intersect.gif +0 -0
  40. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/docs/images/union.gif +0 -0
  41. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/docs/images/xor.gif +0 -0
  42. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/constants.py +0 -0
  43. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/models/__init__.py +0 -0
  44. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/rest/__init__.py +0 -0
  45. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/app.js +0 -0
  46. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/collections/StyleCollection.js +0 -0
  47. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/collections/UserCollection.js +0 -0
  48. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/collections/index.js +0 -0
  49. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/dialogs/confirmDialog.js +0 -0
  50. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/dialogs/editElement.js +0 -0
  51. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/dialogs/editRegionOfInterest.js +0 -0
  52. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/dialogs/editStyleGroups.js +0 -0
  53. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/dialogs/index.js +0 -0
  54. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/dialogs/metadataPlot.js +0 -0
  55. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/dialogs/openAnnotatedImage.js +0 -0
  56. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/dialogs/openImage.js +0 -0
  57. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/dialogs/saveAnnotation.js +0 -0
  58. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/events.js +0 -0
  59. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/index.js +0 -0
  60. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/main.js +0 -0
  61. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/models/StyleModel.js +0 -0
  62. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/models/index.js +0 -0
  63. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/package.json +0 -0
  64. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/panels/AnnotationSelector.js +0 -0
  65. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/panels/DrawWidget.js +0 -0
  66. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/panels/FrameSelectorWidget.js +0 -0
  67. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/panels/MetadataPlot.js +0 -0
  68. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/panels/MetadataWidget.js +0 -0
  69. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/panels/OverviewWidget.js +0 -0
  70. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/panels/RegionSelector.js +0 -0
  71. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/panels/ZoomWidget.js +0 -0
  72. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/panels/index.js +0 -0
  73. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/router.js +0 -0
  74. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/routes.js +0 -0
  75. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/static/favicon.png +0 -0
  76. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/stylesheets/body/configView.styl +0 -0
  77. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/stylesheets/body/image.styl +0 -0
  78. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/stylesheets/dialogs/editStyleGroups.styl +0 -0
  79. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/stylesheets/dialogs/openAnnotatedImage.styl +0 -0
  80. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/stylesheets/dialogs/saveAnnotation.styl +0 -0
  81. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/stylesheets/layout/header.styl +0 -0
  82. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/stylesheets/layout/headerAnalyses.styl +0 -0
  83. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/stylesheets/layout/headerImage.styl +0 -0
  84. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/stylesheets/layout/layout.styl +0 -0
  85. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/stylesheets/panels/annotationSelector.styl +0 -0
  86. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/stylesheets/panels/drawWidget.styl +0 -0
  87. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/stylesheets/panels/frameSelectorWidget.styl +0 -0
  88. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/stylesheets/panels/metadataPlot.styl +0 -0
  89. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/stylesheets/panels/metadataWidget.styl +0 -0
  90. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/stylesheets/panels/overviewWidget.styl +0 -0
  91. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/stylesheets/panels/regionSelector.styl +0 -0
  92. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/stylesheets/panels/zoomWidget.styl +0 -0
  93. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/stylesheets/popover/annotationContextMenu.styl +0 -0
  94. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/stylesheets/popover/annotationPopover.styl +0 -0
  95. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/stylesheets/views/itemList.styl +0 -0
  96. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/templates/body/configView.pug +0 -0
  97. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/templates/body/image.pug +0 -0
  98. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/templates/dialogs/annotatedImageList.pug +0 -0
  99. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/templates/dialogs/confirmDialog.pug +0 -0
  100. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/templates/dialogs/editElement.pug +0 -0
  101. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/templates/dialogs/editRegionOfInterest.pug +0 -0
  102. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/templates/dialogs/editStyleGroups.pug +0 -0
  103. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/templates/dialogs/metadataPlot.pug +0 -0
  104. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/templates/dialogs/openAnnotatedImage.pug +0 -0
  105. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/templates/dialogs/openImage.pug +0 -0
  106. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/templates/dialogs/saveAnnotation.pug +0 -0
  107. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/templates/layout/header.pug +0 -0
  108. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/templates/layout/headerAnalyses.pug +0 -0
  109. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/templates/layout/headerImage.pug +0 -0
  110. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/templates/layout/headerUser.pug +0 -0
  111. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/templates/layout/layout.pug +0 -0
  112. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/templates/panels/annotationSelector.pug +0 -0
  113. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/templates/panels/drawWidget.pug +0 -0
  114. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/templates/panels/drawWidgetElement.pug +0 -0
  115. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/templates/panels/frameSelectorWidget.pug +0 -0
  116. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/templates/panels/metadataPlot.pug +0 -0
  117. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/templates/panels/metadataWidgetPanel.pug +0 -0
  118. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/templates/panels/overviewWidget.pug +0 -0
  119. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/templates/panels/panel.pug +0 -0
  120. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/templates/panels/regionSelector.pug +0 -0
  121. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/templates/panels/zoomWidget.pug +0 -0
  122. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/templates/popover/annotationContextMenu.pug +0 -0
  123. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/templates/popover/annotationPopover.pug +0 -0
  124. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/templates/popover/annotationPopoverMetadata.pug +0 -0
  125. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/templates/popover/pixelmapContextMenu.pug +0 -0
  126. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/views/HierarchyWidget.js +0 -0
  127. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/views/View.js +0 -0
  128. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/views/body/ConfigView.js +0 -0
  129. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/views/body/ImageView.js +0 -0
  130. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/views/body/index.js +0 -0
  131. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/views/index.js +0 -0
  132. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/views/itemList.js +0 -0
  133. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/views/itemPage.js +0 -0
  134. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/views/layout/HeaderAnalysesView.js +0 -0
  135. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/views/layout/HeaderImageView.js +0 -0
  136. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/views/layout/HeaderUserView.js +0 -0
  137. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/views/layout/HeaderView.js +0 -0
  138. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/views/layout/index.js +0 -0
  139. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/views/popover/AnnotationContextMenu.js +0 -0
  140. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/views/popover/AnnotationPopover.js +0 -0
  141. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/views/popover/PixelmapContextMenu.js +0 -0
  142. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/views/popover/index.js +0 -0
  143. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/views/utils.js +0 -0
  144. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/vue/components/ColorPickerInput.vue +0 -0
  145. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/vue/components/EditHeatmapOrGridData.vue +0 -0
  146. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/vue/components/EditHeatmapOrGridDataContainer.vue +0 -0
  147. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/web_client/webpack.helper.js +0 -0
  148. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui/webroot.mako +0 -0
  149. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui.egg-info/dependency_links.txt +0 -0
  150. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui.egg-info/entry_points.txt +0 -0
  151. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui.egg-info/not-zip-safe +0 -0
  152. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui.egg-info/requires.txt +0 -0
  153. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/histomicsui.egg-info/top_level.txt +0 -0
  154. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/requirements-dev.txt +0 -0
  155. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/setup.cfg +0 -0
  156. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/setup.py +0 -0
  157. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/tests/__init__.py +0 -0
  158. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/tests/girder_utilities.py +0 -0
  159. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/tests/test_files/.histomicsui_config.yaml +0 -0
  160. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/tests/test_files/sample.anot +0 -0
  161. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/tests/test_files/sample.meta +0 -0
  162. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/tests/test_files/sample_girder_id.anot +0 -0
  163. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/tests/test_files/test_analysis_detection.xml +0 -0
  164. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/tests/test_files/test_analysis_features.xml +0 -0
  165. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/tests/test_handlers.py +0 -0
  166. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/tests/test_load.py +0 -0
  167. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/tests/web_client_specs/.eslintrc +0 -0
  168. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/tests/web_client_specs/analysisSpec.js +0 -0
  169. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/tests/web_client_specs/annotationSpec.js +0 -0
  170. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/tests/web_client_specs/girderUISpec.js +0 -0
  171. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/tests/web_client_specs/huiSpec.js +0 -0
  172. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/tests/web_client_specs/huiTest.js +0 -0
  173. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/tests/web_client_specs/itemSpec.js +0 -0
  174. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/tests/web_client_specs/metadataPanelSpec.js +0 -0
  175. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/tests/web_client_specs/metadataPlotSpec.js +0 -0
  176. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/tests/web_client_specs/overviewPanelSpec.js +0 -0
  177. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/tests/web_client_specs/panelLayoutSpec.js +0 -0
  178. {histomicsui-1.4.7.dev46 → histomicsui-1.4.7.dev49}/tests/web_client_specs/pixelmapCategorySpec.js +0 -0
@@ -84,7 +84,7 @@ jobs:
84
84
  steps:
85
85
  - checkout
86
86
  - tox:
87
- env: flake8,lintclient
87
+ env: lint,lintclient
88
88
  release:
89
89
  docker:
90
90
  - image: girder/tox-and-node
@@ -11,3 +11,5 @@ b566911831095bb4c161e2161e2d1a33cf3f4f18
11
11
  f1c2190ab04ab867c655b4217f807e9f567772c8
12
12
  # PR 296: Use stylus-supremacy for linting and reformating stylus files
13
13
  9475b89640a6de84788b79ba68d5ed9aeb1a9ff4
14
+ # PR 359: Apply ruff formatting and linting
15
+ 97b21f031e4769043b2c3a464ea4cf8e9a60c219
@@ -2,7 +2,7 @@
2
2
  # See https://pre-commit.com/hooks.html for more hooks
3
3
  repos:
4
4
  - repo: https://github.com/pre-commit/pre-commit-hooks
5
- rev: v4.4.0
5
+ rev: v4.5.0
6
6
  hooks:
7
7
  - id: check-added-large-files
8
8
  - id: check-ast
@@ -42,7 +42,7 @@ repos:
42
42
  files: README.rst
43
43
  name: rst-linter of README.rst
44
44
  - repo: https://github.com/codespell-project/codespell
45
- rev: v2.2.5
45
+ rev: v2.2.6
46
46
  hooks:
47
47
  - id: codespell
48
48
  args:
@@ -59,8 +59,15 @@ repos:
59
59
  args:
60
60
  - '--options'
61
61
  - './histomicsui/web_client/package.json'
62
+ - repo: https://github.com/astral-sh/ruff-pre-commit
63
+ # Ruff version.
64
+ rev: v0.1.0
65
+ hooks:
66
+ - id: ruff
67
+ args: [--fix, --exit-non-zero-on-fix]
68
+ types_or: [python, pyi, jupyter]
62
69
  - repo: https://github.com/asottile/pyupgrade
63
- rev: v3.10.1
70
+ rev: v3.15.0
64
71
  hooks:
65
72
  - id: pyupgrade
66
73
  args:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: histomicsui
3
- Version: 1.4.7.dev46
3
+ Version: 1.4.7.dev49
4
4
  Summary: Organize, visualize, and analyze histology images.
5
5
  Home-page: https://github.com/DigitalSlideArchive/histomicsui
6
6
  Author: Kitware, Inc.
@@ -58,7 +58,7 @@ except DistributionNotFound:
58
58
 
59
59
  _template = os.path.join(
60
60
  os.path.dirname(__file__),
61
- 'webroot.mako'
61
+ 'webroot.mako',
62
62
  )
63
63
 
64
64
 
@@ -155,29 +155,35 @@ def validateListOrJSON(doc):
155
155
  })
156
156
  def validateHistomicsUIColor(doc):
157
157
  if not doc['value']:
158
- raise ValidationException('The banner color may not be empty', 'value')
158
+ msg = 'The banner color may not be empty'
159
+ raise ValidationException(msg, 'value')
159
160
  elif not re.match(r'^#[0-9A-Fa-f]{6}$', doc['value']):
160
- raise ValidationException('The banner color must be a hex color triplet', 'value')
161
+ msg = 'The banner color must be a hex color triplet'
162
+ raise ValidationException(msg, 'value')
161
163
 
162
164
 
163
165
  @setting_utilities.validator(PluginSettings.HUI_BRAND_NAME)
164
166
  def validateHistomicsUIBrandName(doc):
165
167
  if not doc['value']:
166
- raise ValidationException('The brand name may not be empty', 'value')
168
+ msg = 'The brand name may not be empty'
169
+ raise ValidationException(msg, 'value')
167
170
 
168
171
 
169
172
  @setting_utilities.validator(PluginSettings.HUI_WEBROOT_PATH)
170
173
  def validateHistomicsUIWebrootPath(doc):
171
174
  if not doc['value']:
172
- raise ValidationException('The webroot path may not be empty', 'value')
175
+ msg = 'The webroot path may not be empty'
176
+ raise ValidationException(msg, 'value')
173
177
  if re.match(r'^girder$', doc['value']):
174
- raise ValidationException('The webroot path may not be "girder"', 'value')
178
+ msg = 'The webroot path may not be "girder"'
179
+ raise ValidationException(msg, 'value')
175
180
 
176
181
 
177
182
  @setting_utilities.validator(PluginSettings.HUI_ALTERNATE_WEBROOT_PATH)
178
183
  def validateHistomicsUIAlternateWebrootPath(doc):
179
184
  if re.match(r'(^,|)girder(,|$)', doc['value']):
180
- raise ValidationException('The alternate webroot path may not contain "girder"', 'value')
185
+ msg = 'The alternate webroot path may not contain "girder"'
186
+ raise ValidationException(msg, 'value')
181
187
 
182
188
 
183
189
  @setting_utilities.validator(PluginSettings.HUI_QUARANTINE_FOLDER)
@@ -197,14 +203,14 @@ SettingDefault.defaults.update({
197
203
  PluginSettings.HUI_HELP_URL:
198
204
  'https://github.com/DigitalSlideArchive/HistomicsUI/blob/master/docs/controls.rst',
199
205
  PluginSettings.HUI_HELP_TOOLTIP: 'Mouse and keyboard controls',
200
- PluginSettings.HUI_HELP_TEXT: 'Help'
206
+ PluginSettings.HUI_HELP_TEXT: 'Help',
201
207
  })
202
208
 
203
209
 
204
210
  @setting_utilities.validator({
205
211
  PluginSettings.HUI_HELP_URL,
206
212
  PluginSettings.HUI_HELP_TOOLTIP,
207
- PluginSettings.HUI_HELP_TEXT
213
+ PluginSettings.HUI_HELP_TEXT,
208
214
  })
209
215
  def validateHistomicsUIHelp(doc):
210
216
  pass
@@ -257,7 +263,7 @@ class WebrootHistomicsUI(Webroot):
257
263
  'huiBannerColor': Setting().get(PluginSettings.HUI_BANNER_COLOR),
258
264
  'huiHelpURL': Setting().get(PluginSettings.HUI_HELP_URL),
259
265
  'huiHelpTooltip': Setting().get(PluginSettings.HUI_HELP_TOOLTIP),
260
- 'huiHelpText': Setting().get(PluginSettings.HUI_HELP_TEXT)
266
+ 'huiHelpText': Setting().get(PluginSettings.HUI_HELP_TEXT),
261
267
  })
262
268
  return super()._renderHTML()
263
269
 
@@ -327,8 +333,9 @@ def restrict_downloads(info):
327
333
  def wrapped(*args, **kwargs):
328
334
  if (not getCurrentToken() and len(args) >= 1 and
329
335
  args[0] and args[0].get('size', 0) >= limit):
336
+ msg = 'You must be logged in or have a valid auth token.'
330
337
  raise AccessException(
331
- 'You must be logged in or have a valid auth token.')
338
+ msg)
332
339
  return fun(*args, **kwargs)
333
340
  return wrapped
334
341
  File().download = limitLengthDownload(
@@ -129,7 +129,7 @@ def process_annotations(event): # noqa
129
129
 
130
130
  file = File().load(
131
131
  event.info.get('file', {}).get('_id'),
132
- level=AccessType.READ, user=user
132
+ level=AccessType.READ, user=user,
133
133
  )
134
134
  startTime = time.time()
135
135
 
@@ -139,7 +139,8 @@ def process_annotations(event): # noqa
139
139
  try:
140
140
  if file['size'] > int(large_image.config.getConfig(
141
141
  'max_annotation_input_file_length', 1024 ** 3)):
142
- raise Exception('File is larger than will be read into memory.')
142
+ msg = 'File is larger than will be read into memory.'
143
+ raise Exception(msg)
143
144
  data = []
144
145
  with File().open(file) as fptr:
145
146
  while True:
@@ -189,12 +190,15 @@ def quarantine_item(item, user, makePlaceholder=True):
189
190
  """
190
191
  folder = Setting().get(PluginSettings.HUI_QUARANTINE_FOLDER)
191
192
  if not folder:
192
- raise RestException('The quarantine folder is not configured.')
193
+ msg = 'The quarantine folder is not configured.'
194
+ raise RestException(msg)
193
195
  folder = Folder().load(folder, force=True, exc=True)
194
196
  if not folder:
195
- raise RestException('The quarantine folder does not exist.')
197
+ msg = 'The quarantine folder does not exist.'
198
+ raise RestException(msg)
196
199
  if str(folder['_id']) == str(item['folderId']):
197
- raise RestException('The item is already in the quarantine folder.')
200
+ msg = 'The item is already in the quarantine folder.'
201
+ raise RestException(msg)
198
202
  originalFolder = Folder().load(item['folderId'], force=True)
199
203
  quarantineInfo = {
200
204
  'originalFolderId': item['folderId'],
@@ -202,7 +206,7 @@ def quarantine_item(item, user, makePlaceholder=True):
202
206
  'originalBaseParentId': item['baseParentId'],
203
207
  'originalUpdated': item['updated'],
204
208
  'quarantineUserId': user['_id'],
205
- 'quarantineTime': datetime.datetime.now(datetime.timezone.utc)
209
+ 'quarantineTime': datetime.datetime.now(datetime.timezone.utc),
206
210
  }
207
211
  item = Item().move(item, folder)
208
212
  if makePlaceholder:
@@ -216,7 +220,7 @@ def quarantine_item(item, user, makePlaceholder=True):
216
220
  if makePlaceholder:
217
221
  placeholderInfo = {
218
222
  'quarantined': True,
219
- 'quarantineTime': quarantineInfo['quarantineTime']
223
+ 'quarantineTime': quarantineInfo['quarantineTime'],
220
224
  }
221
225
  placeholder.setdefault('meta', {})['quarantine'] = placeholderInfo
222
226
  placeholder = Item().updateItem(placeholder)
@@ -232,10 +236,12 @@ def restore_quarantine_item(item, user):
232
236
  :returns: the modified item.
233
237
  """
234
238
  if not item.get('meta', {}).get('quarantine'):
235
- raise RestException('The item has no quarantine record.')
239
+ msg = 'The item has no quarantine record.'
240
+ raise RestException(msg)
236
241
  folder = Folder().load(item['meta']['quarantine']['originalFolderId'], force=True)
237
242
  if not folder:
238
- raise RestException('The original folder is not accessible.')
243
+ msg = 'The original folder is not accessible.'
244
+ raise RestException(msg)
239
245
  if 'placeholderItemId' in item['meta']['quarantine']:
240
246
  placeholder = Item().load(item['meta']['quarantine']['placeholderItemId'], force=True)
241
247
  else:
@@ -256,7 +262,7 @@ def process_metadata(event):
256
262
  return
257
263
  file = File().load(
258
264
  event.info.get('file', {}).get('_id'),
259
- level=AccessType.READ, user=results['user']
265
+ level=AccessType.READ, user=results['user'],
260
266
  )
261
267
 
262
268
  if not file:
@@ -15,7 +15,7 @@ class Aperio(Item):
15
15
  aperio_re = re.compile(
16
16
  r'^(?P<barcode>(?P<case>' +
17
17
  TCGAModel.case_re.pattern + r')[0-9a-z-]*)\.xml',
18
- flags=re.I
18
+ flags=re.I,
19
19
  )
20
20
 
21
21
  def initialize(self, **kwargs):
@@ -32,14 +32,16 @@ class Aperio(Item):
32
32
  try:
33
33
  Item().load(imageId, force=True)
34
34
  except Exception:
35
+ msg = 'The item is not associated with a valid image.'
35
36
  raise ValidationException(
36
- 'The item is not associated with a valid image.'
37
+ msg,
37
38
  )
38
39
 
39
40
  files = Item().childFiles(doc)
40
41
  if files.count() != 1:
42
+ msg = 'The annotation item must have exactly one file.'
41
43
  raise ValidationException(
42
- 'The annotation item must have exactly one file.'
44
+ msg,
43
45
  )
44
46
 
45
47
  meta.setdefault('tag', None)
@@ -72,7 +74,7 @@ class Aperio(Item):
72
74
  name = doc['name']
73
75
  d = self.aperio_re.match(name).groupdict()
74
76
  image = TCGAImage().findOne({
75
- 'tcga.barcode': d['barcode'].upper()
77
+ 'tcga.barcode': d['barcode'].upper(),
76
78
  })
77
79
  self.importDocument(doc, image, **kwargs)
78
80
 
@@ -84,7 +86,8 @@ class Aperio(Item):
84
86
  except ValidationException:
85
87
  pass
86
88
  else:
87
- raise ValidationException('Invalid model type')
89
+ msg = 'Invalid model type'
90
+ raise ValidationException(msg)
88
91
 
89
92
  def findAperio(self, image, tag=None, **kwargs):
90
93
  """Find Aperio annotations associated with the given image."""
@@ -9,24 +9,27 @@ class Case(TCGAModel, Folder):
9
9
 
10
10
  TCGAType = 'case'
11
11
  TCGAIndices = [
12
- 'tcga.label'
12
+ 'tcga.label',
13
13
  ]
14
14
 
15
15
  def validate(self, doc, **kwargs):
16
16
  if doc.get('parentCollection') != 'folder':
17
+ msg = 'A Case model must be a child of a folder'
17
18
  raise ValidationException(
18
- 'A Case model must be a child of a folder'
19
+ msg,
19
20
  )
20
21
  super().validate(doc, **kwargs)
21
22
  cohort = Cohort().load(
22
23
  doc['parentId'], force=True)
23
24
  if not cohort or self.getTCGAType(cohort) != 'cohort':
25
+ msg = 'A Case model must be a child of a cohort'
24
26
  raise ValidationException(
25
- 'A Case model must be a child of a cohort'
27
+ msg,
26
28
  )
27
29
  if not self.case_re.match(self.getTCGA(doc).get('label', '')):
30
+ msg = 'Invalid label in TCGA metadata'
28
31
  raise ValidationException(
29
- 'Invalid label in TCGA metadata'
32
+ msg,
30
33
  )
31
34
  return doc
32
35
 
@@ -35,11 +38,12 @@ class Case(TCGAModel, Folder):
35
38
 
36
39
  recurse = kwargs.get('recurse', False)
37
40
  parent = Cohort().load(
38
- doc.get('parentId'), force=True
41
+ doc.get('parentId'), force=True,
39
42
  )
40
43
  if not parent:
44
+ msg = 'Invalid folder document'
41
45
  raise ValidationException(
42
- 'Invalid folder document'
46
+ msg,
43
47
  )
44
48
  tcga = self.getTCGA(parent)
45
49
  tcga['label'] = doc['name']
@@ -51,7 +55,7 @@ class Case(TCGAModel, Folder):
51
55
 
52
56
  childModel = Slide()
53
57
  children = Folder().childFolders(
54
- doc, 'folder', user=kwargs.get('user')
58
+ doc, 'folder', user=kwargs.get('user'),
55
59
  )
56
60
  for child in children:
57
61
  try:
@@ -11,8 +11,9 @@ class Cohort(TCGAModel, Folder):
11
11
  def validate(self, doc, **kwargs):
12
12
  super().validate(doc, **kwargs)
13
13
  if doc['parentCollection'] != 'collection':
14
+ msg = 'A Cohort model must be a child of a collection'
14
15
  raise ValidationException(
15
- 'A Cohort model must be a child of a collection'
16
+ msg,
16
17
  )
17
18
  return doc
18
19
 
@@ -28,7 +29,7 @@ class Cohort(TCGAModel, Folder):
28
29
 
29
30
  childModel = Case()
30
31
  children = Folder().childFolders(
31
- doc, 'folder', user=kwargs.get('user')
32
+ doc, 'folder', user=kwargs.get('user'),
32
33
  )
33
34
  for child in children:
34
35
  try:
@@ -14,27 +14,32 @@ class Image(TCGAModel, Item):
14
14
  def validate(self, doc, **kwargs):
15
15
  super().validate(doc, **kwargs)
16
16
  if 'largeImage' not in doc:
17
+ msg = 'An image item must be a "large_image"'
17
18
  raise ValidationException(
18
- 'An image item must be a "large_image"'
19
+ msg,
19
20
  )
20
21
  slide = Slide().load(
21
22
  doc['folderId'], force=True)
22
23
  if not slide or self.getTCGAType(slide) != 'slide':
24
+ msg = 'An image must be a child of a slide'
23
25
  raise ValidationException(
24
- 'An image must be a child of a slide'
26
+ msg,
25
27
  )
26
28
  tcga = self.getTCGA(doc)
27
29
  if not self.case_re.match(tcga.get('case', '')):
30
+ msg = 'Invalid case name in TCGA metadata'
28
31
  raise ValidationException(
29
- 'Invalid case name in TCGA metadata'
32
+ msg,
30
33
  )
31
34
  if not self.barcode_re.match(tcga.get('barcode', '')):
35
+ msg = 'Invalid barcode in TCGA metadata'
32
36
  raise ValidationException(
33
- 'Invalid barcode in TCGA metadata'
37
+ msg,
34
38
  )
35
39
  if not self.uuid_re.match(tcga.get('uuid', '')):
40
+ msg = 'Invalid uuid in TCGA metadata'
36
41
  raise ValidationException(
37
- 'Invalid uuid in TCGA metadata'
42
+ msg,
38
43
  )
39
44
 
40
45
  return doc
@@ -46,11 +51,12 @@ class Image(TCGAModel, Item):
46
51
  try:
47
52
  return ImageItem.createImageItem(
48
53
  doc, file,
49
- user=user, token=token, createJob=False
54
+ user=user, token=token, createJob=False,
50
55
  )
51
56
  except Exception:
57
+ msg = 'Could not generate a large_image item'
52
58
  raise ValidationException(
53
- 'Could not generate a large_image item'
59
+ msg,
54
60
  )
55
61
 
56
62
  def _findImageFile(self, doc):
@@ -64,18 +70,20 @@ class Image(TCGAModel, Item):
64
70
  token = kwargs.get('token')
65
71
  fileId = self._findImageFile(doc)
66
72
  if fileId is None:
73
+ msg = 'Could not find a TCGA slide in item'
67
74
  raise ValidationException(
68
- 'Could not find a TCGA slide in item'
75
+ msg,
69
76
  )
70
77
  self._setLargeImage(doc, fileId, user, token)
71
78
 
72
79
  name = doc['name']
73
80
  parent = Slide().load(
74
- doc.get('folderId'), force=True
81
+ doc.get('folderId'), force=True,
75
82
  )
76
83
  if not parent:
84
+ msg = 'Invalid item document'
77
85
  raise ValidationException(
78
- 'Invalid item document'
86
+ msg,
79
87
  )
80
88
  tcga = self.getTCGA(parent)
81
89
  tcga.update(self.parseImage(name))
@@ -58,13 +58,13 @@ class TCGAModel:
58
58
  #: Matches valid uuid's
59
59
  uuid_re = re.compile(
60
60
  r'[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}',
61
- flags=re.I
61
+ flags=re.I,
62
62
  )
63
63
 
64
64
  #: Matches valid tcga barcodes
65
65
  barcode_re = re.compile(
66
66
  case_re.pattern + r'[0-9a-z-]*',
67
- flags=re.I
67
+ flags=re.I,
68
68
  )
69
69
 
70
70
  #: Parses tcga slide image file names
@@ -72,7 +72,7 @@ class TCGAModel:
72
72
  r'^(?P<barcode>(?P<case>' +
73
73
  case_re.pattern + r')[0-9a-z-]*)\.' +
74
74
  r'(?P<uuid>' + uuid_re.pattern + r')\.svs$',
75
- flags=re.I
75
+ flags=re.I,
76
76
  )
77
77
 
78
78
  #: Parses tcga pathology report file names
@@ -80,7 +80,7 @@ class TCGAModel:
80
80
  r'^(?P<case>' + case_re.pattern +
81
81
  r')\.(?P<uuid>' + uuid_re.pattern +
82
82
  r')\.pdf$',
83
- flags=re.I
83
+ flags=re.I,
84
84
  )
85
85
 
86
86
  def initialize(self, **kwargs):
@@ -149,14 +149,15 @@ class TCGAModel:
149
149
  def getTCGACollection(self):
150
150
  """Get the unique TCGA collection from the settings collection."""
151
151
  tcga = Setting().get(
152
- TCGACollectionSettingKey
152
+ TCGACollectionSettingKey,
153
153
  )
154
154
  if tcga is None:
155
+ msg = 'TCGA collection id not initialized in settings'
155
156
  raise Exception(
156
- 'TCGA collection id not initialized in settings'
157
+ msg,
157
158
  )
158
159
  return Collection().load(
159
- tcga, force=True
160
+ tcga, force=True,
160
161
  )
161
162
 
162
163
  def __upper(self, obj, key):
@@ -170,7 +171,8 @@ class TCGAModel:
170
171
  def _parse(self, name, regex):
171
172
  m = regex.match(name)
172
173
  if m is None:
173
- raise ValidationException('Invalid name')
174
+ msg = 'Invalid name'
175
+ raise ValidationException(msg)
174
176
  d = m.groupdict()
175
177
  self.__lower(d, 'uuid')
176
178
  self.__upper(d, 'barcode')
@@ -190,7 +192,7 @@ class TCGAModel:
190
192
  """Set the mime type of a file document."""
191
193
  oldType = doc.get('mimeType')
192
194
  newType = mimetypes.guess_type(
193
- doc.get('name', '')
195
+ doc.get('name', ''),
194
196
  )[0]
195
197
  doc['mimeType'] = newType
196
198
  return newType != oldType
@@ -218,8 +220,9 @@ class TCGAModel:
218
220
  return doc
219
221
  except ValidationException:
220
222
  pass
223
+ msg = 'Invalid document id provided'
221
224
  raise ValidationException(
222
- 'Invalid document id provided'
225
+ msg,
223
226
  )
224
227
 
225
228
  def iterateItems(self, doc, **kwargs):
@@ -248,7 +251,7 @@ class TCGAModel:
248
251
  parentType = parentType.lower()
249
252
  q = {
250
253
  'parentId': parent['_id'],
251
- 'parentCollection': parentType
254
+ 'parentCollection': parentType,
252
255
  }
253
256
  q.update(filters or {})
254
257
  return self.find(q, sort=sort, limit=limit, offset=offset)
@@ -25,4 +25,5 @@ class Pathology(TCGAModel, Item):
25
25
  except ValidationException:
26
26
  pass
27
27
  else:
28
- raise ValidationException('Invalid model type')
28
+ msg = 'Invalid model type'
29
+ raise ValidationException(msg)
@@ -11,15 +11,17 @@ class Slide(TCGAModel, Folder):
11
11
 
12
12
  def validate(self, doc, **kwargs):
13
13
  if not doc.get('parentCollection') == 'folder':
14
+ msg = 'A Slide model must be a child of a folder'
14
15
  raise ValidationException(
15
- 'A Slide model must be a child of a folder'
16
+ msg,
16
17
  )
17
18
  super().validate(doc, **kwargs)
18
19
  case = Case().load(
19
20
  doc['parentId'], force=True)
20
21
  if not case or self.getTCGAType(case) != 'case':
22
+ msg = 'A Slide model must be a child of a case'
21
23
  raise ValidationException(
22
- 'A Slide model must be a child of a case'
24
+ msg,
23
25
  )
24
26
  return doc
25
27
 
@@ -28,11 +30,12 @@ class Slide(TCGAModel, Folder):
28
30
 
29
31
  recurse = kwargs.get('recurse', False)
30
32
  parent = Case().load(
31
- doc.get('parentId'), force=True
33
+ doc.get('parentId'), force=True,
32
34
  )
33
35
  if not parent:
36
+ msg = 'Invalid folder document'
34
37
  raise ValidationException(
35
- 'Invalid folder document'
38
+ msg,
36
39
  )
37
40
  tcga = self.getTCGA(parent)
38
41
  tcga.pop('meta', None)
@@ -43,7 +46,7 @@ class Slide(TCGAModel, Folder):
43
46
 
44
47
  childModel = Image()
45
48
  children = Folder().childItems(
46
- doc, user=kwargs.get('user')
49
+ doc, user=kwargs.get('user'),
47
50
  )
48
51
  for child in children:
49
52
  try:
@@ -24,7 +24,7 @@ def addTcgaEndpoints(tcgaRoot):
24
24
  .param('tag', 'Import annotations with this tag',
25
25
  required=False)
26
26
  .param('recursive', 'Perform a recursive search for annotations',
27
- required=False, dataType='boolean')
27
+ required=False, dataType='boolean'),
28
28
  )
29
29
  @access.admin
30
30
  @loadmodel(model='item', level=AccessType.ADMIN)
@@ -38,7 +38,7 @@ def importTCGADocument(self, item, params):
38
38
  return aperio.importTCGADocument(
39
39
  item, tag=tag,
40
40
  user=user, token=token,
41
- recurse=recursive
41
+ recurse=recursive,
42
42
  )
43
43
 
44
44
 
@@ -48,7 +48,7 @@ def importTCGADocument(self, item, params):
48
48
  paramType='path')
49
49
  .param('imageId', 'The ID of the slide image', required=True)
50
50
  .param('tag', 'A searchable tag to store with the metadata',
51
- required=False)
51
+ required=False),
52
52
  )
53
53
  @access.admin
54
54
  @loadmodel(model='item', level=AccessType.ADMIN)
@@ -61,12 +61,12 @@ def importDocument(self, item, params):
61
61
  imageId = params['imageId']
62
62
  image = Item().load(
63
63
  imageId,
64
- user=user, level=AccessType.READ, exc=True
64
+ user=user, level=AccessType.READ, exc=True,
65
65
  )
66
66
  aperio = Aperio()
67
67
  return aperio.importDocument(
68
68
  item, image, tag=tag,
69
- user=user, token=token
69
+ user=user, token=token,
70
70
  )
71
71
 
72
72
 
@@ -74,7 +74,7 @@ def importDocument(self, item, params):
74
74
  Description('Find Aperio annotation items associated with a slide image.')
75
75
  .param('id', 'The ID of the slide image item', paramType='path')
76
76
  .param('tag', 'Filter by the given tag string', required=False)
77
- .pagingParams(defaultSort='name')
77
+ .pagingParams(defaultSort='name'),
78
78
  )
79
79
  @access.public
80
80
  @loadmodel(model='item', level=AccessType.READ)
@@ -86,7 +86,7 @@ def findAperio(self, item, params):
86
86
  aperio = Aperio()
87
87
  docs = list(aperio.findAperio(
88
88
  item, tag=tag,
89
- user=user, level=AccessType.READ
89
+ user=user, level=AccessType.READ,
90
90
  ))
91
91
 
92
92
  for doc in docs:
@@ -99,26 +99,26 @@ def findAperio(self, item, params):
99
99
 
100
100
  @describeRoute(
101
101
  Description('Remove Aperio specific metadata from an item')
102
- .param('id', 'The ID of the annotation item', paramType='path')
102
+ .param('id', 'The ID of the annotation item', paramType='path'),
103
103
  )
104
104
  @access.admin
105
105
  @loadmodel(model='item', level=AccessType.WRITE)
106
106
  @boundHandler()
107
107
  def removeAperio(self, item, params):
108
108
  return Aperio().removeAperio(
109
- item
109
+ item,
110
110
  )
111
111
 
112
112
 
113
113
  @describeRoute(
114
114
  Description('Set the tag associated with the annotation file')
115
115
  .param('id', 'The ID of the annotation file', paramType='path')
116
- .param('tag', 'A searchable tag to store with the metadata')
116
+ .param('tag', 'A searchable tag to store with the metadata'),
117
117
  )
118
118
  @access.admin
119
119
  @loadmodel(model='item', level=AccessType.WRITE)
120
120
  @boundHandler()
121
121
  def modifyAperio(self, item, params):
122
122
  return Aperio().setTag(
123
- item, tag=params.get('tag')
123
+ item, tag=params.get('tag'),
124
124
  )