[System][Script] Improved run_flaschengeist to also export plugin models
This commit is contained in:
parent
d1fcbcf68f
commit
56a0a8e06a
|
@ -17,7 +17,8 @@ Args:
|
|||
|
||||
|
||||
class Plugin:
|
||||
"""Base class for all Plugins"""
|
||||
"""Base class for all Plugins
|
||||
If your class uses custom models add a static property called ``models``"""
|
||||
|
||||
def __init__(self, config=None, blueprint=None, permissions=[]):
|
||||
"""Constructor called by create_app
|
||||
|
|
|
@ -15,13 +15,15 @@ from flaschengeist.decorator import login_required
|
|||
from flaschengeist.controller import userController
|
||||
from flaschengeist.plugins import Plugin, update_user_hook
|
||||
|
||||
from . import balance_controller, permissions
|
||||
from . import balance_controller, permissions, models
|
||||
|
||||
MonkeyPatch.patch_fromisoformat()
|
||||
balance_bp = Blueprint("balance", __name__)
|
||||
|
||||
|
||||
class BalancePlugin(Plugin):
|
||||
models = models
|
||||
|
||||
def __init__(self, config):
|
||||
super().__init__(blueprint=balance_bp, permissions=permissions.permissions)
|
||||
|
||||
|
@ -34,8 +36,6 @@ class BalancePlugin(Plugin):
|
|||
|
||||
def install(self):
|
||||
from flaschengeist.database import db
|
||||
from .models import Transaction
|
||||
|
||||
db.create_all()
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,70 @@
|
|||
#!/usr/bin/python3
|
||||
import inspect
|
||||
import argparse
|
||||
import pkg_resources
|
||||
|
||||
|
||||
class InterfaceGenerator:
|
||||
known = []
|
||||
classes = {}
|
||||
mapper = {"str": "string", "int": "number", "float": "number", "datetime": "Date"}
|
||||
|
||||
def __init__(self, namespace, filename):
|
||||
self.basename = ""
|
||||
self.namespace = namespace
|
||||
self.filename = filename
|
||||
|
||||
def pytype(self, cls):
|
||||
if isinstance(cls, list):
|
||||
return "", "Array<{}>".format(self.pytype(cls[0])[1])
|
||||
# if typing.get_origin(cls) is typing.Optional:
|
||||
# return "?", pytype(typing.get_args(cls)[1])
|
||||
if hasattr(cls, "__name__"):
|
||||
if cls.__name__ in self.mapper:
|
||||
return "", self.mapper[cls.__name__]
|
||||
else:
|
||||
return "", cls.__name__
|
||||
return "?", "any"
|
||||
|
||||
def walker(self, module):
|
||||
if inspect.ismodule(module[1]) and module[1].__name__.startswith(self.basename) and module[1].__name__ not in self.known:
|
||||
self.known.append(module[1].__name__)
|
||||
for cls in inspect.getmembers(module[1], lambda x: inspect.isclass(x) or inspect.ismodule(x)):
|
||||
self.walker(cls)
|
||||
elif (
|
||||
inspect.isclass(module[1])
|
||||
and module[1].__module__.startswith(self.basename)
|
||||
and module[0] not in self.classes
|
||||
and not module[0].startswith("_")
|
||||
and hasattr(module[1], "__annotations__")
|
||||
):
|
||||
d = {
|
||||
param: self.pytype(ptype)
|
||||
for param, ptype in module[1].__annotations__.items()
|
||||
if not param.startswith("_") and not param.endswith("_")
|
||||
}
|
||||
if len(d) == 1:
|
||||
key, value = d.popitem()
|
||||
self.classes[module[0]] = value[1]
|
||||
else:
|
||||
self.classes[module[0]] = d
|
||||
|
||||
def run(self, models):
|
||||
self.basename = models.__name__
|
||||
self.walker(("models", models))
|
||||
|
||||
def write(self):
|
||||
with open(self.filename, "w") as file:
|
||||
file.write("declare namespace {} {{\n".format(self.namespace))
|
||||
for cls, params in self.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")
|
||||
|
||||
|
||||
def install(arguments):
|
||||
|
@ -29,62 +93,18 @@ def run(arguments):
|
|||
|
||||
def export(arguments):
|
||||
import flaschengeist.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("_") and not param.endswith("_")
|
||||
}
|
||||
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")
|
||||
gen = InterfaceGenerator(arguments.namespace, arguments.file)
|
||||
gen.run(models)
|
||||
if arguments.plugins:
|
||||
for entry_point in pkg_resources.iter_entry_points("flaschengeist.plugin"):
|
||||
plg = entry_point.load()
|
||||
if hasattr(plg, "models"):
|
||||
gen.run(plg.models)
|
||||
gen.write()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
@ -105,6 +125,7 @@ if __name__ == "__main__":
|
|||
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")
|
||||
parser_export.add_argument("--plugins", help="Also export plugins", action="store_true")
|
||||
|
||||
args = parser.parse_args()
|
||||
args.func(args)
|
||||
|
|
Loading…
Reference in New Issue