xarray-spatial 0.10.5__tar.gz → 0.10.6__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 (605) hide show
  1. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.claude/commands/deep-sweep.md +8 -7
  2. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.claude/commands/sweep-accuracy.md +14 -11
  3. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.claude/commands/sweep-api-consistency.md +9 -4
  4. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.claude/commands/sweep-metadata.md +13 -10
  5. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.claude/commands/sweep-performance.md +14 -11
  6. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.claude/commands/sweep-security.md +14 -11
  7. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.claude/commands/sweep-style.md +12 -10
  8. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.claude/commands/sweep-test-coverage.md +9 -4
  9. {xarray_spatial-0.10.5/.kilo → xarray_spatial-0.10.6/.claude}/sweep-style-state.csv +1 -0
  10. {xarray_spatial-0.10.5/.kilo → xarray_spatial-0.10.6/.claude}/sweep-test-coverage-state.csv +2 -3
  11. xarray_spatial-0.10.6/.cursor/rules/backend-parity.mdc +68 -0
  12. xarray_spatial-0.10.6/.cursor/rules/bench.mdc +51 -0
  13. xarray_spatial-0.10.6/.cursor/rules/dask-notebook.mdc +58 -0
  14. xarray_spatial-0.10.6/.cursor/rules/deep-sweep.mdc +49 -0
  15. xarray_spatial-0.10.6/.cursor/rules/efficiency-audit.mdc +47 -0
  16. xarray_spatial-0.10.6/.cursor/rules/new-issues.mdc +43 -0
  17. xarray_spatial-0.10.6/.cursor/rules/ready-to-merge.mdc +45 -0
  18. xarray_spatial-0.10.6/.cursor/rules/release-major.mdc +85 -0
  19. xarray_spatial-0.10.6/.cursor/rules/release-minor.mdc +85 -0
  20. xarray_spatial-0.10.6/.cursor/rules/release-patch.mdc +85 -0
  21. xarray_spatial-0.10.6/.cursor/rules/review-contributor-pr.mdc +62 -0
  22. xarray_spatial-0.10.6/.cursor/rules/review-pr.mdc +88 -0
  23. xarray_spatial-0.10.6/.cursor/rules/rockout.mdc +86 -0
  24. xarray_spatial-0.10.6/.cursor/rules/sweep-accuracy.mdc +35 -0
  25. xarray_spatial-0.10.6/.cursor/rules/sweep-api-consistency.mdc +35 -0
  26. xarray_spatial-0.10.6/.cursor/rules/sweep-metadata.mdc +34 -0
  27. xarray_spatial-0.10.6/.cursor/rules/sweep-performance.mdc +38 -0
  28. xarray_spatial-0.10.6/.cursor/rules/sweep-security.mdc +37 -0
  29. xarray_spatial-0.10.6/.cursor/rules/sweep-style.mdc +41 -0
  30. xarray_spatial-0.10.6/.cursor/rules/sweep-test-coverage.mdc +35 -0
  31. xarray_spatial-0.10.6/.cursor/rules/user-guide-notebook.mdc +52 -0
  32. xarray_spatial-0.10.6/.cursor/rules/validate.mdc +52 -0
  33. xarray_spatial-0.10.6/.cursorrules +53 -0
  34. xarray_spatial-0.10.6/.gitattributes +12 -0
  35. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/CHANGELOG.md +35 -0
  36. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/PKG-INFO +1 -1
  37. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xarray_spatial.egg-info/PKG-INFO +1 -1
  38. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xarray_spatial.egg-info/SOURCES.txt +25 -15
  39. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/__init__.py +2 -0
  40. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/_version.py +3 -3
  41. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/aspect.py +1 -1
  42. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/contour.py +18 -12
  43. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/emerging_hotspots.py +116 -88
  44. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/_cog_http.py +22 -7
  45. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/_sidecar.py +38 -20
  46. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/_writer.py +73 -16
  47. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/_writers/eager.py +17 -7
  48. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/golden_corpus/test_dask_gpu.py +6 -5
  49. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/golden_corpus/test_dask_numpy.py +6 -5
  50. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/golden_corpus/test_fsspec.py +11 -7
  51. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/golden_corpus/test_gpu.py +6 -5
  52. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/integration/test_sidecar.py +172 -9
  53. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/parity/test_api_consolidation.py +13 -0
  54. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/write/test_basic.py +20 -0
  55. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/write/test_streaming.py +98 -0
  56. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/write/test_vrt_atomic.py +18 -0
  57. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/hydro/flow_path_dinf.py +9 -2
  58. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/hydro/stream_link_mfd.py +44 -32
  59. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/hydro/stream_order_mfd.py +72 -56
  60. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/hydro/tests/test_flow_path_dinf.py +106 -0
  61. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/hydro/tests/test_stream_link_mfd.py +78 -0
  62. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/hydro/tests/test_stream_order_mfd.py +79 -0
  63. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/polygonize.py +153 -29
  64. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/reproject/__init__.py +18 -14
  65. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/reproject/_grid.py +10 -3
  66. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/reproject/_itrf.py +1 -0
  67. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/reproject/_merge.py +0 -1
  68. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/reproject/_projections.py +30 -97
  69. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/reproject/_projections_cuda.py +29 -27
  70. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_aspect.py +8 -0
  71. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_contour.py +243 -0
  72. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_emerging_hotspots.py +94 -0
  73. xarray_spatial-0.10.6/xrspatial/tests/test_polygonize_issue_2677.py +199 -0
  74. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_reproject.py +52 -44
  75. xarray_spatial-0.10.6/xrspatial/tests/test_sweep_state_csv_merge_2754.py +142 -0
  76. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_utils.py +30 -0
  77. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_viewshed.py +147 -1
  78. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/utils.py +13 -3
  79. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/viewshed.py +63 -3
  80. xarray_spatial-0.10.5/.gitattributes +0 -5
  81. xarray_spatial-0.10.5/xrspatial/reproject/_datum_grids.py +0 -386
  82. xarray_spatial-0.10.5/xrspatial/reproject/grids/at_bev_AT_GIS_GRID.tif +0 -0
  83. xarray_spatial-0.10.5/xrspatial/reproject/grids/au_icsm_A66_National_13_09_01.tif +0 -0
  84. xarray_spatial-0.10.5/xrspatial/reproject/grids/be_ign_bd72lb72_etrs89lb08.tif +0 -0
  85. xarray_spatial-0.10.5/xrspatial/reproject/grids/ch_swisstopo_CHENyx06_ETRS.tif +0 -0
  86. xarray_spatial-0.10.5/xrspatial/reproject/grids/de_adv_BETA2007.tif +0 -0
  87. xarray_spatial-0.10.5/xrspatial/reproject/grids/es_ign_SPED2ETV2.tif +0 -0
  88. xarray_spatial-0.10.5/xrspatial/reproject/grids/nl_nsgi_rdcorr2018.tif +0 -0
  89. xarray_spatial-0.10.5/xrspatial/reproject/grids/pt_dgt_D73_ETRS89_geo.tif +0 -0
  90. xarray_spatial-0.10.5/xrspatial/reproject/grids/uk_os_OSTN15_NTv2_OSGBtoETRS.tif +0 -0
  91. xarray_spatial-0.10.5/xrspatial/reproject/grids/us_noaa_alaska.tif +0 -0
  92. xarray_spatial-0.10.5/xrspatial/reproject/grids/us_noaa_conus.tif +0 -0
  93. xarray_spatial-0.10.5/xrspatial/reproject/grids/us_noaa_hawaii.tif +0 -0
  94. xarray_spatial-0.10.5/xrspatial/reproject/grids/us_noaa_nadcon5_nad27_nad83_1986_conus.tif +0 -0
  95. xarray_spatial-0.10.5/xrspatial/reproject/grids/us_noaa_prvi.tif +0 -0
  96. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.claude/commands/backend-parity.md +0 -0
  97. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.claude/commands/bench.md +0 -0
  98. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.claude/commands/dask-notebook.md +0 -0
  99. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.claude/commands/efficiency-audit.md +0 -0
  100. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.claude/commands/new-issues.md +0 -0
  101. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.claude/commands/ready-to-merge.md +0 -0
  102. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.claude/commands/release-major.md +0 -0
  103. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.claude/commands/release-minor.md +0 -0
  104. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.claude/commands/release-patch.md +0 -0
  105. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.claude/commands/review-contributor-pr.md +0 -0
  106. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.claude/commands/review-pr.md +0 -0
  107. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.claude/commands/rockout.md +0 -0
  108. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.claude/commands/user-guide-notebook.md +0 -0
  109. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.claude/commands/validate.md +0 -0
  110. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.claude/sweep-accuracy-state.csv +0 -0
  111. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.claude/sweep-api-consistency-state.csv +0 -0
  112. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.claude/sweep-metadata-state.csv +0 -0
  113. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.claude/sweep-performance-state.csv +0 -0
  114. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.claude/sweep-security-state.csv +0 -0
  115. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.codex/commands/backend-parity.md +0 -0
  116. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.codex/commands/bench.md +0 -0
  117. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.codex/commands/dask-notebook.md +0 -0
  118. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.codex/commands/deep-sweep.md +0 -0
  119. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.codex/commands/efficiency-audit.md +0 -0
  120. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.codex/commands/new-issues.md +0 -0
  121. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.codex/commands/ready-to-merge.md +0 -0
  122. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.codex/commands/release-major.md +0 -0
  123. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.codex/commands/release-minor.md +0 -0
  124. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.codex/commands/release-patch.md +0 -0
  125. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.codex/commands/review-contributor-pr.md +0 -0
  126. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.codex/commands/review-pr.md +0 -0
  127. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.codex/commands/rockout.md +0 -0
  128. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.codex/commands/sweep-accuracy.md +0 -0
  129. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.codex/commands/sweep-api-consistency.md +0 -0
  130. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.codex/commands/sweep-metadata.md +0 -0
  131. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.codex/commands/sweep-performance.md +0 -0
  132. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.codex/commands/sweep-security.md +0 -0
  133. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.codex/commands/sweep-style.md +0 -0
  134. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.codex/commands/sweep-test-coverage.md +0 -0
  135. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.codex/commands/user-guide-notebook.md +0 -0
  136. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.codex/commands/validate.md +0 -0
  137. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.codex/sweep-accuracy-state.csv +0 -0
  138. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.codex/sweep-api-consistency-state.csv +0 -0
  139. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.codex/sweep-metadata-state.csv +0 -0
  140. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.codex/sweep-performance-state.csv +0 -0
  141. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.codex/sweep-security-state.csv +0 -0
  142. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.codex/sweep-style-state.csv +0 -0
  143. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.codex/sweep-test-coverage-state.csv +0 -0
  144. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.efficiency-audit-baseline.json +0 -0
  145. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.efficiency-audit-baseline.prev.json +0 -0
  146. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  147. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.github/ISSUE_TEMPLATE/feature-proposal.md +0 -0
  148. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.github/ISSUE_TEMPLATE/new-contributor.md +0 -0
  149. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.github/labeler.yml +0 -0
  150. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.github/pull_request_template.md +0 -0
  151. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.github/workflows/benchmarks.yml +0 -0
  152. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.github/workflows/copilot-review.yml +0 -0
  153. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.github/workflows/labeler.yml +0 -0
  154. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.github/workflows/pypi-publish.yml +0 -0
  155. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.github/workflows/test-cog-validator.yml +0 -0
  156. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.github/workflows/test-geotiff-corpus.yml +0 -0
  157. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.github/workflows/test.yml +0 -0
  158. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.github/workflows/welcome-contributor.yml +0 -0
  159. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.gitignore +0 -0
  160. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.kilo/command/backend-parity.md +0 -0
  161. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.kilo/command/bench.md +0 -0
  162. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.kilo/command/dask-notebook.md +0 -0
  163. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.kilo/command/deep-sweep.md +0 -0
  164. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.kilo/command/efficiency-audit.md +0 -0
  165. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.kilo/command/new-issues.md +0 -0
  166. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.kilo/command/ready-to-merge.md +0 -0
  167. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.kilo/command/release-major.md +0 -0
  168. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.kilo/command/release-minor.md +0 -0
  169. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.kilo/command/release-patch.md +0 -0
  170. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.kilo/command/review-contributor-pr.md +0 -0
  171. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.kilo/command/review-pr.md +0 -0
  172. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.kilo/command/rockout.md +0 -0
  173. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.kilo/command/sweep-accuracy.md +0 -0
  174. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.kilo/command/sweep-api-consistency.md +0 -0
  175. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.kilo/command/sweep-metadata.md +0 -0
  176. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.kilo/command/sweep-performance.md +0 -0
  177. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.kilo/command/sweep-security.md +0 -0
  178. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.kilo/command/sweep-style.md +0 -0
  179. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.kilo/command/sweep-test-coverage.md +0 -0
  180. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.kilo/command/user-guide-notebook.md +0 -0
  181. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.kilo/command/validate.md +0 -0
  182. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.kilo/sweep-accuracy-state.csv +0 -0
  183. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.kilo/sweep-api-consistency-state.csv +0 -0
  184. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.kilo/sweep-metadata-state.csv +0 -0
  185. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.kilo/sweep-performance-state.csv +0 -0
  186. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.kilo/sweep-security-state.csv +0 -0
  187. {xarray_spatial-0.10.5/.claude → xarray_spatial-0.10.6/.kilo}/sweep-style-state.csv +0 -0
  188. {xarray_spatial-0.10.5/.claude → xarray_spatial-0.10.6/.kilo}/sweep-test-coverage-state.csv +0 -0
  189. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/.readthedocs.yml +0 -0
  190. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/AI_POLICY.md +0 -0
  191. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/CLAUDE.md +0 -0
  192. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/CODE_OF_CONDUCT.md +0 -0
  193. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/CONTRIBUTING.md +0 -0
  194. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/Citation-styles.md +0 -0
  195. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/LICENSE.txt +0 -0
  196. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/MANIFEST.in +0 -0
  197. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/README.md +0 -0
  198. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/RELEASE.md +0 -0
  199. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/codecov.yml +0 -0
  200. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/pyproject.toml +0 -0
  201. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/setup.cfg +0 -0
  202. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/setup.py +0 -0
  203. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xarray_spatial.egg-info/dependency_links.txt +0 -0
  204. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xarray_spatial.egg-info/entry_points.txt +0 -0
  205. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xarray_spatial.egg-info/not-zip-safe +0 -0
  206. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xarray_spatial.egg-info/requires.txt +0 -0
  207. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xarray_spatial.egg-info/top_level.txt +0 -0
  208. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/__main__.py +0 -0
  209. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/accessor.py +0 -0
  210. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/analytics.py +0 -0
  211. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/balanced_allocation.py +0 -0
  212. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/bilateral.py +0 -0
  213. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/bump.py +0 -0
  214. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/classify.py +0 -0
  215. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/convolution.py +0 -0
  216. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/corridor.py +0 -0
  217. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/cost_distance.py +0 -0
  218. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/curvature.py +0 -0
  219. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/dasymetric.py +0 -0
  220. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/dataset_support.py +0 -0
  221. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/datasets/__init__.py +0 -0
  222. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/datasets/sentinel-2/blue_band.nc +0 -0
  223. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/datasets/sentinel-2/green_band.nc +0 -0
  224. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/datasets/sentinel-2/nir_band.nc +0 -0
  225. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/datasets/sentinel-2/red_band.nc +0 -0
  226. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/datasets/sentinel-2/swir1_band.nc +0 -0
  227. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/datasets/sentinel-2/swir2_band.nc +0 -0
  228. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/diagnostics.py +0 -0
  229. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/diffusion.py +0 -0
  230. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/edge_detection.py +0 -0
  231. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/erosion.py +0 -0
  232. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/experimental/__init__.py +0 -0
  233. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/experimental/min_observable_height.py +0 -0
  234. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/fire.py +0 -0
  235. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/flood.py +0 -0
  236. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/focal.py +0 -0
  237. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geodesic.py +0 -0
  238. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/__init__.py +0 -0
  239. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/_attrs.py +0 -0
  240. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/_backends/__init__.py +0 -0
  241. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/_backends/_gpu_helpers.py +0 -0
  242. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/_backends/dask.py +0 -0
  243. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/_backends/gpu.py +0 -0
  244. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/_backends/vrt.py +0 -0
  245. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/_compression.py +0 -0
  246. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/_coords.py +0 -0
  247. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/_crs.py +0 -0
  248. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/_decode.py +0 -0
  249. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/_dtypes.py +0 -0
  250. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/_encode.py +0 -0
  251. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/_errors.py +0 -0
  252. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/_geotags.py +0 -0
  253. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/_gpu_decode.py +0 -0
  254. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/_header.py +0 -0
  255. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/_layout.py +0 -0
  256. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/_nodata.py +0 -0
  257. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/_overview.py +0 -0
  258. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/_overview_kernels.py +0 -0
  259. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/_reader.py +0 -0
  260. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/_runtime.py +0 -0
  261. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/_safe_xml.py +0 -0
  262. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/_sources.py +0 -0
  263. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/_validation.py +0 -0
  264. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/_vrt.py +0 -0
  265. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/_vrt_validation.py +0 -0
  266. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/_write_layout.py +0 -0
  267. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/_writers/__init__.py +0 -0
  268. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/_writers/gpu.py +0 -0
  269. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/_writers/vrt.py +0 -0
  270. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/__init__.py +0 -0
  271. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/_geotiff_fixtures.py +0 -0
  272. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/_helpers/__init__.py +0 -0
  273. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/_helpers/markers.py +0 -0
  274. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/_helpers/tiff_builders.py +0 -0
  275. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/_helpers/tiff_surgery.py +0 -0
  276. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/attrs/__init__.py +0 -0
  277. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/attrs/test_contract.py +0 -0
  278. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/bench_vs_rioxarray.py +0 -0
  279. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/conftest.py +0 -0
  280. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/golden_corpus/README.md +0 -0
  281. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/golden_corpus/__init__.py +0 -0
  282. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/golden_corpus/_marks.py +0 -0
  283. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/golden_corpus/_oracle.py +0 -0
  284. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/golden_corpus/fixtures/cog_internal_overview_uint16.tif +0 -0
  285. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/golden_corpus/fixtures/compression_deflate_predictor2_uint16.tif +0 -0
  286. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/golden_corpus/fixtures/compression_deflate_predictor3_float32.tif +0 -0
  287. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/golden_corpus/fixtures/compression_jpeg_uint8_ycbcr.tif +0 -0
  288. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/golden_corpus/fixtures/compression_lerc_float32.tif +0 -0
  289. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/golden_corpus/fixtures/compression_lzw_predictor2_int16.tif +0 -0
  290. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/golden_corpus/fixtures/compression_none_uint8.tif +0 -0
  291. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/golden_corpus/fixtures/crs_citation_only.tif +0 -0
  292. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/golden_corpus/fixtures/crs_epsg_3857.tif +0 -0
  293. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/golden_corpus/fixtures/crs_wkt_utm10n.tif +0 -0
  294. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/golden_corpus/fixtures/dtype_float32.tif +0 -0
  295. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/golden_corpus/fixtures/dtype_float64.tif +0 -0
  296. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/golden_corpus/fixtures/dtype_int16.tif +0 -0
  297. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/golden_corpus/fixtures/dtype_int32.tif +0 -0
  298. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/golden_corpus/fixtures/dtype_int8.tif +0 -0
  299. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/golden_corpus/fixtures/dtype_uint16.tif +0 -0
  300. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/golden_corpus/fixtures/dtype_uint32.tif +0 -0
  301. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/golden_corpus/fixtures/dtype_uint8.tif +0 -0
  302. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/golden_corpus/fixtures/extra_tags_uint16.tif +0 -0
  303. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/golden_corpus/fixtures/gdal_metadata_namespaced_uint16.tif +0 -0
  304. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/golden_corpus/fixtures/nodata_int_sentinel_uint16.tif +0 -0
  305. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/golden_corpus/fixtures/nodata_miniswhite_uint8.tif +0 -0
  306. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/golden_corpus/fixtures/nodata_nan_float32.tif +0 -0
  307. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/golden_corpus/fixtures/overview_external_ovr_uint16.tif +0 -0
  308. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/golden_corpus/fixtures/overview_external_ovr_uint16.tif.ovr +0 -0
  309. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/golden_corpus/fixtures/overview_internal_uint16.tif +0 -0
  310. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/golden_corpus/fixtures/planar_separate_uint8_rgb.tif +0 -0
  311. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/golden_corpus/fixtures/sparse_tiled_uint16.tif +0 -0
  312. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/golden_corpus/fixtures/stripped_be_uint16.tif +0 -0
  313. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/golden_corpus/fixtures/stripped_le_uint16.tif +0 -0
  314. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/golden_corpus/fixtures/tiled_be_uint16.tif +0 -0
  315. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/golden_corpus/fixtures/tiled_le_uint16.tif +0 -0
  316. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/golden_corpus/generate.py +0 -0
  317. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/golden_corpus/manifest.yaml +0 -0
  318. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/golden_corpus/test_compression.py +0 -0
  319. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/golden_corpus/test_corpus_determinism.py +0 -0
  320. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/golden_corpus/test_dtype_variants.py +0 -0
  321. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/golden_corpus/test_eager_numpy.py +0 -0
  322. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/golden_corpus/test_http.py +0 -0
  323. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/golden_corpus/test_layout_endian.py +0 -0
  324. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/golden_corpus/test_manifest.py +0 -0
  325. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/golden_corpus/test_metadata_tags.py +0 -0
  326. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/golden_corpus/test_nodata_sentinels.py +0 -0
  327. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/golden_corpus/test_oracle.py +0 -0
  328. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/golden_corpus/test_overview_cog.py +0 -0
  329. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/golden_corpus/test_vrt.py +0 -0
  330. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/gpu/__init__.py +0 -0
  331. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/gpu/test_codec.py +0 -0
  332. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/gpu/test_kernels_and_kwargs.py +0 -0
  333. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/gpu/test_reader.py +0 -0
  334. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/gpu/test_writer.py +0 -0
  335. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/integration/__init__.py +0 -0
  336. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/integration/test_dask_pipeline.py +0 -0
  337. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/integration/test_gpu_pipeline.py +0 -0
  338. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/integration/test_http_sources.py +0 -0
  339. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/parity/__init__.py +0 -0
  340. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/parity/test_backend_matrix.py +0 -0
  341. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/parity/test_finalization.py +0 -0
  342. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/parity/test_pixel_equality.py +0 -0
  343. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/parity/test_reference.py +0 -0
  344. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/parity/test_signature_contract.py +0 -0
  345. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/read/__init__.py +0 -0
  346. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/read/test_basic.py +0 -0
  347. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/read/test_bbox_2555.py +0 -0
  348. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/read/test_bbox_vrt_2668.py +0 -0
  349. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/read/test_compression.py +0 -0
  350. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/read/test_coords.py +0 -0
  351. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/read/test_crs.py +0 -0
  352. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/read/test_degenerate_shapes.py +0 -0
  353. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/read/test_dtypes.py +0 -0
  354. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/read/test_endianness.py +0 -0
  355. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/read/test_georef.py +0 -0
  356. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/read/test_nodata.py +0 -0
  357. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/read/test_overview.py +0 -0
  358. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/read/test_rioxarray_compat_2961.py +0 -0
  359. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/read/test_streaming.py +0 -0
  360. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/read/test_tiling.py +0 -0
  361. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/release_gates/__init__.py +0 -0
  362. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/release_gates/test_features.py +0 -0
  363. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/release_gates/test_stable_features.py +0 -0
  364. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/test_edge_cases.py +0 -0
  365. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/test_fuzz_hypothesis.py +0 -0
  366. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/test_polish.py +0 -0
  367. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/test_round_trip.py +0 -0
  368. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/test_security.py +0 -0
  369. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/test_shutdown_cleanup_2486.py +0 -0
  370. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/test_stable_only_bbox_ordering_2869.py +0 -0
  371. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/test_stable_only_remote_2821.py +0 -0
  372. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/unit/__init__.py +0 -0
  373. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/unit/test_codec_roundtrip.py +0 -0
  374. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/unit/test_compression.py +0 -0
  375. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/unit/test_geotags.py +0 -0
  376. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/unit/test_header.py +0 -0
  377. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/unit/test_ifd.py +0 -0
  378. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/unit/test_input_validation.py +0 -0
  379. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/unit/test_metadata.py +0 -0
  380. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/unit/test_photometric.py +0 -0
  381. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/unit/test_predictor.py +0 -0
  382. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/unit/test_safe_xml.py +0 -0
  383. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/unit/test_signatures.py +0 -0
  384. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/vrt/__init__.py +0 -0
  385. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/vrt/test_dtype_conversion.py +0 -0
  386. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/vrt/test_metadata.py +0 -0
  387. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/vrt/test_missing_sources.py +0 -0
  388. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/vrt/test_parity.py +0 -0
  389. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/vrt/test_source_opt_ins_2672.py +0 -0
  390. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/vrt/test_validation.py +0 -0
  391. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/vrt/test_window.py +0 -0
  392. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/write/__init__.py +0 -0
  393. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/write/test_bigtiff.py +0 -0
  394. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/write/test_cog.py +0 -0
  395. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/write/test_crs.py +0 -0
  396. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/write/test_nodata.py +0 -0
  397. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/geotiff/tests/write/test_overview.py +0 -0
  398. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/glcm.py +0 -0
  399. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/gpu_rtx/__init__.py +0 -0
  400. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/gpu_rtx/_memory.py +0 -0
  401. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/gpu_rtx/cuda_utils.py +0 -0
  402. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/gpu_rtx/hillshade.py +0 -0
  403. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/gpu_rtx/mesh_utils.py +0 -0
  404. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/gpu_rtx/viewshed.py +0 -0
  405. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/hillshade.py +0 -0
  406. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/hydro/__init__.py +0 -0
  407. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/hydro/_boundary_store.py +0 -0
  408. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/hydro/basin_d8.py +0 -0
  409. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/hydro/fill_d8.py +0 -0
  410. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/hydro/flow_accumulation_d8.py +0 -0
  411. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/hydro/flow_accumulation_dinf.py +0 -0
  412. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/hydro/flow_accumulation_mfd.py +0 -0
  413. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/hydro/flow_direction_d8.py +0 -0
  414. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/hydro/flow_direction_dinf.py +0 -0
  415. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/hydro/flow_direction_mfd.py +0 -0
  416. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/hydro/flow_length_d8.py +0 -0
  417. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/hydro/flow_length_dinf.py +0 -0
  418. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/hydro/flow_length_mfd.py +0 -0
  419. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/hydro/flow_path_d8.py +0 -0
  420. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/hydro/flow_path_mfd.py +0 -0
  421. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/hydro/hand_d8.py +0 -0
  422. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/hydro/hand_dinf.py +0 -0
  423. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/hydro/hand_mfd.py +0 -0
  424. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/hydro/sink_d8.py +0 -0
  425. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/hydro/snap_pour_point_d8.py +0 -0
  426. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/hydro/stream_link_d8.py +0 -0
  427. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/hydro/stream_link_dinf.py +0 -0
  428. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/hydro/stream_order_d8.py +0 -0
  429. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/hydro/stream_order_dinf.py +0 -0
  430. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/hydro/tests/__init__.py +0 -0
  431. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/hydro/tests/conftest.py +0 -0
  432. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/hydro/tests/test_basin_d8.py +0 -0
  433. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/hydro/tests/test_fill_d8.py +0 -0
  434. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/hydro/tests/test_flow_accumulation_d8.py +0 -0
  435. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/hydro/tests/test_flow_accumulation_dinf.py +0 -0
  436. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/hydro/tests/test_flow_accumulation_mfd.py +0 -0
  437. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/hydro/tests/test_flow_direction_d8.py +0 -0
  438. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/hydro/tests/test_flow_direction_dinf.py +0 -0
  439. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/hydro/tests/test_flow_direction_mfd.py +0 -0
  440. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/hydro/tests/test_flow_length_d8.py +0 -0
  441. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/hydro/tests/test_flow_length_dinf.py +0 -0
  442. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/hydro/tests/test_flow_length_mfd.py +0 -0
  443. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/hydro/tests/test_flow_path_d8.py +0 -0
  444. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/hydro/tests/test_flow_path_mfd.py +0 -0
  445. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/hydro/tests/test_hand_d8.py +0 -0
  446. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/hydro/tests/test_hand_dinf.py +0 -0
  447. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/hydro/tests/test_hand_mfd.py +0 -0
  448. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/hydro/tests/test_sink_d8.py +0 -0
  449. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/hydro/tests/test_snap_pour_point_d8.py +0 -0
  450. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/hydro/tests/test_stream_link_d8.py +0 -0
  451. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/hydro/tests/test_stream_link_dinf.py +0 -0
  452. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/hydro/tests/test_stream_order_d8.py +0 -0
  453. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/hydro/tests/test_stream_order_dinf.py +0 -0
  454. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/hydro/tests/test_twi_d8.py +0 -0
  455. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/hydro/tests/test_validate_cellsize.py +0 -0
  456. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/hydro/tests/test_validate_mfd_companion_shape.py +0 -0
  457. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/hydro/tests/test_validate_mfd_fractions.py +0 -0
  458. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/hydro/tests/test_validate_scalar_params.py +0 -0
  459. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/hydro/tests/test_validate_secondary_args.py +0 -0
  460. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/hydro/tests/test_watershed_d8.py +0 -0
  461. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/hydro/tests/test_watershed_dinf.py +0 -0
  462. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/hydro/tests/test_watershed_mfd.py +0 -0
  463. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/hydro/twi_d8.py +0 -0
  464. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/hydro/watershed_d8.py +0 -0
  465. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/hydro/watershed_dinf.py +0 -0
  466. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/hydro/watershed_mfd.py +0 -0
  467. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/interpolate/__init__.py +0 -0
  468. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/interpolate/_idw.py +0 -0
  469. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/interpolate/_kriging.py +0 -0
  470. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/interpolate/_spline.py +0 -0
  471. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/interpolate/_validation.py +0 -0
  472. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/kde.py +0 -0
  473. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/mahalanobis.py +0 -0
  474. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/mcda/__init__.py +0 -0
  475. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/mcda/combine.py +0 -0
  476. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/mcda/constrain.py +0 -0
  477. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/mcda/sensitivity.py +0 -0
  478. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/mcda/standardize.py +0 -0
  479. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/mcda/weights.py +0 -0
  480. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/morphology.py +0 -0
  481. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/multispectral.py +0 -0
  482. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/normalize.py +0 -0
  483. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/pathfinding.py +0 -0
  484. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/perlin.py +0 -0
  485. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/polygon_clip.py +0 -0
  486. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/preview.py +0 -0
  487. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/proximity.py +0 -0
  488. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/rasterize.py +0 -0
  489. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/reproject/_crs_utils.py +0 -0
  490. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/reproject/_interpolate.py +0 -0
  491. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/reproject/_lite_crs.py +0 -0
  492. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/reproject/_transform.py +0 -0
  493. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/reproject/_vertical.py +0 -0
  494. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/reproject/grids/us_nga_egm96_15.tif +0 -0
  495. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/resample.py +0 -0
  496. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/sieve.py +0 -0
  497. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/sky_view_factor.py +0 -0
  498. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/slope.py +0 -0
  499. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/surface_distance.py +0 -0
  500. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/terrain.py +0 -0
  501. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/terrain_metrics.py +0 -0
  502. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/__init__.py +0 -0
  503. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/bench_reproject_vs_rioxarray.py +0 -0
  504. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/conftest.py +0 -0
  505. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/general_checks.py +0 -0
  506. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_accessor.py +0 -0
  507. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_analytics.py +0 -0
  508. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_balanced_allocation.py +0 -0
  509. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_bilateral.py +0 -0
  510. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_bump.py +0 -0
  511. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_classify.py +0 -0
  512. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_convolution.py +0 -0
  513. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_corridor.py +0 -0
  514. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_cost_distance.py +0 -0
  515. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_curvature.py +0 -0
  516. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_dask_cupy_gaps.py +0 -0
  517. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_dask_laziness.py +0 -0
  518. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_dasymetric.py +0 -0
  519. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_dataset_support.py +0 -0
  520. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_datasets.py +0 -0
  521. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_diagnostics.py +0 -0
  522. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_diffusion.py +0 -0
  523. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_edge_detection.py +0 -0
  524. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_erosion.py +0 -0
  525. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_fire.py +0 -0
  526. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_flood.py +0 -0
  527. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_focal.py +0 -0
  528. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_fused_overlap.py +0 -0
  529. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_geodesic_aspect.py +0 -0
  530. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_geodesic_slope.py +0 -0
  531. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_glcm.py +0 -0
  532. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_glcm_metric_order.py +0 -0
  533. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_gpu_rtx_has_rtx.py +0 -0
  534. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_gpu_rtx_memory.py +0 -0
  535. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_gpu_rtx_mesh.py +0 -0
  536. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_hillshade.py +0 -0
  537. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_hypsometric_integral.py +0 -0
  538. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_interpolation.py +0 -0
  539. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_kde.py +0 -0
  540. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_lite_crs.py +0 -0
  541. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_mahalanobis.py +0 -0
  542. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_mcda.py +0 -0
  543. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_min_observable_height.py +0 -0
  544. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_morphology.py +0 -0
  545. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_morphology_derived.py +0 -0
  546. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_multi_overlap.py +0 -0
  547. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_multispectral.py +0 -0
  548. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_normalize.py +0 -0
  549. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_northness_eastness.py +0 -0
  550. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_optional_shapely.py +0 -0
  551. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_pathfinding.py +0 -0
  552. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_perlin.py +0 -0
  553. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_polygon_clip.py +0 -0
  554. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_polygonize.py +0 -0
  555. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_polygonize_atol_rtol_backend_coverage_2026_05_27.py +0 -0
  556. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_polygonize_coverage_2026_05_19.py +0 -0
  557. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_polygonize_dask_row_batch_2608.py +0 -0
  558. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_polygonize_issue_2172.py +0 -0
  559. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_polygonize_issue_2583.py +0 -0
  560. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_polygonize_issue_2606.py +0 -0
  561. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_polygonize_issue_2666.py +0 -0
  562. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_polygonize_mask_dtype_coverage_2026_05_29.py +0 -0
  563. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_preview.py +0 -0
  564. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_proximity.py +0 -0
  565. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_rasterize.py +0 -0
  566. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_rasterize_accuracy.py +0 -0
  567. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_rasterize_all_touched_supercover_2169.py +0 -0
  568. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_rasterize_coverage_2026_05_17.py +0 -0
  569. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_rasterize_coverage_2026_05_21.py +0 -0
  570. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_rasterize_coverage_2026_05_27.py +0 -0
  571. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_rasterize_coverage_2026_05_29.py +0 -0
  572. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_rasterize_descending_x_2568.py +0 -0
  573. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_rasterize_gpu_race_2167.py +0 -0
  574. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_rasterize_nan_int_fill_2504.py +0 -0
  575. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_rasterize_nan_propagation_2255.py +0 -0
  576. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_rasterize_partial_dims_2569.py +0 -0
  577. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_rasterize_props_hoist_2506.py +0 -0
  578. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_rasterize_resolution_exact_2573.py +0 -0
  579. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_rasterize_resolution_validation_2576.py +0 -0
  580. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_rasterize_signature_annot_2250.py +0 -0
  581. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_rasterize_signed_step_2566.py +0 -0
  582. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_rasterize_tile_props_slice_2020.py +0 -0
  583. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_rechunk_no_shuffle.py +0 -0
  584. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_reproject_coverage_2026_05_27.py +0 -0
  585. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_reproject_cupy_gate_2564.py +0 -0
  586. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_resample.py +0 -0
  587. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_resample_coverage_2026_05_27.py +0 -0
  588. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_resample_cupy_agg_fallback_2615.py +0 -0
  589. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_resample_input_validation_2574.py +0 -0
  590. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_resample_irregular_coords_2663.py +0 -0
  591. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_resample_signature_annot_2544.py +0 -0
  592. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_sieve.py +0 -0
  593. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_sieve_gdal_parity.py +0 -0
  594. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_sky_view_factor.py +0 -0
  595. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_slope.py +0 -0
  596. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_surface_distance.py +0 -0
  597. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_terrain.py +0 -0
  598. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_terrain_metrics.py +0 -0
  599. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_validation.py +0 -0
  600. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_visibility.py +0 -0
  601. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_zonal.py +0 -0
  602. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/tests/test_zonal_backend_coverage_2026_05_27.py +0 -0
  603. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/visibility.py +0 -0
  604. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/worley.py +0 -0
  605. {xarray_spatial-0.10.5 → xarray_spatial-0.10.6}/xrspatial/zonal.py +0 -0
@@ -120,8 +120,8 @@ with path.open() as f:
120
120
  header = reader.fieldnames
121
121
  rows = [r for r in reader if r["module"] != "{module}"]
122
122
  def _oneline(v):
123
- # merge=union is line-based: a newline inside a quoted field splits
124
- # the record on parallel-agent merges. Force one physical line per
123
+ # Git merges these CSVs line by line, so a newline inside a quoted
124
+ # field splits the record on a merge. Force one physical line per
125
125
  # record by collapsing embedded newlines to " | ".
126
126
  return "" if v is None else str(v).replace("\r\n", " | ").replace("\r", " | ").replace("\n", " | ")
127
127
 
@@ -421,11 +421,12 @@ inspect or push them.
421
421
  per-sweep worktrees via the subagents.
422
422
  - The deliverable from the parent is: validated module, dispatch table,
423
423
  parallel agents, results table. Keep parent output concise.
424
- - Each sweep's state CSV is registered with `merge=union` in
425
- `.gitattributes`, so the N concurrent state updates auto-merge cleanly
426
- even though they all touch the same module's row in different worktrees
427
- -- the last write per row wins, which is the read-update-write semantics
428
- the sweep templates already use.
424
+ - Each sweep's state CSV uses git's default 3-way text merge (no
425
+ `merge=union`; see issue #2754). N concurrent state updates that touch
426
+ the same row surface a normal conflict rather than silently unioning
427
+ duplicate rows. Resolve by keeping one row per module (last write per
428
+ row wins), which is the read-update-write semantics the sweep templates
429
+ already use.
429
430
  - If a sweep template later changes its state-file schema or its audit
430
431
  categories, deep-sweep picks up the change automatically the next time
431
432
  it runs, because each subagent re-reads its sweep file on dispatch.
@@ -67,11 +67,13 @@ slope,2026-03-28,1042,HIGH,1;3,"optional single-line notes"
67
67
  - `notes` is CSV-quoted; newlines must be flattened to spaces on write so
68
68
  every module stays exactly one line.
69
69
 
70
- The file is registered with `merge=union` in `.gitattributes`, so two
71
- parallel sweeps touching different modules auto-merge without conflict.
72
- A transient duplicate-row state can occur after a merge if both branches
73
- modified the same module; the read-update-write cycle in step 5 keys rows
74
- by `module` and last-write-wins, so the next write cleans up.
70
+ The file uses git's default 3-way text merge (no `merge=union`; see
71
+ issue #2754). Two parallel sweeps that touch the CSV surface a normal
72
+ merge conflict rather than silently unioning duplicate rows. Resolve a
73
+ conflict by keeping one row per `module` (latest `last_inspected` wins),
74
+ a single header, and one physical line per record -- or just re-run the
75
+ read-update-write cycle in step 5, which rewrites the whole canonical
76
+ file.
75
77
 
76
78
  ## Step 3 -- Score each module
77
79
 
@@ -264,8 +266,8 @@ If CUDA_AVAILABLE is false:
264
266
  }
265
267
 
266
268
  def _oneline(v):
267
- # merge=union is line-based: a newline inside a quoted field splits
268
- # the record on parallel-agent merges. Force one physical line per
269
+ # Git merges these CSVs line by line, so a newline inside a quoted
270
+ # field splits the record on a merge. Force one physical line per
269
271
  # record by collapsing embedded newlines to " | ".
270
272
  return "" if v is None else str(v).replace("\r\n", " | ").replace("\r", " | ").replace("\n", " | ")
271
273
 
@@ -324,10 +326,11 @@ To reset all tracking: `/sweep-accuracy --reset-state`
324
326
  - Do NOT modify any source files directly. Subagents handle fixes via /rockout.
325
327
  - Keep the output concise -- the table and agent dispatch are the deliverables.
326
328
  - If $ARGUMENTS is empty, use defaults: top 3, no category filter, no exclusions.
327
- - State file (`.claude/sweep-accuracy-state.csv`) is tracked in git, with
328
- `merge=union` set in `.gitattributes` so parallel sweeps touching
329
- different modules auto-merge. Subagents must `git add` and commit it so
330
- the state update lands in the PR.
329
+ - State file (`.claude/sweep-accuracy-state.csv`) is tracked in git and uses git's
330
+ default 3-way text merge (no `merge=union`; see issue #2754), so a
331
+ concurrent change surfaces a conflict instead of silently unioning
332
+ duplicate rows. Subagents must `git add` and commit it so the state
333
+ update lands in the PR.
331
334
  - For subpackage modules (geotiff, reproject, hydro), the subagent should read
332
335
  ALL `.py` files in the subpackage directory, not just `__init__.py`.
333
336
  - Only flag patterns that are ACTUALLY present in the code. Do not report
@@ -62,7 +62,10 @@ module,last_inspected,issue,severity_max,categories_found,notes
62
62
  slope,2026-05-01,1042,HIGH,1;3,"optional single-line notes"
63
63
  ```
64
64
 
65
- The file is registered with `merge=union` in `.gitattributes`.
65
+ This file uses git's default 3-way text merge (no `merge=union`; see
66
+ issue #2754), so a concurrent change surfaces a normal conflict instead
67
+ of silently unioning duplicate rows. Keep one row per `module`, a single
68
+ header, and one physical line per record when resolving.
66
69
 
67
70
  ## Step 3 -- Score each module
68
71
 
@@ -239,8 +242,8 @@ If CUDA_AVAILABLE is false:
239
242
  }
240
243
 
241
244
  def _oneline(v):
242
- # merge=union is line-based: a newline inside a quoted field splits
243
- # the record on parallel-agent merges. Force one physical line per
245
+ # Git merges these CSVs line by line, so a newline inside a quoted
246
+ # field splits the record on a merge. Force one physical line per
244
247
  # record by collapsing embedded newlines to " | ".
245
248
  return "" if v is None else str(v).replace("\r\n", " | ").replace("\r", " | ").replace("\n", " | ")
246
249
 
@@ -285,7 +288,9 @@ To reset: `/sweep-api-consistency --reset-state`
285
288
  - If $ARGUMENTS is empty, use defaults: top 3, no category filter, no
286
289
  exclusions.
287
290
  - State file (`.claude/sweep-api-consistency-state.csv`) is tracked in
288
- git with `merge=union`.
291
+ git and uses git's default 3-way text merge (no `merge=union`; see
292
+ issue #2754), so a concurrent change surfaces a conflict instead of
293
+ silently unioning duplicate rows.
289
294
  - Renames are breaking. The fix path is a deprecation shim, not a
290
295
  hard rename, unless the function has a clearly orphan/private status.
291
296
  - False positives are worse than missed issues.
@@ -68,11 +68,13 @@ slope,2026-05-01,1042,HIGH,1;3,"optional single-line notes"
68
68
  - `notes` is CSV-quoted; newlines must be flattened to spaces on write so
69
69
  every module stays exactly one line.
70
70
 
71
- The file is registered with `merge=union` in `.gitattributes`, so two
72
- parallel sweeps touching different modules auto-merge without conflict.
73
- A transient duplicate-row state can occur after a merge if both branches
74
- modified the same module; the read-update-write cycle in step 5 keys rows
75
- by `module` and last-write-wins, so the next write cleans up.
71
+ The file uses git's default 3-way text merge (no `merge=union`; see
72
+ issue #2754). Two parallel sweeps that touch the CSV surface a normal
73
+ merge conflict rather than silently unioning duplicate rows. Resolve a
74
+ conflict by keeping one row per `module` (latest `last_inspected` wins),
75
+ a single header, and one physical line per record -- or just re-run the
76
+ read-update-write cycle in step 5, which rewrites the whole canonical
77
+ file.
76
78
 
77
79
  ## Step 3 -- Score each module
78
80
 
@@ -267,8 +269,8 @@ If CUDA_AVAILABLE is false:
267
269
  }
268
270
 
269
271
  def _oneline(v):
270
- # merge=union is line-based: a newline inside a quoted field splits
271
- # the record on parallel-agent merges. Force one physical line per
272
+ # Git merges these CSVs line by line, so a newline inside a quoted
273
+ # field splits the record on a merge. Force one physical line per
272
274
  # record by collapsing embedded newlines to " | ".
273
275
  return "" if v is None else str(v).replace("\r\n", " | ").replace("\r", " | ").replace("\n", " | ")
274
276
 
@@ -325,9 +327,10 @@ To reset all tracking: `/sweep-metadata --reset-state`
325
327
  the deliverables.
326
328
  - If $ARGUMENTS is empty, use defaults: top 3, no category filter, no
327
329
  exclusions.
328
- - State file (`.claude/sweep-metadata-state.csv`) is tracked in git, with
329
- `merge=union` set in `.gitattributes` so parallel sweeps touching
330
- different modules auto-merge.
330
+ - State file (`.claude/sweep-metadata-state.csv`) is tracked in git and uses
331
+ git's default 3-way text merge (no `merge=union`; see issue #2754), so a
332
+ concurrent change surfaces a conflict instead of silently unioning
333
+ duplicate rows.
331
334
  - For subpackage modules (geotiff, reproject, hydro), the subagent should
332
335
  read ALL `.py` files in the subpackage directory, not just `__init__.py`.
333
336
  - Only flag patterns that are ACTUALLY present in the code.
@@ -89,11 +89,13 @@ slope,2026-04-15,SAFE,compute-bound,0,,"optional single-line notes"
89
89
  - `notes` is CSV-quoted; newlines must be flattened to spaces on write so
90
90
  every module stays exactly one line.
91
91
 
92
- The file is registered with `merge=union` in `.gitattributes`, so two
93
- parallel sweeps touching different modules auto-merge without conflict.
94
- A transient duplicate-row state can occur after a merge if both branches
95
- modified the same module; the read-update-write cycle in the agent prompt
96
- keys rows by `module` and last-write-wins, so the next write cleans up.
92
+ The file uses git's default 3-way text merge (no `merge=union`; see
93
+ issue #2754). Two parallel sweeps that touch the CSV surface a normal
94
+ merge conflict rather than silently unioning duplicate rows. Resolve a
95
+ conflict by keeping one row per `module` (latest `last_inspected` wins),
96
+ a single header, and one physical line per record -- or just re-run the
97
+ read-update-write cycle in the agent prompt, which rewrites the whole
98
+ canonical file.
97
99
 
98
100
  ### Compute scores
99
101
 
@@ -290,8 +292,8 @@ If CUDA_AVAILABLE is false:
290
292
  }
291
293
 
292
294
  def _oneline(v):
293
- # merge=union is line-based: a newline inside a quoted field splits
294
- # the record on parallel-agent merges. Force one physical line per
295
+ # Git merges these CSVs line by line, so a newline inside a quoted
296
+ # field splits the record on a merge. Force one physical line per
295
297
  # record by collapsing embedded newlines to " | ".
296
298
  return "" if v is None else str(v).replace("\r\n", " | ").replace("\r", " | ").replace("\n", " | ")
297
299
 
@@ -353,10 +355,11 @@ To reset all tracking: `/sweep-performance --reset-state`
353
355
  the deliverables.
354
356
  - If $ARGUMENTS is empty, use defaults: top 3, no category filter, no
355
357
  exclusions.
356
- - State file (`.claude/sweep-performance-state.csv`) is tracked in git, with
357
- `merge=union` set in `.gitattributes` so parallel sweeps touching
358
- different modules auto-merge. Subagents must `git add` and commit it so
359
- the state update lands in the PR.
358
+ - State file (`.claude/sweep-performance-state.csv`) is tracked in git and uses git's
359
+ default 3-way text merge (no `merge=union`; see issue #2754), so a
360
+ concurrent change surfaces a conflict instead of silently unioning
361
+ duplicate rows. Subagents must `git add` and commit it so the state
362
+ update lands in the PR.
360
363
  - For subpackage modules (geotiff, reproject, hydro), the subagent reads ALL
361
364
  `.py` files in the subpackage directory, not just `__init__.py`.
362
365
  - Only flag patterns that are ACTUALLY present in the code. Do not report
@@ -71,11 +71,13 @@ cost_distance,2026-04-10,1150,HIGH,1;2,,"optional single-line notes"
71
71
  - `notes` is CSV-quoted; newlines must be flattened to spaces on write so
72
72
  every module stays exactly one line.
73
73
 
74
- The file is registered with `merge=union` in `.gitattributes`, so two
75
- parallel sweeps touching different modules auto-merge without conflict.
76
- A transient duplicate-row state can occur after a merge if both branches
77
- modified the same module; the read-update-write cycle in step 5 keys rows
78
- by `module` and last-write-wins, so the next write cleans up.
74
+ The file uses git's default 3-way text merge (no `merge=union`; see
75
+ issue #2754). Two parallel sweeps that touch the CSV surface a normal
76
+ merge conflict rather than silently unioning duplicate rows. Resolve a
77
+ conflict by keeping one row per `module` (latest `last_inspected` wins),
78
+ a single header, and one physical line per record -- or just re-run the
79
+ read-update-write cycle in step 5, which rewrites the whole canonical
80
+ file.
79
81
 
80
82
  ## Step 3 -- Score each module
81
83
 
@@ -265,8 +267,8 @@ If CUDA_AVAILABLE is false:
265
267
  }
266
268
 
267
269
  def _oneline(v):
268
- # merge=union is line-based: a newline inside a quoted field splits
269
- # the record on parallel-agent merges. Force one physical line per
270
+ # Git merges these CSVs line by line, so a newline inside a quoted
271
+ # field splits the record on a merge. Force one physical line per
270
272
  # record by collapsing embedded newlines to " | ".
271
273
  return "" if v is None else str(v).replace("\r\n", " | ").replace("\r", " | ").replace("\n", " | ")
272
274
 
@@ -323,10 +325,11 @@ To reset all tracking: `/sweep-security --reset-state`
323
325
  - Do NOT modify any source files directly. Subagents handle fixes via /rockout.
324
326
  - Keep the output concise -- the table and agent dispatch are the deliverables.
325
327
  - If $ARGUMENTS is empty, use defaults: top 3, no category filter, no exclusions.
326
- - State file (`.claude/sweep-security-state.csv`) is tracked in git, with
327
- `merge=union` set in `.gitattributes` so parallel sweeps touching
328
- different modules auto-merge. Subagents must `git add` and commit it so
329
- the state update lands in the PR.
328
+ - State file (`.claude/sweep-security-state.csv`) is tracked in git and uses
329
+ git's default 3-way text merge (no `merge=union`; see issue #2754), so a
330
+ concurrent change surfaces a conflict instead of silently unioning
331
+ duplicate rows. Subagents must `git add` and commit it so the state
332
+ update lands in the PR.
330
333
  - For subpackage modules (geotiff, reproject, hydro), the subagent should read
331
334
  ALL `.py` files in the subpackage directory, not just `__init__.py`.
332
335
  - Only flag patterns that are ACTUALLY present in the code. Do not report
@@ -58,12 +58,13 @@ slope,2026-05-01,1042,MEDIUM,1;4,"optional single-line notes"
58
58
  - `notes` is CSV-quoted; newlines must be flattened to spaces on write so
59
59
  every module stays exactly one line.
60
60
 
61
- The file is covered by the `.claude/sweep-*-state.csv merge=union` rule in
62
- `.gitattributes`, so two parallel sweeps touching different modules
63
- auto-merge without conflict. A transient duplicate-row state can occur
64
- after a merge if both branches modified the same module; the
65
- read-update-write cycle in step 5 keys rows by `module` and last-write-wins,
66
- so the next write cleans up.
61
+ The file uses git's default 3-way text merge (no `merge=union`; see
62
+ issue #2754). Two parallel sweeps that touch the CSV surface a normal
63
+ merge conflict rather than silently unioning duplicate rows. Resolve a
64
+ conflict by keeping one row per `module` (latest `last_inspected` wins),
65
+ a single header, and one physical line per record -- or just re-run the
66
+ read-update-write cycle in step 5, which rewrites the whole canonical
67
+ file.
67
68
 
68
69
  ## Step 3 -- Score each module
69
70
 
@@ -302,10 +303,11 @@ To reset all tracking: `/sweep-style --reset-state`
302
303
  - Do NOT modify any source files directly. Subagents handle fixes via /rockout.
303
304
  - Keep the output concise -- the table and agent dispatch are the deliverables.
304
305
  - If $ARGUMENTS is empty, use defaults: top 3, no category filter, no exclusions.
305
- - State file (`.claude/sweep-style-state.csv`) is tracked in git, covered by
306
- the `.claude/sweep-*-state.csv merge=union` rule in `.gitattributes` so
307
- parallel sweeps touching different modules auto-merge. Subagents must
308
- `git add` and commit it so the state update lands in the PR.
306
+ - State file (`.claude/sweep-style-state.csv`) is tracked in git and uses
307
+ git's default 3-way text merge (no `merge=union`; see issue #2754), so a
308
+ concurrent change surfaces a conflict instead of silently unioning
309
+ duplicate rows. Subagents must `git add` and commit it so the state
310
+ update lands in the PR.
309
311
  - For subpackage modules (geotiff, reproject, hydro), the subagent should run
310
312
  flake8 + isort across ALL `.py` files in the subpackage directory, not
311
313
  just `__init__.py`.
@@ -63,7 +63,10 @@ module,last_inspected,issue,severity_max,categories_found,notes
63
63
  slope,2026-05-01,1042,HIGH,1;3,"optional single-line notes"
64
64
  ```
65
65
 
66
- `merge=union` is set in `.gitattributes`.
66
+ This file uses git's default 3-way text merge (no `merge=union`; see
67
+ issue #2754), so a concurrent change surfaces a normal conflict instead
68
+ of silently unioning duplicate rows. Keep one row per `module`, a single
69
+ header, and one physical line per record when resolving.
67
70
 
68
71
  ## Step 3 -- Score each module
69
72
 
@@ -240,8 +243,8 @@ If CUDA_AVAILABLE is false:
240
243
  }
241
244
 
242
245
  def _oneline(v):
243
- # merge=union is line-based: a newline inside a quoted field splits
244
- # the record on parallel-agent merges. Force one physical line per
246
+ # Git merges these CSVs line by line, so a newline inside a quoted
247
+ # field splits the record on a merge. Force one physical line per
245
248
  # record by collapsing embedded newlines to " | ".
246
249
  return "" if v is None else str(v).replace("\r\n", " | ").replace("\r", " | ").replace("\n", " | ")
247
250
 
@@ -287,7 +290,9 @@ To reset: `/sweep-test-coverage --reset-state`
287
290
  - Keep parent output concise.
288
291
  - Default: top 3, no filter.
289
292
  - State file `.claude/sweep-test-coverage-state.csv` is tracked in git
290
- with `merge=union`.
293
+ and uses git's default 3-way text merge (no `merge=union`; see issue
294
+ #2754), so a concurrent change surfaces a conflict instead of silently
295
+ unioning duplicate rows.
291
296
  - The "fix" is *tests, not source*. If a test reveals a bug, file a
292
297
  separate issue — do not change source in this sweep's PRs.
293
298
  - False positives are worse than missed issues.
@@ -8,6 +8,7 @@ interpolate-kriging,2026-06-04,2916,MEDIUM,1;4,"flake8 E128 x2: continuation-lin
8
8
  polygonize,2026-05-27,2534,HIGH,1;3;4,"F401 line 58 (is_cupy_array unused, not re-exported). E127 lines 83/88 (overload continuation indent in generated_jit). isort: 5-line .utils import block collapses to one line at 100-char limit. Cat 2 clean. Cat 5 grep clean."
9
9
  proximity,2026-05-29,2725,HIGH,1;3;4;5,"F841 line 1274 original_chunks dead local in unbounded dask+cupy branch (refactor leftover). Cat 5 mutable default target_values: list = [] in proximity/allocation/direction -> None sentinel, normalized to [] in body (never mutated, behaviour preserved). E128 line 291 np.where continuation under-indent in _vectorized_calc_direction. isort: re-sorted xrspatial import block + blank line after inline import cupy as cp. flake8+isort clean after fix; 69 proximity tests pass + new parametrized regression test. Pre-existing E127 (test_proximity.py 726/752) + test-file isort drift left untouched (out of module scope)."
10
10
  rasterize,2026-05-27,2503,HIGH,1;3,F401 line 15 + F811 line 1193 (paired: local import warnings shadowed unused module-level import); E306 line 1775 (nested @cuda.jit). isort clean. Cat 5 grep clean. Fix in PR #2507.
11
+ reproject,2026-06-08,3049,HIGH,1;2;3;4,"flake8 baseline 57 across the 10 reproject files. Cat 3 HIGH: F401 'numpy as np' unused in _projections_cuda.py; F841 nine dead locals in _projections.py (e12, m2 chained-assign, phi_approx, a, two half_e, t_90, south_f, Q) - all assigned-never-read, math unchanged. Cat 1: E702 semicolon statements split (_projections.py + _projections_cuda.py Clenshaw loops); E127/E128 continuation indents fixed across both files; E302 blank line added in _itrf.py and _projections.py; E501 x3 wrapped. Two dense polynomial-coefficient continuation lines in _projections.py keep noqa: E128 (visual-indent alignment hits col 60 -> E501). Cat 2: W391 trailing blank removed from _projections.py. Cat 4 isort: _grid.py/_merge.py blank-line trim + deferred-import re-sort in _projections_cuda.py. Cat 5 grep clean (d: dict annotation is not a shadow; no bare except / mutable defaults / ==None,True,False). flake8+isort clean after fix; 435 reproject tests pass on numpy/dask/cupy. PR open."
11
12
  resample,2026-05-27,2543,MEDIUM,4,isort drift only: 4 multi-line parenthesised imports collapsed to single/one-per-line under line_length=100 (top-of-file scipy.ndimage + xrspatial.utils; local cupyx imports in _nan_aware_interp_cupy and _interp_block_cupy); two blank-line nits after import math in _run_dask_numpy/_run_dask_cupy. flake8 clean. Cat 5 grep clean. 169 resample tests pass.
12
13
  slope,2026-05-29,2685,HIGH,1;3;4,"F401 line 26 (VALID_BOUNDARY_MODES unused, not re-exported). E402+E305 line 48 (geodesic import block sat after _geodesic_cuda_dims; moved up to top-of-file imports). E501 line 260 (cupy kernel launch, 108 chars) wrapped. isort: consolidated/regrouped xrspatial imports (dataset_support, geodesic, utils). Cat 2 clean. Cat 5 grep clean. 41 slope + 21 geodesic_slope tests pass."
13
14
  viewshed,2026-05-29,2690,HIGH,1;4;5,"flake8 E127 x2 (L2013-2014 _viewshed_distance_sweep sig); isort .utils import reflow; shadowed builtin id->node_id (L1409,1474). Fixed via /rockout PR. No behavioural change."
@@ -1,16 +1,15 @@
1
1
  module,last_inspected,issue,severity_max,categories_found,notes
2
2
  aspect,2026-06-02,2742;2829,HIGH,3;4,"#2742: degenerate shapes (1x1/Nx1/1xN) + geodesic boundary modes; tests added all 4 backends, GPU-validated. #2829: northness/eastness method='geodesic' branch was untested (planar only); added correctness (diagonal surface where planar!=geodesic) + 4-backend parity, GPU-validated. all-NaN planar/geodesic returns all-NaN (correct). Inf input -> silent -1/flat on spike cell: possible source bug, out of scope for test-only sweep, not filed. Dedup: rectangular-cell oracle #2781 + cell-size #2780 already merged, not duplicated."
3
- contour,2026-05-29,2704;2710,HIGH,2;5,"Pass 1 (2026-05-29): added TestInfHandling, TestCRSPropagation, TestNonDefaultDims to test_contour.py (5 passed + 2 strict-xfail on a CUDA host; full file 29 passed, 2 xfailed). All four backends (numpy / cupy / dask+numpy / dask+cupy) were already exercised with cross-backend segment-equality assertions (TestBackendEquivalence), and ran green locally on the CUDA host -- Cat 1 well covered, no new backend tests needed. Cat 2 HIGH (Inf): the marching-squares NaN-skip guard at contour.py:67 uses x!=x which does not catch infinity, so a finite level near a +/-inf corner leaks NaN coordinates into the output. Filed source bug #2704 and added two xfail(strict=True) tests pinning it (+inf and -inf) plus test_inf_far_level_no_crossing covering the safe path where the inf quad classifies as all-above (idx 15) and is skipped before any interpolation. Cat 5 MEDIUM: no test asserted gdf.crs propagation from agg.attrs['crs'] (contour.py:660) -- added test_geopandas_crs_from_attrs (to_epsg()==5070) + test_geopandas_no_crs_attr. Cat 5 MEDIUM: the index-to-coordinate transform (contour.py:644-654) reads agg.dims[0]/[1] coords but no test used non-y/x dims -- added test_lat_lon_dims_coordinate_transform + test_lat_lon_matches_yx_equivalent. PR #2710 (test-only, source untouched). LOW (documented, not fixed): non-square cellsize (cellsize_x != cellsize_y) never exercised -- all tests use res (0.5,0.5); levels=None early-return on all-NaN/all-equal works (probed) but only the explicit-levels all-NaN path is asserted. Cat 3 1x1/Nx1/1xN are rejected by the >=2x2 validation guard and that rejection is already tested (test_too_small, test_minimum_raster)."
3
+ contour,2026-06-08,2704;2710;3044,MEDIUM,1;2,"Pass 2 (2026-06-08, deep-sweep test-coverage): re-swept on a CUDA host. Verified issue #2704 is CLOSED (fixed 2026-06-01 via #2749, kernel now uses np.isfinite at contour.py:73-74); the two prior xfail(strict) #2704 pins were already flipped to plain passing assertions in TestInfHandling (test_inf_corner_no_nan_coords / test_neg_inf_corner_no_nan_coords) -- no stale xfail remained. Found one MEDIUM Cat 1+2 gap: no cross-backend parity test fed NaN input -- TestBackendEquivalence uses elevation_raster_no_nans and test_partial_nan is numpy-only, so numpy-interior NaN-skip vs dask NaN-halo (da.overlap) parity at chunk edges was unpinned. Filed #3044, added TestNaNBackendParity (3 tests: dask, cupy, dask+cupy each assert _segments_by_level equality vs numpy on a partial-NaN ramp with a NaN edge row + interior NaN cell inside a non-edge chunk). All 3 RAN and PASSED on a CUDA host; full file 89 passed, 0 skipped. Probed and verified now-resolved: the prior-pass LOW items are no longer real gaps -- the levels=None all-NaN early-return IS asserted (result==[]) on all 4 backends (numpy L148/dask L163/cupy L178/dask+cupy L194) plus geopandas (test_geopandas_all_nan_keeps_crs). LOW (documented, NOT fixed): non-square cellsize (res[0]!=res[1]) still never exercised -- all tests use create_test_raster res (0.5,0.5); probed live that anisotropic coords transform correctly (y scaled 2.0, x scaled 0.5 -> crossing x=1.25, y spans 0..8), works, so it is a LOW coverage gap not a bug. Cat 3 1x1/Nx1/1xN remain rejected by the >=2x2 guard (tested). Test-only PR for #3044; contour.py untouched. | Pass 1 (2026-05-29): added TestInfHandling, TestCRSPropagation, TestNonDefaultDims to test_contour.py (5 passed + 2 strict-xfail on a CUDA host; full file 29 passed, 2 xfailed). All four backends (numpy / cupy / dask+numpy / dask+cupy) were already exercised with cross-backend segment-equality assertions (TestBackendEquivalence), and ran green locally on the CUDA host -- Cat 1 well covered, no new backend tests needed. Cat 2 HIGH (Inf): the marching-squares NaN-skip guard at contour.py:67 uses x!=x which does not catch infinity, so a finite level near a +/-inf corner leaks NaN coordinates into the output. Filed source bug #2704 and added two xfail(strict=True) tests pinning it (+inf and -inf) plus test_inf_far_level_no_crossing covering the safe path where the inf quad classifies as all-above (idx 15) and is skipped before any interpolation. Cat 5 MEDIUM: no test asserted gdf.crs propagation from agg.attrs['crs'] (contour.py:660) -- added test_geopandas_crs_from_attrs (to_epsg()==5070) + test_geopandas_no_crs_attr. Cat 5 MEDIUM: the index-to-coordinate transform (contour.py:644-654) reads agg.dims[0]/[1] coords but no test used non-y/x dims -- added test_lat_lon_dims_coordinate_transform + test_lat_lon_matches_yx_equivalent. PR #2710 (test-only, source untouched). LOW (documented, not fixed): non-square cellsize (cellsize_x != cellsize_y) never exercised -- all tests use res (0.5,0.5); levels=None early-return on all-NaN/all-equal works (probed) but only the explicit-levels all-NaN path is asserted. Cat 3 1x1/Nx1/1xN are rejected by the >=2x2 validation guard and that rejection is already tested (test_too_small, test_minimum_raster)."
4
4
  focal,2026-05-29,2732,HIGH,1,"Pass (2026-05-29): added test_hotspots_dask_cupy to test_focal.py closing Cat 1 HIGH backend-coverage gap. hotspots() registers dask_cupy_func=_hotspots_dask_cupy (focal.py L1414) but no test invoked it, while mean/apply/focal_stats each have a dedicated dask+cupy test. New test compares dask+cupy vs numpy on chunk interior (matches test_apply_dask_cupy/test_focal_stats_dask_cupy style). RUN on CUDA host: passes; spy confirmed routing through _hotspots_dask_cupy; path matches numpy exactly so no source fix needed. LOW (documented not fixed): Inf/-Inf inputs untested across focal funcs; 1x1 raster not explicitly tested for mean/apply/hotspots (focal_stats 1x1 covered by test_variety_single_cell). Issue #2732."
5
5
  geotiff,2026-06-06,2984,MEDIUM,1;3,"Pass 20 (2026-06-06, deep-sweep test-coverage): filed #2984 and added test_writer.py degenerate-shape GPU write coverage (Cat 1 backend + Cat 3 geometric edge). Read side already covers 1x1/1xN/Nx1 on all 4 backends (read/test_degenerate_shapes.py) and the dask streaming writer covers them (integration/test_dask_pipeline.py); the GPU write path was the gap (smallest shape in gpu/test_writer.py was 2x2). Added test_write_geotiff_gpu_degenerate_round_trip (1x1/1xN/Nx1 x none/deflate) + test_to_geotiff_dask_gpu_degenerate_round_trip (dask+cupy via gpu=True). 9 new tests RUN+passing on a CUDA host. Verified paths work first (not a source bug); transform supplied explicitly via attrs. Wider tree audit (~92k test LOC vs ~33k source): rioxarray-compat (#2961), bbox NaN/Inf/rotated, 8-backend parity matrix, codec round-trips already covered -- no other real gaps. | Pass (2026-06-05 test-coverage sweep): mature module (~31k src / ~124k test LOC, 9 test dirs). Exhaustive existing coverage -- parity/test_backend_matrix.py runs all 4 backends + VRT + HTTP + fsspec; golden_corpus full-manifest parity; read_rioxarray_compat_2961 covers masked/mask_and_scale/parse_coordinates/default_name on eager+dask. Cat1+Cat3 gap found (MEDIUM): degenerate-shape READS (1x1/1xN/Nx1) were tested only on the eager numpy reader (test_edge_cases.py) and the dask streaming WRITE path (integration/test_dask_pipeline.py); the windowed dask READ (chunks=) and GPU READ (gpu=True) on a single-pixel dimension were never exercised (smallest dask-read source in read/test_tiling is 8x8/2x32, parity fixtures 32x32/64x64). Probed: paths work today, no source bug -- pure coverage gap. Added read/test_degenerate_shapes.py (18 tests): dask read x{chunks 1,3,4} x{1x1,1xN,Nx1} + coord/transform/crs parity + GPU read + dask+gpu read. GPU cells RAN and PASSED on this CUDA host (grid-size-1 launch validated). Fixture supplies explicit attrs['transform'] (writer cannot infer pixel size from a 1-element coord axis). Branch deep-sweep-test-coverage-geotiff-degenerate-read-01. NOTE: pre-existing union-merge CRLF/duplicate-record corruption in this CSV left untouched -- appended one clean record; DictReader last-write-wins picks this one."
6
6
  idw,2026-06-04,2919,HIGH,1;4,"cupy/dask+cupy backends untested (Cat1 HIGH); GPU k-reject error path untested (Cat4 MED). Added 6 GPU tests, validated on CUDA host. Inf-in-points (Cat2) and attrs-preservation (Cat5) are LOW, documented not fixed."
7
7
  interpolate-kriging,2026-06-04,2920;2921,HIGH,1;2;3;4;5,"Single public fn kriging(); all 4 backends already had cross-backend parity tests (numpy/cupy/dask+numpy/dask+cupy) incl. cupy & dask+cupy variance -- ran green on CUDA host. Gaps closed (test-only, #2921): Cat1 dask+numpy return_variance branch (_chunk_var) was untested -> added test_dask_return_variance_matches_numpy (atol=1e-12, var ~1e-14). Cat4 nlags only default(15) tested -> added non-default nlags=5 + invalid paths (nlags=0/-1 ValueError, nlags=2.5 TypeError). Cat2/3 two-point <3-lag-bins UserWarning branch -> test_two_point_warns_few_lag_bins. Cat2 all-NaN kriging input -> test_kriging_all_nan_points (only idw covered before). Cat5 output metadata (coords/dims/attrs/name) untested -> added test_output_metadata. Single-point kriging CRASHES (zero-size array reduction in _experimental_variogram, N=1) -- real source bug filed #2920; added xfail(strict, raises=ValueError) test_single_point documenting expected graceful behavior; source fix left to #2920 (test-only PR). LOW/not filed: singular-matrix K_inv-is-None all-NaN branch is defensive and unreachable via public API. GPU-validated."
8
8
  interpolate_spline,2026-06-04,,HIGH,1;3;5,scope=spline-only; cupy+dask_cupy spline backends untested (_tps_cuda_kernel) | n==2 affine branch + metadata untested | added 4 tests to TestSpline all pass on CUDA host | issue-create denied by classifier no GH issue
9
- module,last_inspected,issue,severity_max,categories_found,notes
10
9
  polygonize,2026-05-29,2623,MEDIUM,4,"Pass 3 (2026-05-29): added test_polygonize_mask_dtype_coverage_2026_05_29.py (41 passed, 8 xfailed on a CUDA host). Closes Cat 4 MEDIUM parameter-coverage gap: mask= is documented to accept bool/integer/float values but every prior test passed only a bool mask. Integer masks (int32/int64) now pinned against the same-backend bool-mask output on all four backends x both raster dtypes x connectivity 4/8; float-mask-on-integer-raster also pinned. Each backend is compared to its OWN bool reference to isolate mask-dtype from the unrelated numpy-vs-dask hole-vs-single-ring representation difference. Mutation (drop the not-mask[ij] exclusion in _calculate_regions) flips 11 tests red incl. the pixel-exclusion sanity anchor; clean md5 restore. Surfaced source bug #2623: a float-dtype mask on a float-dtype raster raises TypeError at polygonize.py:918 (mask & nan_mask; bitwise_and undefined for float&bool; cupy/dask route floats through _polygonize_numpy so they crash too; int masks coerce fine). 8 float-mask cases marked xfail(strict, raises=TypeError) referencing #2623. Test-only; source untouched. | Pass 2 (2026-05-27): added test_polygonize_atol_rtol_backend_coverage_2026_05_27.py with 15 tests, all passing on a CUDA host. Closes Cat 4 MEDIUM parameter-coverage gap on atol/rtol forwarding through the cupy and dask+cupy backends. atol/rtol were exposed by #2173 / #2194 and thread through _polygonize_cupy (polygonize.py:808) and _polygonize_dask (polygonize.py:1719); the dask path further plumbs them into dask.delayed(_polygonize_chunk)(...) at lines 1748-1754 and into _bucket_key_for_value for cross-chunk merge bucketing at lines 1757-1758. Pre-existing tests covered non-default atol/rtol only on numpy and dask+numpy. The cupy and dask+cupy dispatchers were untested -- a regression dropping the kwargs there would silently change the float polygon count and would not be caught. Same dispatcher-silently-drops-kwarg pattern fixed by #1561 / #1605 / #1685 / #1810 / #1974 on adjacent GeoTIFF surfaces. 15 tests: cupy strict-equality + default-tolerance pin on _REPRO_2173, dask+cupy strict-equality single-chunk + multi-chunk (engages cross-chunk merge bucket) + default-tolerance multi-chunk pin, cupy intermediate-atol small/large pair, dask+cupy intermediate-atol single/multi-chunk small + single-chunk large, cupy integer atol-ignored matrix, dask+cupy integer atol-ignored single-chunk + multi-chunk, cupy rtol-only large/small matrix. Mutation against _polygonize_cupy float branch (drop atol/rtol kwargs in the _polygonize_numpy forward call at polygonize.py:823-825) flips 3 of 5 cupy tests red; mutation against dask.delayed(_polygonize_chunk)(...) at polygonize.py:1748-1754 (drop atol, rtol args) flips 2 of 6 dask+cupy tests red. Confirmed clean restore via md5sum. Source untouched. Filed issue #2537 (test-only). Cat 4 MEDIUM (parameter coverage on cupy + dask+cupy atol/rtol forwarding). Pass 1 (2026-05-19): added test_polygonize_coverage_2026_05_19.py with 58 tests, all passing on a CUDA host. Closes Cat 3 HIGH 1x1 / Nx1 single-column geometric gaps (Nx1 exercises the nx==1 padding path at polygonize.py:565 and the cupy nx==1 numpy-fallback at polygonize.py:671), Cat 3 MEDIUM 1xN single-row and all-equal-value rasters on all four backends. Closes Cat 2 HIGH NaN parity for cupy + dask+cupy (numpy/dask were already covered by test_polygonize_nan_pixels_excluded*), Cat 2 MEDIUM all-NaN raster on all four backends, Cat 2 HIGH +/-Inf pins on all four backends. Filed source-bug issue #2155: numpy/dask/dask+cupy backends silently absorb Inf cells into adjacent finite polygons because _is_close reduces abs(inf-inf) to nan; cupy backend handles Inf correctly. Pins lock the asymmetric behaviour so the fix is visible. Closes Cat 1 MEDIUM simplify_tolerance + mask= parity gaps on dask+cupy backend (numpy/cupy/dask were already covered). Closes Cat 4 MEDIUM column_name non-default value across geopandas/spatialpandas/geojson return types and Cat 4 MEDIUM validation error paths (bad connectivity, bad transform length, mask shape mismatch, mask underlying-type mismatch). Cat 5 N/A: polygonize returns lists/dataframes, not a DataArray with attrs to propagate."
11
10
  proximity,2026-06-02,2692,HIGH,1;2;3;4;5,"Pass 2 (2026-06-02): added 18 tests to test_proximity.py closing the two MEDIUM gaps Pass 1 left open, all RUN and passing on a CUDA host across numpy/cupy/dask+numpy/dask+cupy (15 cross-backend + 3 error-path). Source untouched. Cat 4 MEDIUM (error path): _process raises ValueError when raster.dims != (y, x) (proximity.py:1043) but no test exercised the swapped x/y guard; test_wrong_dim_order_raises pins it for proximity/allocation/direction. Cat 2 MEDIUM (all-NaN input): Pass 1 noted all-NaN/all-zero on eager numpy+cupy was unpinned; test_all_nan_raster_all_nan_output pins an all-NaN 6x6 raster -> all-NaN float32 output on all four backends x three functions. Remaining LOW (documented): invalid distance_metric string silently falls back to EUCLIDEAN (proximity.py:1049-1051). || PREVIOUS: Pass 1 (2026-05-29): added 65 tests to test_proximity.py closing three coverage gaps, all RUN and passing on a CUDA host (numpy/cupy/dask+numpy/dask+cupy). Issue #2692, PR opened. Source untouched. Cat 3 HIGH: degenerate raster shapes (1x1 single pixel, Nx1 column strip, 1xN row strip) had zero coverage for proximity/allocation/direction on any backend; they stress the line-sweep kernel boundaries (_process_proximity_line) and the GPU brute-force kernel grid sizing (_proximity_cuda_kernel via cuda_args). Pinned all three shapes x three functions x four backends against hand-checked expected values; mutation of a pinned direction expectation confirms teeth. Cat 1/4 HIGH: allocation and direction only ran EUCLIDEAN across backends; MANHATTAN and GREAT_CIRCLE were cross-backend-tested for proximity only. Pinned both metrics x two functions x four backends against the numpy baseline (all match). Cat 5 MEDIUM: no test set non-empty res/crs attrs so the attrs-preservation assertion in general_output_checks compared two empty dicts. proximity reads attrs['res'] via get_dataarray_resolution for bounded-dask chunk padding, so added attrs round-trip tests on four backends plus a bounded-dask test where a res attr matching the coordinate spacing must equal the numpy baseline. A res attr that lies about the spacing mis-sizes the map_overlap depth; source fragility, not a test gap, left for a separate accuracy issue. Cat 2 (NaN/Inf input) already covered by the shared test_raster fixture (embeds np.inf and np.nan, runs on four backends). Remaining LOW: all-NaN / all-zero input on eager numpy+cupy not directly pinned."
12
11
  rasterize,2026-05-29,2614,MEDIUM,4,"Pass 4 (2026-05-29): added test_rasterize_coverage_2026_05_29.py with 11 tests, all passing (pure-Python validation paths, no CUDA needed); filed issue #2614 and opened a test-only PR. Closes Cat 4 MEDIUM error-path gaps that all three prior passes left untouched. (1) Partial width/height: the (width is None) != (height is None) guard in rasterize() raises ValueError naming the given and missing dimension, documented in the docstring, but neither the width-only nor height-only branch had a test; pin both directions plus the width-only+resolution case proving the guard fires before the resolution branch. (2) resolution= input type/shape validation: the type/shape branches (non-number/non-sequence string|dict; wrong-ndim numpy array; wrong-length sequence len 1|3|4; non-numeric elements) had no coverage -- test_rasterize.py's test_invalid_resolution_scalar/tuple only exercise non-finite/non-positive VALUES, not these type/shape guards, so a regression loosening or reordering them would ship silently; pin each branch to its message plus a positive control that a 1-D length-2 numpy array is still accepted. Source untouched."
13
- reproject,2026-05-29,2618,HIGH,3,"Pass 2026-05-29: reproject already has a deep suite (369 tests in test_reproject.py + coverage/gate files) covering all 4 backends, NaN/Inf/all-NaN/all-Inf, 1x1/2x2, metadata, vertical shift, bounds_policy x backends, integer nodata x backends. Gaps found: Cat 3 HIGH single-row (1xN) and single-col (Nx1) strip rasters never tested (hit size<2 branch of _validate_regular_axis + degenerate resampling axis); Cat 3 MEDIUM constant-value/zero-gradient raster never reprojected. Added TestDegenerateShapeReproject (12 tests): 1xN+Nx1 strips x numpy/dask/cupy/dask+cupy, constant raster numpy value-preservation + cross-backend parity. All 12 executed and passed on a CUDA host. Test-only, no source change (#2618). LOW (documented only): _merge._merge_arrays_cupy imported but never called by merge() (host-bounces via _merge_arrays_numpy) - dead-code source observation not a test gap; non-square cellsize reproject only covered via resolution-tuple validation errors not a successful anisotropic run."
12
+ reproject,2026-06-08,2618;3050,HIGH,3;4,"Pass 2026-06-08 (deep-sweep test-coverage): #3050 closes the one live gap found this pass. reproject()'s dask+cupy backend was parity-tested only with resampling='cubic' (TestCupyPyprojFallbackParity::test_projected_to_projected_dask_cupy_match); nearest/bilinear were covered on numpy (end-to-end) and eager cupy (parametrized test_projected_to_projected_numpy_cupy_match) but never on the dask+cupy chunk-assembly path. Parametrized that test over ['nearest','bilinear','cubic']; all 3 RUN+PASS on a CUDA host. Cat 4 MEDIUM (resampling-mode parameter coverage on the dask+cupy backend). Test-only, source untouched. Re-confirmed _merge.merge() has NO genuine cupy/dask+cupy backend (_merge_inmemory/_merge_dask use _merge_arrays_numpy + raster.values; _merge_arrays_cupy is imported but never dispatched = dead code, not a test gap) matching the prior pass's observation. reproject() otherwise saturated across all 4 backends, NaN/Inf/all-NaN, degenerate shapes, metadata, vertical, bounds_policy, integer nodata. LOW (documented, not filed): dask+cupy resampling-mode parity is the only per-mode-per-backend cell that had been missing. || PREVIOUS: Pass 2026-05-29: reproject already has a deep suite (369 tests in test_reproject.py + coverage/gate files) covering all 4 backends, NaN/Inf/all-NaN/all-Inf, 1x1/2x2, metadata, vertical shift, bounds_policy x backends, integer nodata x backends. Gaps found: Cat 3 HIGH single-row (1xN) and single-col (Nx1) strip rasters never tested (hit size<2 branch of _validate_regular_axis + degenerate resampling axis); Cat 3 MEDIUM constant-value/zero-gradient raster never reprojected. Added TestDegenerateShapeReproject (12 tests): 1xN+Nx1 strips x numpy/dask/cupy/dask+cupy, constant raster numpy value-preservation + cross-backend parity. All 12 executed and passed on a CUDA host. Test-only, no source change (#2618). LOW (documented only): _merge._merge_arrays_cupy imported but never called by merge() (host-bounces via _merge_arrays_numpy) - dead-code source observation not a test gap; non-square cellsize reproject only covered via resolution-tuple validation errors not a successful anisotropic run."
14
13
  resample,2026-05-29,2547;2615,HIGH,1;2;3;5,"Pass 2 (2026-05-29): added test_resample_cupy_agg_fallback_2615.py (6 tests, all passing on CUDA host). Closes Cat 1 MEDIUM backend-coverage gap: the cupy eager aggregate CPU fallback for average/min/max at a NON-integer downsample factor (_run_cupy fy==int(fy) branch in resample.py ~L957-973) was never exercised; existing TestCuPyParity used 12x12 scale 0.5 (integer factor 2 -> GPU reshape path) and only median/mode hit the host fallback. New tests use 10x10 scale 0.3 (factor 3.33) for average/min/max parity vs numpy plus a NaN-masked variant. Issue #2615. Module is otherwise very thoroughly covered (test_resample.py + 3 supplementary files); no remaining HIGH gaps found. Pass 1 (2026-05-27): added test_resample_coverage_2026_05_27.py with 70 tests (68 passing, 2 skipped). Closes Cat 3 HIGH Nx1 single-column gap across numpy/cupy/dask+numpy/dask+cupy x 8 methods (nearest/bilinear/cubic/average/min/max/median/mode) plus Nx1 upsample-nearest parity and Nx1 cross-backend aggregate parity. Closes Cat 2 MEDIUM NaN-parity gap on cupy and dask+cupy (existing TestCuPyParity/TestDaskCuPyParity used random data without NaN; the weight-mask gate and spline-prepad had no GPU NaN coverage). Closes Cat 3 MEDIUM all-equal-value raster across 8 methods (downsample) and 3 interp methods (upsample) plus a constant-with-NaN aggregate variant. Closes Cat 5 MEDIUM non-default dim-name propagation: lat/lon, latitude/longitude, and (channel, lat, lon) 3D round-trip without being renamed to y/x; per-dim attrs (units) preserved. Closes Cat 3 MEDIUM empty-raster behaviour pin: 0-row and 0-col rasters raise (currently IndexError) -- contract covered. Filed source-bug issue #2547: cubic on dask backends fails for Nx1 / arrays smaller than depth=16; the 2 skipped tests in this file gate on that fix landing. Source untouched."
15
14
  slope,2026-05-29,2697,MEDIUM,3,"PR #2703: added degenerate-shape tests (1x1/1xN/Nx1) for all 4 planar backends + geodesic; no live bug, pins all-NaN+shape contract. CUDA host: cupy/dask+cupy ran. Backend/NaN/param/metadata coverage already complete."
16
15
  viewshed,2026-05-29,2693,HIGH,1;2;5,"Pass 1 (2026-05-29): added 4 new test groups to test_viewshed.py (13 new tests + 1 xfail, all passing/xfailing on a CUDA+RTX host). Closes Cat 1 HIGH backend-coverage gap: the dask+cupy dispatch path in _viewshed_dask (Tier B) and _viewshed_windowed (max_distance) was registered but never invoked by any test -- added test_viewshed_dask_cupy_flat (analytical-angle parity, atol 0.03) and test_viewshed_dask_cupy_max_distance (windowed GPU run; observer cell 180, corners INVISIBLE). Both use non-zero flat terrain (1.3) because the RTX mesh builder rejects an all-zero raster (#1378). Closes Cat 5 HIGH metadata-preservation gap: only the numpy test_viewshed called general_output_checks; the cupy/dask/dask+cupy and max_distance paths never asserted attrs/coords/dims/array-type preservation. Added parametrised test_viewshed_metadata_preserved over {numpy,cupy,dask+numpy,dask+cupy} x {full, max_distance=2.0}: asserts attrs==, dims==, shape==, x/y coords allclose; runs general_output_checks (full type parity) for all backends except dask+cupy. Closes Cat 2 HIGH NaN-input gap and surfaced source bug #2693: viewshed on a numpy raster crashes with ValueError 'node not found' from _delete_from_tree when a NaN cell sits at certain positions (e.g. (2,4) in a 5x5 with observer at (2,2)), while NaN at (1,1)/(0,0)/(4,4) runs fine. Added test_viewshed_nan_input_supported_positions (parametrised working positions, asserts observer=180 and NaN cell is INVISIBLE/NaN) plus test_viewshed_nan_input_crashing_position (xfail strict, raises, links #2693). Noted but NOT fixed (source change out of scope for test sweep): the dask+cupy backend does not preserve the cupy backing -- _viewshed_dask computes then rewraps via da.from_array(result_np), so the output computes to numpy not cupy; general_output_checks is skipped for dask+cupy for that reason (candidate for the metadata/backend-parity sweep). LOW (documented only): non-square cell sizes; 1x1 and 1xN geometry covered behaviourally by probing (run without error). Test-only PR; viewshed.py untouched."
@@ -0,0 +1,68 @@
1
+ ---
2
+ description: "Verify that all implemented backends produce consistent results for a given function or set of functions"
3
+ globs: "*.py"
4
+ ---
5
+
6
+ # Backend Parity: Cross-Backend Consistency Audit
7
+
8
+ Verify that all implemented backends produce consistent results for a given function or set of functions.
9
+
10
+ ## Step 1 -- Identify targets
11
+
12
+ 1. If the prompt names specific functions (e.g. `slope`, `aspect`), use those.
13
+ 2. If the prompt names a category (e.g. `hydrology`, `surface`, `focal`), read `README.md` to find all functions in that category.
14
+ 3. If the prompt is empty, scan the full feature matrix in `README.md` and test every function that claims support for 2+ backends.
15
+ 4. For each function, read its source file and find the `ArrayTypeFunctionMapping` call to determine which backends are actually implemented.
16
+
17
+ ## Step 2 -- Build test inputs
18
+
19
+ For each target function, create test rasters at three scales:
20
+
21
+ | Name | Size | Purpose |
22
+ |---------|---------|--------------------------------------------------|
23
+ | tiny | 8x6 | Fast, easy to inspect cell-by-cell |
24
+ | medium | 64x64 | Catches chunk-boundary artifacts in dask |
25
+ | large | 256x256 | Stress test, exposes numerical accumulation drift |
26
+
27
+ For each size, generate two variants:
28
+ - **Clean:** no NaN, realistic value range for the function
29
+ - **Dirty:** 5-10% random NaN, some extreme values near dtype limits
30
+
31
+ Use `np.random.default_rng(42)` for reproducibility. Test with at least `float32` and `float64`.
32
+
33
+ ## Step 3 -- Run every backend
34
+
35
+ 1. **NumPy:** `create_test_raster(data, backend='numpy')` -- always the baseline.
36
+ 2. **Dask+NumPy:** test with two chunk configurations: even split and ragged remainder.
37
+ 3. **CuPy:** `create_test_raster(data, backend='cupy')` -- skip if CUDA unavailable.
38
+ 4. **Dask+CuPy:** `create_test_raster(data, backend='dask+cupy')` -- skip if CUDA unavailable.
39
+
40
+ ## Step 4 -- Pairwise comparison
41
+
42
+ For every non-NumPy result, compare against the NumPy baseline. Extract data:
43
+ - Dask: `.data.compute()`
44
+ - CuPy: `.data.get()`
45
+ - Dask+CuPy: `.data.compute().get()`
46
+
47
+ Compute: absolute difference, relative difference, NaN mask agreement, metadata preservation.
48
+
49
+ Pass/fail thresholds:
50
+ - NumPy vs Dask+NumPy: rtol=1e-5, atol=0
51
+ - NumPy vs CuPy: rtol=1e-6, atol=1e-6
52
+ - NumPy vs Dask+CuPy: rtol=1e-6, atol=1e-6
53
+
54
+ A comparison fails if max_abs > atol AND max_rel > rtol, or if NaN masks disagree.
55
+
56
+ ## Step 5 -- Chunk boundary analysis
57
+
58
+ For any Dask comparison that fails, identify which cells diverge and map them to chunk boundaries. Report what percentage of divergent cells are at chunk boundaries vs interior.
59
+
60
+ ## Step 6 -- Generate the report
61
+
62
+ Print a structured report with: functions tested, parity matrix table, failures with root cause analysis, and summary counts.
63
+
64
+ ## General rules
65
+
66
+ - Do not modify any source or test files. This rule is read-only.
67
+ - Use `create_test_raster` from `general_checks.py` for all raster construction.
68
+ - If CUDA is unavailable, skip CuPy and Dask+CuPy gracefully. Report as SKIPPED, not FAIL.
@@ -0,0 +1,51 @@
1
+ ---
2
+ description: "Run ASV benchmarks for the current branch against main and report regressions and improvements"
3
+ globs: "benchmarks/**/*.py"
4
+ ---
5
+
6
+ # Bench: Local Performance Comparison
7
+
8
+ Run ASV benchmarks for the current branch against main and report regressions and improvements.
9
+
10
+ ## Step 1 -- Identify what changed
11
+
12
+ 1. If the prompt names specific benchmark classes or functions, use those directly.
13
+ 2. If the prompt is empty or says "auto", run `git diff origin/main --name-only` to find changed source files under `xrspatial/`. Map each changed file to the corresponding benchmark module in `benchmarks/benchmarks/`.
14
+ 3. If no benchmark exists for the changed code, note this and suggest whether one should be added.
15
+
16
+ ## Step 2 -- Check prerequisites
17
+
18
+ 1. Verify ASV is installed: `python -c "import asv"`. If missing, tell the user to install it.
19
+ 2. Verify the benchmarks directory exists at `benchmarks/`.
20
+ 3. Read `benchmarks/asv.conf.json` to confirm the project name and branch settings.
21
+
22
+ ## Step 3 -- Run the comparison
23
+
24
+ Run ASV in continuous-comparison mode from the `benchmarks/` directory:
25
+
26
+ ```bash
27
+ cd benchmarks && asv continuous origin/main HEAD -b "<regex>" -e
28
+ ```
29
+
30
+ Where `<regex>` is a pattern matching the benchmark classes identified in Step 1.
31
+
32
+ ## Step 4 -- Parse and interpret results
33
+
34
+ Classify each result:
35
+ - REGRESSION: Ratio > 1.2x
36
+ - IMPROVED: Ratio < 0.8x
37
+ - UNCHANGED: Between 0.8x and 1.2x
38
+
39
+ ## Step 5 -- Generate the report
40
+
41
+ Print a table with benchmark name, main time, HEAD time, ratio, and status. List regressions with likely causes, improvements, missing benchmarks, and a recommendation.
42
+
43
+ ## Step 6 -- Suggest benchmark additions
44
+
45
+ If changed functions have no benchmark coverage, describe what a new benchmark should test and ask the user whether to write it.
46
+
47
+ ## General rules
48
+
49
+ - Always run benchmarks from the `benchmarks/` directory.
50
+ - The regression threshold is 1.2x, matching `.github/workflows/benchmarks.yml`.
51
+ - Do not modify any source, test, or benchmark files unless explicitly asked to write a benchmark.
@@ -0,0 +1,58 @@
1
+ ---
2
+ description: "Create a Jupyter notebook that sets up a Dask distributed LocalCluster and walks through an ETL workflow"
3
+ globs: "*.ipynb"
4
+ ---
5
+
6
+ # Dask ETL Notebook
7
+
8
+ Create a Jupyter notebook that sets up a Dask distributed LocalCluster and walks through an ETL (Extract, Transform, Load) workflow.
9
+
10
+ ## Notebook structure
11
+
12
+ 1. Title + one-line description
13
+ 2. Overview (what the pipeline does, what you'll learn)
14
+ 3. Imports
15
+ 4. Cluster Setup -- create and inspect a LocalCluster + Client
16
+ 5. Extract -- load or generate source data as lazy Dask arrays
17
+ 6. Transform -- apply transformations (filtering, rechunking, computation)
18
+ 7. Load -- write results to disk (Zarr, Parquet, GeoTIFF)
19
+ 8. Cleanup -- close the client and cluster
20
+ 9. Summary + next steps
21
+
22
+ ## Cluster Setup
23
+
24
+ Always use this pattern:
25
+ ```python
26
+ from dask.distributed import Client, LocalCluster
27
+
28
+ cluster = LocalCluster(
29
+ n_workers=4,
30
+ threads_per_worker=2,
31
+ memory_limit="2GB",
32
+ )
33
+ client = Client(cluster)
34
+ client
35
+ ```
36
+
37
+ Include a markdown cell noting the dashboard link and that n_workers/memory_limit should be tuned.
38
+
39
+ ## Code conventions
40
+
41
+ - **Lazy by default**: build the computation graph before calling .compute().
42
+ - **Chunking**: explain chunk choices. Use explicit chunks=.
43
+ - **Avoid full materialization mid-pipeline**: no .values or .compute() until the Load phase.
44
+ - **Persist when reused**: if an intermediate result is used in multiple downstream steps, call client.persist().
45
+ - **Cleanup**: always close the client and cluster at the end.
46
+
47
+ ## Data handling
48
+
49
+ - Generate or load data lazily. Wrap numpy arrays with da.from_array(..., chunks=...).
50
+ - For file-based sources, prefer xr.open_dataset with explicit chunks=.
51
+ - For Load phase, prefer Zarr (to_zarr()) as default output format.
52
+
53
+ ## Checklist
54
+
55
+ 1. Pick a data domain from the prompt (or default to geospatial raster).
56
+ 2. Write the full cell sequence following the structure.
57
+ 3. Verify all code cells are syntactically correct and self-contained.
58
+ 4. Ensure the notebook cleans up after itself (cluster closed, temp files noted).