diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 1fc5056b..279ca941 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -21,6 +21,8 @@ Fixed - ``adapt_class_type`` used a locally defined `partial_instance` wrapper function that is not pickleable (`#728 `__). +- ArgumentParser with dashes incorrectly resolves paths to default values (`#736 + `__). v4.40.0 (2025-05-16) diff --git a/jsonargparse/_core.py b/jsonargparse/_core.py index 0dcc3b29..2c92ef16 100644 --- a/jsonargparse/_core.py +++ b/jsonargparse/_core.py @@ -201,6 +201,7 @@ def set_defaults(self, *args: Dict[str, Any], **kwargs: Any) -> None: """ for arg in args: for dest, default in arg.items(): + dest = dest.replace("-", "_") action = _find_action(self, dest) if action is None: raise NSKeyError(f'No action for key "{dest}" to set its default.') @@ -458,7 +459,7 @@ def parse_args( # type: ignore[override] cfg, unk = self.parse_known_args(args=args, namespace=cfg) cfg, unk = self._positional_optionals(cfg, unk) if unk: - self.error(f'Unrecognized arguments: {" ".join(unk)}') + self.error(f"Unrecognized arguments: {' '.join(unk)}") parsed_cfg = self._parse_common( cfg=cfg, diff --git a/jsonargparse_tests/test_dataclass_like.py b/jsonargparse_tests/test_dataclass_like.py index e8fdf548..6ee90059 100644 --- a/jsonargparse_tests/test_dataclass_like.py +++ b/jsonargparse_tests/test_dataclass_like.py @@ -116,6 +116,16 @@ class NestedDefaultsB: a: List[NestedDefaultsA] +@dataclasses.dataclass +class NestedDefaultsC: + field_with_dash: int = 5 + + +@dataclasses.dataclass +class NestedDefaultsD: + c_with_dash: NestedDefaultsC = dataclasses.field(default_factory=NestedDefaultsC) + + def test_add_dataclass_nested_defaults(parser): parser.add_class_arguments(NestedDefaultsB, "data") cfg = parser.parse_args(["--data.a=[{}]"]) @@ -989,6 +999,18 @@ def test_nested_dict(self, parser): assert isinstance(init.model, PydanticNestedDict) assert isinstance(init.model.nested["key"], NestedModel) + def test_dashes_in_nested_dataclass(self): + class UnderscoresToDashesParser(ArgumentParser): + def add_argument(self, *args, **kwargs): + args = [arg.replace("_", "-") for arg in args] + return super().add_argument(*args, **kwargs) + + parser = UnderscoresToDashesParser(parse_as_dict=False, default_env=True) + parser.add_class_arguments(NestedDefaultsD) + ns = parser.parse_args([]) + cfg = parser.instantiate_classes(ns) + assert cfg.c_with_dash.field_with_dash == 5 + # attrs tests