Source code for mloq.cli

"""Command line interface for mloq."""
import os
from pathlib import Path
from typing import Callable, Optional

import click

from mloq.runner import run_command
from mloq.version import __version__


overwrite_opt = click.option(
    "--overwrite/--no-overwrite",
    "-o/ ",
    default=False,
    show_default=True,
    help="Value indicating whether to overwrite existing files.",
)
config_file_opt = click.option(
    "--filename",
    "-f",
    "config_file",
    default=None,
    show_default=True,
    help="Name of the repository config file",
    type=click.Path(exists=True, file_okay=True, dir_okay=True, resolve_path=True),
)
only_config_opt = click.option(
    "--only-config/--everything",
    "-c/ ",
    default=False,
    show_default=True,
    help="Value indicating whether to not generate all the files except mloq.yaml.",
)
output_directory_arg = click.argument(
    "output_directory",
    type=click.Path(exists=True, file_okay=False, dir_okay=True, resolve_path=True),
)

interactive_opt = click.option(
    "--interactive/--no-interactive",
    "-i/ ",
    default=False,
    show_default=True,
    help="If True the configuration values will be defined interactively on the command line.",
)

hydra_args = click.argument("hydra_args", nargs=-1, type=click.UNPROCESSED)


[docs]def mloq_click_command(func): """Wrap a command function to interface with click.""" func = hydra_args(func) func = only_config_opt(func) func = interactive_opt(func) func = overwrite_opt(func) func = output_directory_arg(func) func = config_file_opt(func) func = click.command(context_settings=dict(ignore_unknown_options=True))(func) return func
[docs]class MloqCLI(click.MultiCommand): """Load the commands available at runtime from the files present in the command module.""" command_folder = Path(__file__).parent / "commands"
[docs] def list_commands(self, ctx): """List the names of the mloq commands available.""" rv = [] for filename in os.listdir(self.command_folder): if filename.endswith(".py") and filename != "__init__.py": rv.append(filename[:-3]) rv.sort() return rv
[docs] def get_command(self, ctx, name) -> Callable: """Create the command callable corresponding to the provided command name.""" ns = {} fn = os.path.join(self.command_folder, name + ".py") with open(fn) as f: code = compile(f.read(), fn, "exec") eval(code, ns, ns) command_class = ns[f"{name.capitalize()}CMD"] # TODO: handle exit codes if needed return run_command(command_class)
[docs]@click.command(cls=MloqCLI) def cli(): # noqa: D103 pass
[docs]def welcome_message(extra: bool = False, string: Optional[str] = None): """Welcome message to be displayed during interactive setup.""" click.echo(f"Welcome to the MLOQ {__version__} interactive setup utility.") if extra: click.echo(f"{string}") click.echo() click.echo( "Please enter values for the following settings (just press Enter " "to accept a default value, if one is given in brackets).", ) click.echo()