X-Git-Url: https://wannabe.guru.org/gitweb/?a=blobdiff_plain;f=config.py;h=81351cff145587adb80cfccf0f245aa7134ef3d6;hb=a08ca309cb5bd7971210a9247a38c9bbe376a6e6;hp=e7094f3a5ba6d6c4646a579d2e5e1e47cc8e330a;hpb=09e6d10face80d98a4578ff54192b5c8bec007d7;p=python_utils.git diff --git a/config.py b/config.py index e7094f3..81351cf 100644 --- a/config.py +++ b/config.py @@ -69,7 +69,7 @@ import os import pprint import re import sys -from typing import Any, Dict, List +from typing import Any, Dict, List, Optional # This module is commonly used by others in here and should avoid # taking any unnecessary dependencies back on them. @@ -100,10 +100,12 @@ class LoadFromFile(argparse.Action): # A global parser that we will collect arguments into. +prog = os.path.basename(sys.argv[0]) args = argparse.ArgumentParser( - description=f"This program uses config.py ({__file__}) for global, cross-module configuration.", + description=None, formatter_class=argparse.ArgumentDefaultsHelpFormatter, fromfile_prefix_chars="@", + epilog=f'-----------------------------------------------------------------------------\n{prog} uses config.py ({__file__}) for global, cross-module configuration setup and parsing.\n-----------------------------------------------------------------------------' ) config_parse_called = False @@ -155,18 +157,33 @@ def is_flag_already_in_argv(var: str): return False -def parse() -> Dict[str, Any]: - import string_utils - +def parse(entry_module: Optional[str]) -> Dict[str, Any]: """Main program should call this early in main()""" global config_parse_called if config_parse_called: - return + return config config_parse_called = True global saved_messages + # If we're about to do the usage message dump, put the main module's + # argument group first in the list (if possible), please. + reordered_action_groups = [] + prog = sys.argv[0] + + for arg in sys.argv: + if arg == '--help' or arg == '-h': + for group in args._action_groups: + if entry_module is not None and entry_module in group.title: + reordered_action_groups.insert(0, group) # prepend + elif prog in group.title: + reordered_action_groups.insert(0, group) # prepend + else: + reordered_action_groups.append(group) # append + args._action_groups = reordered_action_groups + # Examine the environment variables to settings that match - # known flags. + # known flags. For a flag called --example_flag the corresponding + # environment variable would be called EXAMPLE_FLAG. usage_message = args.format_usage() optional = False var = '' @@ -193,7 +210,8 @@ def parse() -> Dict[str, Any]: saved_messages.append( f'Initialized from environment: {var} = {value}' ) - if len(chunks) == 1 and string_utils.to_bool(value): + from string_utils import to_bool + if len(chunks) == 1 and to_bool(value): sys.argv.append(var) elif len(chunks) > 1: sys.argv.append(var) @@ -204,12 +222,13 @@ def parse() -> Dict[str, Any]: next # Parse (possibly augmented) commandline args with argparse normally. - #config.update(vars(args.parse_args())) known, unknown = args.parse_known_args() config.update(vars(known)) # Reconstruct the argv with unrecognized flags for the benefit of - # future argument parsers. + # future argument parsers. For example, unittest_main in python + # has some of its own flags. If we didn't recognize it, maybe + # someone else will. sys.argv = sys.argv[:1] + unknown if config['config_savefile']: