hdx-python-country 3.7.3__tar.gz → 3.7.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 (37) hide show
  1. {hdx_python_country-3.7.3 → hdx_python_country-3.7.5}/PKG-INFO +3 -3
  2. {hdx_python_country-3.7.3 → hdx_python_country-3.7.5}/documentation/main.md +3 -0
  3. {hdx_python_country-3.7.3 → hdx_python_country-3.7.5}/pyproject.toml +2 -2
  4. {hdx_python_country-3.7.3 → hdx_python_country-3.7.5}/requirements.txt +15 -13
  5. {hdx_python_country-3.7.3 → hdx_python_country-3.7.5}/src/hdx/location/_version.py +2 -2
  6. {hdx_python_country-3.7.3 → hdx_python_country-3.7.5}/src/hdx/location/adminlevel.py +4 -5
  7. {hdx_python_country-3.7.3 → hdx_python_country-3.7.5}/src/hdx/location/phonetics.py +10 -10
  8. {hdx_python_country-3.7.3 → hdx_python_country-3.7.5}/tests/fixtures/adminlevel.yaml +0 -1
  9. {hdx_python_country-3.7.3 → hdx_python_country-3.7.5}/tests/fixtures/adminlevelparent.yaml +3 -4
  10. {hdx_python_country-3.7.3 → hdx_python_country-3.7.5}/tests/hdx/location/test_adminlevel.py +27 -42
  11. hdx_python_country-3.7.3/src/hdx/location/names.py +0 -31
  12. {hdx_python_country-3.7.3 → hdx_python_country-3.7.5}/.config/coveragerc +0 -0
  13. {hdx_python_country-3.7.3 → hdx_python_country-3.7.5}/.config/pre-commit-config.yaml +0 -0
  14. {hdx_python_country-3.7.3 → hdx_python_country-3.7.5}/.config/pytest.ini +0 -0
  15. {hdx_python_country-3.7.3 → hdx_python_country-3.7.5}/.config/ruff.toml +0 -0
  16. {hdx_python_country-3.7.3 → hdx_python_country-3.7.5}/.github/workflows/publish.yaml +0 -0
  17. {hdx_python_country-3.7.3 → hdx_python_country-3.7.5}/.github/workflows/run-python-tests.yaml +0 -0
  18. {hdx_python_country-3.7.3 → hdx_python_country-3.7.5}/.gitignore +0 -0
  19. {hdx_python_country-3.7.3 → hdx_python_country-3.7.5}/CONTRIBUTING.md +0 -0
  20. {hdx_python_country-3.7.3 → hdx_python_country-3.7.5}/LICENSE +0 -0
  21. {hdx_python_country-3.7.3 → hdx_python_country-3.7.5}/README.md +0 -0
  22. {hdx_python_country-3.7.3 → hdx_python_country-3.7.5}/documentation/.readthedocs.yaml +0 -0
  23. {hdx_python_country-3.7.3 → hdx_python_country-3.7.5}/documentation/pydoc-markdown.yaml +0 -0
  24. {hdx_python_country-3.7.3 → hdx_python_country-3.7.5}/src/hdx/location/Countries & Territories Taxonomy MVP - C&T Taxonomy with HXL Tags.csv +0 -0
  25. {hdx_python_country-3.7.3 → hdx_python_country-3.7.5}/src/hdx/location/__init__.py +0 -0
  26. {hdx_python_country-3.7.3 → hdx_python_country-3.7.5}/src/hdx/location/country.py +0 -0
  27. {hdx_python_country-3.7.3 → hdx_python_country-3.7.5}/src/hdx/location/currency.py +0 -0
  28. {hdx_python_country-3.7.3 → hdx_python_country-3.7.5}/src/hdx/location/wfp_exchangerates.py +0 -0
  29. {hdx_python_country-3.7.3 → hdx_python_country-3.7.5}/tests/fixtures/global_pcode_lengths.csv +0 -0
  30. {hdx_python_country-3.7.3 → hdx_python_country-3.7.5}/tests/fixtures/global_pcodes_adm_1_2.csv +0 -0
  31. {hdx_python_country-3.7.3 → hdx_python_country-3.7.5}/tests/fixtures/secondary_historic_rates.csv +0 -0
  32. {hdx_python_country-3.7.3 → hdx_python_country-3.7.5}/tests/fixtures/secondary_rates.json +0 -0
  33. {hdx_python_country-3.7.3 → hdx_python_country-3.7.5}/tests/hdx/location/Countries_UZB_Deleted.csv +0 -0
  34. {hdx_python_country-3.7.3 → hdx_python_country-3.7.5}/tests/hdx/location/__init__.py +0 -0
  35. {hdx_python_country-3.7.3 → hdx_python_country-3.7.5}/tests/hdx/location/test_country.py +0 -0
  36. {hdx_python_country-3.7.3 → hdx_python_country-3.7.5}/tests/hdx/location/test_currency.py +0 -0
  37. {hdx_python_country-3.7.3 → hdx_python_country-3.7.5}/tests/hdx/location/test_wfp_exchangerates.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: hdx-python-country
3
- Version: 3.7.3
3
+ Version: 3.7.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
  Author: Michael Rans
@@ -25,9 +25,9 @@ Classifier: Programming Language :: Python :: 3.11
25
25
  Classifier: Programming Language :: Python :: 3.12
26
26
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
27
27
  Requires-Python: >=3.8
28
- Requires-Dist: hdx-python-utilities>=3.7.0
28
+ Requires-Dist: hdx-python-utilities>=3.7.2
29
29
  Requires-Dist: libhxl>=5.2.1
30
- Requires-Dist: rapidfuzz
30
+ Requires-Dist: pyphonetics
31
31
  Provides-Extra: dev
32
32
  Requires-Dist: pre-commit; extra == 'dev'
33
33
  Provides-Extra: test
@@ -42,6 +42,9 @@ 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 3.7.5, removed clean_name function. There is now a function normalise in
46
+ HDX Python Utilities.
47
+
45
48
  From 3.5.5, after creating an Adminlevel, call either setup_from_admin_info,
46
49
  setup_from_libhxl_dataset or setup_from_url.
47
50
 
@@ -34,9 +34,9 @@ classifiers = [
34
34
  requires-python = ">=3.8"
35
35
 
36
36
  dependencies = [
37
- "hdx-python-utilities>=3.7.0",
37
+ "hdx-python-utilities>=3.7.2",
38
38
  "libhxl>=5.2.1",
39
- "rapidfuzz",
39
+ "pyphonetics",
40
40
  ]
41
41
  dynamic = ["version"]
42
42
 
@@ -8,7 +8,7 @@ attrs==23.2.0
8
8
  # jsonlines
9
9
  # jsonschema
10
10
  # referencing
11
- certifi==2024.6.2
11
+ certifi==2024.7.4
12
12
  # via requests
13
13
  cfgv==3.4.0
14
14
  # via pre-commit
@@ -18,17 +18,17 @@ charset-normalizer==3.3.2
18
18
  # via requests
19
19
  click==8.1.7
20
20
  # via typer
21
- coverage==7.5.3
21
+ coverage==7.5.4
22
22
  # via pytest-cov
23
23
  distlib==0.3.8
24
24
  # via virtualenv
25
25
  et-xmlfile==1.1.0
26
26
  # via openpyxl
27
- filelock==3.15.3
27
+ filelock==3.15.4
28
28
  # via virtualenv
29
29
  frictionless==5.17.0
30
30
  # via hdx-python-utilities
31
- hdx-python-utilities==3.7.0
31
+ hdx-python-utilities==3.7.2
32
32
  # via hdx-python-country (pyproject.toml)
33
33
  humanize==4.9.0
34
34
  # via frictionless
@@ -60,7 +60,7 @@ loguru==0.7.2
60
60
  # via hdx-python-utilities
61
61
  markdown-it-py==3.0.0
62
62
  # via rich
63
- marko==2.1.1
63
+ marko==2.1.2
64
64
  # via frictionless
65
65
  markupsafe==2.1.5
66
66
  # via jinja2
@@ -68,7 +68,7 @@ mdurl==0.1.2
68
68
  # via markdown-it-py
69
69
  nodeenv==1.9.1
70
70
  # via pre-commit
71
- openpyxl==3.1.4
71
+ openpyxl==3.1.5
72
72
  # via hdx-python-utilities
73
73
  packaging==24.1
74
74
  # via pytest
@@ -84,12 +84,14 @@ ply==3.11
84
84
  # libhxl
85
85
  pre-commit==3.7.1
86
86
  # via hdx-python-country (pyproject.toml)
87
- pydantic==2.7.4
87
+ pydantic==2.8.2
88
88
  # via frictionless
89
- pydantic-core==2.18.4
89
+ pydantic-core==2.20.1
90
90
  # via pydantic
91
91
  pygments==2.18.0
92
92
  # via rich
93
+ pyphonetics==0.5.3
94
+ # via hdx-python-country (pyproject.toml)
93
95
  pytest==8.2.2
94
96
  # via
95
97
  # hdx-python-country (pyproject.toml)
@@ -110,8 +112,6 @@ pyyaml==6.0.1
110
112
  # frictionless
111
113
  # pre-commit
112
114
  # tableschema-to-template
113
- rapidfuzz==3.9.3
114
- # via hdx-python-country (pyproject.toml)
115
115
  ratelimit==2.2.1
116
116
  # via hdx-python-utilities
117
117
  referencing==0.35.1
@@ -164,14 +164,16 @@ typing-extensions==4.12.2
164
164
  # pydantic-core
165
165
  # typer
166
166
  unidecode==1.3.8
167
- # via libhxl
167
+ # via
168
+ # libhxl
169
+ # pyphonetics
168
170
  urllib3==2.2.2
169
171
  # via
170
172
  # libhxl
171
173
  # requests
172
- validators==0.28.3
174
+ validators==0.30.0
173
175
  # via frictionless
174
- virtualenv==20.26.2
176
+ virtualenv==20.26.3
175
177
  # via pre-commit
176
178
  wheel==0.43.0
177
179
  # via libhxl
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '3.7.3'
16
- __version_tuple__ = version_tuple = (3, 7, 3)
15
+ __version__ = version = '3.7.5'
16
+ __version_tuple__ = version_tuple = (3, 7, 5)
@@ -7,10 +7,9 @@ from hxl import InputOptions
7
7
  from hxl.input import HXLIOException
8
8
 
9
9
  from hdx.location.country import Country
10
- from hdx.location.names import clean_name
11
10
  from hdx.location.phonetics import Phonetics
12
11
  from hdx.utilities.dictandlist import dict_of_sets_add
13
- from hdx.utilities.text import multiple_replace
12
+ from hdx.utilities.text import multiple_replace, normalise
14
13
  from hdx.utilities.typehint import ListTuple
15
14
 
16
15
  logger = logging.getLogger(__name__)
@@ -146,7 +145,7 @@ class AdminLevel:
146
145
  self.pcode_to_name[pcode] = adm_name
147
146
 
148
147
  name_to_pcode = self.name_to_pcode.get(countryiso3, {})
149
- name_to_pcode[clean_name(adm_name)] = pcode
148
+ name_to_pcode[normalise(adm_name)] = pcode
150
149
  self.name_to_pcode[countryiso3] = name_to_pcode
151
150
  self.pcode_to_iso3[pcode] = countryiso3
152
151
  self.pcode_to_iso3[pcode] = countryiso3
@@ -156,7 +155,7 @@ class AdminLevel:
156
155
  countryiso3, {}
157
156
  )
158
157
  name_to_pcode = name_parent_to_pcode.get(parent, {})
159
- name_to_pcode[clean_name(adm_name)] = pcode
158
+ name_to_pcode[normalise(adm_name)] = pcode
160
159
  name_parent_to_pcode[parent] = name_to_pcode
161
160
  self.name_parent_to_pcode[countryiso3] = name_parent_to_pcode
162
161
  self.pcode_to_parent[pcode] = parent
@@ -598,7 +597,7 @@ class AdminLevel:
598
597
  if logname:
599
598
  self.errors.add((logname, countryiso3, parent))
600
599
  return None
601
- adm_name_lookup = clean_name(name)
600
+ adm_name_lookup = normalise(name)
602
601
  adm_name_lookup2 = multiple_replace(
603
602
  adm_name_lookup,
604
603
  self.get_admin_name_replacements(countryiso3, parent),
@@ -1,18 +1,18 @@
1
1
  from typing import Callable, Optional
2
2
 
3
- from rapidfuzz import fuzz
3
+ import pyphonetics
4
4
 
5
5
  from hdx.utilities.typehint import ListTuple
6
6
 
7
7
 
8
- class Phonetics:
8
+ class Phonetics(pyphonetics.RefinedSoundex):
9
9
  def match(
10
10
  self,
11
11
  possible_names: ListTuple,
12
12
  name: str,
13
13
  alternative_name: Optional[str] = None,
14
14
  transform_possible_names: ListTuple[Callable] = [],
15
- threshold: float = 60,
15
+ threshold: int = 2,
16
16
  ) -> Optional[int]:
17
17
  """
18
18
  Match name to one of the given possible names. Returns None if no match
@@ -23,22 +23,22 @@ class Phonetics:
23
23
  name (str): Name to match
24
24
  alternative_name (str): Alternative name to match. Defaults to None.
25
25
  transform_possible_names (ListTuple[Callable]): Functions to transform possible names.
26
- threshold (float): Match threshold. Value is 0-100. Defaults to 60.
26
+ threshold: Match threshold. Defaults to 2.
27
27
 
28
28
  Returns:
29
29
  Optional[int]: Index of matching name from possible names or None
30
30
  """
31
- max_similarity = 0
31
+ mindistance = None
32
32
  matching_index = None
33
33
 
34
34
  transform_possible_names.insert(0, lambda x: x)
35
35
 
36
36
  def check_name(name, possible_name):
37
- nonlocal max_similarity, matching_index # noqa: E999
37
+ nonlocal mindistance, matching_index # noqa: E999
38
38
 
39
- similarity = fuzz.token_sort_ratio(name, possible_name)
40
- if similarity > max_similarity:
41
- max_similarity = similarity
39
+ distance = self.distance(name, possible_name)
40
+ if mindistance is None or distance < mindistance:
41
+ mindistance = distance
42
42
  matching_index = i
43
43
 
44
44
  for i, possible_name in enumerate(possible_names):
@@ -51,6 +51,6 @@ class Phonetics:
51
51
  check_name(name, transformed_possible_name)
52
52
  if alternative_name:
53
53
  check_name(alternative_name, transformed_possible_name)
54
- if max_similarity < threshold:
54
+ if mindistance is None or mindistance > threshold:
55
55
  return None
56
56
  return matching_index
@@ -434,7 +434,6 @@ admin_info:
434
434
  - {pcode: XYZ123456, name: Random, iso3: XYZ}
435
435
 
436
436
  countries_fuzzy_try:
437
- - AFG
438
437
  - NER
439
438
  - NGA
440
439
  - UKR
@@ -16,11 +16,10 @@ admin_name_mappings:
16
16
  "AF05|MyMapping3": "AF0501"
17
17
 
18
18
  admin_name_replacements:
19
- "wx": "an"
19
+ " city": ""
20
20
 
21
21
  alt1_admin_name_replacements:
22
- "COD|wx": "an"
22
+ "COD| city": ""
23
23
 
24
24
  alt2_admin_name_replacements:
25
- "CD20|wx": "an"
26
- "CD31|wx": "en"
25
+ "CD20| city": ""
@@ -196,21 +196,12 @@ class TestAdminLevel:
196
196
  "YE30",
197
197
  False,
198
198
  )
