-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: migrate argparse code to typer (#48)
- Loading branch information
Showing
14 changed files
with
492 additions
and
403 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,126 +1,11 @@ | ||
"""Main entry point for VarFish CLI.""" | ||
"""Formal main entry point, forwards to module ``cli``.""" | ||
|
||
import argparse | ||
import logging | ||
import os | ||
import sys | ||
from varfish_cli import cli | ||
|
||
import logzero | ||
from logzero import logger | ||
import toml | ||
|
||
from varfish_cli import __version__ | ||
from varfish_cli.case import run as run_case | ||
from varfish_cli.case import setup_argparse as setup_argparse_case | ||
from varfish_cli.common import CommonConfig, run_nocmd | ||
from varfish_cli.projects import run as run_projects | ||
from varfish_cli.projects import setup_argparse as setup_argparse_projects | ||
from varfish_cli.varannos import run as run_varannos | ||
from varfish_cli.varannos import setup_argparse as setup_argparse_varannos | ||
|
||
#: Paths to search the global configuration in. | ||
GLOBAL_CONFIG_PATHS = ("~/.varfishrc.toml",) | ||
|
||
|
||
def setup_argparse_only(): # pragma: nocover | ||
"""Wrapper for ``setup_argparse()`` that only returns the parser. | ||
Only used in sphinx documentation via ``sphinx-argparse``. | ||
""" | ||
return setup_argparse()[0] | ||
|
||
|
||
def setup_argparse(): | ||
"""Create argument parser.""" | ||
# Construct argument parser and set global options. | ||
parser = argparse.ArgumentParser(prog="varfish-cli") | ||
parser.add_argument("--verbose", action="store_true", default=False, help="Increase verbosity.") | ||
parser.add_argument("--version", action="version", version="%%(prog)s %s" % __version__) | ||
|
||
group = parser.add_argument_group("Basic Configuration") | ||
group.add_argument( | ||
"--no-verify-ssl", | ||
dest="verify_ssl", | ||
default=True, | ||
action="store_false", | ||
help="Disable HTTPS SSL verification", | ||
) | ||
group.add_argument( | ||
"--config", | ||
default=os.environ.get("VARFISH_CONFIG_PATH", None), | ||
help="Path to configuration file.", | ||
) | ||
group.add_argument( | ||
"--varfish-server-url", | ||
default=os.environ.get("VARFISH_SERVER_URL", None), | ||
help="VarFish server URL key to use, defaults to env VARFISH_SERVER_URL.", | ||
) | ||
group.add_argument( | ||
"--varfish-api-token", | ||
default=os.environ.get("VARFISH_API_TOKEN", None), | ||
help="VarFish API token to use, defaults to env VARFISH_API_TOKEN.", | ||
) | ||
|
||
# Add sub parsers for each argument. | ||
subparsers = parser.add_subparsers(dest="cmd") | ||
|
||
setup_argparse_case(subparsers.add_parser("case", help="Work with cases.")) | ||
setup_argparse_projects(subparsers.add_parser("projects", help="Work with projects.")) | ||
setup_argparse_varannos(subparsers.add_parser("varannos", help="Work with varannos module.")) | ||
|
||
return parser, subparsers | ||
|
||
|
||
def main(argv=None): | ||
"""Main entry point before parsing command line arguments.""" | ||
# Setup command line parser. | ||
parser, subparsers = setup_argparse() | ||
|
||
# Actually parse command line arguments. | ||
args = parser.parse_args(argv) | ||
|
||
# Setup logging incl. verbosity. | ||
if args.verbose: # pragma: no cover | ||
level = logging.DEBUG | ||
else: | ||
# Remove module name and line number if not running in debug mode.s | ||
formatter = logzero.LogFormatter( | ||
fmt="%(color)s[%(levelname)1.1s %(asctime)s]%(end_color)s %(message)s" | ||
) | ||
logzero.formatter(formatter) | ||
level = logging.INFO | ||
logzero.loglevel(level=level) | ||
|
||
# Load configuration, if any. | ||
if args.config: | ||
config_paths = (args.config,) | ||
else: | ||
config_paths = GLOBAL_CONFIG_PATHS | ||
for config_path in config_paths: | ||
config_path = os.path.expanduser(os.path.expandvars(config_path)) | ||
if os.path.exists(config_path): | ||
with open(config_path, "rt") as tomlf: | ||
toml_config = toml.load(tomlf) | ||
break | ||
else: | ||
toml_config = None | ||
logger.info("Could not find any of the global configuration files %s.", config_paths) | ||
|
||
# Merge configuration from command line/environment args and configuration file. | ||
config = CommonConfig.create(args, toml_config) | ||
|
||
# Handle the actual command line. | ||
cmds = {None: run_nocmd, "case": run_case, "varannos": run_varannos, "projects": run_projects} | ||
|
||
res = cmds[args.cmd]( | ||
config, toml_config, args, parser, subparsers.choices[args.cmd] if args.cmd else None | ||
) | ||
if not res: | ||
logger.info("All done. Have a nice day!") | ||
else: # pragma: nocover | ||
logger.error("Something did not work out correctly.") | ||
return res | ||
def main(): | ||
cli.typer_click_object() | ||
|
||
|
||
if __name__ == "__main__": # pragma: no cover | ||
sys.exit(main(sys.argv)) | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
"""Code for main entry point.""" | ||
|
||
import logging | ||
import typing | ||
|
||
import typer | ||
import logzero | ||
from logzero import logger | ||
|
||
from varfish_cli import __version__ | ||
from varfish_cli.cli import projects, varannos | ||
from varfish_cli.config import CommonOptions, load_config | ||
|
||
#: Paths to search the global configuration in. | ||
DEFAULT_PATH_VARFISHRC = "~/.varfishrc.toml" | ||
|
||
|
||
def version_callback(value: bool): | ||
"""Callback when called with 'version' or '--version'""" | ||
if value: | ||
print(f"varfish-cli {__version__}") | ||
raise typer.Exit() | ||
|
||
|
||
#: Main CLI ``Typer`` object. | ||
app = typer.Typer(no_args_is_help=True) | ||
|
||
# Register all sub commands. | ||
app.add_typer(varannos.app, name="varannos", help="Varannos-related subcommands") | ||
app.add_typer(projects.app, name="projects", help="Project-related subcommands") | ||
|
||
|
||
@app.command("version") | ||
def main_version(): | ||
"""Print version as "varfish-cli $version".""" | ||
version_callback(True) | ||
|
||
|
||
@app.callback() | ||
def main( | ||
ctx: typer.Context, | ||
version: typing.Annotated[ | ||
typing.Optional[bool], typer.Option("--version", callback=version_callback) | ||
] = None, | ||
verbose: typing.Annotated[ | ||
bool, typer.Option("--verbose", "-v", help="Enable verbose output") | ||
] = False, | ||
verify_ssl: typing.Annotated[ | ||
bool, typer.Option("--verify-ssl/--no-verify-ssl", help="Disable SSL verification") | ||
] = True, | ||
config_path: typing.Annotated[ | ||
str, | ||
typer.Option("--config-path", help="Path to configuration file", envvar="VARFISH_RC_PATH"), | ||
] = DEFAULT_PATH_VARFISHRC, | ||
varfish_server_url: typing.Annotated[ | ||
typing.Optional[str], | ||
typer.Option( | ||
"--varfish-server-url", | ||
help=( | ||
"VarFish server URL key to use, defaults to env VARFISH_SERVER_URL or read " | ||
"from configfile" | ||
), | ||
envvar="VARFISH_SERVER_URL", | ||
), | ||
] = None, | ||
varfish_api_token: typing.Annotated[ | ||
typing.Optional[str], | ||
typer.Option( | ||
"--varfish-server-url", | ||
help=( | ||
"VarFish API token to use, defaults to env VARFISH_API_TOKEN or read from " | ||
"configfile" | ||
), | ||
envvar="VARFISH_API_TOKEN", | ||
), | ||
] = None, | ||
): | ||
"""Callback for main entry point | ||
This function handles the global configuration from configuration file, | ||
environment variables, and command line (in increasing priority). | ||
""" | ||
_ = version | ||
# Setup logging | ||
if verbose: # pragma: no cover | ||
level = logging.DEBUG | ||
else: | ||
# Remove module name and line number if not running in debug mode.s | ||
formatter = logzero.LogFormatter( | ||
fmt="%(color)s[%(levelname)1.1s %(asctime)s]%(end_color)s %(message)s" | ||
) | ||
logzero.formatter(formatter) | ||
level = logging.INFO | ||
logzero.loglevel(level=level) | ||
|
||
# Load configuration file | ||
toml_varfish_server_url, toml_varfish_api_token = load_config(config_path) | ||
if toml_varfish_server_url and not varfish_server_url: | ||
varfish_server_url = toml_varfish_server_url | ||
if toml_varfish_api_token and not varfish_api_token: | ||
varfish_api_token = toml_varfish_api_token | ||
|
||
# Construct common options | ||
ctx.obj = CommonOptions( | ||
verbose=verbose, | ||
verify_ssl=verify_ssl, | ||
config_path=config_path, | ||
varfish_server_url=varfish_server_url, | ||
varfish_api_token=varfish_api_token, | ||
) | ||
logger.info("global configuration = %s", ctx.obj.model_dump_json()) | ||
|
||
|
||
#: Define ``typer`` object that can be called from ``__main__.py``. | ||
typer_click_object = typer.main.get_command(app) |
Oops, something went wrong.