hdx-python-country 4.2.3__tar.gz → 4.2.5__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 (49) hide show
  1. {hdx_python_country-4.2.3 → hdx_python_country-4.2.5}/PKG-INFO +26 -12
  2. {hdx_python_country-4.2.3 → hdx_python_country-4.2.5}/README.md +24 -10
  3. {hdx_python_country-4.2.3 → hdx_python_country-4.2.5}/documentation/index.md +8 -8
  4. {hdx_python_country-4.2.3 → hdx_python_country-4.2.5}/pyproject.toml +5 -4
  5. {hdx_python_country-4.2.3 → hdx_python_country-4.2.5}/src/hdx/location/_version.py +2 -2
  6. {hdx_python_country-4.2.3 → hdx_python_country-4.2.5}/src/hdx/location/adminlevel.py +3 -8
  7. {hdx_python_country-4.2.3 → hdx_python_country-4.2.5}/tests/hdx/location/test_adminlevel.py +0 -26
  8. hdx_python_country-4.2.5/uv.lock +2671 -0
  9. hdx_python_country-4.2.3/uv.lock +0 -2063
  10. {hdx_python_country-4.2.3 → hdx_python_country-4.2.5}/.github/workflows/publish.yaml +0 -0
  11. {hdx_python_country-4.2.3 → hdx_python_country-4.2.5}/.github/workflows/run-python-tests.yaml +0 -0
  12. {hdx_python_country-4.2.3 → hdx_python_country-4.2.5}/.gitignore +0 -0
  13. {hdx_python_country-4.2.3 → hdx_python_country-4.2.5}/.pre-commit-config.yaml +0 -0
  14. {hdx_python_country-4.2.3 → hdx_python_country-4.2.5}/LICENSE +0 -0
  15. {hdx_python_country-4.2.3 → hdx_python_country-4.2.5}/documentation/.readthedocs.yaml +0 -0
  16. {hdx_python_country-4.2.3 → hdx_python_country-4.2.5}/documentation/mkdocs.yaml +0 -0
  17. {hdx_python_country-4.2.3 → hdx_python_country-4.2.5}/src/hdx/location/Countries & Territories Taxonomy MVP - C&T Taxonomy.csv +0 -0
  18. {hdx_python_country-4.2.3 → hdx_python_country-4.2.5}/src/hdx/location/__init__.py +0 -0
  19. {hdx_python_country-4.2.3 → hdx_python_country-4.2.5}/src/hdx/location/country.py +0 -0
  20. {hdx_python_country-4.2.3 → hdx_python_country-4.2.5}/src/hdx/location/currency.py +0 -0
  21. {hdx_python_country-4.2.3 → hdx_python_country-4.2.5}/src/hdx/location/int_timestamp.py +0 -0
  22. {hdx_python_country-4.2.3 → hdx_python_country-4.2.5}/src/hdx/location/wfp_api.py +0 -0
  23. {hdx_python_country-4.2.3 → hdx_python_country-4.2.5}/src/hdx/location/wfp_exchangerates.py +0 -0
  24. {hdx_python_country-4.2.3 → hdx_python_country-4.2.5}/tests/fixtures/adminlevel.yaml +0 -0
  25. {hdx_python_country-4.2.3 → hdx_python_country-4.2.5}/tests/fixtures/adminlevelparent.yaml +0 -0
  26. {hdx_python_country-4.2.3 → hdx_python_country-4.2.5}/tests/fixtures/fixtures-download-global-pcode-lengths.csv +0 -0
  27. {hdx_python_country-4.2.3 → hdx_python_country-4.2.5}/tests/fixtures/fixtures-download-global-pcodes-adm-1-2.csv +0 -0
  28. {hdx_python_country-4.2.3 → hdx_python_country-4.2.5}/tests/fixtures/secondary_historic_rates.csv +0 -0
  29. {hdx_python_country-4.2.3 → hdx_python_country-4.2.5}/tests/fixtures/secondary_rates.json +0 -0
  30. {hdx_python_country-4.2.3 → hdx_python_country-4.2.5}/tests/fixtures/wfp/Currency_List_1.json +0 -0
  31. {hdx_python_country-4.2.3 → hdx_python_country-4.2.5}/tests/fixtures/wfp/Currency_List_2.json +0 -0
  32. {hdx_python_country-4.2.3 → hdx_python_country-4.2.5}/tests/fixtures/wfp/Currency_UsdIndirectQuotation_1.json +0 -0
  33. {hdx_python_country-4.2.3 → hdx_python_country-4.2.5}/tests/fixtures/wfp/Currency_UsdIndirectQuotation_10.json +0 -0
  34. {hdx_python_country-4.2.3 → hdx_python_country-4.2.5}/tests/fixtures/wfp/Currency_UsdIndirectQuotation_2.json +0 -0
  35. {hdx_python_country-4.2.3 → hdx_python_country-4.2.5}/tests/fixtures/wfp/Currency_UsdIndirectQuotation_3.json +0 -0
  36. {hdx_python_country-4.2.3 → hdx_python_country-4.2.5}/tests/fixtures/wfp/Currency_UsdIndirectQuotation_4.json +0 -0
  37. {hdx_python_country-4.2.3 → hdx_python_country-4.2.5}/tests/fixtures/wfp/Currency_UsdIndirectQuotation_5.json +0 -0
  38. {hdx_python_country-4.2.3 → hdx_python_country-4.2.5}/tests/fixtures/wfp/Currency_UsdIndirectQuotation_6.json +0 -0
  39. {hdx_python_country-4.2.3 → hdx_python_country-4.2.5}/tests/fixtures/wfp/Currency_UsdIndirectQuotation_7.json +0 -0
  40. {hdx_python_country-4.2.3 → hdx_python_country-4.2.5}/tests/fixtures/wfp/Currency_UsdIndirectQuotation_8.json +0 -0
  41. {hdx_python_country-4.2.3 → hdx_python_country-4.2.5}/tests/fixtures/wfp/Currency_UsdIndirectQuotation_9.json +0 -0
  42. {hdx_python_country-4.2.3 → hdx_python_country-4.2.5}/tests/fixtures/wfp/Markets_List_AFG_1.json +0 -0
  43. {hdx_python_country-4.2.3 → hdx_python_country-4.2.5}/tests/fixtures/wfp/Markets_List_AFG_2.json +0 -0
  44. {hdx_python_country-4.2.3 → hdx_python_country-4.2.5}/tests/hdx/location/Countries_UZB_Deleted.csv +0 -0
  45. {hdx_python_country-4.2.3 → hdx_python_country-4.2.5}/tests/hdx/location/__init__.py +0 -0
  46. {hdx_python_country-4.2.3 → hdx_python_country-4.2.5}/tests/hdx/location/conftest.py +0 -0
  47. {hdx_python_country-4.2.3 → hdx_python_country-4.2.5}/tests/hdx/location/test_country.py +0 -0
  48. {hdx_python_country-4.2.3 → hdx_python_country-4.2.5}/tests/hdx/location/test_currency.py +0 -0
  49. {hdx_python_country-4.2.3 → hdx_python_country-4.2.5}/tests/hdx/location/test_wfp_exchangerates.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: hdx-python-country
