hdx-python-country 3.9.6__tar.gz → 3.9.8__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 (50) hide show
  1. {hdx_python_country-3.9.6 → hdx_python_country-3.9.8}/PKG-INFO +2 -2
  2. {hdx_python_country-3.9.6 → hdx_python_country-3.9.8}/pyproject.toml +1 -1
  3. {hdx_python_country-3.9.6 → hdx_python_country-3.9.8}/requirements.txt +32 -31
  4. {hdx_python_country-3.9.6 → hdx_python_country-3.9.8}/src/hdx/location/_version.py +16 -3
  5. {hdx_python_country-3.9.6 → hdx_python_country-3.9.8}/src/hdx/location/country.py +78 -30
  6. {hdx_python_country-3.9.6 → hdx_python_country-3.9.8}/src/hdx/location/wfp_api.py +2 -2
  7. {hdx_python_country-3.9.6 → hdx_python_country-3.9.8}/tests/hdx/location/test_country.py +110 -4
  8. {hdx_python_country-3.9.6 → hdx_python_country-3.9.8}/.coveragerc +0 -0
  9. {hdx_python_country-3.9.6 → hdx_python_country-3.9.8}/.github/workflows/publish.yaml +0 -0
  10. {hdx_python_country-3.9.6 → hdx_python_country-3.9.8}/.github/workflows/run-python-tests.yaml +0 -0
  11. {hdx_python_country-3.9.6 → hdx_python_country-3.9.8}/.gitignore +0 -0
  12. {hdx_python_country-3.9.6 → hdx_python_country-3.9.8}/.pre-commit-config.yaml +0 -0
  13. {hdx_python_country-3.9.6 → hdx_python_country-3.9.8}/LICENSE +0 -0
  14. {hdx_python_country-3.9.6 → hdx_python_country-3.9.8}/README.md +0 -0
  15. {hdx_python_country-3.9.6 → hdx_python_country-3.9.8}/documentation/.readthedocs.yaml +0 -0
  16. {hdx_python_country-3.9.6 → hdx_python_country-3.9.8}/documentation/index.md +0 -0
  17. {hdx_python_country-3.9.6 → hdx_python_country-3.9.8}/documentation/mkdocs.yaml +0 -0
  18. {hdx_python_country-3.9.6 → hdx_python_country-3.9.8}/hatch.toml +0 -0
  19. {hdx_python_country-3.9.6 → hdx_python_country-3.9.8}/pytest.ini +0 -0
  20. {hdx_python_country-3.9.6 → hdx_python_country-3.9.8}/ruff.toml +0 -0
  21. {hdx_python_country-3.9.6 → hdx_python_country-3.9.8}/src/hdx/location/Countries & Territories Taxonomy MVP - C&T Taxonomy with HXL Tags.csv +0 -0
  22. {hdx_python_country-3.9.6 → hdx_python_country-3.9.8}/src/hdx/location/__init__.py +0 -0
  23. {hdx_python_country-3.9.6 → hdx_python_country-3.9.8}/src/hdx/location/adminlevel.py +0 -0
  24. {hdx_python_country-3.9.6 → hdx_python_country-3.9.8}/src/hdx/location/currency.py +0 -0
  25. {hdx_python_country-3.9.6 → hdx_python_country-3.9.8}/src/hdx/location/int_timestamp.py +0 -0
  26. {hdx_python_country-3.9.6 → hdx_python_country-3.9.8}/src/hdx/location/wfp_exchangerates.py +0 -0
  27. {hdx_python_country-3.9.6 → hdx_python_country-3.9.8}/tests/fixtures/adminlevel.yaml +0 -0
  28. {hdx_python_country-3.9.6 → hdx_python_country-3.9.8}/tests/fixtures/adminlevelparent.yaml +0 -0
  29. {hdx_python_country-3.9.6 → hdx_python_country-3.9.8}/tests/fixtures/download-global-pcode-lengths.csv +0 -0
  30. {hdx_python_country-3.9.6 → hdx_python_country-3.9.8}/tests/fixtures/download-global-pcodes-adm-1-2.csv +0 -0
  31. {hdx_python_country-3.9.6 → hdx_python_country-3.9.8}/tests/fixtures/secondary_historic_rates.csv +0 -0
  32. {hdx_python_country-3.9.6 → hdx_python_country-3.9.8}/tests/fixtures/secondary_rates.json +0 -0
  33. {hdx_python_country-3.9.6 → hdx_python_country-3.9.8}/tests/fixtures/wfp/Currency_List_1.json +0 -0
  34. {hdx_python_country-3.9.6 → hdx_python_country-3.9.8}/tests/fixtures/wfp/Currency_List_2.json +0 -0
  35. {hdx_python_country-3.9.6 → hdx_python_country-3.9.8}/tests/fixtures/wfp/Currency_UsdIndirectQuotation_1.json +0 -0
  36. {hdx_python_country-3.9.6 → hdx_python_country-3.9.8}/tests/fixtures/wfp/Currency_UsdIndirectQuotation_10.json +0 -0
  37. {hdx_python_country-3.9.6 → hdx_python_country-3.9.8}/tests/fixtures/wfp/Currency_UsdIndirectQuotation_2.json +0 -0
  38. {hdx_python_country-3.9.6 → hdx_python_country-3.9.8}/tests/fixtures/wfp/Currency_UsdIndirectQuotation_3.json +0 -0
  39. {hdx_python_country-3.9.6 → hdx_python_country-3.9.8}/tests/fixtures/wfp/Currency_UsdIndirectQuotation_4.json +0 -0
  40. {hdx_python_country-3.9.6 → hdx_python_country-3.9.8}/tests/fixtures/wfp/Currency_UsdIndirectQuotation_5.json +0 -0
  41. {hdx_python_country-3.9.6 → hdx_python_country-3.9.8}/tests/fixtures/wfp/Currency_UsdIndirectQuotation_6.json +0 -0
  42. {hdx_python_country-3.9.6 → hdx_python_country-3.9.8}/tests/fixtures/wfp/Currency_UsdIndirectQuotation_7.json +0 -0
  43. {hdx_python_country-3.9.6 → hdx_python_country-3.9.8}/tests/fixtures/wfp/Currency_UsdIndirectQuotation_8.json +0 -0
  44. {hdx_python_country-3.9.6 → hdx_python_country-3.9.8}/tests/fixtures/wfp/Currency_UsdIndirectQuotation_9.json +0 -0
  45. {hdx_python_country-3.9.6 → hdx_python_country-3.9.8}/tests/hdx/location/Countries_UZB_Deleted.csv +0 -0
  46. {hdx_python_country-3.9.6 → hdx_python_country-3.9.8}/tests/hdx/location/__init__.py +0 -0
  47. {hdx_python_country-3.9.6 → hdx_python_country-3.9.8}/tests/hdx/location/conftest.py +0 -0
  48. {hdx_python_country-3.9.6 → hdx_python_country-3.9.8}/tests/hdx/location/test_adminlevel.py +0 -0
  49. {hdx_python_country-3.9.6 → hdx_python_country-3.9.8}/tests/hdx/location/test_currency.py +0 -0
  50. {hdx_python_country-3.9.6 → hdx_python_country-3.9.8}/tests/hdx/location/test_wfp_exchangerates.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hdx-python-country
