diff options
Diffstat (limited to 'tools/patman/settings.py')
| -rw-r--r-- | tools/patman/settings.py | 77 | 
1 files changed, 63 insertions, 14 deletions
| diff --git a/tools/patman/settings.py b/tools/patman/settings.py index d66b22be1df..17229e0d823 100644 --- a/tools/patman/settings.py +++ b/tools/patman/settings.py @@ -9,8 +9,10 @@ except Exception:      import ConfigParser  import argparse +from io import StringIO  import os  import re +import sys  from u_boot_pylib import gitutil @@ -226,7 +228,7 @@ nxp = Zhikang Zhang <zhikang.zhang@nxp.com>      f.close() -def _UpdateDefaults(main_parser, config): +def _UpdateDefaults(main_parser, config, argv):      """Update the given OptionParser defaults based on config.      We'll walk through all of the settings from all parsers. @@ -242,6 +244,7 @@ def _UpdateDefaults(main_parser, config):              updated.          config: An instance of _ProjectConfigParser that we will query              for settings. +        argv (list of str or None): Arguments to parse      """      # Find all the parsers and subparsers      parsers = [main_parser] @@ -252,10 +255,45 @@ def _UpdateDefaults(main_parser, config):      # Collect the defaults from each parser      defaults = {}      parser_defaults = [] +    argv = list(argv) +    orig_argv = argv + +    bad = False +    full_parser_list = []      for parser in parsers: -        pdefs = parser.parse_known_args()[0] -        parser_defaults.append(pdefs) -        defaults.update(vars(pdefs)) +        argv_list = [orig_argv] +        special_cases = [] +        if hasattr(parser, 'defaults_cmds'): +           special_cases = parser.defaults_cmds +        for action in parser._actions: +            if action.choices: +                argv_list = [] +                for choice in action.choices: +                    argv = None +                    for case in special_cases: +                        if case[0] == choice: +                            argv = case +                    argv_list.append(argv or [choice]) + +        for argv in argv_list: +            parser.message = None +            old_val = parser.catch_error +            try: +                parser.catch_error = True +                pdefs = parser.parse_known_args(argv)[0] +            finally: +                parser.catch_error = old_val + +            # if parser.message: +                # print('bad', argv, parser.message) +                # bad = True + +            parser_defaults.append(pdefs) +            defaults.update(vars(pdefs)) +            full_parser_list.append(parser) +    if bad: +        print('Internal parsing error') +        sys.exit(1)      # Go through the settings and collect defaults      for name, val in config.items('settings'): @@ -270,12 +308,18 @@ def _UpdateDefaults(main_parser, config):              defaults[name] = val          else:              print("WARNING: Unknown setting %s" % name) +    if 'cmd' in defaults: +        del defaults['cmd'] +    if 'subcmd' in defaults: +        del defaults['subcmd']      # Set all the defaults and manually propagate them to subparsers      main_parser.set_defaults(**defaults) -    for parser, pdefs in zip(parsers, parser_defaults): +    assert len(full_parser_list) == len(parser_defaults) +    for parser, pdefs in zip(full_parser_list, parser_defaults):          parser.set_defaults(**{k: v for k, v in defaults.items()                                 if k in pdefs}) +    return defaults  def _ReadAliasFile(fname): @@ -334,7 +378,7 @@ def GetItems(config, section):          return [] -def Setup(parser, project_name, config_fname=None): +def Setup(parser, project_name, argv, config_fname=None):      """Set up the settings module by reading config files.      Unless `config_fname` is specified, a `.patman` config file local @@ -347,8 +391,9 @@ def Setup(parser, project_name, config_fname=None):          parser:         The parser to update.          project_name:   Name of project that we're working on; we'll look              for sections named "project_section" as well. -        config_fname:   Config filename to read.  An error is raised if it -            does not exist. +        config_fname:   Config filename to read, or None for default, or False +            for an empty config.  An error is raised if it does not exist. +        argv (list of str or None): Arguments to parse, or None for default      """      # First read the git alias file if available      _ReadAliasFile('doc/git-mailrc') @@ -357,12 +402,16 @@ def Setup(parser, project_name, config_fname=None):      if config_fname and not os.path.exists(config_fname):          raise Exception(f'provided {config_fname} does not exist') -    if not config_fname: +    if config_fname is None:          config_fname = '%s/.patman' % os.getenv('HOME') -    has_config = os.path.exists(config_fname) +    git_local_config_fname = os.path.join(gitutil.get_top_level() or '', +                                          '.patman') -    git_local_config_fname = os.path.join(gitutil.get_top_level(), '.patman') -    has_git_local_config = os.path.exists(git_local_config_fname) +    has_config = False +    has_git_local_config = False +    if config_fname is not False: +        has_config = os.path.exists(config_fname) +        has_git_local_config = os.path.exists(git_local_config_fname)      # Read the git local config last, so that its values override      # those of the global config, if any. @@ -371,7 +420,7 @@ def Setup(parser, project_name, config_fname=None):      if has_git_local_config:          config.read(git_local_config_fname) -    if not (has_config or has_git_local_config): +    if config_fname is not False and not (has_config or has_git_local_config):          print("No config file found.\nCreating ~/.patman...\n")          CreatePatmanConfigFile(config_fname) @@ -382,7 +431,7 @@ def Setup(parser, project_name, config_fname=None):      for name, value in GetItems(config, 'bounces'):          bounces.add(value) -    _UpdateDefaults(parser, config) +    return _UpdateDefaults(parser, config, argv)  # These are the aliases we understand, indexed by alias. Each member is a list. | 
