defopt icon indicating copy to clipboard operation
defopt copied to clipboard

feature request: defopt.run add append option

Open ickc opened this issue 3 years ago • 5 comments

See https://docs.python.org/3/library/argparse.html#action:

'append' - This stores a list, and appends each argument value to the list. This is useful to allow an option to be specified multiple times. Example usage:

>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--foo', action='append')
>>> parser.parse_args('--foo 1 --foo 2'.split())
Namespace(foo=['1', '2'])

This feature request is to add an option to defopt.run s.t. parser.add_argument(..., action='append') behavior can be toggled.

ickc avatar Dec 03 '21 03:12 ickc

This and #96 both seem reasonable to me, but adding a global option to defopt.run seems unsatisfying because sooner or later someone will request to be able to specify this only for some of the parameters, perhaps in some deeply nested subcommands hierarchy on top of that...

Off the top of my head, a possibly(?) better solution could be to exploit typing.Annotated here, e.g. Annotated[list[int], defopt.APPEND] here and Annotated[list[int], defopt.VARARGS] for #96. (Note that for the case here, the underlying type annotation should be list[int], not int, because that's what the type of foo would ultimately be in the program.) A PR would be welcome :-) It should also clarify how these options interact with cli_options, as introduced by #92 (which is generalizing strict_kwonly).

anntzer avatar Dec 05 '21 14:12 anntzer

I wonder if it makes more sense to use the annotated method as suggested here or to provide a dictionary to defopt.run to indicate non-default behavior for certain parameters. This would be similar to how alternative parsers are provided as well as custom short cli arguments. It would also stick with the defopt philosophy of not changing the cli function itself, even if the Annotated solution is only in the type hint.

One potentially tricky issue to the dictionary method I've suggested is if the same argument could be passed to multiple commands with different behavior.

Spectre5 avatar Jan 22 '22 07:01 Spectre5

My preference would be to use Annotated. I agree with your point about not changing the CLI function itself, but Annotated is spefically designed to include "context-specific metadata" (that's what its docs say), and CLI info seems suitable there. I am indeed worried about people requesting different customizations for identically-named args being passed to multiple functions (especially now that you added nested subcommands, which suggest that rather complex CLIs are being built).

Your point about the parsers kwarg is well-taken, but that actually predates my involvement in defopt and my personal preference is rather to use the implicitly-constructible-from-str approach whenever possible (see StrWrapper at https://defopt.readthedocs.io/en/stable/features.html#parsers).

anntzer avatar Jan 22 '22 12:01 anntzer

Ok, so to implement this, I guess the first step is adding the functionality to properly handle Annotated. Then it seems that it could be used to solve this issue, #96, and #102. So it seems that it has a bit of value in it.

Annotated is only available in Python 3.9+.

Spectre5 avatar Jan 22 '22 18:01 Spectre5

We depend indirectly on typing_extensions (via typing_inspect), which brings in support for Annotated on older Pythons (in fact, we already (briefly) use Annotated internally, in defopt.signature).

anntzer avatar Jan 22 '22 23:01 anntzer