Open Linusnie opened 1 year ago
Hi @Linusnie!
I appreciate the detailed issue.
Unfortunately, what you described is the best that we can do right now. I think https://github.com/brentyi/tyro/issues/60#issuecomment-1656369002 addresses the same problem:
This is one of a handful of remaining things in
tyro
that I'm not super happy with; it mostly reduces to the limited choices we have when mapping types toargparse
functionality, which we use for all of the low-level CLI stuff.For union types over structures like dataclasses, subparsers make sense because they let us only accept arguments from the chosen types.
The downside is that each parser or subparser can only contain a single set of "child" subparsers. This results in a tree structure that doesn't map exactly to the case where we have multiple Union types. In your case, the tree structure we generate looks like:
# (subcommands have been shortened a bit for brevity) [root parser] ├─ output-head:None │ ├─ optimizer:None │ ├─ optimizer:optimizer ├─ output-head:output-head │ ├─ optimizer:None │ ├─ optimizer:optimizer
...where
optimizer:*
is always actually a subcommand of theoutput-head:*
, and not the root parser. And so we need to pass inoutput-head:*
in order to traverse a step down the tree, where we can then pass in theoptimizer:*
subcommand.Of course open to suggestions here. :)
The best I've been able to come up with is to tear out
argparse
and replace it with an in-house solution — or try to forkargparse
to somehow add this functionality — but of course either would take a lot of development energy, while breaking compatibility withargparse
-reliant tools (for example, we useshtab
for tab completion in the shell).
If you really want this behavior, I guess you could annotate the first field with Union[A1, A2, B1, B2]
, and add some post-processing logic, but this would also add a lot of complexity + downsides.
@brentyi I see, thank you for the explanation! That's unfortunate but I'll try to reduce it to just one subcommand somehow for now then
hi, first off thanks for making this great library! I've run into the following issue: I'd like to have a setting structure with two subcommands, each with separate settings and defaults:
I'd like to be able to set the value for
config.b
while leavingconfig.a
as its default. However if I runpython tyro_test.py b:b2
I get the following error:and the only way(?) to set
config.b
is to setconfig.a
first withpython tyro_test.py a:a1 b:b2
. Is there a way to setconfig.b
via the command line without having to setconfig.a
?