hdx-python-api 6.7.5__tar.gz → 6.7.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 (151) hide show
  1. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/PKG-INFO +3 -3
  2. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/pyproject.toml +2 -2
  3. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/src/hdx/api/_version.py +2 -2
  4. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/src/hdx/data/resource.py +30 -2
  5. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/hdx/data/test_resource.py +38 -0
  6. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/uv.lock +178 -17
  7. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/.github/workflows/publish.yaml +0 -0
  8. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/.github/workflows/run-python-tests.yaml +0 -0
  9. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/.gitignore +0 -0
  10. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/.pre-commit-config.yaml +0 -0
  11. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/CLAUDE.md +0 -0
  12. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/LICENSE +0 -0
  13. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/README.md +0 -0
  14. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/documentation/.readthedocs.yaml +0 -0
  15. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/documentation/index.md +0 -0
  16. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/documentation/mkdocs.yaml +0 -0
  17. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/src/hdx/api/__init__.py +0 -0
  18. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/src/hdx/api/configuration.py +0 -0
  19. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/src/hdx/api/hdx_base_configuration.yaml +0 -0
  20. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/src/hdx/api/locations.py +0 -0
  21. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/src/hdx/api/remotehdx.py +0 -0
  22. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/src/hdx/api/utilities/__init__.py +0 -0
  23. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/src/hdx/api/utilities/date_helper.py +0 -0
  24. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/src/hdx/api/utilities/filestore_helper.py +0 -0
  25. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/src/hdx/api/utilities/hdx_error_handler.py +0 -0
  26. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/src/hdx/api/utilities/hdx_state.py +0 -0
  27. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/src/hdx/api/utilities/hdx_stats.py +0 -0
  28. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/src/hdx/api/utilities/url_utils.py +0 -0
  29. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/src/hdx/data/__init__.py +0 -0
  30. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/src/hdx/data/activity.py +0 -0
  31. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/src/hdx/data/dataset.py +0 -0
  32. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/src/hdx/data/hdxobject.py +0 -0
  33. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/src/hdx/data/location.py +0 -0
  34. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/src/hdx/data/organization.py +0 -0
  35. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/src/hdx/data/resource_matcher.py +0 -0
  36. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/src/hdx/data/resource_view.py +0 -0
  37. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/src/hdx/data/showcase.py +0 -0
  38. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/src/hdx/data/user.py +0 -0
  39. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/src/hdx/data/vocabulary.py +0 -0
  40. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/src/hdx/facades/__init__.py +0 -0
  41. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/src/hdx/facades/infer_arguments.py +0 -0
  42. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/src/hdx/facades/keyword_arguments.py +0 -0
  43. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/src/hdx/facades/simple.py +0 -0
  44. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/__init__.py +0 -0
  45. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/Accepted_Tags.csv +0 -0
  46. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/CKAN/hdx_dataset_static.yaml +0 -0
  47. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/Tag_Mapping.csv +0 -0
  48. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/Tag_Mapping_ChainRuleError.csv +0 -0
  49. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/config/empty.yaml +0 -0
  50. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/config/hdx_base_config.json +0 -0
  51. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/config/hdx_base_config.yaml +0 -0
  52. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/config/hdx_config.json +0 -0
  53. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/config/hdx_config.yaml +0 -0
  54. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/config/hdx_dataset_static.json +0 -0
  55. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/config/hdx_dataset_static.yaml +0 -0
  56. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/config/hdx_datasource_topline.json +0 -0
  57. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/config/hdx_datasource_topline.yaml +0 -0
  58. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/config/hdx_email_configuration.json +0 -0
  59. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/config/hdx_email_configuration.yaml +0 -0
  60. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/config/hdx_missing_site_config.json +0 -0
  61. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/config/hdx_organization_static.json +0 -0
  62. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/config/hdx_organization_static.yaml +0 -0
  63. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/config/hdx_resource_static.json +0 -0
  64. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/config/hdx_resource_static.yaml +0 -0
  65. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/config/hdx_resource_view_static.json +0 -0
  66. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/config/hdx_resource_view_static.yaml +0 -0
  67. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/config/hdx_showcase_static.json +0 -0
  68. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/config/hdx_showcase_static.yaml +0 -0
  69. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/config/hdx_user_static.json +0 -0
  70. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/config/hdx_user_static.yaml +0 -0
  71. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/config/hdx_vocabulary_static.json +0 -0
  72. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/config/hdx_vocabulary_static.yaml +0 -0
  73. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/config/project_configuration.json +0 -0
  74. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/config/project_configuration.yaml +0 -0
  75. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/config/user_agent_config.yaml +0 -0
  76. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/config/user_agent_config2.yaml +0 -0
  77. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/config/user_agent_config3.yaml +0 -0
  78. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/config/user_agent_config_wrong.yaml +0 -0
  79. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/dataset_search_results.yaml +0 -0
  80. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/download_gen_resource/conflict_data_alg.csv +0 -0
  81. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/download_gen_resource/min_qc_conflict_data_alg.csv +0 -0
  82. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/download_gen_resource/qc_conflict_data_alg.csv +0 -0
  83. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/download_gen_resource/test_data_no_data.csv +0 -0
  84. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/download_gen_resource/test_data_no_years.csv +0 -0
  85. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/empty.csv +0 -0
  86. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/gen_resource/conflict_data_alg.csv +0 -0
  87. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/gen_resource/min_qc_conflict_data_alg.csv +0 -0
  88. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/gen_resource/qc_conflict_data_alg.csv +0 -0
  89. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/gen_resource/test_data_no_data.csv +0 -0
  90. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/gen_resource/test_data_no_years.csv +0 -0
  91. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/location/location_list_all_fields.yaml +0 -0
  92. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/location/location_show_results.yaml +0 -0
  93. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/organization/organization_list_all_fields.yaml +0 -0
  94. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/organization/organization_show_results.yaml +0 -0
  95. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/qc_from_rows/qc_conflict_data_alg.csv +0 -0
  96. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/qc_from_rows/qc_conflict_data_alg_one_col.csv +0 -0
  97. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/resource_formats.json +0 -0
  98. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/showcase_all_search_results.yaml +0 -0
  99. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/size_hash/ACLED-All-Africa-File_20170101-to-20170708.xlsx +0 -0
  100. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/state/analysis_dates.txt +0 -0
  101. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/state/last_build_date.txt +0 -0
  102. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/test_data.csv +0 -0
  103. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/test_data.zip +0 -0
  104. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/update_dataset_resources/dem_data_zwe.csv +0 -0
  105. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/update_dataset_resources/dem_indicatorlist_zwe.csv +0 -0
  106. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/update_dataset_resources/expected_resources_to_update.json +0 -0
  107. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/update_dataset_resources/opri_data_zwe.csv +0 -0
  108. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/update_dataset_resources/opri_indicatorlist_zwe.csv +0 -0
  109. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/update_dataset_resources/opri_metadata_zwe.csv +0 -0
  110. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/update_dataset_resources/qc_sdg_data_zwe.csv +0 -0
  111. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/update_dataset_resources/sdg_data_zwe.csv +0 -0
  112. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/update_dataset_resources/sdg_indicatorlist_zwe.csv +0 -0
  113. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/update_dataset_resources/sdg_metadata_zwe.csv +0 -0
  114. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/update_dataset_resources/unesco_dataset.json +0 -0
  115. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/update_dataset_resources/unesco_update_dataset.json +0 -0
  116. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/update_logic/update_logic_resources.yaml +0 -0
  117. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/fixtures/update_logic/update_logic_resources_new.yaml +0 -0
  118. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/hdx/__init__.py +0 -0
  119. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/hdx/api/__init__.py +0 -0
  120. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/hdx/api/test_ckan.py +0 -0
  121. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/hdx/api/test_configuration.py +0 -0
  122. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/hdx/api/test_locations.py +0 -0
  123. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/hdx/api/utilities/__init__.py +0 -0
  124. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/hdx/api/utilities/test_filestore_helper.py +0 -0
  125. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/hdx/api/utilities/test_hdx_error_handler.py +0 -0
  126. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/hdx/api/utilities/test_hdx_state.py +0 -0
  127. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/hdx/api/utilities/test_hdx_stats.py +0 -0
  128. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/hdx/api/utilities/test_url_utils.py +0 -0
  129. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/hdx/conftest.py +0 -0
  130. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/hdx/data/__init__.py +0 -0
  131. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/hdx/data/test_activity.py +0 -0
  132. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/hdx/data/test_dataset_add_hapi_error.py +0 -0
  133. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/hdx/data/test_dataset_core.py +0 -0
  134. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/hdx/data/test_dataset_noncore.py +0 -0
  135. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/hdx/data/test_dataset_resource_generation.py +0 -0
  136. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/hdx/data/test_location.py +0 -0
  137. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/hdx/data/test_organization.py +0 -0
  138. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/hdx/data/test_resource_view.py +0 -0
  139. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/hdx/data/test_showcase.py +0 -0
  140. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/hdx/data/test_update_dataset_resources.py +0 -0
  141. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/hdx/data/test_update_logic.py +0 -0
  142. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/hdx/data/test_user.py +0 -0
  143. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/hdx/data/test_vocabulary.py +0 -0
  144. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/hdx/facades/__init__.py +0 -0
  145. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/hdx/facades/test_infer_arguments.py +0 -0
  146. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/hdx/facades/test_keyword_arguments.py +0 -0
  147. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/tests/hdx/facades/test_simple.py +0 -0
  148. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/workingexample/my_code.py +0 -0
  149. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/workingexample/my_resource.csv +0 -0
  150. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/workingexample/my_resource.xlsx +0 -0
  151. {hdx_python_api-6.7.5 → hdx_python_api-6.7.6}/workingexample/run.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: hdx-python-api
3
- Version: 6.7.5
3
+ Version: 6.7.6
4
4
  Summary: HDX Python API for interacting with the Humanitarian Data Exchange
5
5
  Project-URL: Homepage, https://github.com/OCHA-DAP/hdx-python-api
6
6
  Author: Michael Rans
@@ -28,8 +28,8 @@ Requires-Python: >=3.10
28
28
  Requires-Dist: ckanapi>=4.11
