diff --git a/CHANGELOG.rst b/CHANGELOG.rst index dd0ae753..27c02935 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -26,6 +26,8 @@ Fixed `__). - Union of dataclasses not discarding parameters on class change (`#833 `__). +- Targets of links applied on parse not being instantiated (`#834 + `__). v4.45.0 (2025-12-26) diff --git a/jsonargparse/_core.py b/jsonargparse/_core.py index e813e83c..94327451 100644 --- a/jsonargparse/_core.py +++ b/jsonargparse/_core.py @@ -1223,6 +1223,8 @@ def instantiate_classes( for action in filter_non_parsing_actions(self._actions): if isinstance(action, ActionTypeHint): components.append(action) + elif isinstance(action, ActionLink) and isinstance(action.target[1], ActionTypeHint): + components.append(action.target[1]) if instantiate_groups: skip = {c.dest for c in components} diff --git a/jsonargparse_tests/test_link_arguments.py b/jsonargparse_tests/test_link_arguments.py index ee2b7e60..b9111b2e 100644 --- a/jsonargparse_tests/test_link_arguments.py +++ b/jsonargparse_tests/test_link_arguments.py @@ -492,6 +492,47 @@ def test_on_parse_type_skip_link_targets_dump(parser): assert dump["t2"] == f"{__name__}.Model" +class Field: + def __init__(self, name: str): + self.name = name + + +class Data: + def __init__(self, param: int = 0, fields: List[Field] = []): + self.fields = fields + + +def test_on_parse_list_of_instances_target(parser): + parser.add_class_arguments(Model, "model") + parser.add_class_arguments(Data, "data") + + def link_model_to_data_fields(model): + return [ + { + "class_path": f"{__name__}.Field", + "init_args": {"name": "f1"}, + }, + { + "class_path": f"{__name__}.Field", + "init_args": {"name": "f2"}, + }, + ] + + parser.link_arguments("model", "data.fields", compute_fn=link_model_to_data_fields, apply_on="parse") + + cfg = parser.parse_args(["--model.label=test"]) + assert cfg.data.fields == [ + Namespace(class_path=f"{__name__}.Field", init_args=Namespace(name="f1")), + Namespace(class_path=f"{__name__}.Field", init_args=Namespace(name="f2")), + ] + + init = parser.instantiate_classes(cfg) + assert isinstance(init.data.fields, list) + assert len(init.data.fields) == 2 + assert all(isinstance(f, Field) for f in init.data.fields) + assert [f.name for f in init.data.fields] == ["f1", "f2"] + + # tests for links applied on instantiate