@andymitchhank/

clicky-sanic

Python

No description

fork
loading
Files
  • main.py
  • requirements.txt
main.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
from contextlib import redirect_stdout
from dataclasses import dataclass, asdict
from io import StringIO
from typing import Any

import shlex
import sys

import click
from click.exceptions import ClickException, Abort, Exit
from sanic import Sanic
from sanic.response import json


@click.command()
def hello():
    """ The simplest of all Click commands """
    click.echo('Hello world!')


@click.command()
@click.option('--count', default=1, help='Number of greetings.')
@click.option('--name', prompt='Your name', help='The person to greet.')
def hello_again(count, name):
    """Simple program that greets NAME for a total of COUNT times."""
    for x in range(count):
        click.echo('Hello %s!' % name)


@dataclass(frozen=True)
class CommandOutput:
    """ Represent our output """
    exit_code: int
    stdout: str
    stderr: str
    returned: Any


def get_output(c, *args, **kwargs):
    returned = None
    stderr = None
    exit_code = 0

    kwargs['standalone_mode'] = False

    stdout = StringIO()

    with redirect_stdout(stdout):
        try:
            returned = c(*args, **kwargs)
        except (ClickException, Exit) as e:
            exit_code = e.exit_code
            stderr = str(e)
        except Abort as e:
            exit_code = 1
            stderr = str(e)

    return CommandOutput(exit_code, stdout.getvalue(), stderr, returned)


def get_command(name, module=sys.modules[__name__]):
    """ Return a click.Command object from the specified module """
    c = getattr(module, name)
    if not isinstance(c, click.Command):
        raise AttributeError
    return c


def parse_command_string(s):
    name, *args = shlex.split(s)
    return (name, args)


def run(s):
    """ Put all the pieces together """
    commands = (parse_command_string(cs) for cs in s.split('|'))
    stdout = None
    for name, args in commands:
        obj = {'stdout': stdout}
        stdout = get_output(get_command(name), args=args, obj=obj)
        if stdout.exit_code != 0:
            break
	
    return stdout


app = Sanic()

@app.route('/', methods=['POST'])
async def run_command(request):
    return json(asdict(run(request.body.decode("utf-8"))))

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=8000)