Skip to content

taps.run.parse

parse_args_to_config

parse_args_to_config(argv: Sequence[str]) -> Config

Construct an argument parser and parse string arguments to a config.

Parameters:

  • argv (Sequence[str]) –

    Sequence of string arguments.

Returns:

Source code in taps/run/parse.py
def parse_args_to_config(argv: Sequence[str]) -> Config:
    """Construct an argument parser and parse string arguments to a config.

    Args:
        argv: Sequence of string arguments.

    Returns:
        Configuration.
    """
    parser = argparse.ArgumentParser(
        description="""\
Task Performance Suite (TaPS) CLI.

Application benchmarks can be configured via CLI options, a TOML
configuration file, or a mix of both. CLI options take precedence
over configuration files.

The default behavior of -h/--help is to show only the minimally
relevant set of options. For example, only the process-pool
executor options will be shown if --engine.executor process-pool
is specified; the options for other executors will be suppressed.
This behavior applies to all plugin types.
""",
        prog='python -m taps.run',
        formatter_class=_ArgparseFormatter,
    )
    parser.add_argument(
        '--config',
        '-c',
        default=argparse.SUPPRESS,
        nargs='+',
        help=(
            'Base toml configuration files to load '
            '(file are parsed in order).'
        ),
    )

    app_group = parser.add_argument_group('app options')
    app_group.add_argument(
        '--app',
        choices=list(get_app_configs().keys()),
        default=argparse.SUPPRESS,
        dest='app.name',
        metavar='APP',
        help='App choice {%(choices)s}. (required)',
    )

    engine_group = parser.add_argument_group(
        'engine options',
        description='Engine configuration.',
    )
    engine_group.add_argument(
        '--engine.executor',
        '--executor',
        choices=sorted(get_executor_configs().keys()),
        default=argparse.SUPPRESS,
        dest='engine.executor.name',
        metavar='EXECUTOR',
        help='Executor choice {%(choices)s}. (default: process-pool)',
    )
    engine_group.add_argument(
        '--engine.filter',
        '--filter',
        choices=sorted([*get_filter_configs().keys(), 'none']),
        default=argparse.SUPPRESS,
        dest='engine.filter.name',
        metavar='FILTER',
        help='Filter choice {%(choices)s}. (default: none)',
    )
    engine_group.add_argument(
        '--engine.transformer',
        '--transformer',
        choices=sorted([*get_transformer_configs().keys(), 'none']),
        default=argparse.SUPPRESS,
        dest='engine.transformer.name',
        metavar='TRANSFORMER',
        help='Transformer choice {%(choices)s}. (default: none)',
    )

    if len(argv) == 0 or argv[0] in ['-h', '--help']:
        # Shortcut to print help output if no args or just -h/--help
        # are provided.
        parser.parse_args(['--help'])  # pragma: no cover

    argv = list(argv)

    # Strip --help from argv so we can quickly parse the base options
    # to figure out which config types we will need to use. --help
    # will be parsed again by CliSettingsSource.
    _argv = list(filter(lambda v: v not in ['-h', '--help'], argv))
    base_options = vars(parser.parse_known_args(_argv)[0])
    base_options = {k: v for k, v in base_options.items() if v is not None}
    config_files = base_options.pop('config', [])
    toml_options: dict[str, Any] = {}
    for config_file in config_files:
        toml_options.update(flatten_mapping(_parse_toml_options(config_file)))

    # base_options takes precedence over toml_options if there are
    # matching keys.
    base_options = {**toml_options, **base_options}
    if 'app.name' not in base_options or base_options['app.name'] is None:
        raise ValueError(
            'App name option is required. Either pass --app {APP} via the'
            'CLI arguments or add the app.name attribute to the config '
            'file with --config {PATH}.',
        )

    app_group.description = (
        f'App configuration (selected: {base_options["app.name"]}).'
    )

    settings_cls = _make_config_cls(base_options)
    base_namespace = argparse.Namespace(**base_options)

    cli_settings: CliSettingsSource[Config] = CliSettingsSource(
        settings_cls,
        cli_avoid_json=True,
        # cli_parse_args is annotated as:
        #   "bool | list[str] | tuple[str, ...] | None"
        # which is suitable for argv with is Sequence[str].
        cli_parse_args=argv,
        cli_parse_none_str='none',
        cli_use_class_docs_for_groups=False,
        root_parser=parser,
        add_argument_method=_add_argument,
        add_argument_group_method=_add_argument_group,
        parse_args_method=functools.partial(
            _parse_args,
            namespace=base_namespace,
        ),
        formatter_class=argparse.ArgumentDefaultsHelpFormatter,
    )

    return settings_cls(_cli_settings_source=cli_settings)