199
- assert adminone.get_pcode("YEM", "Ad Jauf", logname="test") == (
200
- "YE16",
201
- False,
202
- )
203
- assert adminone.get_pcode("AFG", "Sar-E-Pul", logname="test") == (
204
- "AF22",
205
- False,
206
- )
207
199
  assert adminone.get_pcode("SOM", "Bay", logname="test") == (
208
200
  "SO24",
209
201
  True,
210
202
  )
211
203
  output = adminone.output_matches()
212
204
  assert output == [
213
- "test - YEM: Matching (fuzzy) Ad Jauf to Al Jawf on map",
214
205
  "test - YEM: Matching (fuzzy) Al Dali to Ad Dali on map",
215
206
  "test - YEM: Matching (fuzzy) Al Dhale'e / الضالع to Ad Dali on map",
216
207
  "test - YEM: Matching (fuzzy) Al_Dhale'a to Ad Dali on map",
@@ -295,19 +286,21 @@ class TestAdminLevel:
295
286
  ) == (None, False)
296
287
 
297
288
  output = admintwo.output_admin_name_replacements()
298
- assert output == ["wx: an"]
289
+ assert output == [" city: "]
299
290
  assert admintwo.get_pcode(
300
- "COD", "City of Mbwxza-Nanga", logname="test"
291
+ "COD", "Mbanza-Ngungu city", logname="test"
301
292
  ) == ("CD2013", False)