3
- Version: 3.9.6
3
+ Version: 3.9.8
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,7 +25,7 @@ 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.8.7
28
+ Requires-Dist: hdx-python-utilities>=3.9.2
29
29
  Requires-Dist: libhxl>=5.2.2
30
30
  Requires-Dist: tenacity
31
31
  Provides-Extra: dev
@@ -34,7 +34,7 @@ classifiers = [
34
34
  requires-python = ">=3.8"
35
35
 
36
36
  dependencies = [
37
- "hdx-python-utilities>=3.8.7",
37
+ "hdx-python-utilities>=3.9.2",
38
38
  "libhxl>=5.2.2",
39
39
  "tenacity",
40
40
  ]
@@ -2,7 +2,7 @@
2
2
  # uv pip compile pyproject.toml --resolver=backtracking --all-extras -o requirements.txt
3
3
  annotated-types==0.7.0
4
4
  # via pydantic
5
- astdoc==1.3.0
5
+ astdoc==1.3.2
6
6
  # via mkapi
7
7
  attrs==25.3.0
8
8
  # via
@@ -14,37 +14,38 @@ babel==2.17.0
14
14
  # via mkdocs-material
15
15
  backrefs==5.9
16
16
  # via mkdocs-material
17
- certifi==2025.7.9
17
+ certifi==2025.8.3
18
18
  # via requests
19
19
  cfgv==3.4.0
20
20
  # via pre-commit
21
21
  chardet==5.2.0
22
22
  # via frictionless
23
- charset-normalizer==3.4.2
23
+ charset-normalizer==3.4.3
24
24
  # via requests
25
25
  click==8.2.1
26
26
  # via
27
27
  # mkdocs
28
+ # mkdocs-material
28
29
  # typer
29
30
  colorama==0.4.6
30
31
  # via mkdocs-material
31
- coverage==7.9.2
32
+ coverage==7.10.7
32
33
  # via pytest-cov
33
- distlib==0.3.9
34
+ distlib==0.4.0
34
35
  # via virtualenv
35
36
  et-xmlfile==2.0.0
36
37
  # via openpyxl
37
- filelock==3.18.0
38
+ filelock==3.19.1
38
39
  # via virtualenv
39
40
  frictionless==5.18.1
40
41
  # via hdx-python-utilities
41
42
  ghp-import==2.1.0
42
43
  # via mkdocs
43
- hdx-python-utilities==3.8.7
44
+ hdx-python-utilities==3.9.2
44
45
  # via hdx-python-country (pyproject.toml)
45
- humanize==4.12.3
46
+ humanize==4.13.0
46
47
  # via frictionless
47
- identify==2.6.12
48
+ identify==2.6.14
48
49
  # via pre-commit
49
50
  idna==3.10
50
51
  # via requests
@@ -64,24 +65,24 @@ jsonlines==4.0.0
64
65
  # via hdx-python-utilities
65
66
  jsonpath-ng==1.7.0
66
67
  # via libhxl
67
- jsonschema==4.24.0
68
+ jsonschema==4.25.1
68
69
  # via
69
70
  # frictionless
70
71
  # tableschema-to-template
71
- jsonschema-specifications==2025.4.1
72
+ jsonschema-specifications==2025.9.1
72
73
  # via jsonschema
73
74
  libhxl==5.2.2
74
75
  # via hdx-python-country (pyproject.toml)
75
76
  loguru==0.7.3
76
77
  # via hdx-python-utilities
77
- markdown==3.8.2
78
+ markdown==3.9
78
79
  # via
79
80
  # mkdocs
80
81
  # mkdocs-material
81
82
  # pymdown-extensions
82
- markdown-it-py==3.0.0
83
+ markdown-it-py==4.0.0
83
84
  # via rich
84
- marko==2.1.4
85
+ marko==2.2.0
85
86
  # via frictionless
86
87
  markupsafe==3.0.2
87
88
  # via
@@ -93,7 +94,7 @@ mergedeep==1.3.4
93
94
  # via
94
95
  # mkdocs
95
96
  # mkdocs-get-deps
96
- mkapi==4.4.3
97
+ mkapi==4.4.5
97
98
  # via hdx-python-country (pyproject.toml)
98
99
  mkdocs==1.6.1
99
100
  # via
@@ -101,7 +102,7 @@ mkdocs==1.6.1
101
102
  # mkdocs-material
102
103
  mkdocs-get-deps==0.2.0
103
104
  # via mkdocs
104
- mkdocs-material==9.6.15
105
+ mkdocs-material==9.6.20
105
106
  # via mkapi
106
107
  mkdocs-material-extensions==1.3.1
107
108
  # via mkdocs-material
@@ -117,9 +118,9 @@ paginate==0.5.7
117
118
  # via mkdocs-material
118
119
  pathspec==0.12.1
119
120
  # via mkdocs
120
- petl==1.7.16
121
+ petl==1.7.17
121
122
  # via frictionless
122
- platformdirs==4.3.8
123
+ platformdirs==4.4.0
123
124
  # via
124
125
  # mkdocs-get-deps
125
126
  # virtualenv
@@ -131,9 +132,9 @@ ply==3.11
131
132
  # via
132
133
  # jsonpath-ng
133
134
  # libhxl
134
- pre-commit==4.2.0
135
+ pre-commit==4.3.0
135
136
  # via hdx-python-country (pyproject.toml)
136
- pydantic==2.11.7
137
+ pydantic==2.11.9
137
138
  # via frictionless
138
139
  pydantic-core==2.33.2
139
140
  # via pydantic
@@ -142,15 +143,15 @@ pygments==2.19.2
142
143
  # mkdocs-material
143
144
  # pytest
144
145
  # rich
145
- pymdown-extensions==10.16
146
+ pymdown-extensions==10.16.1
146
147
  # via mkdocs-material
147
148
  pyphonetics==0.5.3
148
149
  # via hdx-python-utilities
149
- pytest==8.4.1
150
+ pytest==8.4.2
150
151
  # via
151
152
  # hdx-python-country (pyproject.toml)
152
153
  # pytest-cov
153
- pytest-cov==6.2.1
154
+ pytest-cov==7.0.0
154
155
  # via hdx-python-country (pyproject.toml)
155
156
  python-dateutil==2.9.0.post0
156
157
  # via
@@ -179,7 +180,7 @@ referencing==0.36.2
179
180
  # via
180
181
  # jsonschema
181
182
  # jsonschema-specifications
182
- requests==2.32.4
183
+ requests==2.32.5
183
184
  # via
184
185
  # frictionless
185
186
  # libhxl
@@ -189,13 +190,13 @@ requests-file==2.1.0
189
190
  # via hdx-python-utilities
190
191
  rfc3986==2.0.0
191
192
  # via frictionless
192
- rich==14.0.0
193
+ rich==14.1.0
193
194
  # via typer
194
- rpds-py==0.26.0
195
+ rpds-py==0.27.1
195
196
  # via
196
197
  # jsonschema
197
198
  # referencing
198
- ruamel-yaml==0.18.14
199
+ ruamel-yaml==0.18.15
199
200
  # via hdx-python-utilities
200
201
  ruamel-yaml-clib==0.2.12
201
202
  # via ruamel-yaml
@@ -215,9 +216,9 @@ tenacity==9.1.2
215
216
  # via hdx-python-country (pyproject.toml)
216
217
  text-unidecode==1.3
217
218
  # via python-slugify
218
- typer==0.16.0
219
+ typer==0.19.1
219
220
  # via frictionless
220
- typing-extensions==4.14.1
221
+ typing-extensions==4.15.0
221
222
  # via
222
223
  # frictionless
223
224
  # pydantic
@@ -236,7 +237,7 @@ urllib3==2.5.0
236
237
  # requests
237
238
  validators==0.35.0
238
239
  # via frictionless
239
- virtualenv==20.31.2
240
+ virtualenv==20.34.0
240
241
  # via pre-commit
241
242
  watchdog==6.0.0
242
243
  # via mkdocs
@@ -248,7 +249,7 @@ xlrd3==1.1.0
248
249
  # via libhxl
249
250
  xlsx2csv==0.8.4
250
251
  # via hdx-python-utilities
251
- xlsxwriter==3.2.5
252
+ xlsxwriter==3.2.9
252
253
  # via tableschema-to-template
253
254
  xlwt==1.3.0
254
255
  # via hdx-python-utilities
@@ -1,7 +1,14 @@
1
1
  # file generated by setuptools-scm
2
2
  # don't change, don't track in version control
3
3
 
4
- __all__ = ["__version__", "__version_tuple__", "version", "version_tuple"]
4
+ __all__ = [
5
+ "__version__",
6
+ "__version_tuple__",
7
+ "version",
8
+ "version_tuple",
9
+ "__commit_id__",
10
+ "commit_id",
11
+ ]
5
12
 
6
13
  TYPE_CHECKING = False
7
14
  if TYPE_CHECKING:
@@ -9,13 +16,19 @@ if TYPE_CHECKING:
9
16
  from typing import Union
10
17
 
11
18
  VERSION_TUPLE = Tuple[Union[int, str], ...]
19
+ COMMIT_ID = Union[str, None]
12
20
  else:
13
21
  VERSION_TUPLE = object
22
+ COMMIT_ID = object
14
23
 
15
24
  version: str
16
25
  __version__: str
17
26
  __version_tuple__: VERSION_TUPLE
18
27
  version_tuple: VERSION_TUPLE
28
+ commit_id: COMMIT_ID
29
+ __commit_id__: COMMIT_ID
19
30
 
20
- __version__ = version = '3.9.6'
21
- __version_tuple__ = version_tuple = (3, 9, 6)
31
+ __version__ = version = '3.9.8'
32
+ __version_tuple__ = version_tuple = (3, 9, 8)
33
+
34
+ __commit_id__ = commit_id = None
@@ -1,10 +1,8 @@
1
1
  """Country location"""
2
2
 
3
- import copy
4
3
  import logging
5
4
  import os.path
6
5
  import re
7
- from string import punctuation
8
6
  from typing import Dict, List, Optional, Tuple, Union
9
7
 
10
8
  import hxl
@@ -62,6 +60,7 @@ class Country:
62
60
  "BOLIVARIAN",
63
61
  "PLURINATIONAL",
64
62
  "PEOPLE'S",
63
+ "PEOPLES",
65
64
  "DUTCH PART",
66
65
  "FRENCH PART",
67
66
  "MALVINAS",
@@ -721,41 +720,90 @@ class Country:
721
720
  Returns:
722
721
  Tuple[str, List[str]]: Uppercase simplified country name and list of removed words
723
722
  """
724
- countryupper = country.upper()
723
+ # Convert the input into an upper-cased list of words
724
+ countryupper = country.upper().strip()
725
725
  words = get_words_in_sentence(countryupper)
726
+
727
+ # Strip common patterns
726
728
  index = countryupper.find(",")
727
729
  if index != -1:
728
730
  countryupper = countryupper[:index]
729
731
  index = countryupper.find(":")
730
732
  if index != -1:
731
733
  countryupper = countryupper[:index]
732
- regex = re.compile(r"\(.+?\)")
733
- countryupper = regex.sub("", countryupper)
734
- remove = copy.deepcopy(cls.simplifications)
735
- for simplification1, simplification2 in cls.abbreviations.items():
736
- countryupper = countryupper.replace(simplification1, "")
737
- remove.append(simplification2)
738
- for (
739
- simplification1,
740
- simplifications,
741
- ) in cls.multiple_abbreviations.items():
742
- countryupper = countryupper.replace(simplification1, "")
743
- for simplification2 in simplifications:
744
- remove.append(simplification2)
745
- remove = "|".join(remove)
746
- regex = re.compile(
747
- r"[" + punctuation.replace("'", "") + r"]|\b(" + remove + r")\b",
748
- flags=re.IGNORECASE,
749
- )
750
- countryupper = regex.sub("", countryupper)
751
- countryupper = countryupper.strip()
752
- countryupper_words = get_words_in_sentence(countryupper)
753
- if len(countryupper_words) > 1:
754
- countryupper = countryupper_words[0]
755
- if countryupper:
756
- countryupper = countryupper.strip(punctuation)
757
- words.remove(countryupper)
758
- return countryupper, words
734
+
735
+ if countryupper and not (countryupper[0] == "(" and countryupper[-1] == ")"):
736
+ regex = re.compile(r"\(.+?\)")
737
+ countryupper = regex.sub("", countryupper)
738
+
739
+ # Find the words that remain as candidates for the simplified name.
740
+ # These are guaranteed to be a subset of `words` because we have only pruned
741
+ # parts from the sentence and not done any transformative processing.
742
+ candidate_words = get_words_in_sentence(countryupper)
743
+
744
+ if candidate_words:
745
+ # Make the simplifying terms indexable for efficient lookup
746
+ multiword_terms = {}
747
+ singleword_terms = set()
748
+
749
+ for terms in [
750
+ cls.simplifications,
751
+ cls.abbreviations.keys(),
752
+ cls.abbreviations.values(),
753
+ cls.multiple_abbreviations.keys(),
754
+ ] + list(cls.multiple_abbreviations.values()):
755
+ for term in terms:
756
+ if " " in term:
757
+ # Index multi-word terms by the first term against a list of the terms
758
+ term_parts = term.split(" ")
759
+ multiword_terms[term_parts[0]] = term_parts
760
+ else:
761
+ # Add single word terms to the set, and add their dot-less form as well
762
+ singleword_terms.add(term)
763
+ if term[-1] == ".":
764
+ singleword_terms.add(term.strip("."))
765
+
766
+ num_candidate_words = len(candidate_words)
767
+ simplified_term = ""
768
+ enumerated_words = enumerate(candidate_words)
769
+ default = (num_candidate_words, "")
770
+
771
+ # Iterate through the candidate terms until we a) find a non-simplified word
772
+ # or b) hit the end of the list of words
773
+ while (val := next(enumerated_words, default)) != default:
774
+ i, word = val
775
+ if word in singleword_terms:
776
+ # If the word was a single word simplification term then skip it
777
+ continue
778
+ if (
779
+ # If the current term is the first word in a multi-part term
780
+ (term_parts := multiword_terms.get(word))
781
+ # And there are enough words left in the sentence
782
+ and i + len(term_parts) <= num_candidate_words
783
+ # And all of the words in the multi-word phrase are in sequence
784
+ # in the candidate term starting at the current position
785
+ and all(
786
+ candidate_words[i + j] == term_part
787
+ for j, term_part in enumerate(term_parts)
788
+ )
789
+ ):
790
+ # Then skip the other words in the term and continue
791
+ for _ in range(len(term_parts) - 1):
792
+ next(enumerated_words)
793
+
794
+ continue
795
+ # Else we found a word that we aren't dropping - it is our simplified word.
796
+ # Take it and break.
797
+ simplified_term = word
798
+ break
799
+
800
+ if simplified_term:
801
+ # We found a simplified term. Remove it from the list of other terms
802
+ words.remove(simplified_term)
803
+ else:
804
+ simplified_term = ""
805
+
806
+ return simplified_term, words
759
807
 
760
808
  @classmethod
761
809
  def get_iso3_country_code(
@@ -28,8 +28,8 @@ class WFPAPI:
28
28
  """
29
29
 
30
30
  token_url = "https://api.wfp.org/token"
31
- base_url = "https://api.wfp.org/vam-data-bridges/5.0.0/"
32
- scope = "vamdatabridges_commodities-list_get vamdatabridges_commodityunits-list_get vamdatabridges_marketprices-alps_get vamdatabridges_commodities-categories-list_get vamdatabridges_commodityunits-conversion-list_get vamdatabridges_marketprices-priceweekly_get vamdatabridges_markets-geojsonlist_get vamdatabridges_marketprices-pricemonthly_get vamdatabridges_markets-list_get vamdatabridges_currency-list_get vamdatabridges_currency-usdindirectquotation_get"
31
+ base_url = "https://api.wfp.org/vam-data-bridges/6.0.0/"
32
+ scope = "gefs_geoless-items-countries_get vamdatabridges_commodities-list_get vamdatabridges_commodityunits-list_get vamdatabridges_marketprices-alps_get vamdatabridges_commodities-categories-list_get vamdatabridges_commodityunits-conversion-list_get vamdatabridges_marketprices-priceweekly_get vamdatabridges_markets-geojsonlist_get vamdatabridges_marketprices-pricemonthly_get vamdatabridges_markets-list_get vamdatabridges_currency-list_get vamdatabridges_currency-usdindirectquotation_get"
33
33
  default_retry_params = {
34
34
  "retry": retry_if_exception_type(DownloadError),
35
35
  "after": after_log(logger, logging.INFO),
@@ -644,38 +644,144 @@ class TestCountry:
644
644
  ]
645
645
 
646
646
  def test_simplify_countryname(self):
647
- assert Country.simplify_countryname("jpn") == ("JPN", list())
647
+ # Test that we handle the empty string case
648
+ assert Country.simplify_countryname("") == ("", [])
649
+
650
+ # Test that country codes and arbitrary words return just the word but capitalised
651
+ assert Country.simplify_countryname("jpn") == ("JPN", [])
652
+ assert Country.simplify_countryname("test") == ("TEST", [])
653
+
654
+ # Test simplified terms are removed, including abbreviations
648
655
  assert Country.simplify_countryname("United Rep. of Tanzania") == (
649
656
  "TANZANIA",
650
657
  ["UNITED", "REP", "OF"],
651
658
  )
659
+ assert Country.simplify_countryname(
660
+ "The former Yugoslav Republic of Macedonia"
661
+ ) == ("MACEDONIA", ["THE", "FORMER", "YUGOSLAV", "REPUBLIC", "OF"])
662
+
663
+ # Test different word orderings and bracketing are consistent
652
664
  assert Country.simplify_countryname("Micronesia (Federated States of)") == (
653
665
  "MICRONESIA",
654
666
  ["FEDERATED", "STATES", "OF"],
655
667
  )
668
+ assert Country.simplify_countryname("Federated States of Micronesia") == (
669
+ "MICRONESIA",
670
+ ["FEDERATED", "STATES", "OF"],
671
+ )
672
+ assert Country.simplify_countryname("(Federated States of) Micronesia") == (
673
+ "MICRONESIA",
674
+ ["FEDERATED", "STATES", "OF"],
675
+ )
676
+
677
+ # Test that the simplified terms on their own are dropped and that we handle
678
+ # the "no simplified term" case
679
+ assert Country.simplify_countryname("Federated States") == (
680
+ "",
681
+ ["FEDERATED", "STATES"],
682
+ )
683
+
684
+ # Test that multi-word simplifications are dropped
685
+ assert Country.simplify_countryname("French Part of Saint Martin") == (
686
+ "MARTIN",
687
+ ["FRENCH", "PART", "OF", "SAINT"],
688
+ )
689
+ assert Country.simplify_countryname("French Part of Saint-Martin") == (
690
+ "MARTIN",
691
+ ["FRENCH", "PART", "OF", "SAINT"],
692
+ )
693
+ # "French Part" is a simplification and so can't be the simplified term
694
+ assert Country.simplify_countryname("French Part") == ("", ["FRENCH", "PART"])
695
+ # But the words must be consecutive for multi-part terms,
696
+ # so we don't drop "French" and "part" here
697
+ assert Country.simplify_countryname("French and Part") == (
698
+ "FRENCH",
699
+ ["AND", "PART"],
700
+ )
701
+
702
+ # Test that we handle abbreviations with and without punctuation
656
703
  assert Country.simplify_countryname("Dem. Rep. of the Congo") == (
657
704
  "CONGO",
658
705
  ["DEM", "REP", "OF", "THE"],
659
706
  )
707
+ assert Country.simplify_countryname("Dem Rep of the Congo") == (
708
+ "CONGO",
709
+ ["DEM", "REP", "OF", "THE"],
710
+ )
711
+
712
+ # Test that we handle the "Country, Specifics" comma format
660
713
  assert Country.simplify_countryname(
661
714
  "Korea, Democratic People's Republic of"
662
715
  ) == ("KOREA", ["DEMOCRATIC", "PEOPLE'S", "REPUBLIC", "OF"])
663
716
  assert Country.simplify_countryname(
664
717
  "Democratic People's Republic of Korea"
665
718
  ) == ("KOREA", ["DEMOCRATIC", "PEOPLE'S", "REPUBLIC", "OF"])
719
+
720
+ # Test that we handle more bracketed formats
666
721
  assert Country.simplify_countryname("Korea (the Republic of))") == (
667
722
  "KOREA",
668
723
  ["THE", "REPUBLIC", "OF"],
669
724
  )
725
+ # Regression test for bug #70 - partial brackets
670
726
  assert Country.simplify_countryname("Korea (the Republic of") == (
671
727
  "KOREA",
672
728
  ["THE", "REPUBLIC", "OF"],
673
729
  )
674
- assert Country.simplify_countryname(
675
- "The former Yugoslav Republic of Macedonia"
676
- ) == ("MACEDONIA", ["THE", "FORMER", "YUGOSLAV", "REPUBLIC", "OF"])
730
+
731
+ # Test that we don't strip everything just because it's bracketed, even if the brackets
732
+ # are surrounded by whitespace
733
+ assert Country.simplify_countryname("(the Republic of Korea)") == (
734
+ "KOREA",
735
+ ["THE", "REPUBLIC", "OF"],
736
+ )
737
+ assert Country.simplify_countryname(" (the Republic of Korea) ") == (
738
+ "KOREA",
739
+ ["THE", "REPUBLIC", "OF"],
740
+ )
741
+
742
+ # Test that we're actually stripping the brackets and that it's not all just been
743
+ # simplified words that we'd drop anyway, even if they weren't in brackets
744
+ assert Country.simplify_countryname("(Sometimes) Korea") == (
745
+ "KOREA",
746
+ ["SOMETIMES"],
747
+ )
748
+
749
+ # Regression test for bug #75 - apostrophes in simplified term
677
750
  assert Country.simplify_countryname("d'Ivoire Côte") == ("D'IVOIRE", ["CÔTE"])
678
751
 
752
+ # Regression test for bug #77 - other punctuation in simplified term
753
+ assert Country.simplify_countryname("Guinea-Bissau") == ("GUINEA", ["BISSAU"])
754
+
755
+ # Test simplification of terms with apostrophes, and the non-apostrophe form
756
+ assert Country.simplify_countryname("People's Republic of Bangladesh") == (
757
+ "BANGLADESH",
758
+ ["PEOPLE'S", "REPUBLIC", "OF"],
759
+ )
760
+ assert Country.simplify_countryname("Peoples Republic of Bangladesh") == (
761
+ "BANGLADESH",
762
+ ["PEOPLES", "REPUBLIC", "OF"],
763
+ )
764
+ # Known limitation with "smart quote" handling
765
+ assert Country.simplify_countryname("People’s Republic of Bangladesh") == (
766
+ "PEOPLE’S",
767
+ ["REPUBLIC", "OF", "BANGLADESH"],
768
+ )
769
+
770
+ # Simplifying assumes that it isn't getting an address and simplifies to the first
771
+ # part around commas, even if it isn't a country
772
+ assert Country.simplify_countryname("Paris, France") == (
773
+ "PARIS",
774
+ ["FRANCE"],
775
+ )
776
+
777
+ # Some people supply strings that aren't countries
778
+ # (often indirectly via `get_iso3_country_code_fuzzy()`)
779
+ # Ensure the function doesn't error, even if the value is meaningless.
780
+ assert Country.simplify_countryname("3.1 Global scores and ranking") == (
781
+ "3",
782
+ ["1", "GLOBAL", "SCORES", "AND", "RANKING"],
783
+ )
784
+
679
785
  def test_get_iso3_country_code(self):
680
786
  assert Country.get_iso3_country_code("jpn") == "JPN"
681
787
  assert Country.get_iso3_country_code("Dem. Rep. of the Congo") == "COD"