Source code for message_ix_models.tests.util.test_config

from dataclasses import dataclass, field
from typing import Type

import pytest

from message_ix_models.util.config import ConfigHelper


[docs]class TestConfigHelper:
[docs] @pytest.fixture def cls(self) -> Type: """A class which inherits from ConfigHelper.""" @dataclass class Config(ConfigHelper): foo_1: int = 1 foo_2: str = "" foo_3: bool = True return Config
[docs] @pytest.fixture def cls2(self, cls) -> Type: """A class with an attribute.""" @dataclass class Config3: """NOT a ConfigHelper subclass.""" baz_1: int = 1 baz_2: int = 2 @dataclass class Config2(ConfigHelper): bar_1: float = 0.01 subconfig_a: cls = field(default_factory=cls) # type: ignore [valid-type] subconfig_b: Config3 = field(default_factory=Config3) return Config2
@pytest.fixture def c(self, cls): return cls(foo_1=99, foo_2="bar", foo_3=False) @pytest.fixture def c2(self, cls, cls2): result = cls2(bar_1=3.14, subconfig_a=cls(foo_1=99, foo_2="bar", foo_3=False)) result.subconfig_b.baz_1 = 2 result.subconfig_b.baz_2 = 1 return result def test_canonical_name(self, cls): assert "foo_1" == cls._canonical_name("foo 1") assert "foo_2" == cls._canonical_name("foo-2") assert "foo_3" == cls._canonical_name("foo_3") assert None is cls._canonical_name("foo 4") def test_from_dict(self, cls, c): values = {"foo 1": 99, "foo-2": "bar", "foo_3": False} assert c == cls.from_dict({"foo 1": 99, "foo-2": "bar", "foo_3": False}) values.update(foo_4=3.14) with pytest.raises(ValueError): cls.from_dict(values) def test_read_file(self, caplog, tmp_path, cls, cls2, c, c2): # Write a YAML snippet to file yaml_path = tmp_path.joinpath("config.yaml") yaml_path.write_text( """ foo 1: 99 foo-2: bar foo_3: false foo_4: 3.14 """ ) obj1 = cls() # Method runs obj1.read_file(yaml_path, fail=False) # Values are read assert c == obj1, obj1 # Messages are logged assert [ "Config has no attribute for file section 'foo_4'; ignored" ] == caplog.messages caplog.clear() yaml_path.write_text( """ bar_1: 3.14 subconfig a: foo 1: 99 foo-2: bar foo_3: false subconfig-b: # No name manipulation for subkeys here baz_1: 2 baz_2: 1 """ ) obj2 = cls2() # Method runs obj2.read_file(yaml_path, fail=False) # Values are read assert c2 == obj2, obj2 json_path = tmp_path.joinpath("config.json") json_path.write_text( """{ "foo 1": 99, "foo-2": "bar", "foo_3": false } """ ) obj3 = cls() # Method runs obj3.read_file(json_path) # Values are read assert c == obj3, obj3 obj4 = cls() with pytest.raises(NotImplementedError): obj4.read_file(yaml_path.with_suffix(".xlsx")) def test_replace(self, c): result = c.replace(foo_2="baz") assert result is not c assert "baz" == result.foo_2
[docs] def test_update(self, c): """:meth:`.ConfigHelper.update` raises AttributeError.""" with pytest.raises(AttributeError): c.update(foo_4="")