swansonk14 / typed-argument-parser

Typed argument parser for Python
MIT License
494 stars 40 forks source link

[Suggestion] Allow to reference previous arguments as default values #116

Closed Henning742 closed 10 months ago

Henning742 commented 1 year ago

Not a professional coder so I don't know if this suggestion is good.

What I want to accomplish: Say there're two arguments:

exp_name: str = 'your_exp_name' 
exp_dir: str = 'work_dirs/{args.exp_name}' 

then the second line means its default value is using the value of 'exp_name'.

This is my implementation:

import re
def eval_arg_strings(args):
    for k, v in args.__dict__.items():
        if isinstance(v, str):
            to_eval = re.findall(r'{args\.(.+)}', v)
            to_eval = [a for a in to_eval if hasattr(args, a)]
            for key_word in to_eval:
                real_v = getattr(args, key_word)
                assert isinstance(real_v, str)
                setattr(args, k, v.replace("{args." + key_word + "}", real_v))
    return args

Any comment is appreciated, thank you.

martinjm97 commented 10 months ago

While the syntax youre're using is more concise, we believe that this breaks from standard convention. Tap currently supports similar functionality with process_args:

class MyTap(Tap):
    exp_name: str = 'your_exp_name' 
    exp_dir: str | None = None

    def process_args(self):
        if self.exp_dir is None:
            self.exp_dir = f'work_dirs/{self.exp_name}' 

This allows the user to optionally pass exp_dir from the command line and if no exp_dir is specified, return f'work_dirs/{self.exp_name}'

--JK