diff --git a/metagpt/config2.py b/metagpt/config2.py index 6b6f4935b..243a98078 100644 --- a/metagpt/config2.py +++ b/metagpt/config2.py @@ -156,21 +156,21 @@ def merge_dict(dicts: Iterable[Dict]) -> Dict: class ConfigMixin(BaseModel): """Mixin class for configurable objects""" - _config: Optional[Config] = None + config: Optional[Config] = None - def __init__(self, config: Optional[Config] = None): - super().__init__() - self._config = config + def __init__(self, config: Optional[Config] = None, **kwargs): + """Initialize with config""" + super().__init__(**kwargs) + self.set_config(config) - def try_set_parent_config(self, parent_config): + def set(self, k, v, override=False): """Try to set parent config if not set""" - if self._config is None: - self._config = parent_config + if override or not self.__dict__.get(k): + self.__dict__[k] = v - @property - def config(self): - """Get config""" - return self._config + def set_config(self, config: Config, override=False): + """Set config""" + self.set("config", config, override) config = Config.default() diff --git a/tests/metagpt/test_config.py b/tests/metagpt/test_config.py index 5492d1726..81673fc65 100644 --- a/tests/metagpt/test_config.py +++ b/tests/metagpt/test_config.py @@ -29,27 +29,56 @@ def test_config_from_dict(): assert cfg.llm["default"].api_key == "mock_api_key" -class NewModel(ConfigMixin, BaseModel): +class ModelX(ConfigMixin, BaseModel): a: str = "a" b: str = "b" +class WTFMixin(BaseModel): + c: str = "c" + d: str = "d" + + def __init__(self, **data): + super().__init__(**data) + + +class ModelY(WTFMixin, ModelX): + def __init__(self, **data): + super().__init__(**data) + + def test_config_mixin_1(): - new_model = NewModel() + new_model = ModelX() assert new_model.a == "a" assert new_model.b == "b" - assert new_model._config == new_model.config - assert new_model._config is None def test_config_mixin_2(): i = Config(llm={"default": mock_llm_config}) j = Config(llm={"new": mock_llm_config}) - obj = NewModel(config=i) + obj = ModelX(config=i) assert obj.config == i - assert obj._config == i assert obj.config.llm["default"] == mock_llm_config - obj.try_set_parent_config(j) + obj.set_config(j) # obj already has a config, so it will not be set assert obj.config == i + + +def test_config_mixin_3(): + """Test config mixin with multiple inheritance""" + i = Config(llm={"default": mock_llm_config}) + j = Config(llm={"new": mock_llm_config}) + obj = ModelY(config=i) + assert obj.config == i + assert obj.config.llm["default"] == mock_llm_config + + obj.set_config(j) + # obj already has a config, so it will not be set + assert obj.config == i + assert obj.config.llm["default"] == mock_llm_config + + assert obj.a == "a" + assert obj.b == "b" + assert obj.c == "c" + assert obj.d == "d"