hdx-python-country 3.7.2__tar.gz → 3.7.3__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.
- {hdx_python_country-3.7.2 → hdx_python_country-3.7.3}/.config/pre-commit-config.yaml +4 -4
- {hdx_python_country-3.7.2 → hdx_python_country-3.7.3}/.github/workflows/publish.yaml +2 -1
- {hdx_python_country-3.7.2 → hdx_python_country-3.7.3}/.github/workflows/run-python-tests.yaml +4 -6
- {hdx_python_country-3.7.2 → hdx_python_country-3.7.3}/PKG-INFO +3 -3
- {hdx_python_country-3.7.2 → hdx_python_country-3.7.3}/documentation/main.md +2 -2
- {hdx_python_country-3.7.2 → hdx_python_country-3.7.3}/pyproject.toml +14 -18
- {hdx_python_country-3.7.2 → hdx_python_country-3.7.3}/requirements.txt +21 -25
- {hdx_python_country-3.7.2 → hdx_python_country-3.7.3}/src/hdx/location/_version.py +2 -2
- {hdx_python_country-3.7.2 → hdx_python_country-3.7.3}/src/hdx/location/adminlevel.py +12 -8
- {hdx_python_country-3.7.2 → hdx_python_country-3.7.3}/src/hdx/location/names.py +3 -1
- {hdx_python_country-3.7.2 → hdx_python_country-3.7.3}/src/hdx/location/phonetics.py +10 -10
- {hdx_python_country-3.7.2 → hdx_python_country-3.7.3}/tests/fixtures/adminlevel.yaml +1 -0
- {hdx_python_country-3.7.2 → hdx_python_country-3.7.3}/tests/fixtures/adminlevelparent.yaml +4 -3
- {hdx_python_country-3.7.2 → hdx_python_country-3.7.3}/tests/hdx/location/test_adminlevel.py +48 -29
- {hdx_python_country-3.7.2 → hdx_python_country-3.7.3}/.config/coveragerc +0 -0
- {hdx_python_country-3.7.2 → hdx_python_country-3.7.3}/.config/pytest.ini +0 -0
- {hdx_python_country-3.7.2 → hdx_python_country-3.7.3}/.config/ruff.toml +0 -0
- {hdx_python_country-3.7.2 → hdx_python_country-3.7.3}/.gitignore +0 -0
- {hdx_python_country-3.7.2 → hdx_python_country-3.7.3}/CONTRIBUTING.md +0 -0
- {hdx_python_country-3.7.2 → hdx_python_country-3.7.3}/LICENSE +0 -0
- {hdx_python_country-3.7.2 → hdx_python_country-3.7.3}/README.md +0 -0
- {hdx_python_country-3.7.2 → hdx_python_country-3.7.3}/documentation/.readthedocs.yaml +0 -0
- {hdx_python_country-3.7.2 → hdx_python_country-3.7.3}/documentation/pydoc-markdown.yaml +0 -0
- {hdx_python_country-3.7.2 → hdx_python_country-3.7.3}/src/hdx/location/Countries & Territories Taxonomy MVP - C&T Taxonomy with HXL Tags.csv +0 -0
- {hdx_python_country-3.7.2 → hdx_python_country-3.7.3}/src/hdx/location/__init__.py +0 -0
- {hdx_python_country-3.7.2 → hdx_python_country-3.7.3}/src/hdx/location/country.py +0 -0
- {hdx_python_country-3.7.2 → hdx_python_country-3.7.3}/src/hdx/location/currency.py +0 -0
- {hdx_python_country-3.7.2 → hdx_python_country-3.7.3}/src/hdx/location/wfp_exchangerates.py +0 -0
- {hdx_python_country-3.7.2 → hdx_python_country-3.7.3}/tests/fixtures/global_pcode_lengths.csv +0 -0
- {hdx_python_country-3.7.2 → hdx_python_country-3.7.3}/tests/fixtures/global_pcodes_adm_1_2.csv +0 -0
- {hdx_python_country-3.7.2 → hdx_python_country-3.7.3}/tests/fixtures/secondary_historic_rates.csv +0 -0
- {hdx_python_country-3.7.2 → hdx_python_country-3.7.3}/tests/fixtures/secondary_rates.json +0 -0
- {hdx_python_country-3.7.2 → hdx_python_country-3.7.3}/tests/hdx/location/Countries_UZB_Deleted.csv +0 -0
- {hdx_python_country-3.7.2 → hdx_python_country-3.7.3}/tests/hdx/location/__init__.py +0 -0
- {hdx_python_country-3.7.2 → hdx_python_country-3.7.3}/tests/hdx/location/test_country.py +0 -0
- {hdx_python_country-3.7.2 → hdx_python_country-3.7.3}/tests/hdx/location/test_currency.py +0 -0
- {hdx_python_country-3.7.2 → hdx_python_country-3.7.3}/tests/hdx/location/test_wfp_exchangerates.py +0 -0
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
default_language_version:
|
|
2
|
-
python: python3.
|
|
2
|
+
python: python3.12
|
|
3
3
|
repos:
|
|
4
4
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
5
|
-
rev: v4.
|
|
5
|
+
rev: v4.6.0
|
|
6
6
|
hooks:
|
|
7
7
|
- id: trailing-whitespace
|
|
8
8
|
- id: end-of-file-fixer
|
|
9
9
|
- id: check-ast
|
|
10
10
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
11
|
-
rev: v0.4.
|
|
11
|
+
rev: v0.4.8
|
|
12
12
|
hooks:
|
|
13
13
|
# Run the linter.
|
|
14
14
|
- id: ruff
|
|
@@ -17,7 +17,7 @@ repos:
|
|
|
17
17
|
- id: ruff-format
|
|
18
18
|
args: [--config, .config/ruff.toml]
|
|
19
19
|
- repo: https://github.com/astral-sh/uv-pre-commit
|
|
20
|
-
rev: 0.
|
|
20
|
+
rev: 0.2.10
|
|
21
21
|
hooks:
|
|
22
22
|
# Run the pip compile
|
|
23
23
|
- id: pip-compile
|
{hdx_python_country-3.7.2 → hdx_python_country-3.7.3}/.github/workflows/run-python-tests.yaml
RENAMED
|
@@ -26,17 +26,15 @@ jobs:
|
|
|
26
26
|
- name: Install dependencies
|
|
27
27
|
run: |
|
|
28
28
|
python -m pip install --upgrade pip
|
|
29
|
-
|
|
29
|
+
- name: Install Hatch
|
|
30
|
+
uses: pypa/hatch@install
|
|
30
31
|
- name: Test with hatch/pytest
|
|
31
|
-
env:
|
|
32
|
-
WFP_KEY: ${{ secrets.WFP_KEY }}
|
|
33
|
-
WFP_SECRET: ${{ secrets.WFP_SECRET }}
|
|
34
32
|
run: |
|
|
35
|
-
hatch
|
|
33
|
+
hatch test
|
|
36
34
|
- name: Check styling
|
|
37
35
|
if: always()
|
|
38
36
|
run: |
|
|
39
|
-
hatch
|
|
37
|
+
hatch fmt --check
|
|
40
38
|
- name: Publish Unit Test Results
|
|
41
39
|
uses: EnricoMi/publish-unit-test-result-action@v2
|
|
42
40
|
if: always()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: hdx-python-country
|
|
3
|
-
Version: 3.7.
|
|
3
|
+
Version: 3.7.3
|
|
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.
|
|
28
|
+
Requires-Dist: hdx-python-utilities>=3.7.0
|
|
29
29
|
Requires-Dist: libhxl>=5.2.1
|
|
30
|
-
Requires-Dist:
|
|
30
|
+
Requires-Dist: rapidfuzz
|
|
31
31
|
Provides-Extra: dev
|
|
32
32
|
Requires-Dist: pre-commit; extra == 'dev'
|
|
33
33
|
Provides-Extra: test
|
|
@@ -120,8 +120,8 @@ be global or they can be restricted by country or parent (if the AdminLevel
|
|
|
120
120
|
object has been set up with parents). Keys take the form "MAPPING",
|
|
121
121
|
"AFG|MAPPING" or "AF01|MAPPING".
|
|
122
122
|
*admin_name_replacements* is a dictionary of textual replacements to try when
|
|
123
|
-
fuzzy matching. It maps from string to string replacement. The replacements can
|
|
124
|
-
be global or they can be restricted by country or parent (if the AdminLevel
|
|
123
|
+
fuzzy matching. It maps from string to string replacement. The replacements can
|
|
124
|
+
be global or they can be restricted by country or parent (if the AdminLevel
|
|
125
125
|
object has been set up with parents). Keys take the form "STRING_TO_REPLACE",
|
|
126
126
|
"AFG|STRING_TO_REPLACE" or "AF01|STRING_TO_REPLACE".
|
|
127
127
|
*admin_fuzzy_dont* is a list of names for which fuzzy matching should not be
|
|
@@ -34,9 +34,9 @@ classifiers = [
|
|
|
34
34
|
requires-python = ">=3.8"
|
|
35
35
|
|
|
36
36
|
dependencies = [
|
|
37
|
-
"hdx-python-utilities>=3.
|
|
37
|
+
"hdx-python-utilities>=3.7.0",
|
|
38
38
|
"libhxl>=5.2.1",
|
|
39
|
-
"
|
|
39
|
+
"rapidfuzz",
|
|
40
40
|
]
|
|
41
41
|
dynamic = ["version"]
|
|
42
42
|
|
|
@@ -79,25 +79,21 @@ version_scheme = "python-simplified-semver"
|
|
|
79
79
|
|
|
80
80
|
# Tests
|
|
81
81
|
|
|
82
|
-
[tool.hatch.envs.test]
|
|
83
|
-
features = ["test"]
|
|
82
|
+
[tool.hatch.envs.hatch-test]
|
|
83
|
+
features = ["test"]
|
|
84
84
|
|
|
85
|
-
[tool.hatch.envs.test.
|
|
86
|
-
|
|
85
|
+
[[tool.hatch.envs.hatch-test.matrix]]
|
|
86
|
+
python = ["3.12"]
|
|
87
|
+
|
|
88
|
+
[tool.hatch.envs.hatch-test.scripts]
|
|
89
|
+
run = """
|
|
87
90
|
pytest -c .config/pytest.ini --rootdir=. --junitxml=test-results.xml \
|
|
88
91
|
--cov --cov-config=.config/coveragerc --no-cov-on-fail \
|
|
89
92
|
--cov-report=lcov --cov-report=term-missing
|
|
90
93
|
"""
|
|
91
94
|
|
|
92
|
-
[
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
[
|
|
96
|
-
|
|
97
|
-
dependencies = ["ruff"]
|
|
98
|
-
|
|
99
|
-
[tool.hatch.envs.lint.scripts]
|
|
100
|
-
style = [
|
|
101
|
-
"ruff check --config .config/ruff.toml --diff {args:.}",
|
|
102
|
-
"ruff format --config .config/ruff.toml --diff {args:.}",
|
|
103
|
-
]
|
|
95
|
+
[tool.hatch.envs.hatch-static-analysis.scripts]
|
|
96
|
+
format-check = ["ruff format --config .config/ruff.toml --check --diff {args:.}",]
|
|
97
|
+
format-fix = ["ruff format --config .config/ruff.toml {args:.}",]
|
|
98
|
+
lint-check = ["ruff check --config .config/ruff.toml {args:.}",]
|
|
99
|
+
lint-fix = ["ruff check --config .config/ruff.toml --fix {args:.}",]
|
|
@@ -8,7 +8,7 @@ attrs==23.2.0
|
|
|
8
8
|
# jsonlines
|
|
9
9
|
# jsonschema
|
|
10
10
|
# referencing
|
|
11
|
-
certifi==2024.
|
|
11
|
+
certifi==2024.6.2
|
|
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.
|
|
21
|
+
coverage==7.5.3
|
|
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.
|
|
27
|
+
filelock==3.15.3
|
|
28
28
|
# via virtualenv
|
|
29
29
|
frictionless==5.17.0
|
|
30
30
|
# via hdx-python-utilities
|
|
31
|
-
hdx-python-utilities==3.
|
|
31
|
+
hdx-python-utilities==3.7.0
|
|
32
32
|
# via hdx-python-country (pyproject.toml)
|
|
33
33
|
humanize==4.9.0
|
|
34
34
|
# via frictionless
|
|
@@ -36,7 +36,7 @@ identify==2.5.36
|
|
|
36
36
|
# via pre-commit
|
|
37
37
|
idna==3.7
|
|
38
38
|
# via requests
|
|
39
|
-
ijson==3.
|
|
39
|
+
ijson==3.3.0
|
|
40
40
|
# via hdx-python-utilities
|
|
41
41
|
iniconfig==2.0.0
|
|
42
42
|
# via pytest
|
|
@@ -60,17 +60,17 @@ 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.
|
|
63
|
+
marko==2.1.1
|
|
64
64
|
# via frictionless
|
|
65
65
|
markupsafe==2.1.5
|
|
66
66
|
# via jinja2
|
|
67
67
|
mdurl==0.1.2
|
|
68
68
|
# via markdown-it-py
|
|
69
|
-
nodeenv==1.
|
|
69
|
+
nodeenv==1.9.1
|
|
70
70
|
# via pre-commit
|
|
71
|
-
openpyxl==3.1.
|
|
71
|
+
openpyxl==3.1.4
|
|
72
72
|
# via hdx-python-utilities
|
|
73
|
-
packaging==24.
|
|
73
|
+
packaging==24.1
|
|
74
74
|
# via pytest
|
|
75
75
|
petl==1.7.15
|
|
76
76
|
# via frictionless
|
|
@@ -84,21 +84,19 @@ 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.
|
|
87
|
+
pydantic==2.7.4
|
|
88
88
|
# via frictionless
|
|
89
|
-
pydantic-core==2.18.
|
|
89
|
+
pydantic-core==2.18.4
|
|
90
90
|
# via pydantic
|
|
91
91
|
pygments==2.18.0
|
|
92
92
|
# via rich
|
|
93
|
-
|
|
94
|
-
# via hdx-python-country (pyproject.toml)
|
|
95
|
-
pytest==8.2.1
|
|
93
|
+
pytest==8.2.2
|
|
96
94
|
# via
|
|
97
95
|
# hdx-python-country (pyproject.toml)
|
|
98
96
|
# pytest-cov
|
|
99
97
|
pytest-cov==5.0.0
|
|
100
98
|
# via hdx-python-country (pyproject.toml)
|
|
101
|
-
python-dateutil==2.
|
|
99
|
+
python-dateutil==2.9.0.post0
|
|
102
100
|
# via
|
|
103
101
|
# frictionless
|
|
104
102
|
# hdx-python-utilities
|
|
@@ -112,13 +110,15 @@ pyyaml==6.0.1
|
|
|
112
110
|
# frictionless
|
|
113
111
|
# pre-commit
|
|
114
112
|
# 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
|
|
118
118
|
# via
|
|
119
119
|
# jsonschema
|
|
120
120
|
# jsonschema-specifications
|
|
121
|
-
requests==2.32.
|
|
121
|
+
requests==2.32.3
|
|
122
122
|
# via
|
|
123
123
|
# frictionless
|
|
124
124
|
# libhxl
|
|
@@ -137,8 +137,6 @@ ruamel-yaml==0.18.6
|
|
|
137
137
|
# via hdx-python-utilities
|
|
138
138
|
ruamel-yaml-clib==0.2.8
|
|
139
139
|
# via ruamel-yaml
|
|
140
|
-
setuptools==70.0.0
|
|
141
|
-
# via nodeenv
|
|
142
140
|
shellingham==1.5.4
|
|
143
141
|
# via typer
|
|
144
142
|
simpleeval==0.9.13
|
|
@@ -149,7 +147,7 @@ six==1.16.0
|
|
|
149
147
|
# python-dateutil
|
|
150
148
|
stringcase==1.2.0
|
|
151
149
|
# via frictionless
|
|
152
|
-
structlog==24.
|
|
150
|
+
structlog==24.2.0
|
|
153
151
|
# via libhxl
|
|
154
152
|
tableschema-to-template==0.0.13
|
|
155
153
|
# via hdx-python-utilities
|
|
@@ -159,21 +157,19 @@ text-unidecode==1.3
|
|
|
159
157
|
# via python-slugify
|
|
160
158
|
typer==0.12.3
|
|
161
159
|
# via frictionless
|
|
162
|
-
typing-extensions==4.
|
|
160
|
+
typing-extensions==4.12.2
|
|
163
161
|
# via
|
|
164
162
|
# frictionless
|
|
165
163
|
# pydantic
|
|
166
164
|
# pydantic-core
|
|
167
165
|
# typer
|
|
168
166
|
unidecode==1.3.8
|
|
169
|
-
# via
|
|
170
|
-
|
|
171
|
-
# pyphonetics
|
|
172
|
-
urllib3==2.2.1
|
|
167
|
+
# via libhxl
|
|
168
|
+
urllib3==2.2.2
|
|
173
169
|
# via
|
|
174
170
|
# libhxl
|
|
175
171
|
# requests
|
|
176
|
-
validators==0.28.
|
|
172
|
+
validators==0.28.3
|
|
177
173
|
# via frictionless
|
|
178
174
|
virtualenv==20.26.2
|
|
179
175
|
# via pre-commit
|
|
@@ -5,7 +5,6 @@ from typing import Any, Dict, List, Optional, Tuple
|
|
|
5
5
|
import hxl
|
|
6
6
|
from hxl import InputOptions
|
|
7
7
|
from hxl.input import HXLIOException
|
|
8
|
-
from unidecode import unidecode
|
|
9
8
|
|
|
10
9
|
from hdx.location.country import Country
|
|
11
10
|
from hdx.location.names import clean_name
|
|
@@ -147,7 +146,7 @@ class AdminLevel:
|
|
|
147
146
|
self.pcode_to_name[pcode] = adm_name
|
|
148
147
|
|
|
149
148
|
name_to_pcode = self.name_to_pcode.get(countryiso3, {})
|
|
150
|
-
name_to_pcode[
|
|
149
|
+
name_to_pcode[clean_name(adm_name)] = pcode
|
|
151
150
|
self.name_to_pcode[countryiso3] = name_to_pcode
|
|
152
151
|
self.pcode_to_iso3[pcode] = countryiso3
|
|
153
152
|
self.pcode_to_iso3[pcode] = countryiso3
|
|
@@ -157,7 +156,7 @@ class AdminLevel:
|
|
|
157
156
|
countryiso3, {}
|
|
158
157
|
)
|
|
159
158
|
name_to_pcode = name_parent_to_pcode.get(parent, {})
|
|
160
|
-
name_to_pcode[
|
|
159
|
+
name_to_pcode[clean_name(adm_name)] = pcode
|
|
161
160
|
name_parent_to_pcode[parent] = name_to_pcode
|
|
162
161
|
self.name_parent_to_pcode[countryiso3] = name_parent_to_pcode
|
|
163
162
|
self.pcode_to_parent[pcode] = parent
|
|
@@ -642,22 +641,25 @@ class AdminLevel:
|
|
|
642
641
|
break
|
|
643
642
|
if not pcode:
|
|
644
643
|
map_names = list(name_to_pcode.keys())
|
|
645
|
-
lower_mapnames = [x.lower() for x in map_names]
|
|
646
644
|
|
|
647
645
|
def al_transform_1(name):
|
|
648
|
-
|
|
646
|
+
prefix = name[:3]
|
|
647
|
+
if prefix == "al ":
|
|
649
648
|
return f"ad {name[3:]}"
|
|
649
|
+
elif prefix == "ad ":
|
|
650
|
+
return f"al {name[3:]}"
|
|
650
651
|
else:
|
|
651
652
|
return None
|
|
652
653
|
|
|
653
654
|
def al_transform_2(name):
|
|
654
|
-
|
|
655
|
+
prefix = name[:3]
|
|
656
|
+
if prefix == "al " or prefix == "ad ":
|
|
655
657
|
return name[3:]
|
|
656
658
|
else:
|
|
657
659
|
return None
|
|
658
660
|
|
|
659
661
|
matching_index = self.phonetics.match(
|
|
660
|
-
|
|
662
|
+
map_names,
|
|
661
663
|
adm_name_lookup,
|
|
662
664
|
alternative_name=adm_name_lookup2,
|
|
663
665
|
transform_possible_names=[al_transform_1, al_transform_2],
|
|
@@ -714,6 +716,7 @@ class AdminLevel:
|
|
|
714
716
|
countryiso3: str,
|
|
715
717
|
name: str,
|
|
716
718
|
fuzzy_match: bool = True,
|
|
719
|
+
fuzzy_length: int = 4,
|
|
717
720
|
**kwargs: Any,
|
|
718
721
|
) -> Tuple[Optional[str], bool]:
|
|
719
722
|
"""Get pcode for a given name
|
|
@@ -722,6 +725,7 @@ class AdminLevel:
|
|
|
722
725
|
countryiso3 (str): ISO3 country code
|
|
723
726
|
name (str): Name to match
|
|
724
727
|
fuzzy_match (bool): Whether to try fuzzy matching. Defaults to True.
|
|
728
|
+
fuzzy_length (int): Minimum length for fuzzy matching. Defaults to 4.
|
|
725
729
|
**kwargs:
|
|
726
730
|
parent (Optional[str]): Parent admin code
|
|
727
731
|
logname (str): Log using this identifying name. Defaults to not logging.
|
|
@@ -767,7 +771,7 @@ class AdminLevel:
|
|
|
767
771
|
pcode = name_to_pcode.get(name.lower())
|
|
768
772
|
if pcode:
|
|
769
773
|
return pcode, True
|
|
770
|
-
if not fuzzy_match:
|
|
774
|
+
if not fuzzy_match or len(name) < fuzzy_length:
|
|
771
775
|
return None, True
|
|
772
776
|
pcode = self.fuzzy_pcode(countryiso3, name, **kwargs)
|
|
773
777
|
return pcode, False
|
|
@@ -3,7 +3,7 @@ import unicodedata
|
|
|
3
3
|
|
|
4
4
|
from unidecode import unidecode
|
|
5
5
|
|
|
6
|
-
non_ascii = "([^\x00-\x7f])+"
|
|
6
|
+
non_ascii = r"([^\x00-\x7f])+"
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
def clean_name(name: str) -> str:
|
|
@@ -25,5 +25,7 @@ def clean_name(name: str) -> str:
|
|
|
25
25
|
)
|
|
26
26
|
# Remove all non-ASCII characters
|
|
27
27
|
clean_name = re.sub(non_ascii, " ", clean_name)
|
|
28
|
+
clean_name = clean_name.replace("'", "")
|
|
29
|
+
clean_name = re.sub(r"[\W_]", " ", clean_name)
|
|
28
30
|
clean_name = unidecode(clean_name)
|
|
29
31
|
return clean_name.strip().lower()
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
from typing import Callable, Optional
|
|
2
2
|
|
|
3
|
-
import
|
|
3
|
+
from rapidfuzz import fuzz
|
|
4
4
|
|
|
5
5
|
from hdx.utilities.typehint import ListTuple
|
|
6
6
|
|
|
7
7
|
|
|
8
|
-
class Phonetics
|
|
8
|
+
class Phonetics:
|
|
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:
|
|
15
|
+
threshold: float = 60,
|
|
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(pyphonetics.RefinedSoundex):
|
|
|
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: Match threshold. Defaults to
|
|
26
|
+
threshold (float): Match threshold. Value is 0-100. Defaults to 60.
|
|
27
27
|
|
|
28
28
|
Returns:
|
|
29
29
|
Optional[int]: Index of matching name from possible names or None
|
|
30
30
|
"""
|
|
31
|
-
|
|
31
|
+
max_similarity = 0
|
|
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
|
|
37
|
+
nonlocal max_similarity, matching_index # noqa: E999
|
|
38
38
|
|
|
39
|
-
|
|
40
|
-
if
|
|
41
|
-
|
|
39
|
+
similarity = fuzz.token_sort_ratio(name, possible_name)
|
|
40
|
+
if similarity > max_similarity:
|
|
41
|
+
max_similarity = similarity
|
|
42
42
|
matching_index = i
|
|
43
43
|
|
|
44
44
|
for i, possible_name in enumerate(possible_names):
|
|
@@ -51,6 +51,6 @@ class Phonetics(pyphonetics.RefinedSoundex):
|
|
|
51
51
|
check_name(name, transformed_possible_name)
|
|
52
52
|
if alternative_name:
|
|
53
53
|
check_name(alternative_name, transformed_possible_name)
|
|
54
|
-
if
|
|
54
|
+
if max_similarity < threshold:
|
|
55
55
|
return None
|
|
56
56
|
return matching_index
|
|
@@ -16,10 +16,11 @@ admin_name_mappings:
|
|
|
16
16
|
"AF05|MyMapping3": "AF0501"
|
|
17
17
|
|
|
18
18
|
admin_name_replacements:
|
|
19
|
-
"
|
|
19
|
+
"wx": "an"
|
|
20
20
|
|
|
21
21
|
alt1_admin_name_replacements:
|
|
22
|
-
"COD|
|
|
22
|
+
"COD|wx": "an"
|
|
23
23
|
|
|
24
24
|
alt2_admin_name_replacements:
|
|
25
|
-
"CD20|
|
|
25
|
+
"CD20|wx": "an"
|
|
26
|
+
"CD31|wx": "en"
|
|
@@ -182,6 +182,10 @@ class TestAdminLevel:
|
|
|
182
182
|
def test_adminlevel_fuzzy(self, config):
|
|
183
183
|
adminone = AdminLevel(config)
|
|
184
184
|
adminone.setup_from_admin_info(config["admin_info"])
|
|
185
|
+
assert adminone.get_pcode("YEM", "Al_Dhale'a", logname="test") == (
|
|
186
|
+
"YE30",
|
|
187
|
+
False,
|
|
188
|
+
)
|
|
185
189
|
assert adminone.get_pcode("YEM", "Al Dali", logname="test") == (
|
|
186
190
|
"YE30",
|
|
187
191
|
False,
|
|
@@ -192,14 +196,24 @@ class TestAdminLevel:
|
|
|
192
196
|
"YE30",
|
|
193
197
|
False,
|
|
194
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
|
+
)
|
|
195
207
|
assert adminone.get_pcode("SOM", "Bay", logname="test") == (
|
|
196
208
|
"SO24",
|
|
197
209
|
True,
|
|
198
210
|
)
|
|
199
211
|
output = adminone.output_matches()
|
|
200
212
|
assert output == [
|
|
213
|
+
"test - YEM: Matching (fuzzy) Ad Jauf to Al Jawf on map",
|
|
201
214
|
"test - YEM: Matching (fuzzy) Al Dali to Ad Dali on map",
|
|
202
215
|
"test - YEM: Matching (fuzzy) Al Dhale'e / الضالع to Ad Dali on map",
|
|
216
|
+
"test - YEM: Matching (fuzzy) Al_Dhale'a to Ad Dali on map",
|
|
203
217
|
]
|
|
204
218
|
|
|
205
219
|
def test_adminlevel_parent(self, config_parent):
|
|
@@ -281,21 +295,19 @@ class TestAdminLevel:
|
|
|
281
295
|
) == (None, False)
|
|
282
296
|
|
|
283
297
|
output = admintwo.output_admin_name_replacements()
|
|
284
|
-
assert output == ["
|
|
298
|
+
assert output == ["wx: an"]
|
|
285
299
|
assert admintwo.get_pcode(
|
|
286
|
-
"COD", "
|
|
300
|
+
"COD", "City of Mbwxza-Nanga", logname="test"
|
|
287
301
|
) == ("CD2013", False)
|
|
288
302
|
assert admintwo.get_pcode(
|
|
289
|
-
"COD", "
|
|
303
|
+
"COD", "City of Mbwxza-Nanga", parent="CD20", logname="test"
|
|
290
304
|
) == ("CD2013", False)
|
|
291
305
|
assert admintwo.get_pcode(
|
|
292
|
-
"COD", "
|
|
306
|
+
"COD", "City of Mbwxza-Nanga", parent="CD19", logname="test"
|
|
293
307
|
) == (None, False)
|
|
294
|
-
assert admintwo.get_pcode(
|
|
295
|
-
"
|
|
296
|
-
|
|
297
|
-
)
|
|
298
|
-
assert admintwo.get_pcode("MWI", "Blantyre city", logname="test") == (
|
|
308
|
+
assert admintwo.get_pcode(
|
|
309
|
+
"MWI", "City of Blwxtyre", logname="test"
|
|
310
|
+
) == (
|
|
299
311
|
"MW305",
|
|
300
312
|
False,
|
|
301
313
|
)
|
|
@@ -304,58 +316,66 @@ class TestAdminLevel:
|
|
|
304
316
|
"alt1_admin_name_replacements"
|
|
305
317
|
]
|
|
306
318
|
output = admintwo.output_admin_name_replacements()
|
|
307
|
-
assert output == ["COD|
|
|
319
|
+
assert output == ["COD|wx: an"]
|
|
308
320
|
assert admintwo.get_pcode(
|
|
309
|
-
"COD", "
|
|
321
|
+
"COD", "City of Mbwxza-Nanga", logname="test"
|
|
310
322
|
) == ("CD2013", False)
|
|
311
323
|
assert admintwo.get_pcode(
|
|
312
|
-
"COD", "
|
|
324
|
+
"COD", "City of Mbwxza-Nanga", parent="CD20", logname="test"
|
|
313
325
|
) == ("CD2013", False)
|
|
314
326
|
assert admintwo.get_pcode(
|
|
315
|
-
"COD", "
|
|
327
|
+
"COD", "City of Mbwxza-Nanga", parent="CD19", logname="test"
|
|
316
328
|
) == (None, False)
|
|
317
|
-
assert admintwo.get_pcode("COD", "Kenge
|
|
329
|
+
assert admintwo.get_pcode("COD", "Kenge City", logname="test") == (
|
|
318
330
|
"CD3102",
|
|
319
331
|
False,
|
|
320
332
|
)
|
|
333
|
+
assert admintwo.get_pcode("COD", "Kwxge City", logname="test") == (
|
|
334
|
+
None,
|
|
335
|
+
False,
|
|
336
|
+
)
|
|
321
337
|
assert admintwo.get_pcode(
|
|
322
|
-
"COD", "
|
|
323
|
-
) == (
|
|
324
|
-
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
|
+
) == (
|
|
325
343
|
None,
|
|
326
344
|
False,
|
|
327
345
|
)
|
|
328
346
|
assert admintwo.get_pcode(
|
|
329
|
-
"MWI", "
|
|
347
|
+
"MWI", "City of Blwxtyre", parent="MW3", logname="test"
|
|
330
348
|
) == (None, False)
|
|
331
349
|
|
|
332
350
|
admintwo.admin_name_replacements = config_parent[
|
|
333
351
|
"alt2_admin_name_replacements"
|
|
334
352
|
]
|
|
335
353
|
output = admintwo.output_admin_name_replacements()
|
|
336
|
-
assert output == ["CD20|
|
|
354
|
+
assert output == ["CD20|wx: an", "CD31|wx: en"]
|
|
337
355
|
assert admintwo.get_pcode(
|
|
338
|
-
"COD", "
|
|
356
|
+
"COD", "City of Mbwxza-Nanga", logname="test"
|
|
339
357
|
) == (None, False)
|
|
340
358
|
assert admintwo.get_pcode(
|
|
341
|
-
"COD", "
|
|
359
|
+
"COD", "City of Mbwxza-Nanga", parent="CD20", logname="test"
|
|
342
360
|
) == ("CD2013", False)
|
|
343
361
|
assert admintwo.get_pcode(
|
|
344
|
-
"COD", "
|
|
362
|
+
"COD", "City of Mbwxza-Nanga", parent="CD19", logname="test"
|
|
345
363
|
) == (None, False)
|
|
346
|
-
assert admintwo.get_pcode("COD", "
|
|
364
|
+
assert admintwo.get_pcode("COD", "Kwxge City", logname="test") == (
|
|
347
365
|
None,
|
|
348
366
|
False,
|
|
349
367
|
)
|
|
350
368
|
assert admintwo.get_pcode(
|
|
351
|
-
"COD", "
|
|
352
|
-
) == (
|
|
353
|
-
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
|
+
) == (
|
|
354
374
|
None,
|
|
355
375
|
False,
|
|
356
376
|
)
|
|
357
377
|
assert admintwo.get_pcode(
|
|
358
|
-
"MWI", "
|
|
378
|
+
"MWI", "City of Blwxtyre", parent="MW3", logname="test"
|
|
359
379
|
) == (None, False)
|
|
360
380
|
|
|
361
381
|
def test_adminlevel_with_url(self, config, url):
|
|
@@ -457,7 +477,7 @@ class TestAdminLevel:
|
|
|
457
477
|
)
|
|
458
478
|
assert adminone.get_pcode("YEM", "Ad Dali", logname="test") == (
|
|
459
479
|
"YE30",
|
|
460
|
-
|
|
480
|
+
True,
|
|
461
481
|
)
|
|
462
482
|
assert adminone.get_pcode("YEM", "Ad Dal", logname="test") == (
|
|
463
483
|
"YE30",
|
|
@@ -500,7 +520,6 @@ class TestAdminLevel:
|
|
|
500
520
|
"test - NGA: Matching (pcode length conversion) NG015 to Federal Capital Territory on map",
|
|
501
521
|
"test - UKR: Matching (substring) Chernihiv Oblast to Chernihivska on map",
|
|
502
522
|
"test - YEM: Matching (substring) Ad Dal to Ad Dali' on map",
|
|
503
|
-
"test - YEM: Matching (substring) Ad Dali to Ad Dali' on map",
|
|
504
523
|
"test - YEM: Matching (pcode length conversion) YE30 to Ad Dali' on map",
|
|
505
524
|
]
|
|
506
525
|
output = adminone.output_ignored()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{hdx_python_country-3.7.2 → hdx_python_country-3.7.3}/tests/fixtures/global_pcode_lengths.csv
RENAMED
|
File without changes
|
{hdx_python_country-3.7.2 → hdx_python_country-3.7.3}/tests/fixtures/global_pcodes_adm_1_2.csv
RENAMED
|
File without changes
|
{hdx_python_country-3.7.2 → hdx_python_country-3.7.3}/tests/fixtures/secondary_historic_rates.csv
RENAMED
|
File without changes
|
|
File without changes
|
{hdx_python_country-3.7.2 → hdx_python_country-3.7.3}/tests/hdx/location/Countries_UZB_Deleted.csv
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{hdx_python_country-3.7.2 → hdx_python_country-3.7.3}/tests/hdx/location/test_wfp_exchangerates.py
RENAMED
|
File without changes
|