eodag 3.4.3__tar.gz → 3.5.0__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 (262) hide show
  1. {eodag-3.4.3 → eodag-3.5.0}/.github/workflows/deploy.yml +6 -0
  2. {eodag-3.4.3 → eodag-3.5.0}/CHANGES.rst +60 -0
  3. {eodag-3.4.3/eodag.egg-info → eodag-3.5.0}/PKG-INFO +3 -3
  4. {eodag-3.4.3 → eodag-3.5.0}/README.rst +1 -1
  5. {eodag-3.4.3 → eodag-3.5.0}/charts/eodag-server/Chart.yaml +2 -2
  6. {eodag-3.4.3 → eodag-3.5.0}/docs/getting_started_guide/configure.rst +20 -0
  7. {eodag-3.4.3 → eodag-3.5.0}/docs/getting_started_guide/register.rst +1 -1
  8. {eodag-3.4.3 → eodag-3.5.0}/docs/stac_rest.rst +1 -1
  9. {eodag-3.4.3 → eodag-3.5.0}/eodag/api/core.py +75 -1
  10. {eodag-3.4.3 → eodag-3.5.0}/eodag/api/product/metadata_mapping.py +31 -2
  11. {eodag-3.4.3 → eodag-3.5.0}/eodag/config.py +56 -10
  12. {eodag-3.4.3 → eodag-3.5.0}/eodag/plugins/authentication/keycloak.py +3 -1
  13. {eodag-3.4.3 → eodag-3.5.0}/eodag/plugins/authentication/openid_connect.py +21 -3
  14. {eodag-3.4.3 → eodag-3.5.0}/eodag/plugins/authentication/token.py +14 -2
  15. {eodag-3.4.3 → eodag-3.5.0}/eodag/plugins/authentication/token_exchange.py +1 -0
  16. {eodag-3.4.3 → eodag-3.5.0}/eodag/plugins/download/aws.py +1 -1
  17. {eodag-3.4.3 → eodag-3.5.0}/eodag/plugins/manager.py +1 -1
  18. {eodag-3.4.3 → eodag-3.5.0}/eodag/plugins/search/base.py +3 -2
  19. {eodag-3.4.3 → eodag-3.5.0}/eodag/plugins/search/build_search_result.py +10 -4
  20. {eodag-3.4.3 → eodag-3.5.0}/eodag/plugins/search/data_request_search.py +14 -1
  21. {eodag-3.4.3 → eodag-3.5.0}/eodag/plugins/search/qssearch.py +8 -2
  22. {eodag-3.4.3 → eodag-3.5.0}/eodag/resources/ext_product_types.json +1 -1
  23. {eodag-3.4.3 → eodag-3.5.0}/eodag/resources/providers.yml +4 -0
  24. {eodag-3.4.3 → eodag-3.5.0}/eodag/rest/core.py +3 -1
  25. {eodag-3.4.3 → eodag-3.5.0}/eodag/rest/errors.py +9 -4
  26. {eodag-3.4.3 → eodag-3.5.0}/eodag/rest/server.py +3 -1
  27. {eodag-3.4.3 → eodag-3.5.0}/eodag/rest/stac.py +22 -1
  28. {eodag-3.4.3 → eodag-3.5.0}/eodag/utils/__init__.py +3 -0
  29. eodag-3.5.0/eodag/utils/env.py +29 -0
  30. {eodag-3.4.3 → eodag-3.5.0/eodag.egg-info}/PKG-INFO +3 -3
  31. {eodag-3.4.3 → eodag-3.5.0}/eodag.egg-info/SOURCES.txt +1 -0
  32. {eodag-3.4.3 → eodag-3.5.0}/eodag.egg-info/requires.txt +1 -1
  33. {eodag-3.4.3 → eodag-3.5.0}/pyproject.toml +1 -1
  34. {eodag-3.4.3 → eodag-3.5.0}/setup.cfg +1 -1
  35. {eodag-3.4.3 → eodag-3.5.0}/.dockerignore +0 -0
  36. {eodag-3.4.3 → eodag-3.5.0}/.editorconfig +0 -0
  37. {eodag-3.4.3 → eodag-3.5.0}/.gitattributes +0 -0
  38. {eodag-3.4.3 → eodag-3.5.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  39. {eodag-3.4.3 → eodag-3.5.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  40. {eodag-3.4.3 → eodag-3.5.0}/.github/pull_request_template.md +0 -0
  41. {eodag-3.4.3 → eodag-3.5.0}/.github/workflows/changelog.yml +0 -0
  42. {eodag-3.4.3 → eodag-3.5.0}/.github/workflows/fetch.yml +0 -0
  43. {eodag-3.4.3 → eodag-3.5.0}/.github/workflows/github-pages.yml +0 -0
  44. {eodag-3.4.3 → eodag-3.5.0}/.github/workflows/lint-pr-title.yml +0 -0
  45. {eodag-3.4.3 → eodag-3.5.0}/.github/workflows/publish.yml +0 -0
  46. {eodag-3.4.3 → eodag-3.5.0}/.github/workflows/test.yml +0 -0
  47. {eodag-3.4.3 → eodag-3.5.0}/.gitignore +0 -0
  48. {eodag-3.4.3 → eodag-3.5.0}/.pre-commit-config.yaml +0 -0
  49. {eodag-3.4.3 → eodag-3.5.0}/BREAKING_CHANGES.rst +0 -0
  50. {eodag-3.4.3 → eodag-3.5.0}/CODE_OF_CONDUCT.md +0 -0
  51. {eodag-3.4.3 → eodag-3.5.0}/CONTRIBUTING.rst +0 -0
  52. {eodag-3.4.3 → eodag-3.5.0}/LICENSE +0 -0
  53. {eodag-3.4.3 → eodag-3.5.0}/MANIFEST.in +0 -0
  54. {eodag-3.4.3 → eodag-3.5.0}/NOTICE +0 -0
  55. {eodag-3.4.3 → eodag-3.5.0}/charts/eodag-server/Chart.lock +0 -0
  56. {eodag-3.4.3 → eodag-3.5.0}/charts/eodag-server/README.md +0 -0
  57. {eodag-3.4.3 → eodag-3.5.0}/charts/eodag-server/templates/NOTES.txt +0 -0
  58. {eodag-3.4.3 → eodag-3.5.0}/charts/eodag-server/templates/_helpers.tpl +0 -0
  59. {eodag-3.4.3 → eodag-3.5.0}/charts/eodag-server/templates/configmap.yaml +0 -0
  60. {eodag-3.4.3 → eodag-3.5.0}/charts/eodag-server/templates/deployment.yaml +0 -0
  61. {eodag-3.4.3 → eodag-3.5.0}/charts/eodag-server/templates/extra-list.yaml +0 -0
  62. {eodag-3.4.3 → eodag-3.5.0}/charts/eodag-server/templates/hpa.yaml +0 -0
  63. {eodag-3.4.3 → eodag-3.5.0}/charts/eodag-server/templates/ingress.yaml +0 -0
  64. {eodag-3.4.3 → eodag-3.5.0}/charts/eodag-server/templates/pv.yaml +0 -0
  65. {eodag-3.4.3 → eodag-3.5.0}/charts/eodag-server/templates/pvc.yaml +0 -0
  66. {eodag-3.4.3 → eodag-3.5.0}/charts/eodag-server/templates/secret.yaml +0 -0
  67. {eodag-3.4.3 → eodag-3.5.0}/charts/eodag-server/templates/service.yaml +0 -0
  68. {eodag-3.4.3 → eodag-3.5.0}/charts/eodag-server/templates/serviceaccount.yaml +0 -0
  69. {eodag-3.4.3 → eodag-3.5.0}/charts/eodag-server/values.yaml +0 -0
  70. {eodag-3.4.3 → eodag-3.5.0}/docker/run-stac-server.sh +0 -0
  71. {eodag-3.4.3 → eodag-3.5.0}/docker/stac-browser.dockerfile +0 -0
  72. {eodag-3.4.3 → eodag-3.5.0}/docker/stac-server.dockerfile +0 -0
  73. {eodag-3.4.3 → eodag-3.5.0}/docker-compose.yml +0 -0
  74. {eodag-3.4.3 → eodag-3.5.0}/docs/Makefile +0 -0
  75. {eodag-3.4.3 → eodag-3.5.0}/docs/_static/custom.css +0 -0
  76. {eodag-3.4.3 → eodag-3.5.0}/docs/_static/download_methods.png +0 -0
  77. {eodag-3.4.3 → eodag-3.5.0}/docs/_static/eodag_advanced_calls_graph.svg +0 -0
  78. {eodag-3.4.3 → eodag-3.5.0}/docs/_static/eodag_bycs.png +0 -0
  79. {eodag-3.4.3 → eodag-3.5.0}/docs/_static/eodag_fetch_product_types.png +0 -0
  80. {eodag-3.4.3 → eodag-3.5.0}/docs/_static/eodag_logo_160.png +0 -0
  81. {eodag-3.4.3 → eodag-3.5.0}/docs/_static/eodag_logo_160r.png +0 -0
  82. {eodag-3.4.3 → eodag-3.5.0}/docs/_static/eodag_main_calls_graph.svg +0 -0
  83. {eodag-3.4.3 → eodag-3.5.0}/docs/_static/eodag_overview.png +0 -0
  84. {eodag-3.4.3 → eodag-3.5.0}/docs/_static/eodag_stac_client.png +0 -0
  85. {eodag-3.4.3 → eodag-3.5.0}/docs/_static/eodag_stac_server.png +0 -0
  86. {eodag-3.4.3 → eodag-3.5.0}/docs/_static/favicon-32x32.png +0 -0
  87. {eodag-3.4.3 → eodag-3.5.0}/docs/_static/params_mapping_extra.csv +0 -0
  88. {eodag-3.4.3 → eodag-3.5.0}/docs/_static/params_mapping_offline_infos.json +0 -0
  89. {eodag-3.4.3 → eodag-3.5.0}/docs/_static/params_mapping_opensearch.csv +0 -0
  90. {eodag-3.4.3 → eodag-3.5.0}/docs/_static/product_types_information.csv +0 -0
  91. {eodag-3.4.3 → eodag-3.5.0}/docs/_static/progress_1.png +0 -0
  92. {eodag-3.4.3 → eodag-3.5.0}/docs/_static/progress_1_none.png +0 -0
  93. {eodag-3.4.3 → eodag-3.5.0}/docs/_static/progress_2.png +0 -0
  94. {eodag-3.4.3 → eodag-3.5.0}/docs/_static/progress_2_none.png +0 -0
  95. {eodag-3.4.3 → eodag-3.5.0}/docs/_static/stac_browser_example.png +0 -0
  96. {eodag-3.4.3 → eodag-3.5.0}/docs/_static/stac_browser_example_600.png +0 -0
  97. {eodag-3.4.3 → eodag-3.5.0}/docs/add_product_type.rst +0 -0
  98. {eodag-3.4.3 → eodag-3.5.0}/docs/add_provider.rst +0 -0
  99. {eodag-3.4.3 → eodag-3.5.0}/docs/api_reference/assets.rst +0 -0
  100. {eodag-3.4.3 → eodag-3.5.0}/docs/api_reference/call_graphs.rst +0 -0
  101. {eodag-3.4.3 → eodag-3.5.0}/docs/api_reference/core.rst +0 -0
  102. {eodag-3.4.3 → eodag-3.5.0}/docs/api_reference/eoproduct.rst +0 -0
  103. {eodag-3.4.3 → eodag-3.5.0}/docs/api_reference/exceptions.rst +0 -0
  104. {eodag-3.4.3 → eodag-3.5.0}/docs/api_reference/index.rst +0 -0
  105. {eodag-3.4.3 → eodag-3.5.0}/docs/api_reference/searchresult.rst +0 -0
  106. {eodag-3.4.3 → eodag-3.5.0}/docs/api_reference/types.rst +0 -0
  107. {eodag-3.4.3 → eodag-3.5.0}/docs/api_reference/utils.rst +0 -0
  108. {eodag-3.4.3 → eodag-3.5.0}/docs/api_user_guide.rst +0 -0
  109. {eodag-3.4.3 → eodag-3.5.0}/docs/breaking_changes.rst +0 -0
  110. {eodag-3.4.3 → eodag-3.5.0}/docs/changelog.rst +0 -0
  111. {eodag-3.4.3 → eodag-3.5.0}/docs/cli_user_guide.rst +0 -0
  112. {eodag-3.4.3 → eodag-3.5.0}/docs/conf.py +0 -0
  113. {eodag-3.4.3 → eodag-3.5.0}/docs/contribute.rst +0 -0
  114. {eodag-3.4.3 → eodag-3.5.0}/docs/drivers.rst +0 -0
  115. {eodag-3.4.3 → eodag-3.5.0}/docs/getting_started_guide/index.rst +0 -0
  116. {eodag-3.4.3 → eodag-3.5.0}/docs/getting_started_guide/install.rst +0 -0
  117. {eodag-3.4.3 → eodag-3.5.0}/docs/getting_started_guide/overview.rst +0 -0
  118. {eodag-3.4.3 → eodag-3.5.0}/docs/getting_started_guide/product_storage_status.rst +0 -0
  119. {eodag-3.4.3 → eodag-3.5.0}/docs/getting_started_guide/product_types.rst +0 -0
  120. {eodag-3.4.3 → eodag-3.5.0}/docs/getting_started_guide/providers.rst +0 -0
  121. {eodag-3.4.3 → eodag-3.5.0}/docs/getting_started_guide/side_projects.rst +0 -0
  122. {eodag-3.4.3 → eodag-3.5.0}/docs/index.rst +0 -0
  123. {eodag-3.4.3 → eodag-3.5.0}/docs/make.bat +0 -0
  124. {eodag-3.4.3 → eodag-3.5.0}/docs/notebooks/api_user_guide/1_overview.ipynb +0 -0
  125. {eodag-3.4.3 → eodag-3.5.0}/docs/notebooks/api_user_guide/2_providers_products_available.ipynb +0 -0
  126. {eodag-3.4.3 → eodag-3.5.0}/docs/notebooks/api_user_guide/3_configuration.ipynb +0 -0
  127. {eodag-3.4.3 → eodag-3.5.0}/docs/notebooks/api_user_guide/4_search.ipynb +0 -0
  128. {eodag-3.4.3 → eodag-3.5.0}/docs/notebooks/api_user_guide/5_queryables.ipynb +0 -0
  129. {eodag-3.4.3 → eodag-3.5.0}/docs/notebooks/api_user_guide/6_serialize_deserialize.ipynb +0 -0
  130. {eodag-3.4.3 → eodag-3.5.0}/docs/notebooks/api_user_guide/7_crunch.ipynb +0 -0
  131. {eodag-3.4.3 → eodag-3.5.0}/docs/notebooks/api_user_guide/8_download.ipynb +0 -0
  132. {eodag-3.4.3 → eodag-3.5.0}/docs/notebooks/api_user_guide/9_post_process.ipynb +0 -0
  133. {eodag-3.4.3 → eodag-3.5.0}/docs/notebooks/api_user_guide/data/crunch_search_results.geojson +0 -0
  134. {eodag-3.4.3 → eodag-3.5.0}/docs/notebooks/api_user_guide/data/download_search_results.geojson +0 -0
  135. {eodag-3.4.3 → eodag-3.5.0}/docs/notebooks/intro_notebooks.ipynb +0 -0
  136. {eodag-3.4.3 → eodag-3.5.0}/docs/notebooks/tutos/auxdata/Gulf_of_Trieste_seamask_UTM33.cpg +0 -0
  137. {eodag-3.4.3 → eodag-3.5.0}/docs/notebooks/tutos/auxdata/Gulf_of_Trieste_seamask_UTM33.dbf +0 -0
  138. {eodag-3.4.3 → eodag-3.5.0}/docs/notebooks/tutos/auxdata/Gulf_of_Trieste_seamask_UTM33.prj +0 -0
  139. {eodag-3.4.3 → eodag-3.5.0}/docs/notebooks/tutos/auxdata/Gulf_of_Trieste_seamask_UTM33.qix +0 -0
  140. {eodag-3.4.3 → eodag-3.5.0}/docs/notebooks/tutos/auxdata/Gulf_of_Trieste_seamask_UTM33.qpj +0 -0
  141. {eodag-3.4.3 → eodag-3.5.0}/docs/notebooks/tutos/auxdata/Gulf_of_Trieste_seamask_UTM33.shp +0 -0
  142. {eodag-3.4.3 → eodag-3.5.0}/docs/notebooks/tutos/auxdata/Gulf_of_Trieste_seamask_UTM33.shx +0 -0
  143. {eodag-3.4.3 → eodag-3.5.0}/docs/notebooks/tutos/auxdata/sentinel2_tiling_grid_centroids.zip +0 -0
  144. {eodag-3.4.3 → eodag-3.5.0}/docs/notebooks/tutos/tuto_burnt_areas_snappy.ipynb +0 -0
  145. {eodag-3.4.3 → eodag-3.5.0}/docs/notebooks/tutos/tuto_cds.ipynb +0 -0
  146. {eodag-3.4.3 → eodag-3.5.0}/docs/notebooks/tutos/tuto_cop_dem.ipynb +0 -0
  147. {eodag-3.4.3 → eodag-3.5.0}/docs/notebooks/tutos/tuto_ecmwf.ipynb +0 -0
  148. {eodag-3.4.3 → eodag-3.5.0}/docs/notebooks/tutos/tuto_meteoblue.ipynb +0 -0
  149. {eodag-3.4.3 → eodag-3.5.0}/docs/notebooks/tutos/tuto_search_location_tile.ipynb +0 -0
  150. {eodag-3.4.3 → eodag-3.5.0}/docs/notebooks/tutos/tuto_ship_detection.ipynb +0 -0
  151. {eodag-3.4.3 → eodag-3.5.0}/docs/notebooks/tutos/tuto_stac_client.ipynb +0 -0
  152. {eodag-3.4.3 → eodag-3.5.0}/docs/notebooks/tutos/tuto_wekeo.ipynb +0 -0
  153. {eodag-3.4.3 → eodag-3.5.0}/docs/params_mapping.rst +0 -0
  154. {eodag-3.4.3 → eodag-3.5.0}/docs/plugins.rst +0 -0
  155. {eodag-3.4.3 → eodag-3.5.0}/docs/plugins_reference/api.rst +0 -0
  156. {eodag-3.4.3 → eodag-3.5.0}/docs/plugins_reference/auth.rst +0 -0
  157. {eodag-3.4.3 → eodag-3.5.0}/docs/plugins_reference/crunch.rst +0 -0
  158. {eodag-3.4.3 → eodag-3.5.0}/docs/plugins_reference/download.rst +0 -0
  159. {eodag-3.4.3 → eodag-3.5.0}/docs/plugins_reference/search.rst +0 -0
  160. {eodag-3.4.3 → eodag-3.5.0}/docs/stac.rst +0 -0
  161. {eodag-3.4.3 → eodag-3.5.0}/docs/tutos.rst +0 -0
  162. {eodag-3.4.3 → eodag-3.5.0}/eodag/__init__.py +0 -0
  163. {eodag-3.4.3 → eodag-3.5.0}/eodag/api/__init__.py +0 -0
  164. {eodag-3.4.3 → eodag-3.5.0}/eodag/api/product/__init__.py +0 -0
  165. {eodag-3.4.3 → eodag-3.5.0}/eodag/api/product/_assets.py +0 -0
  166. {eodag-3.4.3 → eodag-3.5.0}/eodag/api/product/_product.py +0 -0
  167. {eodag-3.4.3 → eodag-3.5.0}/eodag/api/product/drivers/__init__.py +0 -0
  168. {eodag-3.4.3 → eodag-3.5.0}/eodag/api/product/drivers/base.py +0 -0
  169. {eodag-3.4.3 → eodag-3.5.0}/eodag/api/product/drivers/generic.py +0 -0
  170. {eodag-3.4.3 → eodag-3.5.0}/eodag/api/product/drivers/sentinel1.py +0 -0
  171. {eodag-3.4.3 → eodag-3.5.0}/eodag/api/product/drivers/sentinel2.py +0 -0
  172. {eodag-3.4.3 → eodag-3.5.0}/eodag/api/search_result.py +0 -0
  173. {eodag-3.4.3 → eodag-3.5.0}/eodag/cli.py +0 -0
  174. {eodag-3.4.3 → eodag-3.5.0}/eodag/crunch.py +0 -0
  175. {eodag-3.4.3 → eodag-3.5.0}/eodag/plugins/__init__.py +0 -0
  176. {eodag-3.4.3 → eodag-3.5.0}/eodag/plugins/apis/__init__.py +0 -0
  177. {eodag-3.4.3 → eodag-3.5.0}/eodag/plugins/apis/base.py +0 -0
  178. {eodag-3.4.3 → eodag-3.5.0}/eodag/plugins/apis/ecmwf.py +0 -0
  179. {eodag-3.4.3 → eodag-3.5.0}/eodag/plugins/apis/usgs.py +0 -0
  180. {eodag-3.4.3 → eodag-3.5.0}/eodag/plugins/authentication/__init__.py +0 -0
  181. {eodag-3.4.3 → eodag-3.5.0}/eodag/plugins/authentication/aws_auth.py +0 -0
  182. {eodag-3.4.3 → eodag-3.5.0}/eodag/plugins/authentication/base.py +0 -0
  183. {eodag-3.4.3 → eodag-3.5.0}/eodag/plugins/authentication/generic.py +0 -0
  184. {eodag-3.4.3 → eodag-3.5.0}/eodag/plugins/authentication/header.py +0 -0
  185. {eodag-3.4.3 → eodag-3.5.0}/eodag/plugins/authentication/oauth.py +0 -0
  186. {eodag-3.4.3 → eodag-3.5.0}/eodag/plugins/authentication/qsauth.py +0 -0
  187. {eodag-3.4.3 → eodag-3.5.0}/eodag/plugins/authentication/sas_auth.py +0 -0
  188. {eodag-3.4.3 → eodag-3.5.0}/eodag/plugins/base.py +0 -0
  189. {eodag-3.4.3 → eodag-3.5.0}/eodag/plugins/crunch/__init__.py +0 -0
  190. {eodag-3.4.3 → eodag-3.5.0}/eodag/plugins/crunch/base.py +0 -0
  191. {eodag-3.4.3 → eodag-3.5.0}/eodag/plugins/crunch/filter_date.py +0 -0
  192. {eodag-3.4.3 → eodag-3.5.0}/eodag/plugins/crunch/filter_latest_intersect.py +0 -0
  193. {eodag-3.4.3 → eodag-3.5.0}/eodag/plugins/crunch/filter_latest_tpl_name.py +0 -0
  194. {eodag-3.4.3 → eodag-3.5.0}/eodag/plugins/crunch/filter_overlap.py +0 -0
  195. {eodag-3.4.3 → eodag-3.5.0}/eodag/plugins/crunch/filter_property.py +0 -0
  196. {eodag-3.4.3 → eodag-3.5.0}/eodag/plugins/download/__init__.py +0 -0
  197. {eodag-3.4.3 → eodag-3.5.0}/eodag/plugins/download/base.py +0 -0
  198. {eodag-3.4.3 → eodag-3.5.0}/eodag/plugins/download/creodias_s3.py +0 -0
  199. {eodag-3.4.3 → eodag-3.5.0}/eodag/plugins/download/http.py +0 -0
  200. {eodag-3.4.3 → eodag-3.5.0}/eodag/plugins/download/s3rest.py +0 -0
  201. {eodag-3.4.3 → eodag-3.5.0}/eodag/plugins/search/__init__.py +0 -0
  202. {eodag-3.4.3 → eodag-3.5.0}/eodag/plugins/search/cop_marine.py +0 -0
  203. {eodag-3.4.3 → eodag-3.5.0}/eodag/plugins/search/creodias_s3.py +0 -0
  204. {eodag-3.4.3 → eodag-3.5.0}/eodag/plugins/search/csw.py +0 -0
  205. {eodag-3.4.3 → eodag-3.5.0}/eodag/plugins/search/stac_list_assets.py +0 -0
  206. {eodag-3.4.3 → eodag-3.5.0}/eodag/plugins/search/static_stac_search.py +0 -0
  207. {eodag-3.4.3 → eodag-3.5.0}/eodag/py.typed +0 -0
  208. {eodag-3.4.3 → eodag-3.5.0}/eodag/resources/locations_conf_template.yml +0 -0
  209. {eodag-3.4.3 → eodag-3.5.0}/eodag/resources/product_types.yml +0 -0
  210. {eodag-3.4.3 → eodag-3.5.0}/eodag/resources/shp/ne_110m_admin_0_map_units.VERSION.txt +0 -0
  211. {eodag-3.4.3 → eodag-3.5.0}/eodag/resources/shp/ne_110m_admin_0_map_units.cpg +0 -0
  212. {eodag-3.4.3 → eodag-3.5.0}/eodag/resources/shp/ne_110m_admin_0_map_units.dbf +0 -0
  213. {eodag-3.4.3 → eodag-3.5.0}/eodag/resources/shp/ne_110m_admin_0_map_units.prj +0 -0
  214. {eodag-3.4.3 → eodag-3.5.0}/eodag/resources/shp/ne_110m_admin_0_map_units.shp +0 -0
  215. {eodag-3.4.3 → eodag-3.5.0}/eodag/resources/shp/ne_110m_admin_0_map_units.shx +0 -0
  216. {eodag-3.4.3 → eodag-3.5.0}/eodag/resources/stac.yml +0 -0
  217. {eodag-3.4.3 → eodag-3.5.0}/eodag/resources/stac_api.yml +0 -0
  218. {eodag-3.4.3 → eodag-3.5.0}/eodag/resources/stac_provider.yml +0 -0
  219. {eodag-3.4.3 → eodag-3.5.0}/eodag/resources/user_conf_template.yml +0 -0
  220. {eodag-3.4.3 → eodag-3.5.0}/eodag/rest/__init__.py +0 -0
  221. {eodag-3.4.3 → eodag-3.5.0}/eodag/rest/cache.py +0 -0
  222. {eodag-3.4.3 → eodag-3.5.0}/eodag/rest/config.py +0 -0
  223. {eodag-3.4.3 → eodag-3.5.0}/eodag/rest/constants.py +0 -0
  224. {eodag-3.4.3 → eodag-3.5.0}/eodag/rest/server.wsgi +0 -0
  225. {eodag-3.4.3 → eodag-3.5.0}/eodag/rest/templates/README +0 -0
  226. {eodag-3.4.3 → eodag-3.5.0}/eodag/rest/types/__init__.py +0 -0
  227. {eodag-3.4.3 → eodag-3.5.0}/eodag/rest/types/collections_search.py +0 -0
  228. {eodag-3.4.3 → eodag-3.5.0}/eodag/rest/types/eodag_search.py +0 -0
  229. {eodag-3.4.3 → eodag-3.5.0}/eodag/rest/types/queryables.py +0 -0
  230. {eodag-3.4.3 → eodag-3.5.0}/eodag/rest/types/stac_search.py +0 -0
  231. {eodag-3.4.3 → eodag-3.5.0}/eodag/rest/utils/__init__.py +0 -0
  232. {eodag-3.4.3 → eodag-3.5.0}/eodag/rest/utils/cql_evaluate.py +0 -0
  233. {eodag-3.4.3 → eodag-3.5.0}/eodag/rest/utils/rfc3339.py +0 -0
  234. {eodag-3.4.3 → eodag-3.5.0}/eodag/types/__init__.py +0 -0
  235. {eodag-3.4.3 → eodag-3.5.0}/eodag/types/bbox.py +0 -0
  236. {eodag-3.4.3 → eodag-3.5.0}/eodag/types/download_args.py +0 -0
  237. {eodag-3.4.3 → eodag-3.5.0}/eodag/types/queryables.py +0 -0
  238. {eodag-3.4.3 → eodag-3.5.0}/eodag/types/search_args.py +0 -0
  239. {eodag-3.4.3 → eodag-3.5.0}/eodag/types/whoosh.py +0 -0
  240. {eodag-3.4.3 → eodag-3.5.0}/eodag/utils/exceptions.py +0 -0
  241. {eodag-3.4.3 → eodag-3.5.0}/eodag/utils/import_system.py +0 -0
  242. {eodag-3.4.3 → eodag-3.5.0}/eodag/utils/logging.py +0 -0
  243. {eodag-3.4.3 → eodag-3.5.0}/eodag/utils/notebook.py +0 -0
  244. {eodag-3.4.3 → eodag-3.5.0}/eodag/utils/repr.py +0 -0
  245. {eodag-3.4.3 → eodag-3.5.0}/eodag/utils/requests.py +0 -0
  246. {eodag-3.4.3 → eodag-3.5.0}/eodag/utils/rest.py +0 -0
  247. {eodag-3.4.3 → eodag-3.5.0}/eodag/utils/s3.py +0 -0
  248. {eodag-3.4.3 → eodag-3.5.0}/eodag/utils/stac_reader.py +0 -0
  249. {eodag-3.4.3 → eodag-3.5.0}/eodag.egg-info/dependency_links.txt +0 -0
  250. {eodag-3.4.3 → eodag-3.5.0}/eodag.egg-info/entry_points.txt +0 -0
  251. {eodag-3.4.3 → eodag-3.5.0}/eodag.egg-info/top_level.txt +0 -0
  252. {eodag-3.4.3 → eodag-3.5.0}/get_pypi_latest_version.sh +0 -0
  253. {eodag-3.4.3 → eodag-3.5.0}/pytest.ini +0 -0
  254. {eodag-3.4.3 → eodag-3.5.0}/readthedocs.yml +0 -0
  255. {eodag-3.4.3 → eodag-3.5.0}/requirements-dev.txt +0 -0
  256. {eodag-3.4.3 → eodag-3.5.0}/requirements-docs.txt +0 -0
  257. {eodag-3.4.3 → eodag-3.5.0}/requirements-tutorials.txt +0 -0
  258. {eodag-3.4.3 → eodag-3.5.0}/requirements.txt +0 -0
  259. {eodag-3.4.3 → eodag-3.5.0}/setup.py +0 -0
  260. {eodag-3.4.3 → eodag-3.5.0}/tox.ini +0 -0
  261. {eodag-3.4.3 → eodag-3.5.0}/utils/params_mapping_to_csv.py +0 -0
  262. {eodag-3.4.3 → eodag-3.5.0}/utils/product_types_information_to_csv.py +0 -0
@@ -33,9 +33,12 @@ jobs:
33
33
  source .venv/bin/activate
34
34
  uv pip install python-semantic-release packaging
35
35
  - name: Set Git config
36
+ env:
37
+ TOKEN: ${{ secrets.USER_TOKEN }}
36
38
  run: |
37
39
  git config user.name "github-actions[bot]"
38
40
  git config user.email "'github-actions[bot]@users.noreply.github.com"
41
+ git remote set-url origin https://$TOKEN@github.com/${{ github.repository }}.git
39
42
  - name: Git merge develop in master
40
43
  run: |
41
44
  git checkout master
@@ -62,9 +65,12 @@ jobs:
62
65
  # Get history and tags for SCM versioning to work
63
66
  fetch-depth: 0
64
67
  - name: Set Git config
68
+ env:
69
+ TOKEN: ${{ secrets.USER_TOKEN }}
65
70
  run: |
66
71
  git config user.name "github-actions[bot]"
67
72
  git config user.email "'github-actions[bot]@users.noreply.github.com"
73
+ git remote set-url origin https://$TOKEN@github.com/${{ github.repository }}.git
68
74
  - name: Git merge master in develop
69
75
  run: |
70
76
  git checkout develop
@@ -3,6 +3,66 @@ Release history
3
3
  ===============
4
4
 
5
5
 
6
+ v3.5.0 (2025-06-20)
7
+ ===================
8
+
9
+ Bug Fixes
10
+ ---------
11
+
12
+ * **core**: Always validate PluginConfig before loading (`#1690`_, `59ac437`_)
13
+
14
+ * **core**: Skip provider empty conf on init (`#1687`_, `0a4104e`_)
15
+
16
+ * **plugins**: Raise errors when metadata discovery is not allowed (`#1534`_, `855ffa3`_)
17
+
18
+ Build System
19
+ ------------
20
+
21
+ * Update usgs to 0.3.6 (`#1688`_, `e63cfb1`_)
22
+
23
+ Continuous Integration
24
+ ----------------------
25
+
26
+ * Use personal access token for deploy github action (`#1693`_, `ff777d7`_)
27
+
28
+ Documentation
29
+ -------------
30
+
31
+ * Dead-links and out-of-date param fix (`#1692`_, `445a20e`_)
32
+
33
+ Features
34
+ --------
35
+
36
+ * **core**: Add env variable to whitelist providers (`#1672`_, `b93c4c8`_)
37
+
38
+ * **core**: Add strict product types mode (`#1677`_, `5077fa5`_)
39
+
40
+ * **plugins**: Auth token expiration margin (`#1665`_, `ef5fc18`_)
41
+
42
+ * **server**: Added bbox filter support for collections search (`#1671`_, `5717f0d`_)
43
+
44
+ .. _#1534: https://github.com/CS-SI/eodag/pull/1534
45
+ .. _#1665: https://github.com/CS-SI/eodag/pull/1665
46
+ .. _#1671: https://github.com/CS-SI/eodag/pull/1671
47
+ .. _#1672: https://github.com/CS-SI/eodag/pull/1672
48
+ .. _#1677: https://github.com/CS-SI/eodag/pull/1677
49
+ .. _#1687: https://github.com/CS-SI/eodag/pull/1687
50
+ .. _#1688: https://github.com/CS-SI/eodag/pull/1688
51
+ .. _#1690: https://github.com/CS-SI/eodag/pull/1690
52
+ .. _#1692: https://github.com/CS-SI/eodag/pull/1692
53
+ .. _#1693: https://github.com/CS-SI/eodag/pull/1693
54
+ .. _0a4104e: https://github.com/CS-SI/eodag/commit/0a4104e0518abc70e2133ca98472eea87d673a1c
55
+ .. _445a20e: https://github.com/CS-SI/eodag/commit/445a20e060730642e703615c73225c0df3cc84d0
56
+ .. _5077fa5: https://github.com/CS-SI/eodag/commit/5077fa591496811fb100c1e6b6a3e452cbdbe2a5
57
+ .. _5717f0d: https://github.com/CS-SI/eodag/commit/5717f0deddbf022f2c6d5207ade77de6afb0f9d5
58
+ .. _59ac437: https://github.com/CS-SI/eodag/commit/59ac437de01a8996d247b1f8239f332ed5dc5456
59
+ .. _855ffa3: https://github.com/CS-SI/eodag/commit/855ffa39fa9b914eb39cc20d6e5c2cbbc1b2097a
60
+ .. _b93c4c8: https://github.com/CS-SI/eodag/commit/b93c4c88f323af0eecb0950c90c6862ca9a7c3f4
61
+ .. _e63cfb1: https://github.com/CS-SI/eodag/commit/e63cfb19ca64a2ed65f500ae9678e117a2ea4cf8
62
+ .. _ef5fc18: https://github.com/CS-SI/eodag/commit/ef5fc188e515759c9227584b25805db75f537833
63
+ .. _ff777d7: https://github.com/CS-SI/eodag/commit/ff777d7a1e33f612c5227dba4fecfcec55ff18fc
64
+
65
+
6
66
  v3.4.3 (2025-06-12)
7
67
  ===================
8
68
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: eodag
3
- Version: 3.4.3
3
+ Version: 3.5.0
4
4
  Summary: Earth Observation Data Access Gateway
5
5
  Home-page: https://github.com/CS-SI/eodag
6
6
  Author: CS GROUP - France
@@ -64,7 +64,7 @@ Requires-Dist: OWSLib>=0.27.1; extra == "csw"
64
64
  Provides-Extra: ecmwf
65
65
  Requires-Dist: ecmwf-api-client; extra == "ecmwf"
66
66
  Provides-Extra: usgs
67
- Requires-Dist: usgs>=0.3.1; extra == "usgs"
67
+ Requires-Dist: usgs>=0.3.6; extra == "usgs"
68
68
  Provides-Extra: server
69
69
  Requires-Dist: fastapi>=0.93.0; extra == "server"
70
70
  Requires-Dist: pygeofilter; extra == "server"
@@ -317,7 +317,7 @@ An eodag instance can be exposed through a STAC compliant REST api from the comm
317
317
 
318
318
  .. code-block:: bash
319
319
 
320
- docker run -p 5000:5000 --rm csspace/eodag-server:3.4.3
320
+ docker run -p 5000:5000 --rm csspace/eodag-server:3.5.0
321
321
 
322
322
  You can also browse over your STAC API server using `STAC Browser <https://github.com/radiantearth/stac-browser>`_.
323
323
  Simply run:
@@ -187,7 +187,7 @@ An eodag instance can be exposed through a STAC compliant REST api from the comm
187
187
 
188
188
  .. code-block:: bash
189
189
 
190
- docker run -p 5000:5000 --rm csspace/eodag-server:3.4.3
190
+ docker run -p 5000:5000 --rm csspace/eodag-server:3.5.0
191
191
 
192
192
  You can also browse over your STAC API server using `STAC Browser <https://github.com/radiantearth/stac-browser>`_.
193
193
  Simply run:
@@ -1,5 +1,5 @@
1
1
  apiVersion: v2
2
- appVersion: 3.4.3
2
+ appVersion: 3.5.0
3
3
  dependencies:
4
4
  - name: common
5
5
  repository: oci://registry-1.docker.io/bitnamicharts
@@ -15,4 +15,4 @@ name: eodag-server
15
15
  sources:
16
16
  - https://github.com/CS-SI/eodag
17
17
  type: application
18
- version: 3.4.3
18
+ version: 3.5.0
@@ -157,6 +157,26 @@ Some EODAG core settings can be overriden using environment variables:
157
157
  <https://eodag.readthedocs.io/en/stable/notebooks/api_user_guide/2_providers_products_available.html#Product-types-discovery>`_
158
158
  in place of https://cs-si.github.io/eodag/eodag/resources/ext_product_types.json.
159
159
  If the file is not readable, only user-modified providers will be fetched.
160
+ * ``EODAG_PROVIDERS_WHITELIST`` to restrict EODAG to only use a specific list of providers.
161
+
162
+ If this environment variable is set (as a comma-separated list of provider names), EODAG will only load and use the specified providers.
163
+ All other providers will be ignored, regardless of their presence in configuration files.
164
+
165
+ This is useful for restricting EODAG to a subset of providers, for example in controlled or production environments.
166
+ * ``EODAG_STRICT_PRODUCT_TYPES`` to control how product types are listed.
167
+
168
+ If this environment variable is set to a truthy value (such as ``1``, ``true``, ``yes``, or ``on``), EODAG will only list product types that are present in the main product types configuration file.
169
+ Product types defined only in provider configurations (but not in the main product types configuration) will be ignored.
170
+ If not set, EODAG will also include product types defined only in provider configurations, with minimal metadata.
171
+
172
+ This is useful if you want to strictly control which product types are available, for example to ensure consistency across environments.
173
+
174
+ Example usage:
175
+
176
+ .. code-block:: bash
177
+
178
+ export EODAG_PROVIDERS_WHITELIST=peps,creodias,theia
179
+ export EODAG_STRICT_PRODUCT_TYPES=true
160
180
 
161
181
  CLI configuration
162
182
  ^^^^^^^^^^^^^^^^^
@@ -150,7 +150,7 @@ No authentication needed.
150
150
 
151
151
  ``ecmwf``
152
152
  ^^^^^^^^^
153
- Create an account `here <https://apps.ecmwf.int/registration/>`__.
153
+ Create an account `here <https://www.ecmwf.int/user/login>`__.
154
154
 
155
155
  Then use *email* as ``username`` and *key* as ``password`` from `here <https://api.ecmwf.int/v1/key/>`__ in eodag credentials.
156
156
  EODAG can be used to request for public datasets as for operational archive. Please note that for public datasets you
@@ -115,7 +115,7 @@ available on `https://hub.docker.com/r/csspace/eodag-server <https://hub.docker.
115
115
 
116
116
  .. code-block:: bash
117
117
 
118
- $ docker run -p 5000:5000 --rm csspace/eodag-server:3.4.3
118
+ $ docker run -p 5000:5000 --rm csspace/eodag-server:3.5.0
119
119
 
120
120
  Example
121
121
  -------
@@ -36,6 +36,7 @@ from whoosh.index import exists_in, open_dir
36
36
  from whoosh.qparser import QueryParser
37
37
 
38
38
  from eodag.api.product.metadata_mapping import (
39
+ NOT_AVAILABLE,
39
40
  ONLINE_STATUS,
40
41
  mtd_cfg_as_conversion_and_querypath,
41
42
  )
@@ -79,6 +80,7 @@ from eodag.utils import (
79
80
  string_to_jsonpath,
80
81
  uri_to_path,
81
82
  )
83
+ from eodag.utils.env import is_env_var_true
82
84
  from eodag.utils.exceptions import (
83
85
  AuthenticationError,
84
86
  EodagError,
@@ -175,12 +177,19 @@ class EODataAccessGateway:
175
177
  share_credentials(self.providers_config)
176
178
 
177
179
  # init updated providers conf
180
+ strict_mode = is_env_var_true("EODAG_STRICT_PRODUCT_TYPES")
181
+ available_product_types = set(self.product_types_config.source.keys())
182
+
178
183
  for provider in self.providers_config.keys():
179
184
  provider_config_init(
180
185
  self.providers_config[provider],
181
186
  load_stac_provider_config(),
182
187
  )
183
188
 
189
+ self._sync_provider_product_types(
190
+ provider, available_product_types, strict_mode
191
+ )
192
+
184
193
  # re-build _plugins_manager using up-to-date providers_config
185
194
  self._plugins_manager.rebuild(self.providers_config)
186
195
 
@@ -226,6 +235,61 @@ class EODataAccessGateway:
226
235
  )
227
236
  self.set_locations_conf(locations_conf_path)
228
237
 
238
+ def _sync_provider_product_types(
239
+ self,
240
+ provider: str,
241
+ available_product_types: set[str],
242
+ strict_mode: bool,
243
+ ) -> None:
244
+ """
245
+ Synchronize product types for a provider based on strict or permissive mode.
246
+
247
+ In strict mode, removes product types not in available_product_types.
248
+ In permissive mode, adds empty product type configs for missing types.
249
+
250
+ :param provider: The provider name whose product types should be synchronized.
251
+ :param available_product_types: The set of available product type IDs.
252
+ :param strict_mode: If True, remove unknown product types; if False, add empty configs for them.
253
+ :returns: None
254
+ """
255
+ provider_products = self.providers_config[provider].products
256
+ products_to_remove: list[str] = []
257
+ products_to_add: list[str] = []
258
+
259
+ for product_id in provider_products:
260
+ if product_id == GENERIC_PRODUCT_TYPE:
261
+ continue
262
+
263
+ if product_id not in available_product_types:
264
+ if strict_mode:
265
+ products_to_remove.append(product_id)
266
+ continue
267
+
268
+ empty_product = {
269
+ "title": product_id,
270
+ "abstract": NOT_AVAILABLE,
271
+ }
272
+ self.product_types_config.source[
273
+ product_id
274
+ ] = empty_product # will update available_product_types
275
+ products_to_add.append(product_id)
276
+
277
+ if products_to_add:
278
+ logger.debug(
279
+ "Product types permissive mode, %s added (provider %s)",
280
+ ", ".join(products_to_add),
281
+ provider,
282
+ )
283
+
284
+ if products_to_remove:
285
+ logger.debug(
286
+ "Product types strict mode, ignoring %s (provider %s)",
287
+ ", ".join(products_to_remove),
288
+ provider,
289
+ )
290
+ for id in products_to_remove:
291
+ del self.providers_config[provider].products[id]
292
+
229
293
  def get_version(self) -> str:
230
294
  """Get eodag package version"""
231
295
  return version("eodag")
@@ -608,11 +672,14 @@ class EODataAccessGateway:
608
672
  for product_type_id in p.products: # type: ignore
609
673
  if product_type_id == GENERIC_PRODUCT_TYPE:
610
674
  continue
675
+
611
676
  config = self.product_types_config[product_type_id]
612
677
  config["_id"] = product_type_id
678
+
613
679
  if "alias" in config:
614
680
  product_type_id = config["alias"]
615
681
  product_type = {"ID": product_type_id, **config}
682
+
616
683
  if product_type not in product_types:
617
684
  product_types.append(product_type)
618
685
 
@@ -620,11 +687,18 @@ class EODataAccessGateway:
620
687
  return sorted(product_types, key=itemgetter("ID"))
621
688
 
622
689
  def fetch_product_types_list(self, provider: Optional[str] = None) -> None:
623
- """Fetch product types list and update if needed
690
+ """Fetch product types list and update if needed.
691
+
692
+ If strict mode is enabled (by setting the ``EODAG_STRICT_PRODUCT_TYPES`` environment variable
693
+ to a truthy value), this method will not fetch or update product types and will return immediately.
624
694
 
625
695
  :param provider: The name of a provider or provider-group for which product types
626
696
  list should be updated. Defaults to all providers (None value).
627
697
  """
698
+ strict_mode = is_env_var_true("EODAG_STRICT_PRODUCT_TYPES")
699
+ if strict_mode:
700
+ return
701
+
628
702
  providers_to_fetch = list(self.providers_config.keys())
629
703
  # check if some providers are grouped under a group name which is not a provider name
630
704
  if provider is not None and provider not in self.providers_config:
@@ -54,6 +54,7 @@ from eodag.utils import (
54
54
  string_to_jsonpath,
55
55
  update_nested_dict,
56
56
  )
57
+ from eodag.utils.exceptions import ValidationError
57
58
 
58
59
  if TYPE_CHECKING:
59
60
  from shapely.geometry.base import BaseGeometry
@@ -1286,7 +1287,10 @@ def mtd_cfg_as_conversion_and_querypath(
1286
1287
 
1287
1288
 
1288
1289
  def format_query_params(
1289
- product_type: str, config: PluginConfig, query_dict: dict[str, Any]
1290
+ product_type: str,
1291
+ config: PluginConfig,
1292
+ query_dict: dict[str, Any],
1293
+ error_context: str = "",
1290
1294
  ) -> dict[str, Any]:
1291
1295
  """format the search parameters to query parameters"""
1292
1296
  if "raise_errors" in query_dict.keys():
@@ -1299,10 +1303,26 @@ def format_query_params(
1299
1303
  **config.products.get(product_type, {}).get("metadata_mapping", {}),
1300
1304
  )
1301
1305
 
1306
+ # Raise error if non-queryables parameters are used and raise_mtd_discovery_error configured
1307
+ if (
1308
+ raise_mtd_discovery_error := config.products.get(product_type, {})
1309
+ .get("discover_metadata", {})
1310
+ .get("raise_mtd_discovery_error")
1311
+ ) is None:
1312
+ raise_mtd_discovery_error = getattr(config, "discover_metadata", {}).get(
1313
+ "raise_mtd_discovery_error", False
1314
+ )
1315
+
1302
1316
  query_params: dict[str, Any] = {}
1303
1317
  # Get all the search parameters that are recognised as queryables by the
1304
1318
  # provider (they appear in the queryables dictionary)
1305
- queryables = _get_queryables(query_dict, config, product_type_metadata_mapping)
1319
+ queryables = _get_queryables(
1320
+ query_dict,
1321
+ config,
1322
+ product_type_metadata_mapping,
1323
+ raise_mtd_discovery_error,
1324
+ error_context,
1325
+ )
1306
1326
 
1307
1327
  for eodag_search_key, provider_search_key in queryables.items():
1308
1328
  user_input = query_dict[eodag_search_key]
@@ -1438,6 +1458,8 @@ def _get_queryables(
1438
1458
  search_params: dict[str, Any],
1439
1459
  config: PluginConfig,
1440
1460
  metadata_mapping: dict[str, Any],
1461
+ raise_mtd_discovery_error: bool,
1462
+ error_context: str,
1441
1463
  ) -> dict[str, Any]:
1442
1464
  """Retrieve the metadata mappings that are query-able"""
1443
1465
  logger.debug("Retrieving queryable metadata from metadata_mapping")
@@ -1445,6 +1467,13 @@ def _get_queryables(
1445
1467
  for eodag_search_key, user_input in search_params.items():
1446
1468
  if user_input is not None:
1447
1469
  md_mapping = metadata_mapping.get(eodag_search_key, (None, NOT_MAPPED))
1470
+ # raise an error when a query param not allowed by the provider is found
1471
+ if not isinstance(md_mapping, list) and raise_mtd_discovery_error:
1472
+ raise ValidationError(
1473
+ "Search parameters which are not queryable are disallowed for this product type on this provider: "
1474
+ f"please remove '{eodag_search_key}' from your search parameters. {error_context}",
1475
+ {eodag_search_key},
1476
+ )
1448
1477
  _, md_value = md_mapping
1449
1478
  # query param from defined metadata_mapping
1450
1479
  if md_mapping is not None and isinstance(md_mapping, list):
@@ -194,12 +194,24 @@ class ProviderConfig(yaml.YAMLObject):
194
194
  },
195
195
  )
196
196
  for key in PLUGINS_TOPICS_KEYS:
197
- current_value: Optional[dict[str, Any]] = getattr(self, key, None)
197
+ current_value: Optional[PluginConfig] = getattr(self, key, None)
198
198
  mapping_value = mapping.get(key, {})
199
199
  if current_value is not None:
200
200
  current_value.update(mapping_value)
201
201
  elif mapping_value:
202
- setattr(self, key, PluginConfig.from_mapping(mapping_value))
202
+ try:
203
+ setattr(self, key, PluginConfig.from_mapping(mapping_value))
204
+ except ValidationError as e:
205
+ logger.warning(
206
+ (
207
+ "Could not add %s Plugin config to %s configuration: %s. "
208
+ "Try updating existing %s Plugin configs instead."
209
+ ),
210
+ key,
211
+ self.name,
212
+ str(e),
213
+ ", ".join([k for k in PLUGINS_TOPICS_KEYS if hasattr(self, k)]),
214
+ )
203
215
 
204
216
 
205
217
  class PluginConfig(yaml.YAMLObject):
@@ -256,9 +268,11 @@ class PluginConfig(yaml.YAMLObject):
256
268
  #: Metadata regex pattern used for discovery in search result properties
257
269
  metadata_pattern: str
258
270
  #: Configuration/template that will be used to query for a discovered parameter
259
- search_param: str
271
+ search_param: str | dict[str, Any]
260
272
  #: Path to the metadata in search result
261
273
  metadata_path: str
274
+ #: Whether an error must be raised when using a search parameter which is not queryable or not
275
+ raise_mtd_discovery_error: bool
262
276
 
263
277
  class DiscoverProductTypes(TypedDict, total=False):
264
278
  """Configuration for product types discovery"""
@@ -628,6 +642,10 @@ class PluginConfig(yaml.YAMLObject):
628
642
  #: :class:`~eodag.plugins.authentication.token_exchange.OIDCTokenExchangeAuth`
629
643
  #: Identifies the issuer of the `subject_token`
630
644
  subject_issuer: str
645
+ #: :class:`~eodag.plugins.authentication.token.TokenAuth`
646
+ #: :class:`~eodag.plugins.authentication.openid_connect.OIDCRefreshTokenBase`
647
+ #: Safety buffer to prevent token rejection from unexpected expiry between validity check and request.
648
+ token_expiration_margin: int
631
649
  #: :class:`~eodag.plugins.authentication.token_exchange.OIDCTokenExchangeAuth`
632
650
  #: Audience that the token ID is intended for. :attr:`~eodag.config.PluginConfig.client_id` of the Relying Party
633
651
  audience: str
@@ -648,6 +666,7 @@ class PluginConfig(yaml.YAMLObject):
648
666
  @classmethod
649
667
  def from_mapping(cls, mapping: dict[str, Any]) -> PluginConfig:
650
668
  """Build a :class:`~eodag.config.PluginConfig` from a mapping"""
669
+ cls.validate(tuple(mapping.keys()))
651
670
  c = cls()
652
671
  c.__dict__.update(mapping)
653
672
  return c
@@ -657,7 +676,7 @@ class PluginConfig(yaml.YAMLObject):
657
676
  """Validate a :class:`~eodag.config.PluginConfig`"""
658
677
  if "type" not in config_keys:
659
678
  raise ValidationError(
660
- "A Plugin config must specify the Plugin it configures"
679
+ "A Plugin config must specify the type of Plugin it configures"
661
680
  )
662
681
 
663
682
  def update(self, mapping: Optional[dict[Any, Any]]) -> None:
@@ -689,6 +708,8 @@ def load_default_config() -> dict[str, ProviderConfig]:
689
708
  def load_config(config_path: str) -> dict[str, ProviderConfig]:
690
709
  """Load the providers configuration into a dictionary from a given file
691
710
 
711
+ If EODAG_PROVIDERS_WHITELIST is set, only load listed providers.
712
+
692
713
  :param config_path: The path to the provider config file
693
714
  :returns: The default provider's configuration
694
715
  """
@@ -701,10 +722,23 @@ def load_config(config_path: str) -> dict[str, ProviderConfig]:
701
722
  except yaml.parser.ParserError as e:
702
723
  logger.error("Unable to load configuration")
703
724
  raise e
725
+
704
726
  stac_provider_config = load_stac_provider_config()
727
+
728
+ whitelist_env = os.getenv("EODAG_PROVIDERS_WHITELIST")
729
+ whitelist = None
730
+ if whitelist_env:
731
+ whitelist = {provider for provider in whitelist_env.split(",")}
732
+ logger.info("Using providers whitelist: %s", ", ".join(whitelist))
733
+
705
734
  for provider_config in providers_configs:
735
+ if provider_config is None or (
736
+ whitelist and provider_config.name not in whitelist
737
+ ):
738
+ continue
706
739
  provider_config_init(provider_config, stac_provider_config)
707
740
  config[provider_config.name] = provider_config
741
+
708
742
  return config
709
743
 
710
744
 
@@ -803,7 +837,9 @@ def provider_config_init(
803
837
  pass
804
838
 
805
839
 
806
- def override_config_from_file(config: dict[str, Any], file_path: str) -> None:
840
+ def override_config_from_file(
841
+ config: dict[str, ProviderConfig], file_path: str
842
+ ) -> None:
807
843
  """Override a configuration with the values in a file
808
844
 
809
845
  :param config: An eodag providers configuration dictionary
@@ -818,10 +854,11 @@ def override_config_from_file(config: dict[str, Any], file_path: str) -> None:
818
854
  except yaml.parser.ParserError as e:
819
855
  logger.error("Unable to load user configuration file")
820
856
  raise e
857
+
821
858
  override_config_from_mapping(config, config_in_file)
822
859
 
823
860
 
824
- def override_config_from_env(config: dict[str, Any]) -> None:
861
+ def override_config_from_env(config: dict[str, ProviderConfig]) -> None:
825
862
  """Override a configuration with environment variables values
826
863
 
827
864
  :param config: An eodag providers configuration dictionary
@@ -892,16 +929,25 @@ def override_config_from_env(config: dict[str, Any]) -> None:
892
929
 
893
930
 
894
931
  def override_config_from_mapping(
895
- config: dict[str, Any], mapping: dict[str, Any]
932
+ config: dict[str, ProviderConfig], mapping: dict[str, Any]
896
933
  ) -> None:
897
- """Override a configuration with the values in a mapping
934
+ """Override a configuration with the values in a mapping.
935
+
936
+ If the environment variable ``EODAG_PROVIDERS_WHITELIST`` is set (as a comma-separated list of provider names),
937
+ only the listed providers will be used from the mapping. All other providers in the mapping will be ignored.
898
938
 
899
939
  :param config: An eodag providers configuration dictionary
900
940
  :param mapping: The mapping containing the values to be overriden
901
941
  """
942
+ whitelist_env = os.getenv("EODAG_PROVIDERS_WHITELIST")
943
+ whitelist = None
944
+ if whitelist_env:
945
+ whitelist = {provider for provider in whitelist_env.split(",")}
946
+
902
947
  for provider, new_conf in mapping.items():
903
948
  # check if metada-mapping as already been built as jsonpath in providers_config
904
- if not isinstance(new_conf, dict):
949
+ # or provider not in whitelist
950
+ if not isinstance(new_conf, dict) or (whitelist and provider not in whitelist):
905
951
  continue
906
952
  new_conf_search = new_conf.get("search", {}) or {}
907
953
  new_conf_api = new_conf.get("api", {}) or {}
@@ -930,7 +976,7 @@ def override_config_from_mapping(
930
976
  )
931
977
 
932
978
  # try overriding conf
933
- old_conf: Optional[dict[str, Any]] = config.get(provider)
979
+ old_conf: Optional[ProviderConfig] = config.get(provider)
934
980
  if old_conf is not None:
935
981
  old_conf.update(new_conf)
936
982
  else:
@@ -60,8 +60,10 @@ class KeycloakOIDCPasswordAuth(OIDCRefreshTokenBase):
60
60
  The allowed audiences that have to be present in the user token.
61
61
  * :attr:`~eodag.config.PluginConfig.auth_error_code` (``int``): which error code is
62
62
  returned in case of an authentication error
63
- * :attr:`~eodag.config.PluginConfig.ssl_verify` (``bool``): if the ssl certificates
63
+ * :attr:`~eodag.config.PluginConfig.ssl_verify` (``bool``): If the SSL certificates
64
64
  should be verified in the token request; default: ``True``
65
+ * :attr:`~eodag.config.PluginConfig.token_expiration_margin` (``int``): The margin of time (in seconds)
66
+ before a token is considered expired. Default: 60 seconds
65
67
 
66
68
  Using :class:`~eodag.plugins.download.http.HTTPDownload` a download link
67
69
  ``http://example.com?foo=bar`` will become
@@ -30,7 +30,14 @@ from lxml import etree
30
30
  from requests.auth import AuthBase
31
31
 
32
32
  from eodag.plugins.authentication import Authentication
33
- from eodag.utils import HTTP_REQ_TIMEOUT, USER_AGENT, parse_qs, repeatfunc, urlparse
33
+ from eodag.utils import (
34
+ DEFAULT_TOKEN_EXPIRATION_MARGIN,
35
+ HTTP_REQ_TIMEOUT,
36
+ USER_AGENT,
37
+ parse_qs,
38
+ repeatfunc,
39
+ urlparse,
40
+ )
34
41
  from eodag.utils.exceptions import (
35
42
  AuthenticationError,
36
43
  MisconfiguredError,
@@ -117,13 +124,22 @@ class OIDCRefreshTokenBase(Authentication):
117
124
 
118
125
  def _get_access_token(self) -> str:
119
126
  now = datetime.now(timezone.utc)
120
- if self.access_token and now < self.access_token_expiration:
127
+ expiration_margin = timedelta(
128
+ seconds=getattr(
129
+ self.config, "token_expiration_margin", DEFAULT_TOKEN_EXPIRATION_MARGIN
130
+ )
131
+ )
132
+
133
+ if self.access_token and self.access_token_expiration - now > expiration_margin:
121
134
  logger.debug(
122
135
  f"Existing access_token is still valid until {self.access_token_expiration.isoformat()}."
123
136
  )
124
137
  return self.access_token
125
138
 
126
- elif self.refresh_token and now < self.refresh_token_expiration:
139
+ elif (
140
+ self.refresh_token
141
+ and self.refresh_token_expiration - now > expiration_margin
142
+ ):
127
143
  response = self._get_token_with_refresh_token()
128
144
  logger.debug(
129
145
  "access_token expired, fetching new access_token using refresh_token"
@@ -268,6 +284,8 @@ class OIDCAuthorizationCodeFlowAuth(OIDCRefreshTokenBase):
268
284
  Refers to the name of the query param to be used in the query request
269
285
  * :attr:`~eodag.config.PluginConfig.refresh_token_key` (``str``): The key pointing to
270
286
  the refresh_token in the json response to the POST request to the token server
287
+ * :attr:`~eodag.config.PluginConfig.token_expiration_margin` (``int``): The margin of time (in seconds)
288
+ before a token is considered expired. Default: 60 seconds.
271
289
 
272
290
  """
273
291
 
@@ -31,6 +31,7 @@ from urllib3 import Retry
31
31
 
32
32
  from eodag.plugins.authentication.base import Authentication
33
33
  from eodag.utils import (
34
+ DEFAULT_TOKEN_EXPIRATION_MARGIN,
34
35
  HTTP_REQ_TIMEOUT,
35
36
  REQ_RETRY_BACKOFF_FACTOR,
36
37
  REQ_RETRY_STATUS_FORCELIST,
@@ -90,6 +91,8 @@ class TokenAuth(Authentication):
90
91
  * :attr:`~eodag.config.PluginConfig.retry_status_forcelist` (``list[int]``): :class:`urllib3.util.Retry`
91
92
  ``status_forcelist`` parameter, list of integer HTTP status codes that we should force a retry on; default:
92
93
  ``[401, 429, 500, 502, 503, 504]``
94
+ * :attr:`~eodag.config.PluginConfig.token_expiration_margin` (``int``): The margin of time (in seconds) before
95
+ a token is considered expired. Default: 60 seconds.
93
96
  """
94
97
 
95
98
  def __init__(self, provider: str, config: PluginConfig) -> None:
@@ -152,9 +155,18 @@ class TokenAuth(Authentication):
152
155
 
153
156
  # Use a thread lock to avoid several threads requesting the token at the same time
154
157
  with self.auth_lock:
155
-
158
+ expiration_margin = timedelta(
159
+ seconds=getattr(
160
+ self.config,
161
+ "token_expiration_margin",
162
+ DEFAULT_TOKEN_EXPIRATION_MARGIN,
163
+ )
164
+ )
156
165
  self.validate_config_credentials()
157
- if self.token and self.token_expiration > datetime.now():
166
+ if (
167
+ self.token
168
+ and self.token_expiration - datetime.now() > expiration_margin
169
+ ):
158
170
  logger.debug("using existing access token")
159
171
  return RequestsTokenAuth(
160
172
  self.token, "header", headers=getattr(self.config, "headers", {})
@@ -79,6 +79,7 @@ class OIDCTokenExchangeAuth(Authentication):
79
79
  provider,
80
80
  PluginConfig.from_mapping(
81
81
  {
82
+ "type": "OIDCAuthorizationCodeFlowAuth",
82
83
  "credentials": getattr(self.config, "credentials", {}),
83
84
  **self.config.subject,
84
85
  }