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 os
import sys import sys
from enum import Enum, auto from enum import Enum, auto
from typing import List, Tuple, Iterable, Any, Type from typing import List, Tuple, Iterable, Type, Optional, TypeVar
import click import click
@ -11,42 +12,50 @@ from ..instance import Instance, Project
class KiwiCLI(click.MultiCommand): class KiwiCLI(click.MultiCommand):
"""Command Line Interface spread over multiple files in this directory""" """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""" """list all the commands defined by cmd_*.py files in this directory"""
return ( return [
filename[4:-3] filename[4:-3]
for filename in os.listdir(os.path.abspath(os.path.dirname(__file__))) for filename in os.listdir(os.path.abspath(os.path.dirname(__file__)))
if filename.startswith("cmd_") and filename.endswith(".py") 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""" """import and return a specific command"""
try: 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: except ImportError:
return 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: class KiwiCommand:
@staticmethod @staticmethod
def print_multi_color(*content: Tuple[str, str]): def print_multi_color(*content: Tuple[str, str]) -> None:
for message, color in content: for message, color in content:
click.secho(message, fg=color, nl=False) click.secho(message, fg=color, nl=False)
click.echo() click.echo()
@staticmethod @staticmethod
def print_header(header: str): def print_header(header: str) -> None:
click.secho(header, fg="green", bold=True) click.secho(header, fg="green", bold=True)
@staticmethod @staticmethod
def print_error(error: str): def print_error(error: str) -> None:
click.secho(error, file=sys.stderr, fg="red", bold=True) click.secho(error, file=sys.stderr, fg="red", bold=True)
@staticmethod @staticmethod
def print_list(content: Iterable[str]): def print_list(content: Iterable[str]) -> None:
for item in content: for item in content:
KiwiCommand.print_multi_color( KiwiCommand.print_multi_color(
(" - ", "green"), (" - ", "green"),
@ -54,7 +63,7 @@ class KiwiCommand:
) )
@staticmethod @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 # prompt user as per argument
while True: while True:
try: try:

View file

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

View file

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

View file

@ -13,11 +13,10 @@ from ..instance import Instance, Project
help=f"show actual config contents instead", help=f"show actual config contents instead",
) )
@kiwi_command( @kiwi_command(
"list", cmd_type=KiwiCommandType.SERVICE,
KiwiCommandType.SERVICE,
short_help="Inspect a kiwi-scp instance", 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""" """List projects in this instance, services inside a project or service(s) inside a project"""
@classmethod @classmethod

View file

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