29
29
  Requires-Dist: defopt>=7.0.0
30
30
  Requires-Dist: email-validator
31
- Requires-Dist: hdx-python-country>=4.2.4
32
- Requires-Dist: hdx-python-utilities>=4.2.3
31
+ Requires-Dist: hdx-python-country>=4.2.5
32
+ Requires-Dist: hdx-python-utilities>=4.2.4
33
33
  Requires-Dist: makefun
34
34
  Requires-Dist: requests
35
35
  Provides-Extra: docs
@@ -39,8 +39,8 @@ dependencies = [
39
39
  "ckanapi>=4.11",
40
40
  "defopt>=7.0.0",
41
41
  "email_validator",
42
- "hdx-python-country>=4.2.4",
43
- "hdx-python-utilities>=4.2.3",
42
+ "hdx-python-country>=4.2.5",
43
+ "hdx-python-utilities>=4.2.4",
44
44
  "makefun",
45
45
  "requests",
46
46
  ]
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
18
18
  commit_id: str | None
19
19
  __commit_id__: str | None
20
20
 
21
- __version__ = version = '6.7.5'
22
- __version_tuple__ = version_tuple = (6, 7, 5)
21
+ __version__ = version = '6.7.6'
22
+ __version_tuple__ = version_tuple = (6, 7, 6)
23
23
 
24
24
  __commit_id__ = commit_id = None
@@ -4,13 +4,15 @@ import json
4
4
  import logging
5
5
  from collections.abc import Iterator, Sequence
6
6
  from datetime import datetime
7
- from pathlib import Path
7
+ from pathlib import Path, PureWindowsPath
8
8
  from typing import Any, Optional
9
+ from urllib.parse import urlsplit
9
10
 
10
11
  from hdx.utilities.dateparse import now_utc, now_utc_notz, parse_date
11
12
  from hdx.utilities.downloader import Download
12
13
  from hdx.utilities.file_hashing import get_size_and_hash
13
14
  from hdx.utilities.retriever import Retrieve
15
+ from hdx.utilities.session import get_session
14
16
  from hdx.utilities.uuid import is_valid_uuid
15
17
 
16
18
  import hdx.api.utilities.url_utils
@@ -755,6 +757,22 @@ class Resource(HDXObject):
755
757
  logger.debug(result)
756
758
  return resources
757
759
 
760
+ @staticmethod
761
+ def _get_safe_filename(filename: str) -> str:
762
+ """Strip any directory components (/ or \\) from a filename built from
763
+ resource metadata so downloads cannot be written outside the folder
764
+
765
+ Args:
766
+ filename: Filename to make safe
767
+
768
+ Returns:
769
+ Filename without directory components
770
+ """
771
+ safe_filename = PureWindowsPath(filename).name
772
+ if safe_filename in ("", ".", ".."):
773
+ raise HDXError(f"Invalid filename {filename} for download!")
774
+ return safe_filename
775
+
758
776
  def _download_file(
759
777
  self,
760
778
  url: str,
@@ -773,7 +791,17 @@ class Resource(HDXObject):
773
791
  Returns:
774
792
  Path to downloaded file
775
793
  """
776
- session = hdx.api.utilities.url_utils.get_ckan_ready_session(self.configuration)
794
+ # Only send the HDX API key to the HDX site, not to external resource URLs
795
+ hdx_site_url = self.configuration.get_hdx_site_url()
796
+ if urlsplit(url)[:2] == urlsplit(hdx_site_url)[:2]:
797
+ session = hdx.api.utilities.url_utils.get_ckan_ready_session(
798
+ self.configuration
799
+ )
800
+ else:
801
+ session = get_session(
802
+ full_agent=self.configuration.get_user_agent(), use_env=False
803
+ )
804
+ filename = self._get_safe_filename(filename)
777
805
  with Download(session=session) as downloader:
778
806
  if retriever:
779
807
  downloader = retriever.clone(downloader)
@@ -1225,6 +1225,44 @@ class TestResource:
1225
1225
  with pytest.raises(DownloadError):
1226
1226
  resource2.download()
1227
1227
 
1228
+ def test_download_security(self, configuration, read, monkeypatch):
1229
+ downloads = []
1230
+
1231
+ def download_file(self, url, folder=None, filename=None, path=None, **kwargs):
1232
+ downloads.append((self.session.headers.get("Authorization"), filename))
1233
+ return Path(folder or "tmp") / filename
1234
+
1235
+ monkeypatch.setattr(Download, "download_file", download_file)
1236
+ Configuration.read().set_api_key("12345")
1237
+ resource = Resource.read_from_hdx("74b74ae1-df0c-4716-829f-4f939a046811")
1238
+ resource.download()
1239
+ site_url = resource.configuration.get_hdx_site_url()
1240
+ resource["url"] = f"{site_url}/dataset/x/resource/y/download/a.csv"
1241
+ resource.download()
1242
+ resource["url"] = site_url.replace("https://", "http://")
1243
+ resource.download()
1244
+ assert downloads == [
1245
+ (None, "MyResource1.csv"),
1246
+ ("12345", "MyResource1.csv"),
1247
+ (None, "MyResource1.csv"),
1248
+ ]
1249
+
1250
+ downloads.clear()
1251
+ resource["name"] = "/home/user/.bashrc"
1252
+ resource.download()
1253
+ resource["name"] = "..\\..\\evil"
1254
+ resource.download_datastore()
1255
+ resource["name"] = "evil"
1256
+ resource["format"] = "csv/../../x"
1257
+ resource.download()
1258
+ assert [filename for _, filename in downloads] == [
1259
+ ".bashrc.csv",
1260
+ "evil.csv",
1261
+ "x",
1262
+ ]
1263
+ with pytest.raises(HDXError):
1264
+ Resource._get_safe_filename("a/..")
1265
+
1228
1266
  def test_download_datastore(self, configuration, read, monkeypatch):
1229
1267
  downloads = []
1230
1268
 
@@ -80,7 +80,8 @@ name = "cffi"
80
80
  version = "2.1.1"
81
81
  source = { registry = "https://pypi.org/simple" }
82
82
  dependencies = [
83
- { name = "pycparser", marker = "implementation_name != 'PyPy'" },
83
+ { name = "pycparser", version = "3.11", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11' and implementation_name != 'PyPy'" },
84
+ { name = "pycparser", version = "3.12", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11' and implementation_name != 'PyPy'" },
84
85
  ]
85
86
  sdist = { url = "https://files.pythonhosted.org/packages/9e/ef/008a1939e372c06329a3fce4279c02f328488f3526744906eeec3da7ad5f/cffi-2.1.1.tar.gz", hash = "sha256:dd31f52ea1086513bb9df30f8fcee9b8918323ae067a3d5b78bc826a000712be", size = 530807, upload-time = "2026-08-03T21:21:18.939Z" }
86
87
  wheels = [
@@ -448,6 +449,9 @@ wheels = [
448
449
  name = "coverage"
449
450
  version = "7.16.2"
450
451
  source = { registry = "https://pypi.org/simple" }
452
+ resolution-markers = [
453
+ "python_full_version < '3.11'",
454
+ ]
451
455
  sdist = { url = "https://files.pythonhosted.org/packages/2f/55/d1eaf3e73781174340a00dc1ba2aee8a65f82fadb18e2797b192b6b3925b/coverage-7.16.2.tar.gz", hash = "sha256:ca64d9f1f384f151b9511bec01126072acd2f313439f8ed015a22d8790aab6fa", size = 971999, upload-time = "2026-09-27T12:29:01.118Z" }
452
456
  wheels = [
453
457
  { url = "https://files.pythonhosted.org/packages/60/72/db17bf5f87568ab524413693385be2eeb03e652ab56c54ea05fa85515675/coverage-7.16.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:23219888477edd736b6fcaec1272d47d93b926e999641ffea7e53a1738e70b2b", size = 223670, upload-time = "2026-09-27T12:25:34.675Z" },
@@ -574,7 +578,137 @@ wheels = [
574
578
 
575
579
  [package.optional-dependencies]
576
580
  toml = [
577
- { name = "tomli", marker = "python_full_version <= '3.11'" },
581
+ { name = "tomli", marker = "python_full_version < '3.11'" },
582
+ ]
583
+
584
+ [[package]]
585
+ name = "coverage"
586
+ version = "7.17.0"
587
+ source = { registry = "https://pypi.org/simple" }
588
+ resolution-markers = [
589
+ "python_full_version >= '3.14'",
590
+ "python_full_version >= '3.11' and python_full_version < '3.14'",
591
+ ]
592
+ sdist = { url = "https://files.pythonhosted.org/packages/d2/79/e78bd8f75a9b8e32233ce92d4607f0a21ce88a9156cace2884e7175a82f5/coverage-7.17.0.tar.gz", hash = "sha256:cc010a0a7fbdd9bb8bdfd0d3f04a5151275860213cbd7e2b876b29778489c712", size = 991021, upload-time = "2026-10-22T16:06:50.009Z" }
593
+ wheels = [
594
+ { url = "https://files.pythonhosted.org/packages/75/25/79a66272edd250031aeee6db87d500a0bf76390d0d5f8c2f431fe354715f/coverage-7.17.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:99a7b390cbccc6bf029ca4da3f0f607c218bb4085e9cd6b58a90d14ca12993c3", size = 225837, upload-time = "2026-10-22T16:03:55.622Z" },
595
+ { url = "https://files.pythonhosted.org/packages/52/a6/f5f6fefb2fc1305363927edad1d0a60ce6ef80d6c1a74a79e825f0f670eb/coverage-7.17.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f72640e02a470b57b15cd655820133f6892760209283a363a60e2df932d5f0fe", size = 226257, upload-time = "2026-10-22T16:03:57.164Z" },
596
+ { url = "https://files.pythonhosted.org/packages/28/61/72889bac8eb44c51f8043edb227df551dfdca1fc4819a6c6d67b3f69427b/coverage-7.17.0-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:2dc9233f39149b5a4f4aba17a4b6bc5cca22e52cfc4b06fdb07d014439b8b2ea", size = 258282, upload-time = "2026-10-22T16:03:58.521Z" },
597
+ { url = "https://files.pythonhosted.org/packages/f4/e4/03e4a5644df9b73de0d44d1b82acd18b06c42b5abc3f1433be8363fa983d/coverage-7.17.0-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:8e8113d3852e9377421a61de1917df27b3abb25404a4ecf69f9e64612c4345b5", size = 260506, upload-time = "2026-10-22T16:04:00.116Z" },
598
+ { url = "https://files.pythonhosted.org/packages/6f/4e/949022286df7e59e8633a3a7e6635e0e6b53af7d57074cb0bf8f500373fb/coverage-7.17.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c86a39539d10d666bb819c16c94d7edfc1aa2e0531b937f7c549b83d15177c6e", size = 262600, upload-time = "2026-10-22T16:04:01.49Z" },
599
+ { url = "https://files.pythonhosted.org/packages/27/cf/7d67f60df081006315699b7edb9402c1b47142caf1383f4e56ae8ff1a501/coverage-7.17.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:559f748446ee799803686b5784e3deb54c70d655ac386a860e06b11672504ba7", size = 264609, upload-time = "2026-10-22T16:04:03.286Z" },
600
+ { url = "https://files.pythonhosted.org/packages/e1/e0/9293d94afbc099990a085e88229a51c79b00828aba0f2adda32dc4cc16d1/coverage-7.17.0-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:34d65c9e8e257f48a654908005046fbf1bc48d9540ae3776ad08c0acd010e10c", size = 258382, upload-time = "2026-10-22T16:04:04.804Z" },
601
+ { url = "https://files.pythonhosted.org/packages/24/c8/bcd28efedf262c074dae76f61098739eb02b15f3f716f80cc86f9885b8a9/coverage-7.17.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:5b7fa0997b8eba7378ac66f31ec7f70164490353ab79b9667d37c0d365e50177", size = 260299, upload-time = "2026-10-22T16:04:06.291Z" },
602
+ { url = "https://files.pythonhosted.org/packages/b8/dc/503f55e5e2200933403c90d619d9f779b5060ddd338b1bdc63cd235592cb/coverage-7.17.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:6ae0453a3390e67f7bfbe34417bbdf5b4ebfc21db23fb446a0a41115eeeca6ca", size = 258314, upload-time = "2026-10-22T16:04:07.729Z" },
603
+ { url = "https://files.pythonhosted.org/packages/bb/b1/f1a57c36077cc516240636f7eff0d1427939ed795f096dd2c7769213a56c/coverage-7.17.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:96151262832f3c230ebae23b2d6911ad549e1738465946c97004913ff06112ba", size = 262239, upload-time = "2026-10-22T16:04:09.116Z" },
604
+ { url = "https://files.pythonhosted.org/packages/a8/4f/c2e59d4a132936c7c207b9b69ab99c0f27b14c3c93266e9922aa3b562b37/coverage-7.17.0-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:cd7397de6cc782f00fe5ac1d75e9b306bcfa49c8b6b8dd6ed1f7709393ad40b3", size = 257841, upload-time = "2026-10-22T16:04:10.509Z" },
605
+ { url = "https://files.pythonhosted.org/packages/05/04/50742c0ee8b6c85826ff11737c93ed957fea4c9acf4b4b99804bdac1dd84/coverage-7.17.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9d1fdf82c6fea57b5e9dada509f9ce9638c8334664e2c98c7f6f1ccf3d143ad2", size = 259039, upload-time = "2026-10-22T16:04:11.916Z" },
606
+ { url = "https://files.pythonhosted.org/packages/8e/cd/83ad4bbbfcb6d045a33c14cdca313f6c9275737c67f3b7300222e3239a37/coverage-7.17.0-cp311-cp311-win32.whl", hash = "sha256:38c86e5d74bbfd88a393fa3f91257c1225c63aa6db6d5918de3e49ab04f91c6e", size = 227687, upload-time = "2026-10-22T16:04:13.537Z" },
607
+ { url = "https://files.pythonhosted.org/packages/ca/c8/dcc5a7effa79707eb8a61e699b141cff7c9b46036771274cfb48ea7b765f/coverage-7.17.0-cp311-cp311-win_amd64.whl", hash = "sha256:2ed3097c6817bc1a7fc8ae0a6131db74aa1150d863cccc308237ff362d3226b2", size = 228290, upload-time = "2026-10-22T16:04:14.899Z" },
608
+ { url = "https://files.pythonhosted.org/packages/d1/58/a8553e0dcd38d8136df63964638d2b588e0a4a916bff1bca996244fda693/coverage-7.17.0-cp311-cp311-win_arm64.whl", hash = "sha256:6052e878b628abcd38fa5f2b64abebc686eed4e2267da42434017a9c6d24f241", size = 228199, upload-time = "2026-10-22T16:04:16.351Z" },
609
+ { url = "https://files.pythonhosted.org/packages/0a/25/989fd3b495c4274ac0cf54cb6664326415e60183a7f8a73dd9bbb0b11e34/coverage-7.17.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:0cfdc938ca3319d873d1f1252e60620a39aee4ebf9dbd7cc58238109ebda9c51", size = 225938, upload-time = "2026-10-22T16:04:18.113Z" },
610
+ { url = "https://files.pythonhosted.org/packages/db/cb/14726426bf3241657facbf0f7df7babd8f7d3fcf8e4609b7929f9dceecbc/coverage-7.17.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d523da3c2e4bca49417768bcdb1a443c5b359dc44b8b93a3102e118fce912c40", size = 226166, upload-time = "2026-10-22T16:04:19.524Z" },
611
+ { url = "https://files.pythonhosted.org/packages/8e/97/f95ed32cd3cfbe261a3598e694cb770cefc7b2d13ff013418d6f70a44dde/coverage-7.17.0-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:adbf3450c0f3f2b2854e282a8758f2b3eddf787eeff24ec9c9bc2cbc38328cc1", size = 258462, upload-time = "2026-10-22T16:04:21.079Z" },
612
+ { url = "https://files.pythonhosted.org/packages/91/ac/eb4c31f741509a9ef48cf6f28385e98e9de0785599282252eee252ff8af7/coverage-7.17.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:85932227e9dd38e62cd29c17fefdfecfb919eead6af1e3259522d03cf85de983", size = 261789, upload-time = "2026-10-22T16:04:23.037Z" },
613
+ { url = "https://files.pythonhosted.org/packages/e8/3e/d9cd006d1a3cc5deab07beb29b86cb4a10dd84d66b330820363fb8d310d6/coverage-7.17.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:30f5477aac9c9e4a0a641c55f8f8fddd7f3bd91176c912c50f40ffced96b4034", size = 262322, upload-time = "2026-10-22T16:04:24.94Z" },
614
+ { url = "https://files.pythonhosted.org/packages/c0/3a/4c872c6ae0762b09cdb8e856891bb3f584848cb60b6dda2bacb85fe2f3f0/coverage-7.17.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:0b8bb651a4406fb6a983a905309fec1783443c65e1771b41e92740a0f4a1176b", size = 264600, upload-time = "2026-10-22T16:04:26.444Z" },
615
+ { url = "https://files.pythonhosted.org/packages/df/98/1d41a2373fa98b423bcd70adb91d75e38eafb417955426dbb920b10016f3/coverage-7.17.0-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0edeb6594f080c8de1263cccb239cb316ef77aeb959e2e0f38f2953fcc72a49e", size = 258678, upload-time = "2026-10-22T16:04:27.832Z" },
616
+ { url = "https://files.pythonhosted.org/packages/92/6a/fe04b5e63e76506daa63d90bdfb00a53767fe5df18546b437d6226918d6b/coverage-7.17.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:da94ec0484e84fce5c7bf8d0f54b97767a90d992653a129b35634699d516e0a5", size = 260210, upload-time = "2026-10-22T16:04:29.275Z" },
617
+ { url = "https://files.pythonhosted.org/packages/4f/c3/5c5a78dc19dd4799be9c6ec022316fb25ababaeacfaf0f52f24c56a57b43/coverage-7.17.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a25cc5e8c23a590815c6a7aa43624234d25cb23b21b484adb8a0daed59860db5", size = 258375, upload-time = "2026-10-22T16:04:30.647Z" },
618
+ { url = "https://files.pythonhosted.org/packages/ed/e7/4c1d8eaff4d756fefd15d58c4953a78ab656782fd0e32c5a3465dba61aa0/coverage-7.17.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:db645c81cf4d6bcb392ea1894aad65d55d1588a8472c834b25ca575da3029a56", size = 262422, upload-time = "2026-10-22T16:04:32.053Z" },
619
+ { url = "https://files.pythonhosted.org/packages/a6/2a/0b17c3e2e7b6ff1a5d92eb58915c0d1026668928f961d14dac73cf1b6096/coverage-7.17.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:6a80a11b90c4a03df1502304cf24ff953255b6b5d076ef79066ecf88baaff31f", size = 257875, upload-time = "2026-10-22T16:04:33.824Z" },
620
+ { url = "https://files.pythonhosted.org/packages/d3/2d/eb0cbde0535342df0d17a667163030a3afb67e5eb9e3ad94af9540041584/coverage-7.17.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e4eaf11d6b0f2147f46cfbf06fe7edcca6f095d0120da00ddc2458995ee869fc", size = 260361, upload-time = "2026-10-22T16:04:35.661Z" },
621
+ { url = "https://files.pythonhosted.org/packages/2e/47/1be2a6db7eb655d0a1d899217c3f2469f9121cbbeddac35c1c8173b1482e/coverage-7.17.0-cp312-cp312-win32.whl", hash = "sha256:912a29f338798541d795e2e25903c6fe7a99dee70a40fe4706a9a124649b523e", size = 227747, upload-time = "2026-10-22T16:04:37.102Z" },
622
+ { url = "https://files.pythonhosted.org/packages/11/c5/201c894c57de81875d8b8cc527ba222aa350e8cfb183eb3f6df45d06ad8e/coverage-7.17.0-cp312-cp312-win_amd64.whl", hash = "sha256:88a1a9fb0075b83389dd9b403bb3fce976031b3c2aa0e05e3e57143cf639de69", size = 228325, upload-time = "2026-10-22T16:04:38.989Z" },
623
+ { url = "https://files.pythonhosted.org/packages/0b/5d/196095339b19758cf83f507fb598bc42820ae124745feb3084662729e17a/coverage-7.17.0-cp312-cp312-win_arm64.whl", hash = "sha256:2c680e838ff9e68d491158625ca2c1ddb17d78d791bba96a31f8b839b4990438", size = 228131, upload-time = "2026-10-22T16:04:40.654Z" },
624
+ { url = "https://files.pythonhosted.org/packages/54/e6/1f01afbc9f4fa8ca5e1fa6fdf537a5c58b5765d1b4167ee284cddb9acc72/coverage-7.17.0-cp313-cp313-android_24_arm64_v8a.whl", hash = "sha256:84538c040f4e6214f663459d89372ce4e6b2bbdd9d397ef0dca7b3ecd56b8eb2", size = 227080, upload-time = "2026-10-22T16:04:42.325Z" },
625
+ { url = "https://files.pythonhosted.org/packages/92/7a/bdb7e6260c4a211389aeac9b89dc31662ebe122153ad0ecfd156897912df/coverage-7.17.0-cp313-cp313-android_24_x86_64.whl", hash = "sha256:6abfb6a4cf1cb1b67bc8fccdde177e2d2b781d0d34449e7078156547025140e5", size = 227152, upload-time = "2026-10-22T16:04:43.737Z" },
626
+ { url = "https://files.pythonhosted.org/packages/37/4e/276e7d5b3cfb124871bdb544c27b004a8b4e270e6bf8e7414149c54b5e5b/coverage-7.17.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:ef65e96f0fc1a7c8b7644c7011d47a8228555e7888ac4d6246f715a7f3d7c398", size = 225397, upload-time = "2026-10-22T16:04:45.292Z" },
627
+ { url = "https://files.pythonhosted.org/packages/b3/7d/dac073db12f3c131598a6693253aded581e4d7d622a89864f11bfb0ca2f5/coverage-7.17.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:55939ea4c097fda2edabf80fac5e49bef15597b950a9f29fc56292a895245feb", size = 225705, upload-time = "2026-10-22T16:04:46.603Z" },
628
+ { url = "https://files.pythonhosted.org/packages/00/45/877b0a9248e921080ae91d115c13192d17e308f5aee86bcc7f7bc2a54ed1/coverage-7.17.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:bfb6f868af552c0ceb2d19220b8cbcc2be096ca26163ac30e682a13041433429", size = 225828, upload-time = "2026-10-22T16:04:48.065Z" },
629
+ { url = "https://files.pythonhosted.org/packages/4f/f5/2c48d47abec0e4590b302920334be5ee3854f96bbd22524feabb8d92b220/coverage-7.17.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:8d823d66afd59566030539c49c7a6acaf3083996682be2dda760c63555842094", size = 226088, upload-time = "2026-10-22T16:04:49.513Z" },
630
+ { url = "https://files.pythonhosted.org/packages/a8/a0/ec0442f3f372c7fd742f49b3022edd392f79e37a0048e1fa333f56d01ec3/coverage-7.17.0-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:50678474e714c684b82c108e63fbb8f1bcf1266d8293a49980f1d08526f093b5", size = 257257, upload-time = "2026-10-22T16:04:50.982Z" },
631
+ { url = "https://files.pythonhosted.org/packages/92/e2/eb0927ba93809f76eee69fa1e47999825fc7dbbabc3e0e1a2744f2677acb/coverage-7.17.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:045c1eeb19fb4eae949850a761102fffb3a5f638b97f977912f95843e54f6669", size = 260165, upload-time = "2026-10-22T16:04:52.409Z" },
632
+ { url = "https://files.pythonhosted.org/packages/9a/a2/8d4c6055efb32099b15c9cc33d007b8aabebc4832f372a3274de5ba0afc5/coverage-7.17.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dfb12891a773cbc2132349c77c690a045a882fe3f98b4bda50dfabb01893f9bd", size = 261098, upload-time = "2026-10-22T16:04:53.763Z" },
633
+ { url = "https://files.pythonhosted.org/packages/2c/1e/93412288688a7b03f152a734c8ef086e395108a0a6a746985d3967e220f2/coverage-7.17.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:3067608b4429629f640c1b23d2f69b05d2fd45e00ebb6ee9e8fad220a6c11722", size = 263164, upload-time = "2026-10-22T16:04:55.386Z" },
634
+ { url = "https://files.pythonhosted.org/packages/3c/20/7eb8d805c4f1a212245cef20181dfbf39535357985073d49730ee9cf08d4/coverage-7.17.0-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a1762e85cbbe3b5ff9c6dcbcc1b89d5c72320094292b7b9572bf882c85e428b7", size = 257287, upload-time = "2026-10-22T16:04:56.976Z" },
635
+ { url = "https://files.pythonhosted.org/packages/1a/c1/1df29630b4ed17e135c76390afcc6bd273c3dc5ba2a21a76813a600fe98c/coverage-7.17.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:62bb77987d3f72a0aaa77c567ee7f9806bc2e748c8f46fafbe1fdb90dd148398", size = 259256, upload-time = "2026-10-22T16:04:58.545Z" },
636
+ { url = "https://files.pythonhosted.org/packages/a1/79/2365d1008d28aafe468a450a24c6c63363de794b5140223d67685cd0e205/coverage-7.17.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:6cc31f27240d4e080437e3b8229d92f1d809c9a4f233607385373b73974e183e", size = 257178, upload-time = "2026-10-22T16:05:00.103Z" },
637
+ { url = "https://files.pythonhosted.org/packages/c0/9f/f002952d295d772688dffce0d991e3822795b1e3aad158073712a5a5e86e/coverage-7.17.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:61cde5222f1933d476647c5a25ed1a8678b7703098cb5a15f4a0aa39967d8c28", size = 261275, upload-time = "2026-10-22T16:05:01.462Z" },
638
+ { url = "https://files.pythonhosted.org/packages/40/fe/f9e15fbb426be97cd679ee5d359151e046f103bcd76b5092c318c26ed596/coverage-7.17.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:11f5f7fb2d97a0fe865f5e7bad4eb0619b957637f676bc088d13844adf26ba95", size = 257029, upload-time = "2026-10-22T16:05:02.8Z" },
639
+ { url = "https://files.pythonhosted.org/packages/c2/4a/3c398f38694387334ff4c9f71afc8e15b4fa7db7bc0bea4d5b6032eb0df0/coverage-7.17.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6e09612b1b82c9df1d2b6c85dee88d5aad3e73d77a8ec0b16ac6a7322cbdf5d9", size = 259109, upload-time = "2026-10-22T16:05:04.241Z" },
640
+ { url = "https://files.pythonhosted.org/packages/bd/a9/908a3cf1a2335aec1c788682a06c2f742a62a4f987033f080de1c5fd1997/coverage-7.17.0-cp313-cp313-win32.whl", hash = "sha256:bd3e9eb493631ff1ca34bf5efac25b5c66724f837bf6182c4fc771c55946423d", size = 227691, upload-time = "2026-10-22T16:05:05.636Z" },
641
+ { url = "https://files.pythonhosted.org/packages/13/f7/8cdd7bfd8a63b3e6b133fc395ecfc7b1cb6f561926e7e2ad050de85b83e7/coverage-7.17.0-cp313-cp313-win_amd64.whl", hash = "sha256:f1fc9a7cea899c51d8a53e66c2f082a3d9e461ece32418d3ef0a0b90c32bfd3d", size = 228418, upload-time = "2026-10-22T16:05:07.057Z" },
642
+ { url = "https://files.pythonhosted.org/packages/09/cf/0b3fc57f735cd3831ca13d0be5312a5477d5934066683c5d34018cab7541/coverage-7.17.0-cp313-cp313-win_arm64.whl", hash = "sha256:e65a1e61a68493fbfbe44d8bec71b3231d81b9917f62d3dafe0e105072147e83", size = 228142, upload-time = "2026-10-22T16:05:08.435Z" },
643
+ { url = "https://files.pythonhosted.org/packages/4d/e1/722462fe79912ebebc101497bd16c42413cde2dbae771017f1ec0acb84c2/coverage-7.17.0-cp314-cp314-android_24_arm64_v8a.whl", hash = "sha256:dc5936491e306f2f6f095bd5fba593de11eb0375cee787ca1f245c3a333a523a", size = 227197, upload-time = "2026-10-22T16:05:09.846Z" },
644
+ { url = "https://files.pythonhosted.org/packages/b7/74/826b9c09f2ebfea803bccb391d935688a25309bff8e819fc446bc629c108/coverage-7.17.0-cp314-cp314-android_24_x86_64.whl", hash = "sha256:968c5fb6e0c83cab752d79a70209648ce4d90cae815c60fa229b59e264601062", size = 227314, upload-time = "2026-10-22T16:05:11.422Z" },
645
+ { url = "https://files.pythonhosted.org/packages/6d/19/c8514d7f5e0659a96ff2bc7377119dca6d420e2761c5fc69ae37618734f8/coverage-7.17.0-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:12cb8a20ad904a5811e6660d829a586b216e5254b9b34b76dde8a4d65d827dc6", size = 225477, upload-time = "2026-10-22T16:05:12.761Z" },
646
+ { url = "https://files.pythonhosted.org/packages/81/74/ef9433ce599f07d8633b4ce6e6d6921505c4ef3f7f9006f8eb66e2c278cf/coverage-7.17.0-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:bb5ca66937c55bc85d1a5e9c5900a3e4693a8edf2280a9b3672b7b2661a84b95", size = 225787, upload-time = "2026-10-22T16:05:14.394Z" },
647
+ { url = "https://files.pythonhosted.org/packages/d8/66/26e58981940e8b3944c6a9941bec5c7f50840e7009a046712e3f3bcd9e6a/coverage-7.17.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:5cc15faaf318ee5040d835a62c75bc6f122d837274f3b5efd47bf9fbd4ac5b85", size = 226019, upload-time = "2026-10-22T16:05:15.798Z" },
648
+ { url = "https://files.pythonhosted.org/packages/e9/63/fe175310815cc8357b83b773c9b4c20943c269f217dd825a37c4b4bfe324/coverage-7.17.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:7d6d9d396c8b7bcaf76d774a10140b218111484e54c73a5f2a1b75655381748e", size = 226169, upload-time = "2026-10-22T16:05:17.188Z" },
649
+ { url = "https://files.pythonhosted.org/packages/2c/b0/ac84761f5b4bd226696b0ec4606903d2ef7208abda0aec06c14a4218def4/coverage-7.17.0-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:42e6f170d1ac04b7eb3363310a6c41cdfd82c1fe6bf9ffbc4a86f380bdf091c7", size = 258092, upload-time = "2026-10-22T16:05:18.691Z" },
650
+ { url = "https://files.pythonhosted.org/packages/e9/58/d8bdd65a661913bc12eaaa3e59742b2cb8b94f2e7f78e62184f0a58ca493/coverage-7.17.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:acdb5f3c96046efff9dc6c572a6acb2b8d0da09372d7b9a9ed7249cf7d17434f", size = 261096, upload-time = "2026-10-22T16:05:20.089Z" },
651
+ { url = "https://files.pythonhosted.org/packages/7b/15/5d82e2f0a75ea149e0a6412e137e1d610538772fdfd7199737db7fe234da/coverage-7.17.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3393209f6894713161ee82a9b0e673e58237e0f9733c6638e7a6c0c620ef0b33", size = 262080, upload-time = "2026-10-22T16:05:21.568Z" },
652
+ { url = "https://files.pythonhosted.org/packages/0f/cc/e3ebfd295d1dd47c7bc84a17d73f150465a37ab388dd68fe82b495dc79a0/coverage-7.17.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e9494d9e99389d39e6a96227749af898d8924ff591cb63944f8a98e68582bf0e", size = 264558, upload-time = "2026-10-22T16:05:22.906Z" },
653
+ { url = "https://files.pythonhosted.org/packages/e0/9d/e2adff76d6544bbc6df7366d74967923c2de37ba889a006bfb875bf5857b/coverage-7.17.0-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:032d4c2db4c677eb71d43f2f8b80bf64e9346f7a3f7b6ebb13f1782f3cc6c274", size = 257855, upload-time = "2026-10-22T16:05:24.343Z" },
654
+ { url = "https://files.pythonhosted.org/packages/d9/fd/ecd1e9cddf1c36b5d03c438568b1f53e63db84bb3656539d71b454484c7d/coverage-7.17.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:4343a9378b964eb3cb80fa90406385de91c7e982a769ca9314d848f93bc0d3f2", size = 259933, upload-time = "2026-10-22T16:05:25.79Z" },
655
+ { url = "https://files.pythonhosted.org/packages/40/b6/e17a19dccdbcad494c64691f71c1dba3e55c30625bc29ffbb88ac5a0aa8b/coverage-7.17.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:b609df3d6d900464207532c5170a65c6ede8d2e0b91f151f90008a866395cd76", size = 257972, upload-time = "2026-10-22T16:05:27.185Z" },
656
+ { url = "https://files.pythonhosted.org/packages/6a/0d/37dac534709a3fa43a937c8b0604839bb44b8670b83d143a4b78fec20d1e/coverage-7.17.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:a01ef92caeedfa4f2ad171a3a8e6fece4565de871d8bca428151bf9929f41048", size = 262271, upload-time = "2026-10-22T16:05:28.619Z" },
657
+ { url = "https://files.pythonhosted.org/packages/cb/17/7c05186925b4d64a46c271dfd944e3f0c1ad89db9095c31a6df157a75df2/coverage-7.17.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:a3914e2c98c34b94c26d2add3d2a61ccfd3534fc4eaa879ee290bdbb5184ba6c", size = 257604, upload-time = "2026-10-22T16:05:30.07Z" },
658
+ { url = "https://files.pythonhosted.org/packages/95/65/c241cdee66a0ff86c68f6d37328e735d10e3d30cd6ff66f356039eb688d2/coverage-7.17.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:e8a72b26dc5c9a9422e45472b1d67ba5caf273c524c8668cc04b23062663755e", size = 259714, upload-time = "2026-10-22T16:05:31.402Z" },
659
+ { url = "https://files.pythonhosted.org/packages/db/09/e93233fe2405574ce0a31ed201c0cba3a860e085db5d2828bf12b7dc0790/coverage-7.17.0-cp314-cp314-win32.whl", hash = "sha256:03baf0688e14a5a44ffd1eefa8928dfc92b14565e521174e072b31b971aa1657", size = 227914, upload-time = "2026-10-22T16:05:32.78Z" },
660
+ { url = "https://files.pythonhosted.org/packages/d7/77/04979eb217edb94b94afabb4bcc179f60c746f68d3fd0b12688ba9195730/coverage-7.17.0-cp314-cp314-win_amd64.whl", hash = "sha256:3a4459b0f389dd1e51aac3dbfc4ca35b30cae7dc99caa3c0a086d1997a985709", size = 228543, upload-time = "2026-10-22T16:05:34.118Z" },
661
+ { url = "https://files.pythonhosted.org/packages/a0/38/155f2f2c6769f8c43eca8a5e581443faa0908828650090b97103b4a41376/coverage-7.17.0-cp314-cp314-win_arm64.whl", hash = "sha256:a32ee5831b15ba239bef5d272ae586ca8acea4a661b5f2941f5a0d380e518b23", size = 228396, upload-time = "2026-10-22T16:05:35.951Z" },
662
+ { url = "https://files.pythonhosted.org/packages/52/55/d6751572d9445485c4c5a51ec6ae11caa5c11b7ef2448cdccc884f7f54d9/coverage-7.17.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:9c083e253e96fdeeaf48133fe836cac86ace2db215d235700e7f7532420a200c", size = 226486, upload-time = "2026-10-22T16:05:37.363Z" },
663
+ { url = "https://files.pythonhosted.org/packages/2f/a8/82d37760e537bfdb9fdee285fa1e1b45bc153293d23e2331c7befedd1990/coverage-7.17.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:b88fb4d4d7608cbcebdc7ff7dbffc2115e3b81d6c33a79147cd79d54fcb080f4", size = 226861, upload-time = "2026-10-22T16:05:38.777Z" },
664
+ { url = "https://files.pythonhosted.org/packages/24/96/70ec00a9db6d7bdd3f914eba12057360769f5cb78a98456e71fe1937deb5/coverage-7.17.0-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:2bf3ee38a40c0570c316b9e7507c472469586906a20f289705898528c31aaea8", size = 266849, upload-time = "2026-10-22T16:05:40.285Z" },
665
+ { url = "https://files.pythonhosted.org/packages/77/d8/d99be3bfbb208512f039c80b31e404138a86678fc929a17acd5b7135a6ae/coverage-7.17.0-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:7c570293f001ea91598b90e90cb9b98fddee833e90bbede432cbd218331ccd8e", size = 269402, upload-time = "2026-10-22T16:05:41.585Z" },
666
+ { url = "https://files.pythonhosted.org/packages/82/50/6cbe8b5a5060edbd21ce8109c4e900f8b7656e8b72ede6dc4d82dc0b8bfb/coverage-7.17.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:791f9ee09814dd30d9562b4f4eb037a371485ec1c830b53999d2320d20c4e764", size = 272025, upload-time = "2026-10-22T16:05:42.921Z" },
667
+ { url = "https://files.pythonhosted.org/packages/bd/05/d3633add01e5518dfdacfdbd1be41cb5c581412dd8bccd663edf6ef7fec8/coverage-7.17.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c7c5672ecf1b497de7a0b37743bef40e3b58e3207e9fe2ed6682cb0420836a88", size = 273515, upload-time = "2026-10-22T16:05:44.324Z" },
668
+ { url = "https://files.pythonhosted.org/packages/57/d9/b83387780271bf9ea9f96a3aeb01c1c302c4494a927923c4fa70cd170a3f/coverage-7.17.0-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:337f87e62e1c5f43c8198d879f677c342d152f84d3f157add12558853cbb8eaf", size = 266725, upload-time = "2026-10-22T16:05:45.713Z" },
669
+ { url = "https://files.pythonhosted.org/packages/e4/be/8e80b29764ae3f4d70d44952eee3f3927eb36897490fe799e400adb7f5da/coverage-7.17.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:c8a58baa8eb6154c6645eadcc19b6c089deab78c24a612a83206f2a8a5992a7c", size = 269312, upload-time = "2026-10-22T16:05:47.054Z" },
670
+ { url = "https://files.pythonhosted.org/packages/b8/c9/e702f588fe8d83ca844f133270ad0a49bf650c8cf260551ff6f11a6b6bbf/coverage-7.17.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:fb5745048ee20f796b0e3ab61831049e749acff188563e2af32f58ede957ac1b", size = 266740, upload-time = "2026-10-22T16:05:48.343Z" },
671
+ { url = "https://files.pythonhosted.org/packages/8a/11/ee13ad14b714d75ef07c490b6e43969574a8b8b8c6d67bc741fcbacbf9c3/coverage-7.17.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:7b5abcae74750302ac4bc77351eaee87c450e4abd3b6225eacde3858e260f8b2", size = 271036, upload-time = "2026-10-22T16:05:49.727Z" },
672
+ { url = "https://files.pythonhosted.org/packages/e2/bc/854e8912c11c54aaf416e74602000589c6efbbe1f251dc90202fdabddcb6/coverage-7.17.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:4e153f0bd6509dbf837fd585f489b3328bfd98f2a718a0b15ae63032148b285c", size = 266158, upload-time = "2026-10-22T16:05:51.141Z" },
673
+ { url = "https://files.pythonhosted.org/packages/a8/dd/96432830ddf63bc42654de54eee77a0cd6949cc65769bda06f353323f23a/coverage-7.17.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:e42a835271922fe7bf98c7a05c78d4032f4e52bf5b07fafa1eadfdfc2f0ad22f", size = 268088, upload-time = "2026-10-22T16:05:52.92Z" },
674
+ { url = "https://files.pythonhosted.org/packages/ce/ee/230c6ec065a6629d41cc89323ceb54d37e2650c104f70fc108f4ee7c5051/coverage-7.17.0-cp314-cp314t-win32.whl", hash = "sha256:5900055351ec89fdffb34b27898815106529ded29a9496464c1ebd6313fd40fa", size = 228229, upload-time = "2026-10-22T16:05:54.255Z" },
675
+ { url = "https://files.pythonhosted.org/packages/f0/1d/23eb6aadcb3c00764ff2961c0ff55f5dfa2543856d932b949bbc04fa68e9/coverage-7.17.0-cp314-cp314t-win_amd64.whl", hash = "sha256:5ee9c8bd13a59e301dc2aefe7aa8384633406808de051b1982775667094eb673", size = 229154, upload-time = "2026-10-22T16:05:55.682Z" },
676
+ { url = "https://files.pythonhosted.org/packages/3e/f1/7df117e8e016b7a3ee459e833b3456f3610505afefd071f8727702d98439/coverage-7.17.0-cp314-cp314t-win_arm64.whl", hash = "sha256:0a9cb9a0fb58e6fff5442969af36094ecd6976f4907f179e33b27e15355d8f74", size = 228726, upload-time = "2026-10-22T16:05:57.179Z" },
677
+ { url = "https://files.pythonhosted.org/packages/9f/a1/f9c24911755f91e6f451ca2e2c1804fbcbe9fecbc3310e341bbbbfa1d85b/coverage-7.17.0-cp315-cp315-android_24_arm64_v8a.whl", hash = "sha256:adabc1079ba844b096799ba8638d8df434aca1613f95bb7d5791af320cf05559", size = 227196, upload-time = "2026-10-22T16:05:58.543Z" },
678
+ { url = "https://files.pythonhosted.org/packages/b0/a5/2b665b40c626e6bb40e5e8e23d91170b48b5f2f57186f46b07f2fac42386/coverage-7.17.0-cp315-cp315-android_24_x86_64.whl", hash = "sha256:6b4593d2871c4c801656dd5861e759f8f5156febd6b6061b02f6a72d64618b7b", size = 227315, upload-time = "2026-10-22T16:06:00.409Z" },
679
+ { url = "https://files.pythonhosted.org/packages/3d/8c/22b518d61b930b8a4d62905d046c76a03675ef19b466462011dfb16439a3/coverage-7.17.0-cp315-cp315-ios_13_0_arm64_iphoneos.whl", hash = "sha256:c2c48a36bb970b7265b196032bfd4237c0b373f2b25ef7012d7e905b5b35c19c", size = 225490, upload-time = "2026-10-22T16:06:01.743Z" },
680
+ { url = "https://files.pythonhosted.org/packages/08/5b/d3b141455944e030cd4987f055f8c84a44a1a0b28d81ae93389f44051691/coverage-7.17.0-cp315-cp315-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:f8bc2cd4c6aa58be1ca243fb8cddb6c3c42031fe4403991ad9cf2b3baed03d9f", size = 225797, upload-time = "2026-10-22T16:06:03.423Z" },
681
+ { url = "https://files.pythonhosted.org/packages/03/24/aab2156983f7022361352640c583d08f0238e4cd7463eb921172001b4cfe/coverage-7.17.0-cp315-cp315-macosx_10_15_x86_64.whl", hash = "sha256:cbf0b83ce927de6053279ba61342d9f8892afde1385fcba9144cd05d4023d109", size = 226025, upload-time = "2026-10-22T16:06:04.76Z" },
682
+ { url = "https://files.pythonhosted.org/packages/87/db/94697b9ccf4ec94cdad07bf94e2a21b9702247cb212d2d5f18d2b9c3d0de/coverage-7.17.0-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:66efc0fb99cee34626fc17d3adac9c3cd816bfdad563bb1e983c3ef432f566d4", size = 226193, upload-time = "2026-10-22T16:06:06.167Z" },
683
+ { url = "https://files.pythonhosted.org/packages/a0/fd/db1c4ade4219831d590fff5aa5b7d9ceaf84586e8e60da6fff71b6182251/coverage-7.17.0-cp315-cp315-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:58a304efdf2253fb2ea03d45d0a04cc174a92a0cd5279c28c5bb893ce7410968", size = 258046, upload-time = "2026-10-22T16:06:07.51Z" },
684
+ { url = "https://files.pythonhosted.org/packages/95/ee/84ed138990ed752abd73db4adffc1842d6152017d8e21809cc109a413fda/coverage-7.17.0-cp315-cp315-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:aed06129a9f530a948928260d7d2d81c47261355b0127e3c782251b38958463c", size = 261735, upload-time = "2026-10-22T16:06:08.861Z" },
685
+ { url = "https://files.pythonhosted.org/packages/64/ad/c1e4367bbd1e7d562d6bc979c82b542f2040544e95a8cd995b694caf0e1a/coverage-7.17.0-cp315-cp315-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f6cdb47a9be2d3313829bed1d296086287682a3ee901ff987b3432b45705b771", size = 262819, upload-time = "2026-10-22T16:06:10.49Z" },
686
+ { url = "https://files.pythonhosted.org/packages/b5/3a/e8e8509b0940403eab15d86f70022790a01fce3e971a161919c544953f7a/coverage-7.17.0-cp315-cp315-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:804fbaf81d09b34e2f8b1159d01e211a50713d743d32fd9b2ca6cf0ae507a66f", size = 265194, upload-time = "2026-10-22T16:06:11.847Z" },
687
+ { url = "https://files.pythonhosted.org/packages/1f/77/d64bbdbb734b1059ebcde2b5df567f142a9948079e51af9b0abf8c9ec17b/coverage-7.17.0-cp315-cp315-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b2afebb96da9a1bbca142f8cc12320c14e5c215e0a49cded4f191f5a31506a28", size = 258410, upload-time = "2026-10-22T16:06:13.234Z" },
688
+ { url = "https://files.pythonhosted.org/packages/e2/29/7cf81f08a254532c074eb52cfe6b12bb753d08f2997269c9fac8de359541/coverage-7.17.0-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:bd04fd23206be9ad3de13b0b39313094fafa66a1f6baf70f5471c004a9fac47d", size = 260697, upload-time = "2026-10-22T16:06:14.595Z" },
689
+ { url = "https://files.pythonhosted.org/packages/7f/56/bacea6dee2d5ccb31ab0cfffcee87ca7efa80ff048840209c8013aeaf02e/coverage-7.17.0-cp315-cp315-musllinux_1_2_i686.whl", hash = "sha256:5ebfbc87836529a31d25c2dec1262c38eea852ec1c46c0f690a515a7339d9c5b", size = 258649, upload-time = "2026-10-22T16:06:16.265Z" },
690
+ { url = "https://files.pythonhosted.org/packages/a4/97/fd8a6a63740f9ee177c53b59e2f4d0752369bb0fd154086a1e69aa1fb255/coverage-7.17.0-cp315-cp315-musllinux_1_2_ppc64le.whl", hash = "sha256:a59c3b470ac3b2432af3598a996affbeb10236cd899a005c1c4e517fcff8b592", size = 262989, upload-time = "2026-10-22T16:06:17.85Z" },
691
+ { url = "https://files.pythonhosted.org/packages/c1/37/7cd3d3520d45db3788456452b65446182c08f2a7c276f40c9dd11966be02/coverage-7.17.0-cp315-cp315-musllinux_1_2_riscv64.whl", hash = "sha256:7fef12cec4b96f59e09761cbd4fc9bdf4788062d1ae435b920241fc16c8a9549", size = 257955, upload-time = "2026-10-22T16:06:19.563Z" },
692
+ { url = "https://files.pythonhosted.org/packages/c1/b9/80343a55e07d854927a915cc21a52e350ae1db9ead33f0248507b960785f/coverage-7.17.0-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:a14e8d69464da9cbe1dc29e7116dbd37296d1d51a695327c478e250349085089", size = 260512, upload-time = "2026-10-22T16:06:21.055Z" },
693
+ { url = "https://files.pythonhosted.org/packages/f3/32/e4c816f0cb3efdc6392bb276ff88359729f9dec605bdd3c1c7a44776f759/coverage-7.17.0-cp315-cp315-win32.whl", hash = "sha256:9a66074231799d8884d267234d49f60c90b43a945dfe069646b72f3058cd4e67", size = 227913, upload-time = "2026-10-22T16:06:22.407Z" },
694
+ { url = "https://files.pythonhosted.org/packages/43/14/283120142ac281834808584249b89957de997c28573ddd65ae106b622121/coverage-7.17.0-cp315-cp315-win_amd64.whl", hash = "sha256:79cf71e5f9a48877ccfed5baa2c72f45af4feeaa596249e23eb15b473134830e", size = 228532, upload-time = "2026-10-22T16:06:23.756Z" },
695
+ { url = "https://files.pythonhosted.org/packages/b9/bc/83dbc6c3bd58042afaefcb0cfd7d7a2e3076989a2f3d9bc6e6edac819784/coverage-7.17.0-cp315-cp315-win_arm64.whl", hash = "sha256:09e563b49c81cd0a33734e926d7a4a6ef1778d74304cde2dcc3aff8b30ea1036", size = 228393, upload-time = "2026-10-22T16:06:25.163Z" },
696
+ { url = "https://files.pythonhosted.org/packages/00/ed/9463d1cb1766a2570343a372c2871c7fb4d561e5051f029399f4d57ce947/coverage-7.17.0-cp315-cp315t-macosx_10_15_x86_64.whl", hash = "sha256:a5e2e0625dfc789af0b2e10acfc106b352f314fffbd19e6392a7961c8cbe5d9a", size = 226481, upload-time = "2026-10-22T16:06:26.563Z" },
697
+ { url = "https://files.pythonhosted.org/packages/ae/59/6536c7fa87be13236b4184fc395f14d18f622a5b8ef7448a6bfdf5f24ec0/coverage-7.17.0-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:194562ab1eff0d85aee8a17ce4c5c0bc1ebf70a629a7145257123156ad100fd6", size = 226876, upload-time = "2026-10-22T16:06:27.921Z" },
698
+ { url = "https://files.pythonhosted.org/packages/b0/bc/4ffae6038f78382c9ab6a4969cb5fc01d50b083d119851085807629abe88/coverage-7.17.0-cp315-cp315t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:85682ca89bc4601125dcdff23fa70e6274e13c9ad502fba845e6c274ab2c6569", size = 267241, upload-time = "2026-10-22T16:06:29.356Z" },
699
+ { url = "https://files.pythonhosted.org/packages/c0/60/cae4b708b4217d33ebf66b9c57f8910a257346b3eaf054a78d73605ddc4c/coverage-7.17.0-cp315-cp315t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:0d0fac604a962ff546beb038cba9a5a09d88e6e3f01612fb46f7bd4fe5dc8dca", size = 270079, upload-time = "2026-10-22T16:06:30.736Z" },
700
+ { url = "https://files.pythonhosted.org/packages/a9/84/1225ab04e55a6a2e483e903a5eb0f8f081cb5325df833594534aa288d91c/coverage-7.17.0-cp315-cp315t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:72edd4f9483ae30cd1ba4f230687840ef7b58a16afb1c9e81131fd6d64655f36", size = 272775, upload-time = "2026-10-22T16:06:32.247Z" },
701
+ { url = "https://files.pythonhosted.org/packages/94/ad/567f8dd9246a553aa8753732c41f0e0654e98e9a617d6282e64eae0e6aa8/coverage-7.17.0-cp315-cp315t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:91e487ad07c511da77b574820141a7c2da09bc2a4b4090b5be2424295d100697", size = 274110, upload-time = "2026-10-22T16:06:33.859Z" },
702
+ { url = "https://files.pythonhosted.org/packages/66/5f/e0ee76895df40601e4aedffb6b8e71ea48e276a629fb4488b92cffffca14/coverage-7.17.0-cp315-cp315t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:1cabb31531002fef5197de5df3c84730aef01e750e25154b9813a2583435aba2", size = 267775, upload-time = "2026-10-22T16:06:35.193Z" },
703
+ { url = "https://files.pythonhosted.org/packages/19/6d/d19c6e45e940e5b9ba697b7be9a8e63cef73d90bdea45b670a59df466717/coverage-7.17.0-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:c9ac886242bbd50fb35a2242ba79555a99891e657da33f98b7ca968e3488a350", size = 270268, upload-time = "2026-10-22T16:06:36.597Z" },
704
+ { url = "https://files.pythonhosted.org/packages/27/a3/b2731bb7aef2db800b330603675c3fa58a6497a05d5b5f8625f3b6285f68/coverage-7.17.0-cp315-cp315t-musllinux_1_2_i686.whl", hash = "sha256:d45cdc495671fc99268ff3653e0da4244972e9fc0e1fc3ea9de18781ad28963a", size = 267298, upload-time = "2026-10-22T16:06:37.973Z" },
705
+ { url = "https://files.pythonhosted.org/packages/50/75/d0c90a81b6b6607933109914dc8b0ef0a5f4cacf9482ca868ae773ee5d0b/coverage-7.17.0-cp315-cp315t-musllinux_1_2_ppc64le.whl", hash = "sha256:12961f738d717a046d4bf3f8d1727eb3ebe2ed5478ff96cd6233d4dfc39323d3", size = 271899, upload-time = "2026-10-22T16:06:39.389Z" },
706
+ { url = "https://files.pythonhosted.org/packages/64/1e/f038f3a2614e9ef839a40a184713aca40b8ed79e626ab5cdc388771045df/coverage-7.17.0-cp315-cp315t-musllinux_1_2_riscv64.whl", hash = "sha256:1ee0a982b0e1230b3edf768a7dd022bd2377303763895327ac62deb5efacee03", size = 267380, upload-time = "2026-10-22T16:06:40.97Z" },
707
+ { url = "https://files.pythonhosted.org/packages/c9/30/8d636e639b2d8b1934128573402a7caf66c8cfbc794fa02061d84f115c34/coverage-7.17.0-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:460679f53893081edb94eeed011d26be37228ba649b853fd2aed7e4394fb1f35", size = 268993, upload-time = "2026-10-22T16:06:42.361Z" },
708
+ { url = "https://files.pythonhosted.org/packages/73/7a/219f6b391cb0636242d06c390a8add5af91afa3e92afd0380dbedd34f487/coverage-7.17.0-cp315-cp315t-win32.whl", hash = "sha256:600e121e412cd6bdb52ec105b95c6a04da0c9710d1534f6e64a42db667907802", size = 228216, upload-time = "2026-10-22T16:06:43.714Z" },
709
+ { url = "https://files.pythonhosted.org/packages/f0/3f/514d294319c5eac11494394545de209079f33993e14526c220eab29b2a96/coverage-7.17.0-cp315-cp315t-win_amd64.whl", hash = "sha256:c3e11b81faafb1f063248735c3e2c5c4183fc1db2c7f46782170dd7760dffcbc", size = 229146, upload-time = "2026-10-22T16:06:45.262Z" },
710
+ { url = "https://files.pythonhosted.org/packages/f6/82/c0d8bb0a67df838fc7bc6f4060ffc404fd1154fd18e624d83e6abc41aeef/coverage-7.17.0-cp315-cp315t-win_arm64.whl", hash = "sha256:d472ee1c64868a917a47f02ffb4ac8c22b477f7589d57a3eb0c58b1ad4f0137c", size = 228716, upload-time = "2026-10-22T16:06:47.097Z" },
711
+ { url = "https://files.pythonhosted.org/packages/c9/17/48032919343afa2906112d458aceda2043afdb24a2ee8eb4c60904d8ddf1/coverage-7.17.0-py3-none-any.whl", hash = "sha256:bac487dce0d2aff28ddf1a533a916f771416eee0e493960f611e49037b878e9d", size = 217383, upload-time = "2026-10-22T16:06:48.471Z" },
578
712
  ]
579
713
 
580
714
  [[package]]
@@ -888,8 +1022,8 @@ requires-dist = [
888
1022
  { name = "ckanapi", specifier = ">=4.11" },
889
1023
  { name = "defopt", specifier = ">=7.0.0" },
890
1024
  { name = "email-validator" },
891
- { name = "hdx-python-country", specifier = ">=4.2.4" },
892
- { name = "hdx-python-utilities", specifier = ">=4.2.3" },
1025
+ { name = "hdx-python-country", specifier = ">=4.2.5" },
1026
+ { name = "hdx-python-utilities", specifier = ">=4.2.4" },
893
1027
  { name = "makefun" },
894
1028
  { name = "mkapi", marker = "extra == 'docs'" },
895
1029
  { name = "requests" },
@@ -909,20 +1043,20 @@ dev = [
909
1043
 
910
1044
  [[package]]
911
1045
  name = "hdx-python-country"
912
- version = "4.2.4"
1046
+ version = "4.2.5"
913
1047
  source = { registry = "https://pypi.org/simple" }
914
1048
  dependencies = [
915
1049
  { name = "hdx-python-utilities" },
916
1050
  { name = "tenacity" },
917
1051
  ]
918
- sdist = { url = "https://files.pythonhosted.org/packages/b7/65/7d61838e5517a6f6386dfeee0280a096a2582b76eb5807c80bd6990600e0/hdx_python_country-4.2.4.tar.gz", hash = "sha256:72da67fb7e3500d26ae1695ab97d3fc7ccda02c2534c306f67a469a70a4396bc", size = 599679, upload-time = "2026-10-22T03:51:20.255Z" }
1052
+ sdist = { url = "https://files.pythonhosted.org/packages/94/7f/3672fd36ebefe7609e1d33a5dba81e9286d848d99684124893b4b575ac4b/hdx_python_country-4.2.5.tar.gz", hash = "sha256:66d86f93a6357e3771fb6869659aa6022bff6fb5eaf810505a6ae6b6ff4c5f19", size = 611408, upload-time = "2026-10-23T04:33:10.217Z" }
919
1053
  wheels = [
920
- { url = "https://files.pythonhosted.org/packages/1b/5c/e13346717a0ef48630d011180adc301cdf8a299cc04c421e88a19c999506/hdx_python_country-4.2.4-py3-none-any.whl", hash = "sha256:3c0682597ef408ebb6b70456f7e99f356e16f37c5fbeb979f76305a441bc74e4", size = 57193, upload-time = "2026-10-22T03:51:19.116Z" },
1054
+ { url = "https://files.pythonhosted.org/packages/5a/f9/124240adc1373991de24c628bb800b776477c528729f28e0f773297f93f6/hdx_python_country-4.2.5-py3-none-any.whl", hash = "sha256:c2adb1aed704bc12ad32cbf47468c2ab8ebec675634b828e26bd7566b93e6680", size = 57409, upload-time = "2026-10-23T04:33:08.83Z" },
921
1055
  ]
922
1056
 
923
1057
  [[package]]
924
1058
  name = "hdx-python-utilities"
925
- version = "4.2.3"
1059
+ version = "4.2.4"
926
1060
  source = { registry = "https://pypi.org/simple" }
927
1061
  dependencies = [
928
1062
  { name = "frictionless" },
@@ -942,9 +1076,9 @@ dependencies = [
942
1076
  { name = "xlsx2csv" },
943
1077
  { name = "xlwt" },
944
1078
  ]
945
- sdist = { url = "https://files.pythonhosted.org/packages/d7/70/d9e4db28e720510cf69ec75632784209c310f52994190a1f2dc15c508415/hdx_python_utilities-4.2.3.tar.gz", hash = "sha256:8e5213f93f51018049beb8808452e21ad70a441ff7607fa91d21574b00ee78fd", size = 2194034, upload-time = "2026-10-22T03:45:33.14Z" }
1079
+ sdist = { url = "https://files.pythonhosted.org/packages/19/1d/b18aabb4f744a3841b79fd8f1f26439039b253bcc846203a8f00288781e9/hdx_python_utilities-4.2.4.tar.gz", hash = "sha256:9e70d9d6793745967e8e759071a70bc4f0fa94eb5afcd180063bdc59ceca3a84", size = 2207998, upload-time = "2026-10-23T03:09:23.884Z" }
946
1080
  wheels = [
947
- { url = "https://files.pythonhosted.org/packages/14/56/de5aedca24a55cd95ae4b0dfdf37ba16b054dafea86f40765c8cc15a2782/hdx_python_utilities-4.2.3-py3-none-any.whl", hash = "sha256:13391adca4e82b9b3ef526562efac5d0123292f01645360073b1be5cab3e29d7", size = 67607, upload-time = "2026-10-22T03:45:31.376Z" },
1081
+ { url = "https://files.pythonhosted.org/packages/ab/c2/8dbbd48b770fcaa2da0b5780cb179d4cc72899d86a4a4f41295c74bd73e2/hdx_python_utilities-4.2.4-py3-none-any.whl", hash = "sha256:2377d3d24464408d5e861293686947637069463091f5287fc8bf7a858e1a493d", size = 67590, upload-time = "2026-10-23T03:09:22.644Z" },
948
1082
  ]
949
1083
 
950
1084
  [[package]]
@@ -1647,11 +1781,27 @@ wheels = [
1647
1781
  name = "pycparser"
1648
1782
  version = "3.11"
1649
1783
  source = { registry = "https://pypi.org/simple" }
1784
+ resolution-markers = [
1785
+ "python_full_version < '3.11'",
1786
+ ]
1650
1787
  sdist = { url = "https://files.pythonhosted.org/packages/da/a8/c5fdbeee588bb8ada9458774f43adf1bdd30bd59157055142183e769a024/pycparser-3.11.tar.gz", hash = "sha256:d875f09c3507d00e1aba0eecc6dcadc1352f30fff09dc6bff2f1c2935e97c2bc", size = 113796, upload-time = "2026-10-09T12:56:59.539Z" }
1651
1788
  wheels = [
1652
1789
  { url = "https://files.pythonhosted.org/packages/90/11/0e6f11117525ff0eec40ebac3d313376f102df93ca44ad9e893ee85e4f89/pycparser-3.11-py3-none-any.whl", hash = "sha256:51d5a8ba2be0bbe440b99d2112604c95bbbc3c2748a64260186c541e1729cd80", size = 51178, upload-time = "2026-10-09T12:56:58.131Z" },
1653
1790
  ]
1654
1791
 
1792
+ [[package]]
1793
+ name = "pycparser"
1794
+ version = "3.12"
1795
+ source = { registry = "https://pypi.org/simple" }
1796
+ resolution-markers = [
1797
+ "python_full_version >= '3.14'",
1798
+ "python_full_version >= '3.11' and python_full_version < '3.14'",
1799
+ ]
1800
+ sdist = { url = "https://files.pythonhosted.org/packages/cb/27/eeb9f307bf07060f3d9f9aa0fb8c15b01bdfded0a941e4b2719c7f94cacd/pycparser-3.12.tar.gz", hash = "sha256:f03387877eab82ce01bbdfd0ba7252ee55a90b1c708d5129e2ce915475cf1db6", size = 158785, upload-time = "2026-10-22T13:40:03.56Z" }
1801
+ wheels = [
1802
+ { url = "https://files.pythonhosted.org/packages/b6/ae/315bbeee126a769cbde43cf4908acb4b40408d8bf8bbf334dd7368d8dadf/pycparser-3.12-py3-none-any.whl", hash = "sha256:a076f3f489b39b43ed13563a1dafe42447445bec2e294154ec5c57fcdda4c85e", size = 62600, upload-time = "2026-10-22T13:40:02.021Z" },
1803
+ ]
1804
+
1655
1805
  [[package]]
1656
1806
  name = "pydantic"
1657
1807
  version = "2.14.1"
@@ -1874,7 +2024,8 @@ name = "pytest-cov"
1874
2024
  version = "7.1.0"
1875
2025
  source = { registry = "https://pypi.org/simple" }
1876
2026
  dependencies = [
1877
- { name = "coverage", extra = ["toml"] },
2027
+ { name = "coverage", version = "7.16.2", source = { registry = "https://pypi.org/simple" }, extra = ["toml"], marker = "python_full_version < '3.11'" },
2028
+ { name = "coverage", version = "7.17.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" },
1878
2029
  { name = "pluggy" },
1879
2030
  { name = "pytest" },
1880
2031
  ]
@@ -1897,14 +2048,15 @@ wheels = [
1897
2048
 
1898
2049
  [[package]]
1899
2050
  name = "python-dateutil"
1900
- version = "2.9.0.post0"
2051
+ version = "3.0.0"
1901
2052
  source = { registry = "https://pypi.org/simple" }
1902
2053
  dependencies = [
1903
2054
  { name = "six" },
2055
+ { name = "tzdata" },
1904
2056
  ]
1905
- sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432, upload-time = "2024-03-01T18:36:20.211Z" }
2057
+ sdist = { url = "https://files.pythonhosted.org/packages/0e/df/f15f80383f152452d8985b36d95cb8751f901a3e0ff4cd27f7e118f168e2/python_dateutil-3.0.0.tar.gz", hash = "sha256:7ebcb3c29a92f3ceafe79a7a48a5c45677e9e004bbeec5742ac0bbb00560b7a2", size = 271066, upload-time = "2026-10-21T23:41:45.075Z" }
1906
2058
  wheels = [
1907
- { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload-time = "2024-03-01T18:36:18.57Z" },
2059
+ { url = "https://files.pythonhosted.org/packages/5a/17/cebee01d1c0c1441174cf0456ddc91b280d79acb65340c05e41d77866ee8/python_dateutil-3.0.0-py2.py3-none-any.whl", hash = "sha256:3c79630202e4152c6add678446984236efe4f57e84d8e892aab0637bab82e9fd", size = 94659, upload-time = "2026-10-21T23:41:43.431Z" },
1908
2060
  ]
1909
2061
 
1910
2062
  [[package]]
@@ -2911,6 +3063,15 @@ wheels = [
2911
3063
  { url = "https://files.pythonhosted.org/packages/67/81/4add07e5172b7ac40d8ed5ff580409a7801a4fe26d529bdd915401dabfbe/typing_inspection-0.4.4-py3-none-any.whl", hash = "sha256:65b8397ba37ccbce054456aaccddfc91e6e3083c92824df348d96ca832f3f147", size = 14750, upload-time = "2026-08-12T12:37:24.648Z" },
2912
3064
  ]
2913
3065
 
3066
+ [[package]]
3067
+ name = "tzdata"
3068
+ version = "2026.5"
3069
+ source = { registry = "https://pypi.org/simple" }
3070
+ sdist = { url = "https://files.pythonhosted.org/packages/d9/68/f1b440335057bfce71b6e50a9d09445aa2ecbd08359a337976627b8409e7/tzdata-2026.5.tar.gz", hash = "sha256:8cc73c0a0bfca7dbfa59235d60b2eff82231dee33f53d206db1acd9173cfc0a7", size = 200404, upload-time = "2026-10-03T09:23:14.143Z" }
3071
+ wheels = [
3072
+ { url = "https://files.pythonhosted.org/packages/94/21/1e5995a1c920cce14e4bffae20c665ec10e7ed03ab25e006cd741092b718/tzdata-2026.5-py2.py3-none-any.whl", hash = "sha256:b683bd1b6659ddcd810ff02ad09ba821d4bf1065072805063eb35c49617905ac", size = 347996, upload-time = "2026-10-03T09:23:12.535Z" },
3073
+ ]
3074
+
2914
3075
  [[package]]
2915
3076
  name = "urllib3"
2916
3077
  version = "2.8.0"
@@ -2947,7 +3108,7 @@ wheels = [
2947
3108
 
2948
3109
  [[package]]
2949
3110
  name = "virtualenv"
2950
- version = "21.14.12"
3111
+ version = "21.14.13"
2951
3112
  source = { registry = "https://pypi.org/simple" }
2952
3113
  dependencies = [
2953
3114
  { name = "distlib" },
@@ -2959,9 +3120,9 @@ dependencies = [
2959
3120
  { name = "python-discovery" },
2960
3121
  { name = "typing-extensions", marker = "python_full_version < '3.11'" },
2961
3122
  ]
2962
- sdist = { url = "https://files.pythonhosted.org/packages/c9/2c/1a69b3346931e9a7db9cc00cc0fa847c843a85fa7cf52a598f57261c68df/virtualenv-21.14.12.tar.gz", hash = "sha256:bbcfb78e36c22ad70c6917c4aecb5e63477d3c138e9f88c946f320e31859c76a", size = 5562800, upload-time = "2026-10-21T01:58:51.724Z" }
3123
+ sdist = { url = "https://files.pythonhosted.org/packages/70/aa/bff50daee0488e16d611258a9b6c5a1d0c9e128f8ca424e9f4e1c0444ef2/virtualenv-21.14.13.tar.gz", hash = "sha256:de5307ba4b9a0001d9c8ea02832d38f63ca432880f416c1bface61c4323fd905", size = 5570301, upload-time = "2026-10-22T20:10:16.952Z" }
2963
3124
  wheels = [
2964
- { url = "https://files.pythonhosted.org/packages/a0/92/f3b8af2d36ddec4dc61dc25655dc010e419ff456cb4ca0e720c8112f1047/virtualenv-21.14.12-py3-none-any.whl", hash = "sha256:7820aeaef23f1f59a96458edfc7f9d3deac937155718de15f1c9a64471e15551", size = 5556824, upload-time = "2026-10-21T01:58:48.505Z" },
3125
+ { url = "https://files.pythonhosted.org/packages/bb/a9/c10d8a44a29fb94a18b43fdf11f38caca53ae7c9406f11a72b1cb8f624f1/virtualenv-21.14.13-py3-none-any.whl", hash = "sha256:5fbb04138a4861580b78ba9110d529a26bc48fcc93c8ec36bc0202eeed96a788", size = 5557094, upload-time = "2026-10-22T20:10:15.096Z" },
2965
3126
  ]
2966
3127
 
2967
3128
  [[package]]
File without changes
File without changes
File without changes