SimpleParsing icon indicating copy to clipboard operation
SimpleParsing copied to clipboard

List fields cannot be used with subparser fields

Open lebrice opened this issue 2 years ago • 2 comments

Describe the bug

Can't use fields with nargs="*" with a subparser field that comes after it. The values passed for the list field are incorrectly assumed to be values for the subparser, and so a "incorrect value for argument : Must be one of <A, B, C>"-like error is raised.

UPDATE: Seems like list fields aren't actually the issue: The problem only appeared when using Union[float, List[float]] as a type annotation. Changing the type annotation to List[float] solved the issue.

lebrice avatar Jan 22 '22 19:01 lebrice

@dataclass
class Train:
    """Example of a command to start a Training run."""
    # the training directory
    train_dir: Path = Path("~/train")

    def execute(self):
        print(f"Training in directory {self.train_dir}")


@dataclass
class Test:
    """Example of a command to start a Test run."""
    # the testing directory
    test_dir: Path = Path("~/train")

    def execute(self):
        print(f"Testing in directory {self.test_dir}")


@dataclass
class Program:
    """Available commands and common options"""
    command: Union[Train, Test]
    strlist: List[str] = field(default=None)  # list of the locations

    def execute(self):
        print(self.strlist)
        return self.command.execute()


if __name__ == "__main__":
    parser = ArgumentParser()
    parser.add_arguments(Program, dest="prog")
    args = parser.parse_args()
    prog: Program = args.prog
    prog.execute()

If you run this script with these parameters you will get those output where list does not parsed correctly

$ python run.py --strlist='test2 tes2t' train
['test2 tes2t']
Training in directory ~/train

Running script like this:

$ python run.py --strlist 'test2 tes2t' train

Gives me an error run.py: error: the following arguments are required: prog.command

How can I mix subparsers and list of string parameters:

parser.add_argument("--strlist", nargs="+", type=str, required=True)

johnatannvmd avatar Feb 01 '22 12:02 johnatannvmd

The same problem applies to combining the add_config_path_arg=True with subparsers. I'm adding as a comment under this issue (rather than a new issue) because under the covers the config flag is added as a nargs="*" option. Let me know if you'd rather I raised as a separate issue.

The following invocation fails with RuntimeError: Unable to determine what function to use in order to load path deploy into a dictionary since the path's extension isn't registered in the extensions_to_loading_fn dictionary. That's because it's trying to parse subcommand as a filename and the extension ("") isn't recognised.

python run.py --config config.yaml subcommand

but this works:

python run.py subcommand --config config.yaml 

Example code:

from dataclasses import dataclass

from simple_parsing import ArgumentParser


@dataclass
class Dummy:
    value: str


parser = ArgumentParser(add_config_path_arg=True)
parser.add_arguments(Dummy, dest="config")
subparsers = parser.add_subparsers()
subcommand = subparsers.add_parser("subcommand")
args = parser.parse_args()

MartinHowarth avatar Feb 02 '23 10:02 MartinHowarth