3
- Version: 4.2.3
3
+ Version: 4.2.5
4
4
  Summary: HDX Python country code and exchange rate (fx) utilities
5
5
  Project-URL: Homepage, https://github.com/OCHA-DAP/hdx-python-country
6
6
  Project-URL: Repository, https://github.com/OCHA-DAP/hdx-python-country
@@ -27,7 +27,7 @@ Classifier: Programming Language :: Python :: 3.13
27
27
  Classifier: Programming Language :: Python :: 3.14
28
28
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
29
29
  Requires-Python: >=3.10
30
- Requires-Dist: hdx-python-utilities<5,>=4.2.1
30
+ Requires-Dist: hdx-python-utilities<5,>=4.2.4
31
31
  Requires-Dist: tenacity
32
32
  Provides-Extra: docs
33
33
  Requires-Dist: mkapi; extra == 'docs'
@@ -55,7 +55,7 @@ fuzzy matching for English look up that can handle abbreviations in country name
55
55
  Dem. for Democratic and Rep. for Republic.
56
56
 
57
57
  Mapping administration level names from a source to a given base set is also handled
58
- including phonetic fuzzy name matching.
58
+ including fuzzy name matching.
59
59
 
60
60
  It also provides foreign exchange rates and conversion from amounts in local
61
61
  currency to USD and vice-versa. The conversion relies on Yahoo Finance, falling
