lebrice / SimpleParsing

Simple, Elegant, Typed Argument Parsing with argparse
MIT License
384 stars 46 forks source link

Allow only a single cli argument for multiple different dataclasses. #299

Open dln22 opened 5 months ago

dln22 commented 5 months ago

Imagine I have the following case:

from dataclasses import dataclass
from simple_parsing import ArgumentParser

@dataclass
class A:
    shared_arg: str
    argA: str

@dataclass
class B:
    shared_arg: str
    argB: str

@dataclass
class C:
    argC1: B
    argC2: str

parser = ArgumentParser()
parser.add_arguments(A, dest="A")
parser.add_arguments(C, dest="C")
parser.parse_args()

then running the parser shows: usage: test.py [-h] --shared_arg str --argA str --argC2 str --argC1.shared_arg str --argB str

where you can see that there are two shared_arg arguments: --shared_arg and --argC1.shared_arg

If I try to use the ALWAYS_MERGE conflict resolution, then that results in --argB argument being removed, plus it is dependent on the order in which we register dataclass arguments to the parser. As an example, adding first A and then C works, but removes the --argB as previously mentioned. Adding first C and then A crashes with ValueError: list.remove(x): x not in list error.

I think an option for having only one argument for multiple (and/or nested) dataclasses is a good feature to have, as there are a lot of use cases where objects share certain arguments and it would be nice to keep the same arguments in these objects in sync?

lebrice commented 5 months ago

Hello there @dln22 , thanks for posting!

If I understand what you're asking correctly, you'd like to share a field between multiple dataclasses (with the arguments from all dataclasses being added to the same parser), correct? For example, you'd like to supply --shared_arg=123 and have that value be reflected in args.A.shared_arg and args.B.shared_arg ?

If so, that's an interesting question. I think this echoes #143 a little bit. There might already be a way to get this to work using the dest argument of the simple_parsing.field function, but I'm not sure.

I'll think about this a bit. Thanks again for posting.

dln22 commented 4 months ago

That's correct, and thanks for looking into my question! One thought I had was to add a different merging strategy, where, if arguments are named the same and have the same types, we could just add them only once to the allowed CLI args and once passed, these args would then propagate to whichever dataclasses use them. Thanks!