Type hinting in CLI, KiwiCommand class names, removed kiwi_command name parameter

This commit is contained in:
Jörn-Michael Miehe 2021-11-17 16:23:55 +01:00
parent 512ee9ba87
commit 9095b57b23
5 changed files with 31 additions and 27 deletions

View file

@ -1,7 +1,8 @@
import importlib
import os
import sys
from enum import Enum, auto
from typing import List, Tuple, Iterable, Any, Type
from typing import List, Tuple, Iterable, Type, Optional, TypeVar
import click
@ -11,42 +12,50 @@ from ..instance import Instance, Project
class KiwiCLI(click.MultiCommand):
"""Command Line Interface spread over multiple files in this directory"""
def list_commands(self, ctx):
def list_commands(self, ctx: click.Context) -> List[str]:
"""list all the commands defined by cmd_*.py files in this directory"""
return (
return [
filename[4:-3]
for filename in os.listdir(os.path.abspath(os.path.dirname(__file__)))
if filename.startswith("cmd_") and filename.endswith(".py")
)
]
def get_command(self, ctx, name):
def get_command(self, ctx: click.Context, cmd_name: str) -> Optional[click.Command]:
"""import and return a specific command"""
try:
mod = __import__(f"kiwi_scp.commands.cmd_{name}", None, None, ["CMD"])
cmd_module = importlib.import_module(f"kiwi_scp.commands.cmd_{cmd_name}")
except ImportError:
return
return mod.CMD
for cmd_name in dir(cmd_module):
member = getattr(cmd_module, cmd_name)
if isinstance(member, click.Command):
return member
T = TypeVar("T")
class KiwiCommand:
@staticmethod
def print_multi_color(*content: Tuple[str, str]):
def print_multi_color(*content: Tuple[str, str]) -> None:
for message, color in content:
click.secho(message, fg=color, nl=False)
click.echo()
@staticmethod
def print_header(header: str):
def print_header(header: str) -> None:
click.secho(header, fg="green", bold=True)
@staticmethod
def print_error(error: str):
def print_error(error: str) -> None:
click.secho(error, file=sys.stderr, fg="red", bold=True)
@staticmethod
def print_list(content: Iterable[str]):
def print_list(content: Iterable[str]) -> None:
for item in content:
KiwiCommand.print_multi_color(
(" - ", "green"),
@ -54,7 +63,7 @@ class KiwiCommand:
)
@staticmethod
def user_query(description: str, default: Any, cast_to: Type[Any] = str):
def user_query(description: str, default: T, cast_to: Type[T] = str) -> T:
# prompt user as per argument
while True:
try:

View file

@ -15,17 +15,16 @@ from ..instance import Instance, Project
)
@click.argument(
"compose_cmd",
metavar="CMD",
metavar="COMMAND",
)
@kiwi_command(
"cmd",
KiwiCommandType.PROJECT,
cmd_type=KiwiCommandType.PROJECT,
short_help="Run docker-compose command",
# ignore arguments looking like options
# just pass everything down to docker-compose
context_settings={"ignore_unknown_options": True},
)
class CMD(KiwiCommand):
class CmdCommand(KiwiCommand):
"""Run raw docker-compose command in a project"""
@classmethod

View file

@ -30,11 +30,10 @@ _logger = logging.getLogger(__name__)
help=f"use default values even if {KIWI_CONF_NAME} is present",
)
@kiwi_command(
"init",
KiwiCommandType.INSTANCE,
cmd_type=KiwiCommandType.INSTANCE,
short_help="Initializes kiwi-scp",
)
class CMD(KiwiCommand):
class InitCommand(KiwiCommand):
"""Initialize or reconfigure a kiwi-scp instance"""
@classmethod

View file

@ -13,11 +13,10 @@ from ..instance import Instance, Project
help=f"show actual config contents instead",
)
@kiwi_command(
"list",
KiwiCommandType.SERVICE,
cmd_type=KiwiCommandType.SERVICE,
short_help="Inspect a kiwi-scp instance",
)
class CMD(KiwiCommand):
class ListCommand(KiwiCommand):
"""List projects in this instance, services inside a project or service(s) inside a project"""
@classmethod

View file

@ -29,14 +29,12 @@ _logger = logging.getLogger(__name__)
def kiwi_command(
name: str,
command_type: KiwiCommandType,
cmd_type: KiwiCommandType = KiwiCommandType.SERVICE,
**decorator_kwargs,
) -> Callable:
def decorator(command_cls: Type[KiwiCommand]) -> Callable:
@click.command(
name,
help=command_cls.__doc__,
**decorator_kwargs,
)
@ -71,10 +69,10 @@ def kiwi_command(
else:
KiwiCommand.print_error(f"Project '{project_name}' not in kiwi-scp instance at '{ctx.directory}'!")
if command_type is KiwiCommandType.PROJECT:
if cmd_type is KiwiCommandType.PROJECT:
cmd = _project_arg(cmd)
elif command_type is KiwiCommandType.SERVICE:
elif cmd_type is KiwiCommandType.SERVICE:
cmd = _project_arg(cmd)
cmd = _services_arg(cmd)