diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 87a789b1..b6bc59b0 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -24,6 +24,8 @@ Fixed `__). - Optional callable that returns a class instance with a lambda default, produces an invalid string default. +- dataclass single parameter change incorrectly resetting previous values (`#464 + `__). v4.27.5 (2024-02-12) diff --git a/jsonargparse/_typehints.py b/jsonargparse/_typehints.py index eb6f050c..67ec5eb6 100644 --- a/jsonargparse/_typehints.py +++ b/jsonargparse/_typehints.py @@ -863,7 +863,8 @@ def adapt_typehints( elif isinstance(val, (dict, Namespace)): val = parser.parse_object(val, defaults=sub_defaults.get() or list_item) elif isinstance(val, NestedArg): - val = parser.parse_args([f"--{val.key}={val.val}"]) + prev_val = prev_val if isinstance(prev_val, Namespace) else None + val = parser.parse_args([f"--{val.key}={val.val}"], namespace=prev_val) else: raise_unexpected_value(f"Type {typehint} expects a dict or Namespace", val) diff --git a/jsonargparse_tests/test_dataclass_like.py b/jsonargparse_tests/test_dataclass_like.py index df8b4318..0402eee8 100644 --- a/jsonargparse_tests/test_dataclass_like.py +++ b/jsonargparse_tests/test_dataclass_like.py @@ -8,6 +8,7 @@ import yaml from jsonargparse import ( + ActionConfigFile, ArgumentError, ArgumentParser, Namespace, @@ -359,6 +360,20 @@ def test_optional_dataclass_type_null_value(): assert cfg == parser_optional_data.instantiate_classes(cfg) +@dataclasses.dataclass +class SingleParamChange: + p1: int = 0 + p2: int = 0 + + +def test_optional_dataclass_single_param_change(parser): + parser.add_argument("--config", action=ActionConfigFile) + parser.add_argument("--data", type=Optional[SingleParamChange]) + config = {"data": {"p1": 1}} + cfg = parser.parse_args([f"--config={config}", "--data.p2=2"]) + assert cfg.data == Namespace(p1=1, p2=2) + + @dataclasses.dataclass class ModelConfig: data: Optional[Dict[str, Any]] = None