Skip to content

Commit

Permalink
Check if constituents of common regions are in native regions (IAMcon…
Browse files Browse the repository at this point in the history
…sortium#463)

* Check if constituents of common regions are in native regions

* Update hash to fix tests

* Fix error message

* Remove redundant check

* Check excluded regions

---------

Co-authored-by: David Almeida <almeida@iiasa.ac.at>
  • Loading branch information
dc-almeida and David Almeida authored Jan 31, 2025
1 parent 6ec1e19 commit fc26782
Show file tree
Hide file tree
Showing 7 changed files with 36 additions and 4 deletions.
4 changes: 4 additions & 0 deletions nomenclature/error.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@
"region_not_defined",
"Region(s)\n{regions}\nin {file}\nnot found in RegionCodeList",
),
"ConstituentsNotNativeError": (
"constituents_not_native",
"Constituent region(s)\n{regions}\nin {file} not found in native region(s)",
),
}

PydanticCustomErrors = namedtuple("PydanticCustomErrors", pydantic_custom_error_config)
Expand Down
15 changes: 15 additions & 0 deletions nomenclature/processor/region.py
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,21 @@ def check_exclude_common_region_overlap(
) -> "RegionAggregationMapping":
return _check_exclude_region_overlap(v, "common_regions")

@model_validator(mode="after")
@classmethod
def check_constituent_regions_in_native_regions(
cls, v: "RegionAggregationMapping"
) -> "RegionAggregationMapping":
if v.common_regions and v.native_regions:
if missing := set(
[cr for r in v.common_regions for cr in r.constituent_regions]
).difference([r.name for r in v.native_regions] + v.exclude_regions):
raise PydanticCustomError(
*custom_pydantic_errors.ConstituentsNotNativeError,
{"regions": missing, "file": v.file},
)
return v

@classmethod
def from_file(cls, file: Path | str) -> "RegionAggregationMapping":
"""Initialize a RegionAggregationMapping from a file.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,3 @@ native_regions:
common_regions:
- World:
- region_a
- region_b
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ dimensions:
repositories:
common-definitions:
url: https://github.com/IAMconsortium/common-definitions.git/
hash: cb85704
hash: 091c0fe
definitions:
region:
repository: common-definitions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ dimensions:
repositories:
common-definitions:
url: https://github.com/IAMconsortium/common-definitions.git/
hash: cb85704
hash: 091c0fe
definitions:
region:
repository:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Constituent region is not defined in native region
model: model_a
native_regions:
- region_a: alternative_name_a
- region_b: alternative_name_b
common_regions:
- common_region_1:
- region_a
- region_b
- region_c
6 changes: 5 additions & 1 deletion tests/test_region_aggregation.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,10 @@ def test_mapping():
"illegal_mapping_model_only.yaml",
"one of 'native_regions' and 'common_regions'",
),
(
"illegal_mapping_constituent_native_missing.yaml",
"Constituent region\(s\)\n.*\n",
),
],
)
def test_illegal_mappings(file, error_msg_pattern):
Expand Down Expand Up @@ -196,7 +200,7 @@ def test_region_processor_wrong_args():

def test_region_processor_multiple_wrong_mappings(simple_definition):
# Read in the entire region_aggregation directory and return **all** errors
msg = "Collected 9 errors"
msg = "Collected 10 errors"

with pytest.raises(ValueError, match=msg):
RegionProcessor.from_directory(
Expand Down

0 comments on commit fc26782

Please sign in to comment.