#!/usr/bin/python3 import inspect import argparse def install(arguments): from flaschengeist.app import create_app, install_all app = create_app() with app.app_context(): install_all() def run(arguments): from flaschengeist.app import create_app app = create_app() with app.app_context(): if arguments.debug: app.run(arguments.host, arguments.port, debug=True) else: try: import bjoern bjoern.run(app, arguments.host, arguments.port, reuse_port=True) except ImportError: app.run(arguments.host, arguments.port, debug=False) def export(arguments): import flaschengeist.system.models as models known = [] classes = {} def pytype(cls): if isinstance(cls, list): return "", "Array<{}>".format(pytype(cls[0])[1]) #if typing.get_origin(cls) is typing.Optional: # return "?", pytype(typing.get_args(cls)[1]) mapper = {"str": "string", "int": "number", "float": "number", "datetime": "Date"} if hasattr(cls, "__name__"): if cls.__name__ in mapper: return "", mapper[cls.__name__] else: return "", cls.__name__ return "?", "any" def walker(mod): if inspect.ismodule(mod[1]) and mod[1].__name__.startswith(models.__name__) and mod[1].__name__ not in known: known.append(mod[1].__name__) for cls in inspect.getmembers(mod[1], lambda x: inspect.isclass(x) or inspect.ismodule(x)): walker(cls) elif ( inspect.isclass(mod[1]) and mod[1].__module__.startswith(models.__name__) and mod[0] not in classes and not mod[0].startswith("_") and hasattr(mod[1], "__annotations__") ): d = {param: pytype(ptype) for param, ptype in mod[1].__annotations__.items() if not param.startswith("_")} if len(d) == 1: key, value = d.popitem() classes[mod[0]] = value[1] else: classes[mod[0]] = d from flaschengeist.app import create_app app = create_app() with app.app_context(): walker(("models", models)) with open(arguments.file, "w") as file: file.write("declare namespace {} \{\n".format(arguments.namespace)) for cls, params in classes.items(): if isinstance(params, str): file.write("\ttype {} = {};\n".format(cls, params)) else: file.write("\tinterface {} {{\n".format(cls)) for name in params: file.write("\t\t{}{}: {};\n".format(name, *params[name])) file.write("\t}\n") file.write("}\n") if __name__ == "__main__": # create the top-level parser parser = argparse.ArgumentParser() subparsers = parser.add_subparsers(help="sub-command help", dest="sub_command") subparsers.required = True parser_run = subparsers.add_parser("run", help="run flaschengeist") parser_run.set_defaults(func=run) parser_run.add_argument("--host", help="set hostname to listen on", default="127.0.0.1") parser_run.add_argument("--port", help="set port to listen on", type=int, default=5000) parser_run.add_argument("--debug", help="run in debug mode", action="store_true") parser_install = subparsers.add_parser( "install", help="run database setup for flaschengeist and all installed plugins" ) parser_install.set_defaults(func=install) parser_export = subparsers.add_parser("export", help="export models to typescript interfaces") parser_export.set_defaults(func=export) parser_export.add_argument("--file", help="Filename where to save", default="flaschengeist.d.ts") parser_export.add_argument("--namespace", help="Namespace of declarations", default="FG") args = parser.parse_args() args.func(args)