crosvm/tools/impl/cli.py
Dennis Kempin 11a48d4cca tools: refactoring: Split common.py into multiple files
This is a refactoring with no functionality change. The common.py
file is split up so we will be able to use the parts that have no
third party dependencies separately.

For now, keep common.py and re-export everything, so we do not
introduce issues in other tools.

BUG=b:267499599
TEST=presubmit

Change-Id: Idf6d45bd90f5cf448fb9dd88df540af3da0f7f88
Reviewed-on: https://chromium-review.googlesource.com/c/crosvm/crosvm/+/4482141
Reviewed-by: Zihan Chen <zihanchen@google.com>
Commit-Queue: Dennis Kempin <denniskempin@google.com>
2023-05-02 17:04:27 +00:00

89 lines
2.4 KiB
Python

#!/usr/bin/env python3
# Copyright 2023 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""
Provides a framework for command line interfaces based on argh.
It automatically adds common arguments, such as -v, -vv and --color to provide consistent
behavior.
"""
import argparse
import sys
import traceback
from typing import (
Any,
Callable,
Optional,
)
from .util import (
add_common_args,
parse_common_args,
print_timing_info,
record_time,
verbose,
ensure_packages_exist,
)
ensure_packages_exist("argh")
import argh # type: ignore
# Hack: argh does not support type annotations. This prevents type errors.
argh: Any # type: ignore
def run_main(main_fn: Callable[..., Any], usage: Optional[str] = None):
run_commands(default_fn=main_fn, usage=usage)
def run_commands(
*functions: Callable[..., Any],
default_fn: Optional[Callable[..., Any]] = None,
usage: Optional[str] = None,
):
"""
Allow the user to call the provided functions with command line arguments translated to
function arguments via argh: https://pythonhosted.org/argh
"""
exit_code = 0
try:
parser = argparse.ArgumentParser(
description=usage,
# Docstrings are used as the description in argparse, preserve their formatting.
formatter_class=argparse.RawDescriptionHelpFormatter,
# Do not allow implied abbreviations. Abbreviations should be manually specified.
allow_abbrev=False,
)
add_common_args(parser)
# Add provided commands to parser. Do not use sub-commands if we just got one function.
if functions:
argh.add_commands(parser, functions) # type: ignore
if default_fn:
argh.set_default_command(parser, default_fn) # type: ignore
with record_time("Total Time"):
# Call main method
argh.dispatch(parser) # type: ignore
except Exception as e:
if verbose():
traceback.print_exc()
else:
print(e)
exit_code = 1
if parse_common_args().timing_info:
print_timing_info()
sys.exit(exit_code)
if __name__ == "__main__":
import doctest
(failures, num_tests) = doctest.testmod(optionflags=doctest.ELLIPSIS)
sys.exit(1 if failures > 0 else 0)