From 4be7aa7cdbd4be301690d63e4af812de5d086e09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=B5?= Date: Sun, 11 Aug 2024 15:33:16 +0000 Subject: [PATCH] btcli/bt.config: various improvements - implement recursive apply function for (sub^n)argparser - use recursive apply to eliminate repeated code - move adding standard bt.config args to separate function - *use recursive apply to add standard bt.config args to all parsers - *make strict=True the default - eliminate redundant COMMANDS.item.name field - remove obsolete COMMANDS looping code - remove redundant dest= argument - fix some comments The changes marked * implement a functional improvement, the rest is for improved maintainability. --- bittensor/cli.py | 33 ++++------- bittensor/config.py | 135 +++++++++++++++++++++----------------------- 2 files changed, 76 insertions(+), 92 deletions(-) diff --git a/bittensor/cli.py b/bittensor/cli.py index e86fa013c4..cfc6ac11f5 100644 --- a/bittensor/cli.py +++ b/bittensor/cli.py @@ -104,7 +104,6 @@ } COMMANDS = { "subnets": { - "name": "subnets", "aliases": ["s", "subnet"], "help": "Commands for managing and viewing subnetworks.", "commands": { @@ -118,7 +117,6 @@ }, }, "root": { - "name": "root", "aliases": ["r", "roots"], "help": "Commands for managing and viewing the root network.", "commands": { @@ -140,7 +138,6 @@ }, }, "wallet": { - "name": "wallet", "aliases": ["w", "wallets"], "help": "Commands for managing and viewing wallets.", "commands": { @@ -165,7 +162,6 @@ }, }, "stake": { - "name": "stake", "aliases": ["st", "stakes"], "help": "Commands for staking and removing stake and setting child hotkey accounts.", "commands": { @@ -178,7 +174,6 @@ }, }, "weights": { - "name": "weights", "aliases": ["wt", "weight"], "help": "Commands for managing weight for subnets.", "commands": { @@ -187,7 +182,6 @@ }, }, "sudo": { - "name": "sudo", "aliases": ["su", "sudos"], "help": "Commands for subnet management", "commands": { @@ -197,7 +191,6 @@ }, }, "legacy": { - "name": "legacy", "aliases": ["l"], "help": "Miscellaneous commands.", "commands": { @@ -206,7 +199,6 @@ }, }, "info": { - "name": "info", "aliases": ["i"], "help": "Instructions for enabling autocompletion for the CLI.", "commands": { @@ -300,21 +292,18 @@ def __create_parser__() -> "argparse.ArgumentParser": # Add arguments for each sub-command. cmd_parsers = parser.add_subparsers(dest="command") # Add argument parsers for all available commands. - for command in COMMANDS.values(): - if isinstance(command, dict): - subcmd_parser = cmd_parsers.add_parser( - name=command["name"], - aliases=command["aliases"], - help=command["help"], - ) - subparser = subcmd_parser.add_subparsers( - help=command["help"], dest="subcommand", required=True - ) + for name, command in COMMANDS.items(): + subcmd_parser = cmd_parsers.add_parser( + name=name, + aliases=command["aliases"], + help=command["help"], + ) + subparser = subcmd_parser.add_subparsers( + help=command["help"], dest="subcommand", required=True + ) - for subcommand in command["commands"].values(): - subcommand.add_args(subparser) - else: - command.add_args(cmd_parsers) + for subcommand in command["commands"].values(): + subcommand.add_args(subparser) return parser diff --git a/bittensor/config.py b/bittensor/config.py index 59ad4451b8..570dd66c82 100644 --- a/bittensor/config.py +++ b/bittensor/config.py @@ -74,50 +74,7 @@ def __init__( if parser == None: return None - # Optionally add config specific arguments - try: - parser.add_argument( - "--config", - type=str, - help="If set, defaults are overridden by passed file.", - ) - except: - # this can fail if --config has already been added. - pass - - try: - parser.add_argument( - "--strict", - action="store_true", - help="""If flagged, config will check that only exact arguments have been set.""", - default=False, - ) - except: - # this can fail if --strict has already been added. - pass - - try: - parser.add_argument( - "--no_version_checking", - action="store_true", - help="Set ``true`` to stop cli version checking.", - default=False, - ) - except: - # this can fail if --no_version_checking has already been added. - pass - - try: - parser.add_argument( - "--no_prompt", - dest="no_prompt", - action="store_true", - help="Set ``true`` to stop cli from prompting the user.", - default=False, - ) - except: - # this can fail if --no_version_checking has already been added. - pass + config.apply_to_parser_recursive(parser, config.add_standard_args) # Get args from argv if not passed in. if args == None: @@ -187,32 +144,13 @@ def __init__( all_default_args = default_params.__dict__.keys() | [] ## Make a dict with keys as args and values as argparse.SUPPRESS defaults_as_suppress = {key: argparse.SUPPRESS for key in all_default_args} - ## Set the defaults to argparse.SUPPRESS, should remove them from the namespace - parser_no_defaults.set_defaults(**defaults_as_suppress) - parser_no_defaults._defaults.clear() # Needed for quirk of argparse - - ### Check for subparsers and do the same - if parser_no_defaults._subparsers != None: - for action in parser_no_defaults._subparsers._actions: - # Should only be the "command" subparser action - if isinstance(action, argparse._SubParsersAction): - # Set the defaults to argparse.SUPPRESS, should remove them from the namespace - # Each choice is the keyword for a command, we need to set the defaults for each of these - ## Note: we also need to clear the _defaults dict for each, this is a quirk of argparse - cmd_parser: argparse.ArgumentParser - for cmd_parser in action.choices.values(): - # If this choice is also a subparser, set defaults recursively - if cmd_parser._subparsers: - for action in cmd_parser._subparsers._actions: - # Should only be the "command" subparser action - if isinstance(action, argparse._SubParsersAction): - cmd_parser: argparse.ArgumentParser - for cmd_parser in action.choices.values(): - cmd_parser.set_defaults(**defaults_as_suppress) - cmd_parser._defaults.clear() # Needed for quirk of argparse - else: - cmd_parser.set_defaults(**defaults_as_suppress) - cmd_parser._defaults.clear() # Needed for quirk of argparse + + def l_set_defaults(l_parser): + ## Set the defaults to argparse.SUPPRESS, should remove them from the namespace + l_parser.set_defaults(**defaults_as_suppress) + l_parser._defaults.clear() # Needed for quirk of argparse + + config.apply_to_parser_recursive(parser_no_defaults, l_set_defaults) ## Reparse the args, but this time with the defaults as argparse.SUPPRESS params_no_defaults = config.__parse_args__( @@ -231,6 +169,63 @@ def __init__( ] } + @staticmethod + def apply_to_parser_recursive(parser, callback, depth=0): + callback(parser) + if not parser._subparsers: + return + for action in parser._subparsers._actions: + if not isinstance(action, argparse._SubParsersAction): + continue + for cmd_parser in action.choices.values(): + config.apply_to_parser_recursive(cmd_parser, callback, depth=depth + 1) + + @staticmethod + def add_standard_args(parser): + # Optionally add config specific arguments + try: + parser.add_argument( + "--config", + type=str, + help="If set, defaults are overridden by passed file.", + ) + except: + # this can fail if --config has already been added. + pass + + try: + parser.add_argument( + "--strict", + action="store_true", + help="If flagged, config will check that only exact arguments have been set.", + default=False, + ) + except: + # this can fail if --strict has already been added. + pass + + try: + parser.add_argument( + "--no_version_checking", + action="store_true", + help="Set ``true`` to stop cli version checking.", + default=False, + ) + except: + # this can fail if --no_version_checking has already been added. + pass + + try: + parser.add_argument( + "--no_prompt", + action="store_true", + help="Set ``true`` to stop cli from prompting the user.", + default=False, + ) + except Exception as e: + # this can fail if --no_prompt has already been added. + pass + @staticmethod def __split_params__(params: argparse.Namespace, _config: "config"): # Splits params on dot syntax i.e neuron.axon_port and adds to _config