Created
June 13, 2021 16:08
-
-
Save raven4752/c522a2e81d4046da5922c3b1e08f292f to your computer and use it in GitHub Desktop.
expose python function to cmd in one line
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
a lazy wrapper to export python function directly as command line interface with one line of code | |
""" | |
import click | |
from functools import wraps, partial | |
import inspect | |
def get_prefix(key: str, prefix_set: set): | |
for i in range(1, len(key)): | |
if key[:i] not in prefix_set: | |
prefix_set.add(key[:i]) | |
return key[:i] | |
def parse_doc_string(f): | |
""" | |
parse func string and return a map with param name as key and param doc as value and func description | |
""" | |
params_name_doc_map = {} | |
func_desc = "" | |
if f.__doc__: | |
for line in f.__doc__.split('\n'): | |
if not func_desc and line: | |
func_desc = line | |
if line.strip().startswith(":param"): | |
line = line.replace(":param", "").strip().split(":") | |
if len(line) == 2: | |
params_name_doc_map[line[0]] = line[1] | |
return params_name_doc_map, func_desc | |
def lazy_cmd(func, cli_group: click.group = None): | |
signature = inspect.signature(func) | |
prefix_set = set() | |
param_doc_map, func_desc = parse_doc_string(func) | |
f = func | |
if func_desc: | |
f.__doc__ = func_desc | |
for k, v in signature.parameters.items(): | |
prefix = get_prefix(k, prefix_set) | |
help_k = param_doc_map.get(k, "") | |
if v.default is v.empty: | |
f = click.option('-' + prefix, '--' + k, help=help_k, required=True)(f) | |
else: | |
f = click.option('-' + prefix, '--' + k, help=help_k, default=v.default)(f) | |
if cli_group is not None: | |
f = cli_group.command()(f) | |
else: | |
f = click.command()(f) | |
@wraps(func) | |
def with_lazy_option_and_cmd(*args, **kwargs): | |
""" | |
use functions default params as click options | |
:param args: | |
:param kwargs: | |
:return: | |
""" | |
return f(*args, **kwargs) | |
return with_lazy_option_and_cmd | |
@click.group() | |
def cli(): | |
pass | |
@partial(lazy_cmd, cli=cli) | |
def bar(foo): | |
print("bar " + foo) | |
@partial(lazy_cmd, cli=cli) | |
def foo(bar, count=1): | |
""" | |
func def | |
:param bar: sss | |
:param count: foo name | |
:return: | |
""" | |
for n in range(count): | |
print(bar) | |
if __name__ == '__main__': | |
cli() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment