pysits 2.0.0.dev7__tar.gz → 2.0.0.dev8__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 (212) hide show
  1. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/PKG-INFO +2 -1
  2. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pyproject.toml +2 -1
  3. pysits-2.0.0.dev8/pysits/network.py +100 -0
  4. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/sits/ml.py +3 -1
  5. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/sits/utils.py +31 -8
  6. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/tests/conftest.py +51 -0
  7. pysits-2.0.0.dev8/tests/test_network.py +160 -0
  8. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/tests/test_utils.py +20 -0
  9. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/uv.lock +74 -1
  10. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/.gitattributes +0 -0
  11. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/.github/actions/setup-pysits/action.yml +0 -0
  12. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/.github/workflows/ruff.yaml +0 -0
  13. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/.github/workflows/tests.yaml +0 -0
  14. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/.gitignore +0 -0
  15. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/.pre-commit-config.yaml +0 -0
  16. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/LICENSE +0 -0
  17. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/README.md +0 -0
  18. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/conda/meta.yaml +0 -0
  19. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/__init__.py +0 -0
  20. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/backend/__init__.py +0 -0
  21. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/backend/arrow.py +0 -0
  22. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/backend/functions.py +0 -0
  23. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/backend/loaders.py +0 -0
  24. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/backend/pkgs.py +0 -0
  25. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/backend/rinterface.py +0 -0
  26. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/conversions/__init__.py +0 -0
  27. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/conversions/clojure.py +0 -0
  28. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/conversions/common.py +0 -0
  29. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/conversions/decorators.py +0 -0
  30. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/conversions/dsl/__init__.py +0 -0
  31. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/conversions/dsl/base.py +0 -0
  32. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/conversions/dsl/mask.py +0 -0
  33. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/conversions/dsl/tuning.py +0 -0
  34. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/conversions/stac.py +0 -0
  35. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/conversions/tibble.py +0 -0
  36. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/conversions/vector.py +0 -0
  37. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/conversions/xarray.py +0 -0
  38. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/__init__.py +0 -0
  39. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/impute_linear.md +0 -0
  40. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/impute_mean.md +0 -0
  41. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/impute_mean_window.md +0 -0
  42. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/impute_median.md +0 -0
  43. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/plot.md +0 -0
  44. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_accuracy.md +0 -0
  45. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_accuracy_summary.md +0 -0
  46. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_add_base_cube.md +0 -0
  47. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_apply.md +0 -0
  48. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_as_geopandas.md +0 -0
  49. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_bands.md +0 -0
  50. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_barlow_twins.md +0 -0
  51. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_bbox.md +0 -0
  52. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_classify.md +0 -0
  53. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_clean.md +0 -0
  54. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_cluster_clean.md +0 -0
  55. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_cluster_dendro.md +0 -0
  56. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_cluster_frequency.md +0 -0
  57. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_colors.md +0 -0
  58. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_colors_qgis.md +0 -0
  59. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_colors_reset.md +0 -0
  60. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_colors_set.md +0 -0
  61. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_colors_show.md +0 -0
  62. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_combine_predictions.md +0 -0
  63. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_confidence_sampling.md +0 -0
  64. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_config.md +0 -0
  65. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_config_show.md +0 -0
  66. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_config_user_file.md +0 -0
  67. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_contrastive_learning.md +0 -0
  68. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_cube.md +0 -0
  69. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_cube_copy.md +0 -0
  70. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_encode.md +0 -0
  71. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_formula_linear.md +0 -0
  72. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_formula_logref.md +0 -0
  73. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_geo_dist.md +0 -0
  74. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_get_class.md +0 -0
  75. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_get_data.md +0 -0
  76. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_get_probs.md +0 -0
  77. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_kfold_validate.md +0 -0
  78. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_label_classification.md +0 -0
  79. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_labels.md +0 -0
  80. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_labels_summary.md +0 -0
  81. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_lightgbm.md +0 -0
  82. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_lighttae.md +0 -0
  83. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_list_collections.md +0 -0
  84. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_lstm_fcn.md +0 -0
  85. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_merge.md +0 -0
  86. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_mixture_model.md +0 -0
  87. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_mlp.md +0 -0
  88. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_model_export.md +0 -0
  89. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_mosaic.md +0 -0
  90. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_parallel.md +0 -0
  91. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_patterns.md +0 -0
  92. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_pre_train.md +0 -0
  93. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_pred_features.md +0 -0
  94. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_pred_normalize.md +0 -0
  95. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_pred_references.md +0 -0
  96. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_pred_sample.md +0 -0
  97. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_predictors.md +0 -0
  98. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_random_sampling.md +0 -0
  99. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_reclassify.md +0 -0
  100. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_reduce.md +0 -0
  101. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_reduce_imbalance.md +0 -0
  102. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_regularize.md +0 -0
  103. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_resnet.md +0 -0
  104. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_rfor.md +0 -0
  105. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_roi_to_tiles.md +0 -0
  106. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_sample.md +0 -0
  107. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_sampling_design.md +0 -0
  108. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_sankey.md +0 -0
  109. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_segment.md +0 -0
  110. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_select.md +0 -0
  111. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_show_prediction.md +0 -0
  112. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_slic.md +0 -0
  113. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_smooth.md +0 -0
  114. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_snic.md +0 -0
  115. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_som_clean_samples.md +0 -0
  116. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_som_evaluate_cluster.md +0 -0
  117. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_som_map.md +0 -0
  118. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_som_remove_samples.md +0 -0
  119. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_ssl_lejepa.md +0 -0
  120. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_ssl_mae.md +0 -0
  121. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_ssl_vicreg.md +0 -0
  122. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_stats.md +0 -0
  123. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_stratified_sampling.md +0 -0
  124. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_svm.md +0 -0
  125. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_tae.md +0 -0
  126. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_tempcnn.md +0 -0
  127. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_texture.md +0 -0
  128. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_tiles_to_roi.md +0 -0
  129. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_timeline.md +0 -0
  130. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_timeseries_to_csv.md +0 -0
  131. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_to_csv.md +0 -0
  132. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_to_xlsx.md +0 -0
  133. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_train.md +0 -0
  134. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_tuning.md +0 -0
  135. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_tuning_hparams.md +0 -0
  136. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_uncertainty.md +0 -0
  137. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_uncertainty_sampling.md +0 -0
  138. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_validate.md +0 -0
  139. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_variance.md +0 -0
  140. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_view.md +0 -0
  141. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/sits_xgboost.md +0 -0
  142. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/content/summary.md +0 -0
  143. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/docs/decorators.py +0 -0
  144. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/extras/__init__.py +0 -0
  145. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/extras/earthdatalogin.py +0 -0
  146. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/extras/torch.py +0 -0
  147. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/jinja.py +0 -0
  148. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/models/__init__.py +0 -0
  149. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/models/base.py +0 -0
  150. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/models/data/__init__.py +0 -0
  151. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/models/data/accuracy.py +0 -0
  152. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/models/data/base.py +0 -0
  153. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/models/data/cube.py +0 -0
  154. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/models/data/frame.py +0 -0
  155. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/models/data/frame_accessor.py +0 -0
  156. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/models/data/matrix.py +0 -0
  157. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/models/data/table.py +0 -0
  158. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/models/data/ts.py +0 -0
  159. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/models/data/tuning.py +0 -0
  160. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/models/data/vector.py +0 -0
  161. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/models/frame.py +0 -0
  162. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/models/ml.py +0 -0
  163. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/models/resolver.py +0 -0
  164. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/models/visual.py +0 -0
  165. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/settings.py +0 -0
  166. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/sits/__init__.py +0 -0
  167. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/sits/colors.py +0 -0
  168. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/sits/config.py +0 -0
  169. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/sits/context.py +0 -0
  170. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/sits/cube.py +0 -0
  171. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/sits/data.py +0 -0
  172. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/sits/exporters/__init__.py +0 -0
  173. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/sits/exporters/files.py +0 -0
  174. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/sits/exporters/sf.py +0 -0
  175. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/sits/exporters/xarray.py +0 -0
  176. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/sits/impute.py +0 -0
  177. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/sits/segment.py +0 -0
  178. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/sits/tiles.py +0 -0
  179. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/sits/ts.py +0 -0
  180. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/sits/tuning.py +0 -0
  181. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/sits/visualization.py +0 -0
  182. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/templates/cube.html +0 -0
  183. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/templates/plot.html +0 -0
  184. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/templates/tuning.html +0 -0
  185. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/visualization/__init__.py +0 -0
  186. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/visualization/base.py +0 -0
  187. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/visualization/device.py +0 -0
  188. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/visualization/host.py +0 -0
  189. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/visualization/leaflet.py +0 -0
  190. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/pysits/visualization/options.py +0 -0
  191. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/tests/test_backend.py +0 -0
  192. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/tests/test_classification.py +0 -0
  193. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/tests/test_config.py +0 -0
  194. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/tests/test_conversions.py +0 -0
  195. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/tests/test_cube.py +0 -0
  196. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/tests/test_data.py +0 -0
  197. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/tests/test_dsl.py +0 -0
  198. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/tests/test_embedding.py +1 -1
  199. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/tests/test_exporters.py +0 -0
  200. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/tests/test_exporters_geopandas.py +0 -0
  201. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/tests/test_exporters_xarray.py +0 -0
  202. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/tests/test_extras.py +0 -0
  203. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/tests/test_indexing.py +0 -0
  204. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/tests/test_ml_models.py +0 -0
  205. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/tests/test_resolver.py +0 -0
  206. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/tests/test_rl_models.py +0 -0
  207. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/tests/test_som.py +0 -0
  208. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/tests/test_tiles.py +0 -0
  209. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/tests/test_tuning.py +0 -0
  210. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/tests/test_validation.py +0 -0
  211. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/tests/test_visual_models.py +0 -0
  212. {pysits-2.0.0.dev7 → pysits-2.0.0.dev8}/tests/test_visualization.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: pysits
3
- Version: 2.0.0.dev7
3
+ Version: 2.0.0.dev8
4
4
  Summary: Python wrapper for the sits R package
5
5
  Project-URL: Homepage, https://github.com/e-sensing/pysits
6
6
  Project-URL: Issue Tracker, https://github.com/e-sensing/pysits/issues
@@ -17,6 +17,7 @@ Classifier: Programming Language :: Python :: 3
17
17
  Classifier: Topic :: Scientific/Engineering :: GIS
18
18
  Requires-Python: <4,>=3.10
19
19
  Requires-Dist: geopandas>=1.1.0
20
+ Requires-Dist: httpx2>=2.13.0
20
21
  Requires-Dist: jinja2>=3.1.6
21
22
  Requires-Dist: matplotlib>=3.10.1
22
23
  Requires-Dist: pandas>=2.2.3
@@ -17,7 +17,7 @@
17
17
 
18
18
  [project]
19
19
  name = "pysits"
20
- version = "2.0.0.dev7"
20
+ version = "2.0.0.dev8"
21
21
  description = "Python wrapper for the sits R package"
22
22
  readme = "README.md"
23
23
  requires-python = ">=3.10,<4"
@@ -71,6 +71,7 @@ dependencies = [
71
71
  "shapely>=2.1.1",
72
72
  "pyarrow>=20.0.0",
73
73
  "jinja2>=3.1.6",
74
+ "httpx2>=2.13.0",
74
75
  ]
75
76
 
76
77
  [project.urls]
@@ -0,0 +1,100 @@
1
+ #
2
+ # Copyright (C) 2025 sits developers.
3
+ #
4
+ # This program is free software; you can redistribute it and/or modify it
5
+ # under the terms of the GNU General Public License as published by
6
+ # the Free Software Foundation; either version 2 of the License, or
7
+ # (at your option) any later version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with this program; if not, see <https://www.gnu.org/licenses/>.
16
+ #
17
+
18
+ """Network operations."""
19
+
20
+ import os
21
+ import tempfile
22
+ from collections.abc import Iterator
23
+ from contextlib import contextmanager
24
+ from pathlib import Path
25
+ from urllib.parse import urlparse
26
+
27
+ import httpx2
28
+
29
+ #
30
+ # Supported URL schemes
31
+ #
32
+ REMOTE_SCHEMES = ("http", "https")
33
+
34
+
35
+ #
36
+ # Auxiliary functions
37
+ #
38
+ def is_remote(location: str | Path) -> bool:
39
+ """Check if a location points to a remote resource.
40
+
41
+ Args:
42
+ location (str | Path): File location (local path or URL).
43
+
44
+ Returns:
45
+ bool: ``True`` when ``location`` is an URL with a supported scheme.
46
+
47
+ Notes:
48
+ - Supported schemes are ``http`` and ``https``.
49
+ """
50
+ return urlparse(str(location)).scheme in REMOTE_SCHEMES
51
+
52
+
53
+ #
54
+ # File management
55
+ #
56
+ @contextmanager
57
+ def fetch_to_tempfile(url: str, *, suffix: str = "") -> Iterator[Path]:
58
+ """Download a remote file to a temporary file.
59
+
60
+ Args:
61
+ url (str): File URL.
62
+
63
+ suffix (str): Suffix for the temporary file name.
64
+
65
+ Yields:
66
+ Path: Path of the downloaded file.
67
+
68
+ Raises:
69
+ httpx2.HTTPError: If the file cannot be downloaded.
70
+
71
+ Notes:
72
+ - The temporary file is removed when the context exits, including
73
+ when the download fails or the caller raises.
74
+ """
75
+ # Create a temporary file
76
+ descriptor, name = tempfile.mkstemp(suffix=suffix)
77
+
78
+ # Name as path
79
+ local_file = Path(name)
80
+
81
+ # Try to download the file
82
+ try:
83
+ # Open the stream in binary mode
84
+ with os.fdopen(descriptor, "wb") as stream:
85
+ # Enable redirects to facilitate operations on remote files
86
+ # stored in systems like huggingface and similar platforms.
87
+ with httpx2.stream("GET", url, follow_redirects=True) as response:
88
+ # Raise an exception if the response is not successful
89
+ response.raise_for_status()
90
+
91
+ # Write the content to the temporary file
92
+ for chunk in response.iter_bytes():
93
+ stream.write(chunk)
94
+
95
+ # Yield the path to the temporary file
96
+ yield local_file
97
+
98
+ finally:
99
+ # Remove the temporary file
100
+ local_file.unlink(missing_ok=True)
@@ -84,7 +84,9 @@ sits_lightgbm = closure_factory("sits_lightgbm")
84
84
  sits_ssl_mae = closure_factory("sits_ssl_mae", converters=dl_converters)
