Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Check if constituents of common regions are in native regions #463

Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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]):
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