302
293
  assert admintwo.get_pcode(
303
- "COD", "City of Mbwxza-Nanga", parent="CD20", logname="test"
294
+ "COD", "Mbanza-Ngungu city", parent="CD20", logname="test"
304
295
  ) == ("CD2013", False)
305
296
  assert admintwo.get_pcode(
306
- "COD", "City of Mbwxza-Nanga", parent="CD19", logname="test"
297
+ "COD", "Mbanza-Ngungu city", parent="CD19", logname="test"
307
298
  ) == (None, False)
308
- assert admintwo.get_pcode(
309
- "MWI", "City of Blwxtyre", logname="test"
310
- ) == (
299
+ assert admintwo.get_pcode("COD", "Kenge city", logname="test") == (
300
+ "CD3102",
301
+ False,
302
+ )
303
+ assert admintwo.get_pcode("MWI", "Blantyre city", logname="test") == (
311
304
  "MW305",
312
305
  False,
313
306
  )
@@ -316,66 +309,58 @@ class TestAdminLevel:
316
309
  "alt1_admin_name_replacements"
317
310
  ]
318
311
  output = admintwo.output_admin_name_replacements()
319
- assert output == ["COD|wx: an"]
312
+ assert output == ["COD| city: "]
320
313
  assert admintwo.get_pcode(
321
- "COD", "City of Mbwxza-Nanga", logname="test"
314
+ "COD", "Mbanza-Ngungu city", logname="test"
322
315
  ) == ("CD2013", False)
323
316
  assert admintwo.get_pcode(
324
- "COD", "City of Mbwxza-Nanga", parent="CD20", logname="test"
317
+ "COD", "Mbanza-Ngungu city", parent="CD20", logname="test"
325
318
  ) == ("CD2013", False)
326
319
  assert admintwo.get_pcode(
327
- "COD", "City of Mbwxza-Nanga", parent="CD19", logname="test"
320
+ "COD", "Mbanza-Ngungu city", parent="CD19", logname="test"
328
321
  ) == (None, False)
