Created
November 25, 2022 22:23
-
-
Save wrongu/52ad0fbcda040f658dff3f604e609692 to your computer and use it in GitHub Desktop.
Argparse action-handler trick to add new command line arguments at parsing time depending on value of some other argument
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import argparse | |
from typing import Dict | |
class ActionHandler(argparse.Action): | |
def __init__(self, *args, **kwargs): | |
super(ActionHandler, self).__init__(*args, **kwargs) | |
# ran_once is used to flag if __call__ has been run yet. This avoids an infinite loop. | |
self.ran_once = False | |
def __call__(self, parser, args, values, option_string=None): | |
if not self.ran_once: | |
self.ran_once = True | |
if values == "alpha": | |
# Add an extra option called '--bar' | |
parser.add_argument("--bar", default=1, type=int) | |
elif values == "bravo": | |
# Add an extra option called '--baz' | |
parser.add_argument("--baz", default=2.0, type=float) | |
# Recursive parse, storing results in the same 'args' Namespace object so it's transparent to the caller. | |
parser.parse_known_args(namespace=args) | |
def my_parse_args(parser): | |
# Pre-parse onece to populate any extra subparser stuff. Using 'parse_known_args' is permissive | |
# and doesn't raise any errors for unrecognized values. | |
parser.parse_known_args() | |
# Parse for real! | |
return parser.parse_args() | |
parser = argparse.ArgumentParser() | |
parser.add_argument("--foo", default="alpha", choices=["alpha", "bravo"], action=ActionHandler) | |
args = my_parse_args(parser) | |
print(args) | |
# Test cases to try out | |
# $ python3 -m conditional_argparse # should see (foo=alpha, bar=1) | |
# $ python3 -m conditional_argparse --foo alpha --bar 2 # should see (foo=alpha, bar=2) | |
# $ python3 -m conditional_argparse --foo alpha --baz 5.0 # Error! baz is only defined if foo=bravo | |
# $ python3 -m conditional_argparse --foo bravo --baz 5.0 # should see (foo=alpha, baz=5.0) | |
# $ python3 -m conditional_argparse --foo bravo --bar 2 # Error! bar is only defined if foo=alpha |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment