Added command.py
Module is responsible for allowing the creation, registering and initilisation of soypak commands. Added class@RegisterCommand: - used by command classes as a metaclass. Will be auto-invoked upon the class' declaration. - checks if a command is registered already with an existing name. - uses the class' `__doc__` attribute to register an entry on the help display message with name and summary. Added class@Command: - Inherited by command classes. - Keeps record of the registered commands and the instance of the class which can then be invoked during `get_command()`. - Command@get_command (static method): find and return an initialised instance of a command that has been registered. Otherwise return `None`. - Command@run (virtual): to be implemented on a child class of `Command`.
This commit is contained in:
parent
5700eea0ed
commit
500ddd2a77
58
soypak/cli/command.py
Normal file
58
soypak/cli/command.py
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
import argparse
|
||||
import sys
|
||||
import soypak.cli.parser as parser
|
||||
|
||||
|
||||
class RegisterCommand(type):
|
||||
"""Register a new command to soypak and add help information to the parser.
|
||||
|
||||
This class is to be used as metaclass for commands.
|
||||
"""
|
||||
def __init__(cls, name, bases, _dict):
|
||||
super().__init__(name, bases, _dict)
|
||||
# get the name of the command
|
||||
name = getattr(cls, "__cmd_name__", None)
|
||||
if name is None:
|
||||
raise Exception("Command has no registered name.")
|
||||
|
||||
# check if the command already exists (means we have duplicate registered name)
|
||||
if name in Command.registered_cmds:
|
||||
raise Exception("Duplicate command, already exists.")
|
||||
|
||||
# add the command to the registered list, with `name` and class object
|
||||
Command.registered_cmds[name] = cls
|
||||
# fetch the documentation for the command
|
||||
_help = cls.__doc__
|
||||
if not _help:
|
||||
raise Exception("Command does not provide a __doc__ attribute for usage.")
|
||||
# add the command to the argparse._action_groups list (will appear as a positional in help message)
|
||||
parser.SoypakParser.add_action_command(cmd=name, help=_help.split('\n')[0])
|
||||
|
||||
|
||||
class Command:
|
||||
"""Class for creating a new type of command. Keep record of the registered commands for soypak."""
|
||||
# store all registered commands. Those are commands which soypak implements
|
||||
registered_cmds: dict[str, RegisterCommand] = {}
|
||||
|
||||
def __init__(self) -> None:
|
||||
# get/create the parser instance
|
||||
self.parser = parser.SoypakParser()
|
||||
|
||||
|
||||
@staticmethod
|
||||
def get_command(name, *, args: list[str]) -> RegisterCommand | None:
|
||||
"""Fetch and initialise a registered command, or return `None` is command cannot be found."""
|
||||
return (
|
||||
Command.registered_cmds[name](data=parser.SoypakParser().namespace, args=args) if name in
|
||||
Command.registered_cmds else None
|
||||
)
|
||||
|
||||
|
||||
def die(self):
|
||||
"""System exit with status code 0"""
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
def run(self):
|
||||
"""Virtual method which must be overridden by a new implementation in the child class."""
|
||||
raise RuntimeError("Virtual method must be overridden by child class.")
|
||||
Loading…
Reference in New Issue
Block a user