@@ -146,24 +146,38 @@ documentation at `documentation/index.md`.
146
146
  ## WFP DataBridges Client
147
147
 
148
148
  The `WFPAPI` class (`hdx.location.wfp_api`) uses WFP's `data-bridges-client` library, which is
149
- published on WFP's own package index rather than PyPI. To install it, use the `wfp` extra with
150
- that index added:
149
+ published on WFP's own package index rather than PyPI. That index hosts only
150
+ `data-bridges-client`, so install it from there first without dependencies, then install the
151
+ `wfp` extra from PyPI:
151
152
 
152
153
  ```shell
153
- pip install "hdx-python-country[wfp]" \
154
- --extra-index-url https://d2i4vvypvg40rv.cloudfront.net/pypi/ \
155
- --index-strategy unsafe-best-match
154
+ pip install "data-bridges-client>=9,<10" --no-deps \
155
+ --index-url https://d2i4vvypvg40rv.cloudfront.net/pypi/
156
+ pip install "hdx-python-country[wfp]"
156
157
  ```
157
158
 
158
- If using `uv`, add the following to your project's `pyproject.toml`:
159
+ Avoid `--extra-index-url`: pip then picks the highest version from either index, so a package
160
+ published on PyPI under the name `data-bridges-client` would be installed instead.
161
+
162
+ If using `uv`, add the following to your project's `pyproject.toml` so that only
163
+ `data-bridges-client` is fetched from WFP's index. `data-bridges-client` must be a direct
164
+ dependency because `tool.uv.sources` does not apply to transitive dependencies; without it, uv
165
+ falls back to an old `hdx-python-country` that has no `wfp` extra:
159
166
 
160
167
  ```toml
161
- [tool.uv]
162
- index-strategy = "unsafe-best-match"
168
+ [project]
169
+ dependencies = [
170
+ "hdx-python-country[wfp]",
171
+ "data-bridges-client>=9,<10",
172
+ ]
163
173
 
164
174
  [[tool.uv.index]]
165
175
  name = "wfp"
166
176
  url = "https://d2i4vvypvg40rv.cloudfront.net/pypi/"
177
+ explicit = true
178
+
179
+ [tool.uv.sources]
180
+ data-bridges-client = { index = "wfp" }
167
181
  ```
168
182
 
169
- then run `uv sync --extra wfp`.
183
+ then run `uv sync`.
@@ -18,7 +18,7 @@ fuzzy matching for English look up that can handle abbreviations in country name
18
18
  Dem. for Democratic and Rep. for Republic.
19
19
 
20
20
  Mapping administration level names from a source to a given base set is also handled
21
- including phonetic fuzzy name matching.
21
+ including fuzzy name matching.
22
22
 
23
23
  It also provides foreign exchange rates and conversion from amounts in local
24
24
  currency to USD and vice-versa. The conversion relies on Yahoo Finance, falling
@@ -109,24 +109,38 @@ documentation at `documentation/index.md`.
109
109
  ## WFP DataBridges Client
110
110
 
111
111
  The `WFPAPI` class (`hdx.location.wfp_api`) uses WFP's `data-bridges-client` library, which is
112
- published on WFP's own package index rather than PyPI. To install it, use the `wfp` extra with
113
- that index added:
112
+ published on WFP's own package index rather than PyPI. That index hosts only
113
+ `data-bridges-client`, so install it from there first without dependencies, then install the
114
+ `wfp` extra from PyPI:
114
115
 
115
116
  ```shell
116
- pip install "hdx-python-country[wfp]" \
117
- --extra-index-url https://d2i4vvypvg40rv.cloudfront.net/pypi/ \
118
- --index-strategy unsafe-best-match
117
+ pip install "data-bridges-client>=9,<10" --no-deps \
118
+ --index-url https://d2i4vvypvg40rv.cloudfront.net/pypi/
119
+ pip install "hdx-python-country[wfp]"
119
120
  ```
120
121
 
121
- If using `uv`, add the following to your project's `pyproject.toml`:
122
+ Avoid `--extra-index-url`: pip then picks the highest version from either index, so a package
123
+ published on PyPI under the name `data-bridges-client` would be installed instead.
124
+
125
+ If using `uv`, add the following to your project's `pyproject.toml` so that only
126
+ `data-bridges-client` is fetched from WFP's index. `data-bridges-client` must be a direct
127
+ dependency because `tool.uv.sources` does not apply to transitive dependencies; without it, uv
128
+ falls back to an old `hdx-python-country` that has no `wfp` extra:
122
129
 
