diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 440bff1e..8c41fe53 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -30,6 +30,8 @@ Fixed - Incorrect replacement of ``**kwargs`` when ``*args`` present in parameter resolver. - Override of ``class_path`` not discarding ``init_args`` when loading from config file. +- Invalid values given to the ``compute_fn`` of a argument link applied on parse + without showing an understandable error message. Changed ^^^^^^^ diff --git a/jsonargparse/link_arguments.py b/jsonargparse/link_arguments.py index ddd802d8..67d47fd4 100644 --- a/jsonargparse/link_arguments.py +++ b/jsonargparse/link_arguments.py @@ -5,7 +5,7 @@ from argparse import Action, SUPPRESS from collections import defaultdict from typing import Any, Callable, List, Optional, Tuple, Type, Union -from .actions import _ActionConfigLoad, _ActionSubCommands, ActionConfigFile, filter_default_actions, _find_parent_action +from .actions import _ActionConfigLoad, _ActionSubCommands, ActionConfigFile, filter_default_actions, _find_action, _find_parent_action from .namespace import Namespace, split_key_leaf from .type_checking import ArgumentParser, _ArgumentGroup @@ -207,6 +207,7 @@ def apply_parsing_links(parser: 'ArgumentParser', cfg: Namespace) -> None: for source_key, source_action in action.source: if ActionTypeHint.is_subclass_typehint(source_action[0]) and source_key not in cfg: parser.logger.debug(f'Link {action.option_strings[0]} ignored since source {source_action[0]._typehint} does not have that parameter.') + parser._check_value_key(source_action[0], cfg[source_action[0].dest], source_action[0].dest, None) args.append(cfg[source_key]) except KeyError: continue diff --git a/jsonargparse_tests/test_link_arguments.py b/jsonargparse_tests/test_link_arguments.py index f853b1e0..e78ae650 100755 --- a/jsonargparse_tests/test_link_arguments.py +++ b/jsonargparse_tests/test_link_arguments.py @@ -37,6 +37,23 @@ def a_prod(a): self.assertEqual(dump, {'a': {'v1': 2, 'v2': -5}}) + def test_link_arguments_on_parse_invalid_compute_fn_arg(self): + parser = ArgumentParser(error_handler=None) + parser.add_argument('--cal1', type=Calendar, default=lazy_instance(TextCalendar)) + parser.add_argument('--cal2', type=Calendar, default=lazy_instance(Calendar)) + parser.link_arguments( + 'cal1', + 'cal2.init_args.firstweekday', + compute_fn=lambda c: c.init_args.firstweekday+1, + ) + cfg = parser.parse_args(['--cal1.init_args.firstweekday=2']) + self.assertEqual(cfg.cal1.init_args.firstweekday, 2) + self.assertEqual(cfg.cal2.init_args.firstweekday, 3) + with self.assertRaises(ParserError) as cm: + parser.parse_args(['--cal1.class_path.init_args.firstweekday=2']) + self.assertIn('Parser key "cal1"', str(cm.exception)) + + def test_link_arguments_on_parse_add_class_arguments(self): class ClassA: def __init__(self, v1: int = 2, v2: int = 3):