~fabrixxm/climatik

bb6e1aed0ae2e8446a16a458098c53248ea988ea — fabrixxm 2 years ago dc266e6
Allow to set command name in decorator

Param `command_name` passed to decorator will override function name
1 files changed, 32 insertions(+), 3 deletions(-)

M climatik/__init__.py
M climatik/__init__.py => climatik/__init__.py +32 -3
@@ 55,17 55,43 @@ def run(prog:str=None, usage:str=None, description:str=None, **kwargs):
    execute(parser)


def command(fnc:Callable):
def _optional_arg_decorator(fn:Callable):
    """ Decorate a function decorator to allow optional parameters to be passed to the decorated decorator...

    (from https://stackoverflow.com/a/20966822. yeah! stackoverflow!)
    """
    def wrapped_decorator(*args, **kwargs):
        if (len(args)==1 and callable(args[0])):
            return fn(*args)
        else:
            def real_decorator(decoratee):
                return fn(decoratee, *args, **kwargs)
            return real_decorator
    return wrapped_decorator

@_optional_arg_decorator
def command(fnc:Callable, command_name:str=None):
    """Build subcommand from function

    Subcommand name will be the function name and arguments are parsed to build the command line.
    Optionally, subcommand name can be passed as parameter:
    
        @command('name')
        def test():
            ...


    Each positional argument will be a positional paramenter.
    Each positional argument of the decorated function will be a positional paramenter.
    
    Each optional argument will be an optional flag.

    Type hints are used to covert types from command line string.
    
    An argument with `bool` type is converted to an optional flag parameter (with default sematic as "False")
    
    To create an optional positional paramenter, use the `typing.Optional` type as hint with the parameter type,
    e.g. `Optional[str]`
    e.g. `Optional[str]` and default value `None`

    Function docstring is used to set command's help and description.



@@ 181,7 207,10 @@ def command(fnc:Callable):
        name = name.replace("_", "-")
        command['args'][name] = arg

    commands[fnc.__name__] = command
    if command_name is None:
        command_name = fnc.__name__

    commands[command_name] = command
    return fnc