argparse_dataclass icon indicating copy to clipboard operation
argparse_dataclass copied to clipboard

Printing default values as well as help from the command line

Open akinwilson opened this issue 10 months ago • 5 comments
trafficstars

I am trying to use the ArgumentDefaultsHelpFormatter class from the original argparse library to enhance the displayed help information when using the ArgumentParser class from the argparse_dataclass library. Suppose I run the following script.py with the help - -h - flag

from dataclasses import dataclass, field 
from argparse_dataclass import ArgumentParser
from argparse import ArgumentDefaultsHelpFormatter

@dataclass
class Args:
    val_a : int = field(default=30522, metadata={'help':'info about val_a'})
    val_b :int = field(default=768, metadata={'help':'info about val_b'})
    val_c : str = field(default='foo', metadata={'help':'info about val_c'})
    

if __name__ == "__main__":
    parser =ArgumentParser(Args,formatter_class=ArgumentDefaultsHelpFormatter)
    args = parser.parse_args()

I would expect the terminal output to be like:

usage: script.py [-h] [--val-a VAL_A ] [--val-b VAL_B] [--val-c VAL_C]

options:
  -h, --help            show this help message and exit
  --val-a VAL_A
                        info about val_a (default:30522)
  --val-b VAL_B 
                        info about val_b (default: 768)
  --val-c VAL_C 
                        info about val_c (default: foo)

but its actually like:

usage: script.py [-h] [--val-a VAL_A ] [--val-b VAL_B] [--val-c VAL_C]

options:
  -h, --help            show this help message and exit
  --val-a VAL_A
                        info about val_a (default: <dataclasses._MISSING_TYPE object at 0x711c99aeed70>)
  --val-b VAL_B 
                        info about val_b (default: <dataclasses._MISSING_TYPE object at 0x711c99aeed70>)
  --val-c VAL_C 
                        info about val_c (default: <dataclasses._MISSING_TYPE object at 0x711c99aeed70>)

Does anyone know how to rectify this behavior?

EDIT As I am seeking help from multiple places on the subject, the other being a stack overflow post, it was pointed out that this behavior is due to these lines in the source code

could potentially editing these lines in the source code from

def _add_dataclass_options(
    options_class: Type[OptionsType], parser: argparse.ArgumentParser
) -> None:
    if not is_dataclass(options_class):
        raise TypeError("cls must be a dataclass")

    for field in fields(options_class):
        args = field.metadata.get("args", [f"--{_get_arg_name(field)}"])
        positional = not args[0].startswith("-")
        kwargs = {
            "type": field.metadata.get("type", field.type),
            "help": field.metadata.get("help", None),
        }

to

def _add_dataclass_options(
    options_class: Type[OptionsType], parser: argparse.ArgumentParser
) -> None:
    if not is_dataclass(options_class):
        raise TypeError("cls must be a dataclass")

    for field in fields(options_class):
        args = field.metadata.get("args", [f"--{_get_arg_name(field)}"])
        positional = not args[0].startswith("-")
        kwargs = {
            "type": field.metadata.get("type", field.type),
            "help": field.metadata.get("help", None),
            "default": field.default,
        }

stop this behavior from happening?

akinwilson avatar Jan 24 '25 08:01 akinwilson