123
130
  ```toml
124
- [tool.uv]
125
- index-strategy = "unsafe-best-match"
131
+ [project]
132
+ dependencies = [
133
+ "hdx-python-country[wfp]",
134
+ "data-bridges-client>=9,<10",
135
+ ]
126
136
 
127
137
  [[tool.uv.index]]
128
138
  name = "wfp"
129
139
  url = "https://d2i4vvypvg40rv.cloudfront.net/pypi/"
140
+ explicit = true
141
+
142
+ [tool.uv.sources]
143
+ data-bridges-client = { index = "wfp" }
130
144
  ```
131
145
 
132
- then run `uv sync --extra wfp`.
146
+ then run `uv sync`.
@@ -42,11 +42,13 @@ The code for the library is [here](https://github.com/OCHA-DAP/hdx-python-countr
42
42
  The library has detailed API documentation which can be found in the menu at the top.
43
43
 
44
44
  ## Breaking Changes
45
+ From 4.2.4, the AdminLevel matcher parameter is removed and HDX Python Utilities
46
+ 4.2.3 or later is required.
47
+
45
48
  From 4.2.0, AdminLevel fuzzy matches using RapidFuzzMatcher (with its place_name_scorer)
46
- from HDX Python Utilities rather than Phonetics by default. Pass matcher=Phonetics() for
47
- the previous behaviour. Names made of parts are resolved from their parts and lists of
48
- names are not fuzzy matched (see Administration Level). Fuzzy matching is now tried when
49
- parent is "" as well as when it is None.
49
+ from HDX Python Utilities rather than Phonetics by default. Names made of parts are
50
+ resolved from their parts and lists of names are not fuzzy matched (see Administration
51
+ Level). Fuzzy matching is now tried when parent is "" as well as when it is None.
50
52
 
51
53
  From 4.1.1, HXL hashtags no longer used in AdminLevel class. The header names are used
52
54
  instead. setup_from_iterable replaces setup_from_admin_info and
@@ -167,9 +169,8 @@ A Retrieve object can be passed in the *retriever* parameter that enables
167
169
  saving data downloaded to a file or loading previously saved data depending
168
170
  on how the Retrieve object is configured.
169
171
 
170
- The *matcher* parameter sets the fuzzy name matcher. It defaults to
171
- RapidFuzzMatcher from HDX Python Utilities with its place_name_scorer. Phonetics
172
- from HDX Python Utilities can be passed instead.
172
+ Fuzzy name matching uses RapidFuzzMatcher from HDX Python Utilities with its
173
+ place_name_scorer.
173
174
 
174
175
  Before fuzzy matching, a name made of parts split by separators (",", ";", "/",
175
176
  ":", "&", newline, "and", "et") or a hyphen is resolved from its parts. A name
@@ -212,7 +213,6 @@ Examples of usage:
212
213
  assert admintwo.get_pcode("AFG", "Kabul", parent="AF01") == ("AF0101", True)
213
214
  adminlevel.get_pcode("KHM", "Kampot & Kep") # returns (None, False)
214
215
  admintwo.get_pcode("VEN", "Falcón, Acosta", parent="VE11") # returns ("VE1101", False)
215
- adminlevel = AdminLevel(config, matcher=Phonetics()) # use Phonetics
216
216
 
217
217
  There is basic admin 1 p-code length conversion by default. A more advanced
218
218
  p-code length conversion can be activated by calling *load_pcode_formats*
@@ -36,7 +36,7 @@ dynamic = ["version"]
36
36
  requires-python = ">=3.10"
37
37
 
38
38
  dependencies = [
39
- "hdx-python-utilities>=4.2.1,<5",
39
+ "hdx-python-utilities>=4.2.4,<5",
40
40
  "tenacity",
41
41
  ]
42
42
 
@@ -82,12 +82,13 @@ allow-direct-references = true
82
82
  # uv (Package Management)
83
83
  # ----------------------------------------------------------------------------
84
84
 
85
- [tool.uv]
86
- index-strategy = "unsafe-best-match"
87
-
88
85
  [[tool.uv.index]]
89
86
  name = "wfp"
90
87
  url = "https://d2i4vvypvg40rv.cloudfront.net/pypi/"
88
+ explicit = true
89
+
90
+ [tool.uv.sources]
91
+ data-bridges-client = { index = "wfp" }
91
92
 
92
93
  # ----------------------------------------------------------------------------
93
94
  # Ruff (Linting & Formatting)
@@ -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 = '4.2.3'
22
- __version_tuple__ = version_tuple = (4, 2, 3)
21
+ __version__ = version = '4.2.5'
22
+ __version_tuple__ = version_tuple = (4, 2, 5)
23
23
 
24
24
  __commit_id__ = commit_id = None
@@ -6,7 +6,6 @@ from typing import Any
6
6
 
7
7
  from hdx.utilities.dictandlist import dict_of_sets_add
8
8
  from hdx.utilities.matching import (
9
- Phonetics,
10
9
  RapidFuzzMatcher,
11
10
  multiple_replace,
12
11
  resolve_name_parts,
@@ -43,17 +42,14 @@ class AdminLevel:
43
42
  to files or to enable already saved files to be used instead of downloading
44
43
  from urls.
45
44
 
46
- The matcher parameter overrides the fuzzy name matcher that fuzzy_pcode
47
- tries last. It defaults to hdx.utilities.matching.RapidFuzzMatcher with
48
- its place_name_scorer. hdx.utilities.matching.Phonetics can be passed
49
- instead.
45
+ The fuzzy name matcher that fuzzy_pcode tries last is
46
+ hdx.utilities.matching.RapidFuzzMatcher with its place_name_scorer.
50
47
 
51
48
  Args:
52
49
  admin_config: Configuration dictionary. Defaults to {}.
53
50
  admin_level: Admin level. Defaults to 1.
54
51
  admin_level_overrides: Countries at other admin levels.
55
52
  retriever: Retriever object to use for loading/saving files.
56
- matcher: Fuzzy name matcher to use. Defaults to None (RapidFuzzMatcher).
57
53
  """
58
54
 
59
55
  pcode_regex = re.compile(r"^([a-zA-Z]{2,3})(\d+)$")
@@ -69,7 +65,6 @@ class AdminLevel:
69
65
  admin_level: int = 1,
70
66
  admin_level_overrides: dict | None = None,
71
67
  retriever: Retrieve | None = None,
72
- matcher: Phonetics | RapidFuzzMatcher | None = None,
73
68
  ) -> None:
74
69
  self._admin_level_overrides = admin_level_overrides or {}
75
70
  self._retriever: Retrieve | None = retriever
@@ -81,7 +76,7 @@ class AdminLevel:
81
76
  self._use_parent = False
82
77
  self._zeroes = {}
83
78
  self._parent_admins = []
84
- self._matcher = matcher or RapidFuzzMatcher(RapidFuzzMatcher.place_name_scorer)
79
+ self._matcher = RapidFuzzMatcher(RapidFuzzMatcher.place_name_scorer)
85
80
  self.init_matches_errors()
86
81
  self.admin_level = admin_level
87
82
  self.pcodes = []
@@ -205,32 +205,6 @@ class TestAdminLevel:
205
205
  "test - YEM: Matching (fuzzy) Al_Dhale'a to Ad Dali on map",
206
206
  ]
207
207
 
208
- def test_adminlevel_custom_matcher(self, config):
209
- class AlwaysFirstMatcher:
210
- def match(
211
- self,
212
- possible_names,
213
- name,
214
- alternative_name=None,
215
- transform_possible_names=(),
216
- threshold=None,
217
- ):
218
- return 0
219
-
220
- adminone = AdminLevel(config)
221
- adminone.setup_from_iterable(config["admin_info"])
222
- assert adminone.get_pcode("YEM", "Zzznotarealplace", logname="test") == (
223
- None,
224
- False,
225
- )
226
-
227
- adminone = AdminLevel(config, matcher=AlwaysFirstMatcher())
228
- adminone.setup_from_iterable(config["admin_info"])
229
- pcode, exact = adminone.get_pcode("YEM", "Zzznotarealplace", logname="test")
230
- assert exact is False
231
- assert pcode is not None
232
- assert adminone.pcode_to_iso3[pcode] == "YEM"
233
-
234
208
  def test_adminlevel_list_of_names(self):
235
209
  def row(countryiso3, level, pcode, name, parent):
236
210
  return {