Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Help behavior inconsistent after calling parse_known_args #277

Open
pfrwilson opened this issue Jul 27, 2023 · 2 comments
Open

Help behavior inconsistent after calling parse_known_args #277

pfrwilson opened this issue Jul 27, 2023 · 2 comments

Comments

@pfrwilson
Copy link

Describe the bug
The behavior of parser.print_help is different after calling parser.parse_known_args(), but it behaves correctly when calling the superclass (argparse.ArgumentParser) version of the function.

To Reproduce

# issue.py 

INTENDED_BEHAVIOR = False

from dataclasses import dataclass
from simple_parsing import ArgumentParser
parser = ArgumentParser(add_help=False)
parser.add_argument('-h', action='store_true')

@dataclass
class UseCase1Config: 
    name: str = None 
    a: int = 1 
    b: int = 2

@dataclass
class UseCase2Config: 
    c: int = 3
    b: int = 4

parser.add_argument('--use_case', choices=['A', 'B'], required=True)    
if INTENDED_BEHAVIOR:   
    # behaves correctly if calling the argparse.ArgumentParser version of the method 
    args, _ = super(type(parser), parser).parse_known_args() 
else: 
    args, _ = parser.parse_known_args()

# print(args)
if args.use_case == 'A':
    parser.add_arguments(UseCase1Config, dest='use_case_config') 
elif args.use_case == 'B':
    parser.add_arguments(UseCase2Config, dest='use_case_config')

args = parser.parse_args()
if args.h: 
    parser.print_help()
print(args)

Expected behavior
The console should print a different message depending on which use case is specified:

$ python issue.py --use_case B -h
usage: test.py [-h] --use_case {A,B} [-c int] [-b int]

options:
  -h
  --use_case {A,B}

UseCase2Config ['use_case_config']:
  UseCase2Config(c: int = 3, b: int = 4)

  -c int, --c int   (default: 3)
  -b int, --b int   (default: 4)
Namespace(h=True, use_case='B', use_case_config=UseCase2Config(c=3, b=4))

$ python issue.py --use_case A -h
usage: test.py [-h] --use_case {A,B} [--name str] [-a int] [-b int]

options:
  -h
  --use_case {A,B}

UseCase1Config ['use_case_config']:
  UseCase1Config(name: str = None, a: int = 1, b: int = 2)

  --name str
  -a int, --a int   (default: 1)
  -b int, --b int   (default: 2)
Namespace(h=True, use_case='A', use_case_config=UseCase1Config(name=None, a=1, b=2))

Actual behavior
The help message ignores the added dataclass, even though the correct dataclass is added to the config, with default values

$ python issue.py --use_case A -h
usage: test.py [-h] --use_case {A,B}

options:
  -h
  --use_case {A,B}
Namespace(h=True, use_case='A', use_case_config=UseCase1Config(name=None, a=1, b=2))

$ python issue.py --use_case B -h
usage: test.py [-h] --use_case {A,B}

options:
  -h
  --use_case {A,B}
Namespace(h=True, use_case='B', use_case_config=UseCase2Config(c=3, b=4))

Desktop (please complete the following information):

  • Version Mac OS 13.3
  • Python version: 3.10?

Additional context
I am developing a system for dynamically added configuration groups with appropriate help message for the user e.g.

$ python test.py -h 
usage: test.py [-h] [--use_case {A,B}]

options:
  -h
  --use_case {A,B}
Namespace(h=True, use_case=None)
$ usage: test.py [-h] [--use_case {A,B}] [--name str] [-a int] [-b int]

options:
  -h
  --use_case {A,B}

UseCase1Config ['use_case_config']:
  UseCase1Config(name: str = None, a: int = 1, b: int = 2)

  --name str
  -a int, --a int   (default: 1)
  -b int, --b int   (default: 2)
Namespace(h=True, use_case='A', use_case_config=UseCase1Config(name=None, a=1, b=2))

I believe this will be useful in alot of use cases, in particular one I had in mind was specifying a machine learning model (e.g resnet, inception) then having the correct constructor args dynamically added to the configuration and being given a more detailed help message as you go.

@lebrice
Copy link
Owner

lebrice commented Aug 3, 2023

Hello there @pfrwilson, thanks for posting!

Good catch, there does seem to be some statefullness going on with the parse_known_args. I'll take a look.

By the way, are you familiar with the subgroups feature of simple-parsing? There is even an example that looks quite a bit like your use-case, here: https://github.com/lebrice/SimpleParsing/tree/master/examples/subgroups

As for the loading of config files for each subgroup, note that there is currently a bug with the dynamic selection of the subgroup dataclass (#276 ) but I'm working on it ;)

Thanks again for posting, I'll try to take a look at this soon.

@pfrwilson
Copy link
Author

Hi @lebrice, thanks for your response! No I was not previously aware of the subgroups feature, but i'm excited to check it out as it does appear to address the same use-case already.

Love this project by the way!

Thanks again.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants