lebrice / SimpleParsing

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

Setting `add_config_path_arg=True` in `ArgumentParser` overwrites options with defaults #247

Closed rhaps0dy closed 1 year ago

rhaps0dy commented 1 year ago

Describe the bug Creating an ArgumentParser sets the values of

        FieldWrapper.add_dash_variants = add_option_string_dash_variants
        FieldWrapper.argument_generation_mode = argument_generation_mode
        FieldWrapper.nested_mode = nested_mode

so creating an ArgumentParser with default arguments inside parsing (as happens with add_config_path_arg=True) overwrites any custom settings of these.

To Reproduce

Create the program reproduce.py:

import simple_parsing
from dataclasses import dataclass

@dataclass
class Baz:
    arg: int = 2

@dataclass
class Foo:
    baz: Baz = Baz()

if __name__ == "__main__":
    parser = simple_parsing.ArgumentParser(
        add_config_path_arg=True,  # setting to False works fine
        argument_generation_mode=simple_parsing.ArgumentGenerationMode.NESTED,
    )
    parser.add_arguments(Foo, "foo")
    args = parser.parse_args()

and run python reproduce.py --help

Expected behavior At the very bottom, the argument arg should be accessible via --foo.baz.arg. It should print this:

usage: reproduce.py [-h] [--foo.baz.arg int]

options:
  -h, --help         show this help message and exit

Foo ['foo']:
  Foo(baz: __main__.Baz = Baz(arg=2))

Baz ['foo.baz']:
  Baz(arg: int = 2)

  --foo.baz.arg int  (default: 2)

Actual behavior Prints

usage: reproduce.py [-h] [--config_path Path] [--arg int]

options:
  -h, --help          show this help message and exit
  --config_path Path  Path to a config file containing default values to use. (default: None)

Foo ['foo']:
  Foo(baz: __main__.Baz = Baz(arg=2))

Baz ['foo.baz']:
  Baz(arg: int = 2)

  --arg int           (default: 2)