X-Git-Url: https://wannabe.guru.org/gitweb/?a=blobdiff_plain;f=config.py;h=81351cff145587adb80cfccf0f245aa7134ef3d6;hb=c79ecbf708a63a54a9c3e8d189b65d4794930082;hp=672e1ae0328e6d7e5b99ccbc4d702adfcd516f32;hpb=a838c154135b2420d9047a101caf24a2c9f593c2;p=python_utils.git diff --git a/config.py b/config.py index 672e1ae..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,9 +157,7 @@ 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: @@ -165,8 +165,25 @@ def parse() -> Dict[str, Any]: 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']: