From fab701f442d6295f340312dee03e83f5f77da502 Mon Sep 17 00:00:00 2001 From: Philip Hackstock <20710924+phackstock@users.noreply.github.com> Date: Thu, 18 Jan 2024 12:06:01 +0100 Subject: [PATCH 01/18] Add output_directory option to parse_model_registration --- nomenclature/__init__.py | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/nomenclature/__init__.py b/nomenclature/__init__.py index 1f4fb850..8815d58f 100644 --- a/nomenclature/__init__.py +++ b/nomenclature/__init__.py @@ -1,5 +1,6 @@ import logging from importlib.metadata import version +from pathlib import Path import yaml @@ -46,16 +47,21 @@ def create_yaml_from_xlsx(source, target, sheet_name, col, attrs=None): ).to_yaml(target) -def parse_model_registration(model_registration_file): +def parse_model_registration( + model_registration_file: str | Path, output_directory: str | Path = Path(".") +) -> None: """Parses a model registration file and writes the definitions & mapping yaml files Parameters ---------- - source : str, path, file-like object + model_registration_file : str, path, file-like object Path to xlsx model registration file. - file_name : str - Model-identifier part of the yaml file names. + output_directory : str, path, file-like object + Directory, where the model mapping and region file will be saved; default: "." """ + if not isinstance(output_directory, Path): + output_directory = Path(output_directory) + region_aggregregation_mapping = RegionAggregationMapping.from_file( model_registration_file ) @@ -63,7 +69,9 @@ def parse_model_registration(model_registration_file): x if (x.isalnum() or x in "._- ") else "_" for x in region_aggregregation_mapping.model[0] ) - region_aggregregation_mapping.to_yaml(f"{file_model_name}_mapping.yaml") + region_aggregregation_mapping.to_yaml( + output_directory / f"{file_model_name}_mapping.yaml" + ) if native_regions := [ { region_aggregregation_mapping.model[ @@ -71,5 +79,9 @@ def parse_model_registration(model_registration_file): ]: region_aggregregation_mapping.upload_native_regions } ]: - with open(f"{file_model_name}_regions.yaml", "w") as f: - yaml.dump(native_regions, f) + with open( + (output_directory / f"{file_model_name}_regions.yaml"), + "w", + encoding="utf-8", + ) as file: + yaml.dump(native_regions, file) From ea5aea3c6d4f1b7f7d79a1be8729050735a85afd Mon Sep 17 00:00:00 2001 From: Philip Hackstock <20710924+phackstock@users.noreply.github.com> Date: Thu, 18 Jan 2024 12:06:47 +0100 Subject: [PATCH 02/18] Remove multiple option to be in line with cli standards --- nomenclature/cli.py | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/nomenclature/cli.py b/nomenclature/cli.py index 9938dac1..23a9ef1a 100644 --- a/nomenclature/cli.py +++ b/nomenclature/cli.py @@ -1,4 +1,3 @@ -import ast from pathlib import Path from typing import List, Optional @@ -12,16 +11,6 @@ cli = click.Group() -class PythonLiteralOption(click.Option): - def type_cast_value(self, ctx, value): - if value is None: - return None - try: - return ast.literal_eval(value) - except Exception: - raise click.BadParameter(value) - - @cli.command("validate-yaml") @click.argument("path", type=click.Path(exists=True, path_type=Path)) def cli_valid_yaml(path: Path): @@ -49,7 +38,8 @@ def cli_valid_yaml(path: Path): @click.option( "--dimensions", help="Optional list of dimensions", - cls=PythonLiteralOption, + type=str, + multiple=True, default=None, ) def cli_valid_project( From 4c925f5f8c08546a1c41dcbfba4a4fa19164420a Mon Sep 17 00:00:00 2001 From: Philip Hackstock <20710924+phackstock@users.noreply.github.com> Date: Thu, 18 Jan 2024 12:06:58 +0100 Subject: [PATCH 03/18] Update cli tests --- tests/test_cli.py | 79 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 60 insertions(+), 19 deletions(-) diff --git a/tests/test_cli.py b/tests/test_cli.py index 9d0f4753..0f049783 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -1,13 +1,16 @@ import subprocess import sys -from click.testing import CliRunner -from nomenclature import cli -from nomenclature.testing import assert_valid_yaml, assert_valid_structure -import pytest +import pandas as pd import pydantic - +import pytest +from click.testing import CliRunner from conftest import TEST_DATA_DIR +from pandas.testing import assert_frame_equal +from pyam import IAMC_IDX, IamDataFrame, assert_iamframe_equal + +from nomenclature import cli +from nomenclature.testing import assert_valid_structure, assert_valid_yaml runner = CliRunner() @@ -156,7 +159,11 @@ def test_cli_custom_dimensions_runs(): "validate-project", str(TEST_DATA_DIR / "non-default_dimensions"), "--dimensions", - "['variable', 'region', 'scenario']", + "variable", + "--dimensions", + "region", + "--dimensions", + "scenario", ], ) assert result_valid.exit_code == 0 @@ -172,7 +179,7 @@ def test_cli_custom_dimensions_fails(): "validate-project", str(TEST_DATA_DIR / "non-default_dimensions"), "--dimensions", - "['variable', 'region', 'foo']", + "foo", ], ) assert result_invalid.exit_code == 1 @@ -190,7 +197,9 @@ def test_cli_empty_dimensions_run(): "validate-project", str(TEST_DATA_DIR / "non-default_dimensions_one_empty"), "--dimensions", - "['variable', 'region']", + "variable", + "--dimensions", + "region", ], ) assert result_valid.exit_code == 0 @@ -255,19 +264,51 @@ def test_cli_empty_definitions_dir(): assert "`definitions` directory is empty" in str(cli_result.exception) -def test_cli_empty_dimensions(): - """Assert that an error is raised when an empty list is given as dimensions""" - - cli_result = runner.invoke( +def test_check_region_aggregation(tmp_path): + IamDataFrame( + pd.DataFrame( + [ + ["m_a", "s_a", "region_A", "Primary Energy", "EJ/yr", 1, 2], + ["m_a", "s_a", "region_B", "Primary Energy", "EJ/yr", 3, 4], + ["m_a", "s_a", "World", "Primary Energy", "EJ/yr", 5, 6], + ], + columns=IAMC_IDX + [2005, 2010], + ) + ).to_excel(tmp_path / "data.xlsx") + runner.invoke( cli, [ - "validate-project", - str(TEST_DATA_DIR / "non-default_dimensions"), - "--dimensions", - "[]", + "check-region-aggregation", + str(tmp_path / "data.xlsx"), + "--workflow-directory", + str(TEST_DATA_DIR / "region_processing"), + "--definitions", + "dsd", + "--mappings", + "partial_aggregation", + "--processed-data", + str(tmp_path / "results.xlsx"), + "--differences", + str(tmp_path / "differences.xlsx"), ], ) - assert cli_result.exit_code == 1 - assert isinstance(cli_result.exception, ValueError) - assert "No dimensions to validate." in str(cli_result.exception) + # Check differences + exp_difference = pd.DataFrame( + [ + ["m_a", "s_a", "World", "Primary Energy", "EJ/yr", 2005, 5, 4, 20.0], + ], + columns=IAMC_IDX + ["year", "original", "aggregated", "difference (%)"], + ) + assert_frame_equal( + pd.read_excel(tmp_path / "differences.xlsx"), exp_difference, check_dtype=False + ) + + # Check aggregation result + exp_result = IamDataFrame( + pd.DataFrame( + [["m_a", "s_a", "World", "Primary Energy", "EJ/yr", 5, 6]], + columns=IAMC_IDX + [2005, 2010], + ) + ) + assert_iamframe_equal(IamDataFrame(tmp_path / "results.xlsx"), exp_result) From a1ef4524ac1432c9f97adcd013fdbb3768bbe3e6 Mon Sep 17 00:00:00 2001 From: Philip Hackstock <20710924+phackstock@users.noreply.github.com> Date: Thu, 18 Jan 2024 12:07:15 +0100 Subject: [PATCH 04/18] Add classmethod decorator --- nomenclature/codelist.py | 1 + 1 file changed, 1 insertion(+) diff --git a/nomenclature/codelist.py b/nomenclature/codelist.py index f4b00cd3..d54700ed 100644 --- a/nomenclature/codelist.py +++ b/nomenclature/codelist.py @@ -54,6 +54,7 @@ def check_stray_tag(cls, v: Dict[str, Code]) -> Dict[str, Code]: return v @field_validator("mapping") + @classmethod def check_end_whitespace( cls, v: Dict[str, Code], info: ValidationInfo ) -> Dict[str, Code]: From 77b7bcd89e23475d7730819285ae33f67a543ede Mon Sep 17 00:00:00 2001 From: Philip Hackstock <20710924+phackstock@users.noreply.github.com> Date: Thu, 18 Jan 2024 12:07:30 +0100 Subject: [PATCH 05/18] Add two checks for setting CodeList items --- nomenclature/codelist.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/nomenclature/codelist.py b/nomenclature/codelist.py index d54700ed..37da4965 100644 --- a/nomenclature/codelist.py +++ b/nomenclature/codelist.py @@ -67,9 +67,13 @@ def check_end_whitespace( ) return v - def __setitem__(self, key, value): + def __setitem__(self, key: str, value: Code) -> None: if key in self.mapping: raise ValueError(f"Duplicate item in {self.name} codelist: {key}") + if not isinstance(value, Code): + raise TypeError("Codelist can only contain Code items") + if key != value.name: + raise ValueError("Key has to be equal to code name") self.mapping[key] = value def __getitem__(self, k): From fa86de75c61e9489ab029549f55e59b0cb8c6d25 Mon Sep 17 00:00:00 2001 From: Philip Hackstock <20710924+phackstock@users.noreply.github.com> Date: Thu, 18 Jan 2024 12:08:02 +0100 Subject: [PATCH 06/18] Validate default value for local_path --- nomenclature/config.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/nomenclature/config.py b/nomenclature/config.py index 8295a835..fa7d94a1 100644 --- a/nomenclature/config.py +++ b/nomenclature/config.py @@ -3,7 +3,7 @@ import yaml from git import Repo -from pydantic import BaseModel, ValidationInfo, field_validator, model_validator +from pydantic import BaseModel, Field, ValidationInfo, field_validator, model_validator class CodeListConfig(BaseModel): @@ -27,9 +27,8 @@ class Repository(BaseModel): url: str hash: str | None = None release: str | None = None - local_path: Path | None = ( - None # defined via the `repository` name in the configuration - ) + local_path: Path | None = Field(default=None, validate_default=True) + # defined via the `repository` name in the configuration @model_validator(mode="after") @classmethod From 25d51ce97977bb55c76cf10a1310d5cdeee7cdfd Mon Sep 17 00:00:00 2001 From: Philip Hackstock <20710924+phackstock@users.noreply.github.com> Date: Thu, 18 Jan 2024 12:08:23 +0100 Subject: [PATCH 07/18] Remove unnecessary check --- nomenclature/config.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/nomenclature/config.py b/nomenclature/config.py index fa7d94a1..92aea787 100644 --- a/nomenclature/config.py +++ b/nomenclature/config.py @@ -109,14 +109,6 @@ def check_definitions_repository( definitions_repos = v.definitions.repos if v.definitions else {} mapping_repos = {"mappings": v.mappings.repository} if v.mappings else {} repos = {**definitions_repos, **mapping_repos} - if repos and not v.repositories: - raise ValueError( - ( - "If repositories are used for definitions or mappings, they need " - "to be defined under `repositories`" - ) - ) - for use, repository in repos.items(): if repository not in v.repositories: raise ValueError((f"Unknown repository '{repository}' in {use}.")) From 783077a5532427f0d136a7ead2a1c3145b82b850 Mon Sep 17 00:00:00 2001 From: Philip Hackstock <20710924+phackstock@users.noreply.github.com> Date: Thu, 18 Jan 2024 12:09:20 +0100 Subject: [PATCH 08/18] Raise NotImplementedError --- nomenclature/processor/processor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nomenclature/processor/processor.py b/nomenclature/processor/processor.py index 92267327..ac3cfb1f 100644 --- a/nomenclature/processor/processor.py +++ b/nomenclature/processor/processor.py @@ -7,4 +7,4 @@ class Processor(BaseModel, abc.ABC): @abc.abstractmethod def apply(self, df: IamDataFrame) -> IamDataFrame: - return + raise NotImplementedError From 27d3d60c778f705c2416d0b7c56f6cf8c0435df5 Mon Sep 17 00:00:00 2001 From: Philip Hackstock <20710924+phackstock@users.noreply.github.com> Date: Thu, 18 Jan 2024 12:09:33 +0100 Subject: [PATCH 09/18] Remove unused equality operators --- nomenclature/processor/region.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/nomenclature/processor/region.py b/nomenclature/processor/region.py index 10d0c61a..fe9ea14a 100644 --- a/nomenclature/processor/region.py +++ b/nomenclature/processor/region.py @@ -61,9 +61,6 @@ def target_native_region(self) -> str: """ return self.rename if self.rename is not None else self.name - def __eq__(self, other: "NativeRegion") -> bool: - return super().__eq__(other) - class CommonRegion(BaseModel): """Common region used for model intercomparison. @@ -92,9 +89,6 @@ def rename_dict(self): "rename_dict is only available for single constituent regions" ) - def __eq__(self, other: "CommonRegion") -> bool: - return super().__eq__(other) - class RegionAggregationMapping(BaseModel): """Hold information for region processing on a per-model basis. From 385ae0a69c1d21ed2b4e8aa603f738f92e52a55c Mon Sep 17 00:00:00 2001 From: Philip Hackstock <20710924+phackstock@users.noreply.github.com> Date: Thu, 18 Jan 2024 12:09:49 +0100 Subject: [PATCH 10/18] Refine dict representation --- nomenclature/processor/region.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/nomenclature/processor/region.py b/nomenclature/processor/region.py index fe9ea14a..a8502786 100644 --- a/nomenclature/processor/region.py +++ b/nomenclature/processor/region.py @@ -407,7 +407,9 @@ def __eq__(self, other: "RegionAggregationMapping") -> bool: return self.model_dump(exclude={"file"}) == other.model_dump(exclude={"file"}) def to_yaml(self, file) -> None: - dict_representation = {"model": self.model} + dict_representation = { + "model": self.model[0] if len(self.model) == 1 else self.model + } if self.native_regions: dict_representation["native_regions"] = [ {native_region.name: native_region.rename} From a17f3fbaf9911d74d2d6c8b8f4319e8067d9d707 Mon Sep 17 00:00:00 2001 From: Philip Hackstock <20710924+phackstock@users.noreply.github.com> Date: Thu, 18 Jan 2024 12:10:06 +0100 Subject: [PATCH 11/18] Adjust after cli changes --- nomenclature/testing.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/nomenclature/testing.py b/nomenclature/testing.py index 66fc2b83..28069981 100644 --- a/nomenclature/testing.py +++ b/nomenclature/testing.py @@ -132,10 +132,7 @@ def assert_valid_structure( f"Definitions directory not found: {path / definitions}" ) - if dimensions == []: # if "dimensions" were specified as "[]" - raise ValueError("No dimensions to validate.") - - if dimensions is None: # if "dimensions" were not specified + if dimensions == (): # if "dimensions" were not specified dimensions = [x.stem for x in (path / definitions).iterdir() if x.is_dir()] if not dimensions: raise FileNotFoundError( From 412b09761696311244def5ef81c02317d310a6b1 Mon Sep 17 00:00:00 2001 From: Philip Hackstock <20710924+phackstock@users.noreply.github.com> Date: Thu, 18 Jan 2024 12:10:21 +0100 Subject: [PATCH 12/18] Add explicit config tests --- tests/test_config.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 tests/test_config.py diff --git a/tests/test_config.py b/tests/test_config.py new file mode 100644 index 00000000..3e72cb72 --- /dev/null +++ b/tests/test_config.py @@ -0,0 +1,25 @@ +from pathlib import Path +from pytest import raises + +from nomenclature.config import Repository, NomenclatureConfig + +from conftest import TEST_DATA_DIR + + +def test_hash_and_release_raises(): + with raises(ValueError, match="`hash` or `release` can be provided, not both"): + NomenclatureConfig.from_file( + TEST_DATA_DIR / "nomenclature_configs" / "hash_and_release.yaml" + ) + + +def test_setting_local_path_raises(): + with raises(ValueError, match="`local_path` must not be set"): + Repository(local_path=Path(".")) + + +def test_unknown_repo_raises(): + with raises(ValueError, match="Unknown repository 'common-definitions'"): + NomenclatureConfig.from_file( + TEST_DATA_DIR / "nomenclature_configs" / "unknown_repo.yaml" + ) From b813a55ba4d1fec42b85987ce1c6821fe1da6f94 Mon Sep 17 00:00:00 2001 From: Philip Hackstock <20710924+phackstock@users.noreply.github.com> Date: Thu, 18 Jan 2024 12:10:37 +0100 Subject: [PATCH 13/18] Change pytest raise import --- tests/test_code.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/tests/test_code.py b/tests/test_code.py index 2f2ee44c..d9ccb15e 100644 --- a/tests/test_code.py +++ b/tests/test_code.py @@ -1,10 +1,11 @@ import pytest +from pytest import raises from nomenclature.code import Code, VariableCode, RegionCode, MetaCode def test_variable_without_unit_raises(): - with pytest.raises(ValueError, match="unit\n.*required"): + with raises(ValueError, match="unit\n.*required"): VariableCode(name="No unit") @@ -26,7 +27,7 @@ def test_variable_alias_setting(): @pytest.mark.parametrize("illegal_key", ["contains-hyphen", "also not allowed", "True"]) def test_illegal_additional_attribute(illegal_key): match = f"{illegal_key}.*'code1'.*not allowed" - with pytest.raises(ValueError, match=match): + with raises(ValueError, match=match): Code(name="code1", extra_attributes={illegal_key: True}) @@ -161,7 +162,7 @@ def test_RegionCode_iso3_code_list_fail(): "IBL, ITL, LIC, MLA, BEG, FRT, ANB, GDR, LXB, MNO, NTD, NRW, PRE, EPA, " # noqa "SWD, CEW, GTR, SOR" # noqa ) - with pytest.raises(ValueError, match=error_pattern): + with raises(ValueError, match=error_pattern): RegionCode(name="Western Europe", hierarchy="R5OECD", iso3_codes=iso3_codes) @@ -171,7 +172,7 @@ def test_RegionCode_iso3_code_str_fail(): "iso3_codes\n" " Value error, Region 'Austria' has invalid ISO3 country code\(s\): AUTT" ) - with pytest.raises(ValueError, match=error_pattern): + with raises(ValueError, match=error_pattern): RegionCode(name="Austria", hierarchy="country", iso3_codes="AUTT") From be2d7ffe5ff4abc71272a3fd228516dab8ebcea9 Mon Sep 17 00:00:00 2001 From: Philip Hackstock <20710924+phackstock@users.noreply.github.com> Date: Thu, 18 Jan 2024 12:10:49 +0100 Subject: [PATCH 14/18] Add two explicit Code tests --- tests/test_code.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/test_code.py b/tests/test_code.py index d9ccb15e..c228c5e1 100644 --- a/tests/test_code.py +++ b/tests/test_code.py @@ -183,3 +183,13 @@ def test_MetaCode_allowed_values_attribute(): ) assert meta.allowed_values == [True] + + +def test_code_with_multi_key_dict_raises(): + with raises(ValueError, match="Code is not a single name-attributes mapping"): + Code.from_dict({"name": "", "illegal second key": ""}) + + +def test_code_with_definition_and_description_raises(): + with raises(ValueError, match="Found both 'definition' and 'description'"): + Code.from_dict({"Code": {"definition": "", "description": ""}}) From 0d4ad620506f4530822303b49d388db04233c361 Mon Sep 17 00:00:00 2001 From: Philip Hackstock <20710924+phackstock@users.noreply.github.com> Date: Thu, 18 Jan 2024 12:11:37 +0100 Subject: [PATCH 15/18] Add CodeList tests --- tests/test_codelist.py | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/tests/test_codelist.py b/tests/test_codelist.py index bdc6767b..4fd0a5c0 100644 --- a/tests/test_codelist.py +++ b/tests/test_codelist.py @@ -1,9 +1,9 @@ -import pytest +from pytest import raises import pandas as pd import pandas.testing as pdt import logging -from nomenclature.code import Code, RegionCode, MetaCode +from nomenclature.code import Code, RegionCode, MetaCode, VariableCode from nomenclature.codelist import ( CodeList, VariableCodeList, @@ -25,6 +25,28 @@ def test_simple_codelist(): assert type(codelist["Some Variable"].bool) == bool # this is a boolean +def test_codelist_adding_duplicate_raises(): + codelist = VariableCodeList.from_directory( + "variable", TEST_DATA_DIR / "simple_codelist" + ) + with raises(ValueError, match="Duplicate item in variable codelist: Some Variable"): + codelist["Some Variable"] = "" + + +def test_codelist_adding_non_code_raises(): + codelist = CodeList(name="test") + + with raises(TypeError, match="Codelist can only contain Code items"): + codelist["Some Variable"] = "" + + +def test_codelist_name_key_mismatch(): + codelist = CodeList(name="test") + + with raises(ValueError, match="Key has to be equal to code name"): + codelist["Some Variable"] = Code(name="Some other variable") + + def test_codelist_to_yaml(): """Cast a codelist to yaml format""" code = VariableCodeList.from_directory( @@ -44,7 +66,7 @@ def test_codelist_to_yaml(): def test_duplicate_code_raises(): """Check that code conflicts across different files raises""" match = "Duplicate item in variable codelist: Some Variable" - with pytest.raises(ValueError, match=match): + with raises(ValueError, match=match): VariableCodeList.from_directory( "variable", TEST_DATA_DIR / "duplicate_code_raises" ) @@ -53,7 +75,7 @@ def test_duplicate_code_raises(): def test_duplicate_tag_raises(): """Check that code conflicts across different files raises""" match = "Duplicate item in tag codelist: Tag" - with pytest.raises(ValueError, match=match): + with raises(ValueError, match=match): VariableCodeList.from_directory( "variable", TEST_DATA_DIR / "duplicate_tag_raises" ) @@ -138,7 +160,7 @@ def test_stray_tag_fails(): """Check that typos in a tag raises expected error""" match = r"Unexpected {} in codelist: Primary Energy\|{Feul}" - with pytest.raises(ValueError, match=match): + with raises(ValueError, match=match): VariableCodeList.from_directory( "variable", TEST_DATA_DIR / "stray_tag" / "definitions" / "variable" ) @@ -148,7 +170,7 @@ def test_end_whitespace_fails(): """Check that typos in a tag raises expected error""" match = "Unexpected whitespace at the end of a scenario code: 'scenario2 '" - with pytest.raises(ValueError, match=match): + with raises(ValueError, match=match): CodeList.from_directory( "scenario", TEST_DATA_DIR / "end_whitespace" / "definitions" / "scenario" ) From 89af10a32d4ba10f9ba7bb091fee5d01d6370d87 Mon Sep 17 00:00:00 2001 From: Philip Hackstock <20710924+phackstock@users.noreply.github.com> Date: Thu, 18 Jan 2024 12:11:48 +0100 Subject: [PATCH 16/18] Config test data --- .../data/nomenclature_configs/hash_and_release.yaml | 12 ++++++++++++ tests/data/nomenclature_configs/unknown_repo.yaml | 3 +++ 2 files changed, 15 insertions(+) create mode 100644 tests/data/nomenclature_configs/hash_and_release.yaml create mode 100644 tests/data/nomenclature_configs/unknown_repo.yaml diff --git a/tests/data/nomenclature_configs/hash_and_release.yaml b/tests/data/nomenclature_configs/hash_and_release.yaml new file mode 100644 index 00000000..8e8a0fe5 --- /dev/null +++ b/tests/data/nomenclature_configs/hash_and_release.yaml @@ -0,0 +1,12 @@ +repositories: + common-definitions: + url: https://github.com/IAMconsortium/common-definitions.git/ + hash: asdf + release: "1.0" +definitions: + region: + repository: common-definitions + country: true + variable: + repository: common-definitions + repository_dimension_path: definitions/variable diff --git a/tests/data/nomenclature_configs/unknown_repo.yaml b/tests/data/nomenclature_configs/unknown_repo.yaml new file mode 100644 index 00000000..08187c7a --- /dev/null +++ b/tests/data/nomenclature_configs/unknown_repo.yaml @@ -0,0 +1,3 @@ +definitions: + region: + repository: common-definitions From 19c8591e7981d37847bacc94a42550d61de255ea Mon Sep 17 00:00:00 2001 From: Philip Hackstock <20710924+phackstock@users.noreply.github.com> Date: Thu, 18 Jan 2024 12:12:00 +0100 Subject: [PATCH 17/18] Add explicit model registration parser test --- .../model-registration-template.xlsx | Bin 0 -> 25941 bytes tests/test_model_registration_parser.py | 28 ++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 tests/data/model_registration/model-registration-template.xlsx create mode 100644 tests/test_model_registration_parser.py diff --git a/tests/data/model_registration/model-registration-template.xlsx b/tests/data/model_registration/model-registration-template.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..d3a95d3355690b093f76e7a5cc3ad1c7373d89af GIT binary patch literal 25941 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

-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 Date: Mon, 22 Jan 2024 13:04:26 +0100 Subject: [PATCH 18/18] Apply suggestions from code review Co-authored-by: Daniel Huppmann --- nomenclature/__init__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/nomenclature/__init__.py b/nomenclature/__init__.py index 8815d58f..4733c50d 100644 --- a/nomenclature/__init__.py +++ b/nomenclature/__init__.py @@ -57,7 +57,8 @@ def parse_model_registration( model_registration_file : str, path, file-like object Path to xlsx model registration file. output_directory : str, path, file-like object - Directory, where the model mapping and region file will be saved; default: "." + Directory where the model mapping and region file will be saved; + defaults to current working directory """ if not isinstance(output_directory, Path): output_directory = Path(output_directory)