329
- assert admintwo.get_pcode("COD", "Kenge City", logname="test") == (
322
+ assert admintwo.get_pcode("COD", "Kenge city", logname="test") == (
330
323
  "CD3102",
331
324
  False,
332
325
  )
333
- assert admintwo.get_pcode("COD", "Kwxge City", logname="test") == (
334
- None,
335
- False,
336
- )
337
326
  assert admintwo.get_pcode(
338
- "COD", "Kwxge City", parent="CD31", logname="test"
339
- ) == (None, False)
340
- assert admintwo.get_pcode(
341
- "MWI", "City of Blwxtyre", logname="test"
342
- ) == (
327
+ "COD", "Kenge city", parent="CD31", logname="test"
328
+ ) == ("CD3102", False)
329
+ assert admintwo.get_pcode("MWI", "Blantyre city", logname="test") == (
343
330
  None,
344
331
  False,
345
332
  )
346
333
  assert admintwo.get_pcode(
347
- "MWI", "City of Blwxtyre", parent="MW3", logname="test"
334
+ "MWI", "Blantyre city", parent="MW3", logname="test"
348
335
  ) == (None, False)
349
336
 
350
337
  admintwo.admin_name_replacements = config_parent[
351
338
  "alt2_admin_name_replacements"
352
339
  ]
353
340
  output = admintwo.output_admin_name_replacements()
354
- assert output == ["CD20|wx: an", "CD31|wx: en"]
341
+ assert output == ["CD20| city: "]
355
342
  assert admintwo.get_pcode(
356
- "COD", "City of Mbwxza-Nanga", logname="test"
343
+ "COD", "Mbanza-Ngungu city", logname="test"
357
344
  ) == (None, False)
358
345
  assert admintwo.get_pcode(
359
- "COD", "City of Mbwxza-Nanga", parent="CD20", logname="test"
346
+ "COD", "Mbanza-Ngungu city", parent="CD20", logname="test"
360
347
  ) == ("CD2013", False)
361
348
  assert admintwo.get_pcode(
362
- "COD", "City of Mbwxza-Nanga", parent="CD19", logname="test"
349
+ "COD", "Mbanza-Ngungu city", parent="CD19", logname="test"
363
350
  ) == (None, False)
364
- assert admintwo.get_pcode("COD", "Kwxge City", logname="test") == (
351
+ assert admintwo.get_pcode("COD", "Kenge city", logname="test") == (
365
352
  None,
366
353
  False,
367
354
  )
368
355
  assert admintwo.get_pcode(
369
- "COD", "Kwxge City", parent="CD31", logname="test"
370
- ) == ("CD3102", False)
371
- assert admintwo.get_pcode(
372
- "MWI", "City of Blwxtyre", logname="test"
373
- ) == (
356
+ "COD", "Kenge city", parent="CD31", logname="test"
357
+ ) == (None, False)
358
+ assert admintwo.get_pcode("MWI", "Blantyre city", logname="test") == (
374
359
  None,
375
360
  False,
376
361
  )
377
362
  assert admintwo.get_pcode(
378
- "MWI", "City of Blwxtyre", parent="MW3", logname="test"
363
+ "MWI", "Blantyre city", parent="MW3", logname="test"
379
364
  ) == (None, False)
380
365
 
381
366
  def test_adminlevel_with_url(self, config, url):
@@ -1,31 +0,0 @@
1
- import re
2
- import unicodedata
3
-
4
- from unidecode import unidecode
5
-
6
- non_ascii = r"([^\x00-\x7f])+"
7
-
8
-
9
- def clean_name(name: str) -> str:
10
- """
11
- Replace accented characters with non-accented ones in given name. Also
12
- strip whitespace from start and end and make lwoercase.
13
-
14
- Args:
15
- name (str): Name to change
16
-
17
- Returns:
18
- str: Name without accented characters
19
- """
20
- #
21
- clean_name = "".join(
22
- c
23
- for c in unicodedata.normalize("NFD", name)
24
- if unicodedata.category(c) != "Mn"
25
- )
26
- # Remove all non-ASCII characters
27
- clean_name = re.sub(non_ascii, " ", clean_name)
28
- clean_name = clean_name.replace("'", "")
29
- clean_name = re.sub(r"[\W_]", " ", clean_name)
30
- clean_name = unidecode(clean_name)
31
- return clean_name.strip().lower()