diff --git a/configargparse.py b/configargparse.py index 01cb589..6d843b4 100644 --- a/configargparse.py +++ b/configargparse.py @@ -1472,17 +1472,15 @@ def convert_item_to_command_line_arg(self, action, key, value): "'false', 'yes', 'no', 'on', 'off', '1' or '0'" % (key, value) ) elif isinstance(value, list): - accepts_list_and_has_nargs = ( - action is not None - and action.nargs is not None - and ( - isinstance(action, argparse._StoreAction) - or isinstance(action, argparse._AppendAction) - ) - and ( - action.nargs in ("+", "*") - or (isinstance(action.nargs, int) and action.nargs > 1) - ) + # Only nargs is relevant here: any action, including a custom + # argparse.Action subclass, consumes several values when nargs + # allows it. Testing the action class as well would be redundant, + # since actions that cannot consume a list have an nargs that + # fails the test below anyway: 0 or None for store_const, count + # and friends, 'A...' for subparsers, '...' for REMAINDER. + accepts_list_and_has_nargs = action is not None and ( + action.nargs in ("+", "*") + or (isinstance(action.nargs, int) and action.nargs > 1) ) if action is None or isinstance(action, argparse._AppendAction): diff --git a/tests/test_configargparse.py b/tests/test_configargparse.py index b6ec6be..291c392 100644 --- a/tests/test_configargparse.py +++ b/tests/test_configargparse.py @@ -430,6 +430,32 @@ def testPositionalAndConfigVarLists(self): self.assertEqual(ns.arg, ["Shell", "someword", "anotherword"]) self.assertEqual(ns.a, "positional_value") + def testCustomActionWithNargsAndConfigVarList(self): + # https://github.com/bw2/ConfigArgParse/issues/354 + class CustomAction(configargparse.Action): + def __call__(self, parser, namespace, values, option_string=None): + setattr(namespace, self.dest, values) + + self.initParser() + self.add_arg("-x", "--arg", nargs="+", action=CustomAction) + + ns = self.parse("", config_file_contents="""arg = [foo, bar]""") + self.assertEqual(ns.arg, ["foo", "bar"]) + + def testCustomActionWithoutNargsAndConfigVarList(self): + class CustomAction(configargparse.Action): + def __call__(self, parser, namespace, values, option_string=None): + setattr(namespace, self.dest, values) + + self.initParser() + self.add_arg("-x", "--arg", action=CustomAction) + + self.assertParseArgsRaises( + "arg can't be set to a list", + args="", + config_file_contents="""arg = [foo, bar]""", + ) + def testMutuallyExclusiveArgs(self): config_file = tempfile.NamedTemporaryFile(mode="w", delete=False)