85
85
  sits_ssl_lejepa = closure_factory("sits_ssl_lejepa", converters=dl_converters)
86
86
  sits_ssl_vicreg = closure_factory("sits_ssl_vicreg", converters=dl_converters)
87
- sits_ssl_barlow_twins = closure_factory("sits_ssl_barlow_twins", converters=dl_converters)
87
+ sits_ssl_barlow_twins = closure_factory(
88
+ "sits_ssl_barlow_twins", converters=dl_converters
89
+ )
88
90
 
89
91
  sits_barlow_twins = closure_factory("sits_barlow_twins", converters=dl_converters)
90
92
  sits_contrastive_learning = closure_factory(
@@ -27,6 +27,7 @@ from pysits.models.resolver import (
27
27
  resolve_and_invoke_accuracy_class,
28
28
  resolve_and_invoke_content_class,
29
29
  )
30
+ from pysits.network import fetch_to_tempfile, is_remote
30
31
 
31
32
  #
32
33
  # Data class resolver
@@ -56,19 +57,41 @@ def read_rds(file: str | Path) -> SITSFrame:
56
57
  """Read RDS file compatible with SITS.
57
58
 
58
59
  Args:
59
- file (str | Path): RDS file.
60
+ file (str | Path): RDS file. It can be a local path or an HTTP(S) URL.
60
61
 
61
62
  Returns:
62
63
  SITSFrame: SITS Data instance (can be a ``cube`` or a ``time-series`` object).
63
- """
64
- file = Path(file)
65
64
 
66
- # Check if file exists
67
- if not file.exists():
68
- raise FileNotFoundError("Failed to read RDS: File does not exist.")
65
+ Raises:
66
+ FileNotFoundError: If a local RDS file does not exist. A missing
67
+ remote file is reported by ``httpx2`` instead,
68
+ as an ``HTTPStatusError``.
69
+
70
+ httpx2.HTTPError: If a remote RDS file cannot be downloaded.
69
71
 
70
- # Read RDS
71
- rds_content = r_fnc_read_rds(file.as_posix())
72
+ ValueError: If the RDS file has an object not supported by sits.
73
+ """
74
+ # If is remote file, we download it
75
+ if is_remote(file):
76
+ # Remote files are downloaded before being read. In R, it is possible
77
+ # to read RDS straight from an ``url`` connection, but that only works
78
+ # when the content is gzipped: the other compressions ``saveRDS`` produces
79
+ # (``xz`` and ``bzip2``) are rejected when read this way.
80
+ # So we download the file to a temporary file and read it from there to avoid
81
+ # this issue.
82
+ with fetch_to_tempfile(str(file), suffix=".rds") as local_file:
83
+ # Download and read content!
84
+ rds_content = r_fnc_read_rds(local_file.as_posix())
85
+
86
+ else:
87
+ file = Path(file)
88
+
89
+ # Check if file exists
90
+ if not file.exists():
91
+ raise FileNotFoundError("Failed to read RDS: File does not exist.")
92
+
93
+ # Read RDS
94
+ rds_content = r_fnc_read_rds(file.as_posix())
72
95
 
73
96
  # Resolve and invoke data class
74
97
  for resolver in RDS_RESOLVERS:
@@ -25,6 +25,10 @@ import os
25
25
  os.environ.setdefault("MPLBACKEND", "Agg")
26
26
 
27
27
  import webbrowser
28
+ from functools import partial
29
+ from http.server import SimpleHTTPRequestHandler, ThreadingHTTPServer
30
+ from pathlib import Path
31
+ from threading import Thread
28
32
  from typing import Any
29
33
 
30
34
  import matplotlib
@@ -36,6 +40,11 @@ from pysits.sits.cube import sits_cube
36
40
  from pysits.sits.utils import r_package_dir
37
41
  from pysits.visualization.options import reset_plot_options
38
42
 
43
+ #
44
+ # Path prefix the test server answers with a redirect
45
+ #
46
+ REDIRECT_PREFIX = "/redirect/"
47
+
39
48
 
40
49
  #
41
50
  # Helpers
@@ -107,3 +116,45 @@ def no_browser(monkeypatch):
107
116
  monkeypatch.setattr(webbrowser, "open_new_tab", lambda x: None)
108
117
 
109
118
  yield
119
+
120
+
121
+ class _RedirectingRequestHandler(SimpleHTTPRequestHandler):
122
+ """Serve a directory with a redirect."""
123
+
124
+ def do_GET(self) -> None: # noqa: N802 (name defined by the base class)
125
+ # If path starts with a given prefix, simulate a redirect
126
+ if self.path.startswith(REDIRECT_PREFIX):
127
+ # Simulate a redirect
128
+ self.send_response(302)
129
+ self.send_header("Location", self.path[len(REDIRECT_PREFIX) - 1 :])
130
+ self.end_headers()
131
+
132
+ return
133
+
134
+ super().do_GET()
135
+
136
+ def log_message(self, *args, **kwargs) -> None:
137
+ """Keep the per-request log out of the test output."""
138
+
139
+
140
+ @pytest.fixture
141
+ def http_server(tmp_path: Path):
142
+ """HTTP server serving a directory with a redirect."""
143
+ handler = partial(
144
+ _RedirectingRequestHandler,
145
+ directory=str(tmp_path),
146
+ )
147
+ server = ThreadingHTTPServer(("127.0.0.1", 0), handler)
148
+
149
+ # Start the server in a daemon thread
150
+ thread = Thread(target=server.serve_forever, daemon=True)
151
+ thread.start()
152
+
153
+ # Yield the directory and its base URL
154
+ try:
155
+ yield tmp_path, f"http://127.0.0.1:{server.server_port}"
156
+
157
+ # Shutdown the server
158
+ finally:
159
+ server.shutdown()
160
+ server.server_close()
@@ -0,0 +1,160 @@
1
+ #
2
+ # Copyright (C) 2025 sits developers.
3
+ #
4
+ # This program is free software; you can redistribute it and/or modify it
5
+ # under the terms of the GNU General Public License as published by
6
+ # the Free Software Foundation; either version 2 of the License, or
7
+ # (at your option) any later version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with this program; if not, see <https://www.gnu.org/licenses/>.
16
+ #
17
+
18
+ """Unit tests for network operations."""
19
+
20
+ import socket
21
+ import tempfile
22
+ from pathlib import Path
23
+ from threading import Thread
24
+
25
+ import httpx2
26
+ import pytest
27
+
28
+ from pysits.network import fetch_to_tempfile, is_remote
29
+
30
+
31
+ #
32
+ # Auxiliary functions
33
+ #
34
+ def temporary_files() -> set[Path]:
35
+ """List the files currently in the temporary directory."""
36
+ return set(Path(tempfile.gettempdir()).iterdir())
37
+
38
+
39
+ #
40
+ # Fixtures
41
+ #
42
+ @pytest.fixture
43
+ def raw_server():
44
+ """HTTP Server."""
45
+ server_sockets = []
46
+
47
+ def start(response: bytes) -> str:
48
+ """Start the HTTP server."""
49
+ # Create a socket and bind it to a random port
50
+ server_socket = socket.socket()
51
+ server_socket.bind(("127.0.0.1", 0))
52
+ server_socket.listen(1)
53
+ server_sockets.append(server_socket)
54
+
55
+ # Start a thread to serve the response
56
+ def serve() -> None:
57
+ try:
58
+ connection, _ = server_socket.accept()
59
+ connection.recv(4096)
60
+ connection.sendall(response)
61
+ connection.close()
62
+
63
+ except OSError:
64
+ pass
65
+
66
+ # Start the thread
67
+ Thread(target=serve, daemon=True).start()
68
+
69
+ # Return the URL of the server
70
+ return f"http://127.0.0.1:{server_socket.getsockname()[1]}/samples.rds"
71
+
72
+ yield start
73
+
74
+ for server_socket in server_sockets:
75
+ server_socket.close()
76
+
77
+
78
+ #
79
+ # Tests
80
+ #
81
+ @pytest.mark.parametrize(
82
+ ("location", "expected"),
83
+ [
84
+ ("https://example.org/samples.rds", True),
85
+ ("http://example.org/samples.rds", True),
86
+ ("/data/samples.rds", False),
87
+ ("/home/user/samples.rds", False),
88
+ # Note: ``urlparse`` reads the drive letter as the scheme,
89
+ # so a Windows path must not be mistaken for a remote location
90
+ (r"C:\data\samples.rds", False),
91
+ ],
92
+ )
93
+ def test_is_remote(location: str, expected: bool):
94
+ """Test remote location identification."""
95
+ assert is_remote(location) is expected
96
+
97
+
98
+ def test_fetch_to_tempfile_downloads_and_cleans_up(http_server):
99
+ """Test remote content download."""
100
+ directory, base_url = http_server
101
+
102
+ # Save payload
103
+ samples_file_local = directory / "samples.rds"
104
+ samples_file_local.write_bytes(b"sits-payload")
105
+
106
+ # Fetch the file
107
+ samples_file_remote = f"{base_url}/samples.rds"
108
+
109
+ with fetch_to_tempfile(samples_file_remote, suffix=".rds") as local_file:
110
+ assert local_file.read_bytes() == b"sits-payload"
111
+
112
+ # Check the file is deleted
113
+ assert not local_file.exists()
114
+
115
+
116
+ def test_fetch_to_tempfile_follows_redirects(http_server):
117
+ """Test redirect following."""
118
+ directory, base_url = http_server
119
+
120
+ # Save payload
121
+ samples_file_local = directory / "samples.rds"
122
+ samples_file_local.write_bytes(b"sits-payload")
123
+
124
+ # Fetch the file
125
+ samples_file_remote = f"{base_url}/redirect/samples.rds"
126
+
127
+ with fetch_to_tempfile(samples_file_remote, suffix=".rds") as local_file:
128
+ assert local_file.read_bytes() == b"sits-payload"
129
+
130
+
131
+ def test_fetch_to_tempfile_rejects_error_status(http_server):
132
+ """Test error response handling."""
133
+ _, base_url = http_server
134
+
135
+ # Save payload
136
+ before = temporary_files()
137
+
138
+ # Fetch file
139
+ with pytest.raises(httpx2.HTTPStatusError):
140
+ with fetch_to_tempfile(f"{base_url}/non-existing-file.rds"):
141
+ pass
142
+
143
+ assert temporary_files() == before
144
+
145
+
146
+ def test_fetch_to_tempfile_rejects_truncated_response(raw_server):
147
+ """Test truncated response handling."""
148
+ # Create a server that returns a truncated response
149
+ url = raw_server(b"HTTP/1.1 200 OK\r\nContent-Length: 5000\r\n\r\n" + b"x" * 100)
150
+
151
+ # Save payload
152
+ before = temporary_files()
153
+
154
+ # Fetch file
155
+ with pytest.raises(httpx2.RemoteProtocolError):
156
+ with fetch_to_tempfile(url):
157
+ pass
158
+
159
+ # Check the file is deleted
160
+ assert temporary_files() == before
@@ -53,6 +53,26 @@ def test_read_rds(tmp_path: Path):
53
53
  assert isinstance(rds_content, SITSTimeSeriesModel)
54
54
 
55
55
 
56
+ @pytest.mark.parametrize("compress", ["gzip", "xz", "bzip2"])
57
+ def test_read_rds_remote(http_server, compress: str):
58
+ """Test read RDS from a remote file."""
59
+ directory, base_url = http_server
60
+
61
+ # Save RDS
62
+ r_fnc_save_rds = load_function_from_package("base::saveRDS")
63
+ r_fnc_save_rds(
64
+ samples_modis_ndvi._instance,
65
+ (directory / "samples.rds").as_posix(),
66
+ compress=compress,
67
+ )
68
+
69
+ # Read remote RDS
70
+ rds_content = read_rds(f"{base_url}/samples.rds")
71
+
72
+ # Check the content
73
+ assert isinstance(rds_content, SITSTimeSeriesModel)
74
+
75
+
56
76
  def test_read_rds_file_not_found():
57
77
  """Test read RDS file not found."""
58
78
  with pytest.raises(FileNotFoundError):
@@ -28,6 +28,20 @@ wheels = [
28
28
  { url = "https://files.pythonhosted.org/packages/99/91/8acff4f5e50511b911bbccb72b8628a49c68ce14148cd9f6431094859a90/annotated_types-0.8.0-py3-none-any.whl", hash = "sha256:f072f4d804ea359e4eaf198b1af7a8b0943881a87f31bb764f8bf219bb9419e0", size = 13427, upload-time = "2026-07-23T20:16:12.938Z" },
29
29
  ]
30
30
 
31
+ [[package]]
32
+ name = "anyio"
33
+ version = "4.15.1"
34
+ source = { registry = "https://pypi.org/simple" }
35
+ dependencies = [
36
+ { name = "exceptiongroup", marker = "python_full_version < '3.11'" },
37
+ { name = "idna" },
38
+ { name = "typing-extensions", marker = "python_full_version < '3.15'" },
39
+ ]
40
+ sdist = { url = "https://files.pythonhosted.org/packages/a9/d2/f4d173e22df740bc37b1db102b386ba719b66e95b0f0d751f556b387e6d2/anyio-4.15.1.tar.gz", hash = "sha256:9f28306018cbd6d329e64a36d58256edff76dd996fe423bc957326e578b82a94", size = 276966, upload-time = "2026-09-05T10:42:39.44Z" }
41
+ wheels = [
42
+ { url = "https://files.pythonhosted.org/packages/12/b8/4bd346e22b28902df4d651910f5242c28d84e4a5c2435ca5c3f797ed7e2e/anyio-4.15.1-py3-none-any.whl", hash = "sha256:6152fdbbf9a77fdec97731721bebf7c4c44f7c29b424b0065826173efc7ed101", size = 132079, upload-time = "2026-09-05T10:42:37.923Z" },
43
+ ]
44
+
31
45
  [[package]]
32
46
  name = "appnope"
33
47
  version = "0.1.4"
@@ -752,6 +766,54 @@ wheels = [
752
766
  { url = "https://files.pythonhosted.org/packages/be/82/79e02a0e5dd4aca81894842b9d6522624a40048a913c6384efb2987a4144/geopandas-1.1.0-py3-none-any.whl", hash = "sha256:b19b18bdc736ee05b237f5e9184211c452768a4c883f7d7f8421b0cbe1da5875", size = 338014, upload-time = "2025-06-01T16:54:29.239Z" },
753
767
  ]
754
768
 
769
+ [[package]]
770
+ name = "h11"
771
+ version = "0.16.0"
772
+ source = { registry = "https://pypi.org/simple" }
773
+ sdist = { url = "https://files.pythonhosted.org/packages/01/ee/02a2c011bdab74c6fb3c75474d40b3052059d95df7e73351460c8588d963/h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1", size = 101250, upload-time = "2025-04-24T03:35:25.427Z" }
774
+ wheels = [
775
+ { url = "https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86", size = 37515, upload-time = "2025-04-24T03:35:24.344Z" },
776
+ ]
777
+
778
+ [[package]]
779
+ name = "httpcore2"
780
+ version = "2.13.0"
781
+ source = { registry = "https://pypi.org/simple" }
782
+ dependencies = [
783
+ { name = "h11" },
784
+ { name = "truststore" },
785
+ ]
786
+ sdist = { url = "https://files.pythonhosted.org/packages/15/8c/e925b1c92018abb3a1863ce1549d76d2381e334d21d65d4ac8f65dabd78a/httpcore2-2.13.0.tar.gz", hash = "sha256:2adc8be4fb285fbcd6d894298db3b52c177e74b6674eda3a76bd36be3292a3db", size = 67740, upload-time = "2026-09-14T14:18:04.717Z" }
787
+ wheels = [
788
+ { url = "https://files.pythonhosted.org/packages/7e/0d/117a771a2bb91df334b66bf4da14cd02f21aefbcfe53180f336ce55e8f90/httpcore2-2.13.0-py3-none-any.whl", hash = "sha256:35ae5be347aa40467b4a5dc032ac67ebb6d27189fc97e8cebcf99616f6a1bb9e", size = 83162, upload-time = "2026-09-14T14:18:02.529Z" },
789
+ ]
790
+
791
+ [[package]]
792
+ name = "httpx2"
793
+ version = "2.13.0"
794
+ source = { registry = "https://pypi.org/simple" }
795
+ dependencies = [
796
+ { name = "anyio", marker = "sys_platform != 'emscripten'" },
797
+ { name = "httpcore2", marker = "sys_platform != 'emscripten'" },
798
+ { name = "httpx2-jsfetch", marker = "python_full_version >= '3.12' and sys_platform == 'emscripten'" },
799
+ { name = "idna" },
800
+ { name = "truststore", marker = "sys_platform != 'emscripten'" },
801
+ { name = "typing-extensions", marker = "python_full_version < '3.13'" },
802
+ ]
803
+ sdist = { url = "https://files.pythonhosted.org/packages/b9/a0/e9deef4654132857b5a5dbe4eddd0ac59c2814500e11f2f5044cd81103ee/httpx2-2.13.0.tar.gz", hash = "sha256:81bd07dc67a3701729ef1f777a3c00c915d4539604fdb5afd327f8682f6b7b44", size = 100290, upload-time = "2026-09-14T14:18:05.486Z" }
804
+ wheels = [
805
+ { url = "https://files.pythonhosted.org/packages/fe/d1/a0c72b0e006df654709fbc366cc5bcb53e5aee13e1e3395152c6dd293376/httpx2-2.13.0-py3-none-any.whl", hash = "sha256:fc12720cedf72faa26cca6b4ca394e05c894e7d7933fc45cafe767960804e49a", size = 95565, upload-time = "2026-09-14T14:18:03.553Z" },
806
+ ]
807
+
808
+ [[package]]
809
+ name = "httpx2-jsfetch"
810
+ version = "1.0"
811
+ source = { registry = "https://pypi.org/simple" }
812
+ sdist = { url = "https://files.pythonhosted.org/packages/cd/c4/0e5636363151a2a1795e0a77617168b9ca438e1748ec05fc9b5687f93d64/httpx2_jsfetch-1.0.tar.gz", hash = "sha256:70a0e3eabfef7cce5ad9c629f7d01ca05e418f586646f4ddf14782e4c1454c60", size = 6872, upload-time = "2026-08-07T00:13:07.492Z" }
813
+ wheels = [
814
+ { url = "https://files.pythonhosted.org/packages/9b/43/832f631d32e4f1211caa2ba368317739fe71f0b8530e4c9d15dc454bac2a/httpx2_jsfetch-1.0-py3-none-any.whl", hash = "sha256:cb916b707601e69a07721aabc8f3f6659be3a6893bc1ff5c6f9e02241df2da32", size = 6382, upload-time = "2026-08-07T00:13:06.567Z" },
815
+ ]
816
+
755
817
  [[package]]
756
818
  name = "identify"
757
819
  version = "2.6.12"
@@ -2266,10 +2328,11 @@ wheels = [
2266
2328
 
2267
2329
  [[package]]
2268
2330
  name = "pysits"
2269
- version = "2.0.0.dev7"
2331
+ version = "2.0.0.dev8"
2270
2332
  source = { editable = "." }
2271
2333
  dependencies = [
2272
2334
  { name = "geopandas" },
2335
+ { name = "httpx2" },
2273
2336
  { name = "jinja2" },
2274
2337
  { name = "matplotlib", version = "3.10.9", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" },
2275
2338
  { name = "matplotlib", version = "3.11.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" },
@@ -2316,6 +2379,7 @@ requires-dist = [
2316
2379
  { name = "cloudpickle", marker = "extra == 'dev'", specifier = ">=3.1.1" },
2317
2380
  { name = "dask", marker = "extra == 'xarray'", specifier = ">=2025.3.0" },
2318
2381
  { name = "geopandas", specifier = ">=1.1.0" },
2382
+ { name = "httpx2", specifier = ">=2.13.0" },
2319
2383
  { name = "ipykernel", marker = "extra == 'dev'", specifier = ">=6.29.0" },
2320
2384
  { name = "jinja2", specifier = ">=3.1.6" },
2321
2385
  { name = "matplotlib", specifier = ">=3.10.1" },
@@ -3541,6 +3605,15 @@ wheels = [
3541
3605
  { url = "https://files.pythonhosted.org/packages/ad/66/0d785f0bc5e4315a96c989bb476d0fc07ea4f85132550c7b156ca2035d52/traitlets-5.16.1-py3-none-any.whl", hash = "sha256:f775618166caa0396c8e337099240f2bd3e5e917d203b2e6fbe21a58d3cb1f6b", size = 86211, upload-time = "2026-08-03T08:32:34.48Z" },
3542
3606
  ]
3543
3607
 
3608
+ [[package]]
3609
+ name = "truststore"
3610
+ version = "0.10.4"
3611
+ source = { registry = "https://pypi.org/simple" }
3612
+ sdist = { url = "https://files.pythonhosted.org/packages/53/a3/1585216310e344e8102c22482f6060c7a6ea0322b63e026372e6dcefcfd6/truststore-0.10.4.tar.gz", hash = "sha256:9d91bd436463ad5e4ee4aba766628dd6cd7010cf3e2461756b3303710eebc301", size = 26169, upload-time = "2025-08-12T18:49:02.73Z" }
3613
+ wheels = [
3614
+ { url = "https://files.pythonhosted.org/packages/19/97/56608b2249fe206a67cd573bc93cd9896e1efb9e98bce9c163bcdc704b88/truststore-0.10.4-py3-none-any.whl", hash = "sha256:adaeaecf1cbb5f4de3b1959b42d41f6fab57b2b1666adb59e89cb0b53361d981", size = 18660, upload-time = "2025-08-12T18:49:01.46Z" },
3615
+ ]
3616
+
3544
3617
  [[package]]
3545
3618
  name = "typing-extensions"
3546
3619
  version = "4.16.0"
File without changes
File without changes
File without changes
File without changes
File without changes