Skip to content

Commit

Permalink
Added the countries attribute and check_iso3_codes() method to Region…
Browse files Browse the repository at this point in the history
…Code object (#240)

* Added the countries attribute and check_iso3_codes() method

* Added validator decorator and changed tests

* Added pycountry to dependencies in the setup.cfg file

* Added message to error, test still failing

* Added ValueError and other small fixes

* Fixed failing ValueError test

---------

Co-authored-by: Philip Hackstock <20710924+phackstock@users.noreply.github.com>
  • Loading branch information
GretchenSchowalter and phackstock authored May 17, 2023
1 parent be48466 commit cdddd46
Show file tree
Hide file tree
Showing 3 changed files with 162 additions and 43 deletions.
16 changes: 16 additions & 0 deletions nomenclature/code.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import json
import re
import pycountry
from keyword import iskeyword
from pathlib import Path
from typing import Any, Dict, List, Optional, Set, Union
Expand Down Expand Up @@ -219,6 +220,21 @@ class RegionCode(Code):
"""

hierarchy: str = None
countries: List[str] = None

@validator("countries")
def check_iso3_codes(cls, v, values) -> List[str]:
"""Verifies that each ISO3 code is valid according to pycountry library."""
invalid_iso3_codes: List[str] = []
for country in v:
if pycountry.countries.get(alpha_3=country) is None:
invalid_iso3_codes.append(country)
if invalid_iso3_codes:
raise ValueError(
f"Region {values['name']} has invalid"
f" ISO3 country codes: {invalid_iso3_codes}"
)
return v


class MetaCode(Code):
Expand Down
87 changes: 44 additions & 43 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -1,43 +1,44 @@
[metadata]
name = nomenclature-iamc
author = Scenario Services team, ECE program, IIASA
author_email = ece-scse@iiasa.ac.at
license = APACHE-2.0
description = Package for managing codelists & attributes for IAMC-format datasets
long_description = file: README.md
long_description_content_type = text/markdown
url = https://github.com/IAMconsortium/nomenclature

[options]
packages = nomenclature
include_package_data = True
python_requires = >= 3.8
install_requires =
click >= 8
pyam-iamc >= 1.7.0
openpyxl
setuptools >= 41
pydantic
pyyaml
jsonschema
setuptools_scm
pandas >= 1.5.2
numpy
setup_requires =
setuptools >= 41
setuptools_scm

[options.extras_require]
tests =
pytest
docs =
sphinx
sphinx-click
numpydoc

[options.entry_points]
console_scripts =
nomenclature = nomenclature:cli

[flake8]
max-line-length = 88
[metadata]
name = nomenclature-iamc
author = Scenario Services team, ECE program, IIASA
author_email = ece-scse@iiasa.ac.at
license = APACHE-2.0
description = Package for managing codelists & attributes for IAMC-format datasets
long_description = file: README.md
long_description_content_type = text/markdown
url = https://github.com/IAMconsortium/nomenclature

[options]
packages = nomenclature
include_package_data = True
python_requires = >= 3.8
install_requires =
click >= 8
pyam-iamc >= 1.7.0
openpyxl
setuptools >= 41
pydantic
pyyaml
jsonschema
setuptools_scm
pandas >= 1.5.2
numpy
pycountry
setup_requires =
setuptools >= 41
setuptools_scm

[options.extras_require]
tests =
pytest
docs =
sphinx
sphinx-click
numpydoc

[options.entry_points]
console_scripts =
nomenclature = nomenclature:cli

[flake8]
max-line-length = 88
102 changes: 102 additions & 0 deletions tests/test_code.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,108 @@ def test_RegionCode_hierarchy_attribute():
assert reg.hierarchy == "R5"


def test_RegionCode_iso3_code():
reg = RegionCode(
name="Western Europe",
hierarchy="R5OECD",
countries=[
"DNK",
"IRL",
"AUT",
"FIN",
"FRA",
"DEU",
"GRC",
"ISL",
"ITA",
"LIE",
"MLT",
"BEL",
"FRO",
"AND",
"GIB",
"LUX",
"MCO",
"NLD",
"NOR",
"PRT",
"ESP",
"SWE",
"CHE",
"GBR",
"SMR",
],
)

assert reg.countries == [
"DNK",
"IRL",
"AUT",
"FIN",
"FRA",
"DEU",
"GRC",
"ISL",
"ITA",
"LIE",
"MLT",
"BEL",
"FRO",
"AND",
"GIB",
"LUX",
"MCO",
"NLD",
"NOR",
"PRT",
"ESP",
"SWE",
"CHE",
"GBR",
"SMR",
]


def test_RegionCode_iso3_code_fail():
countries = [
"DMK",
"IPL",
"ATZ",
"FNL",
"FRE",
"DEX",
"GRE",
"IBL",
"ITL",
"LIC",
"MLA",
"BEG",
"FRT",
"ANB",
"GDR",
"LXB",
"MNO",
"NTD",
"NRW",
"PRE",
"EPA",
"SWD",
"CEW",
"GTR",
"SOR",
]

error_pattern = (
"1 validation error for RegionCode\ncountries\n Reg"
"ion Western Europe has invalid ISO3 country codes"
": \['DMK', 'IPL', 'ATZ', 'FNL', 'FRE', 'DEX', 'GRE'," # noqa
" 'IBL', 'ITL', 'LIC', 'MLA', 'BEG', 'FRT', 'ANB', " # noqa
"'GDR', 'LXB', 'MNO', 'NTD', 'NRW', 'PRE', 'EPA', " # noqa
"'SWD', 'CEW', 'GTR', 'SOR'\] \(type=value_error\)" # noqa
)
with pytest.raises(ValueError, match=error_pattern):
RegionCode(name="Western Europe", hierarchy="R5OECD", countries=countries)

def test_MetaCode_allowed_values_attribute():
meta = MetaCode(
name="MetaCode test",
Expand Down

0 comments on commit cdddd46

Please sign in to comment.