[Script] Enhanced and added future compatibility for API export.
* Python >= 3.9 required for API export.
This commit is contained in:
parent
900b5efff5
commit
85f83f46d5
|
@ -104,13 +104,13 @@ class DrinkPriceVolume(db.Model, ModelSerializeMixin):
|
||||||
|
|
||||||
__tablename__ = "drink_price_volume"
|
__tablename__ = "drink_price_volume"
|
||||||
id: int = db.Column("id", db.Integer, primary_key=True)
|
id: int = db.Column("id", db.Integer, primary_key=True)
|
||||||
volume: float = db.Column(db.Numeric(precision=5, scale=2, asdecimal=False))
|
|
||||||
prices: [DrinkPrice] = db.relationship(DrinkPrice, back_populates="volume", cascade="all,delete,delete-orphan")
|
|
||||||
ingredients: Union[DrinkIngredient, ExtraIngredient] = []
|
|
||||||
# TODO: Really protected or just not exported (e.g. name_)?
|
|
||||||
_ingredients: [Ingredient] = db.relationship("Ingredient", foreign_keys=Ingredient.volume_id)
|
|
||||||
|
|
||||||
drink_id = db.Column(db.Integer, db.ForeignKey("drink.id"), nullable=False)
|
drink_id = db.Column(db.Integer, db.ForeignKey("drink.id"), nullable=False)
|
||||||
|
volume: float = db.Column(db.Numeric(precision=5, scale=2, asdecimal=False))
|
||||||
|
ingredients: list[DrinkIngredient, ExtraIngredient] = []
|
||||||
|
|
||||||
|
prices: list[DrinkPrice] = db.relationship(DrinkPrice, back_populates="volume", cascade="all,delete,delete-orphan")
|
||||||
|
# TODO: Really protected or just not exported (e.g. name_)?
|
||||||
|
_ingredients: list[Ingredient] = db.relationship("Ingredient", foreign_keys=Ingredient.volume_id)
|
||||||
|
|
||||||
|
|
||||||
class Drink(db.Model, ModelSerializeMixin):
|
class Drink(db.Model, ModelSerializeMixin):
|
||||||
|
@ -127,8 +127,8 @@ class Drink(db.Model, ModelSerializeMixin):
|
||||||
cost_price_pro_volume: Optional[float] = db.Column(db.Numeric(precision=5, scale=3, asdecimal=False))
|
cost_price_pro_volume: Optional[float] = db.Column(db.Numeric(precision=5, scale=3, asdecimal=False))
|
||||||
cost_price_package_netto: Optional[float] = db.Column(db.Numeric(precision=5, scale=3, asdecimal=False))
|
cost_price_package_netto: Optional[float] = db.Column(db.Numeric(precision=5, scale=3, asdecimal=False))
|
||||||
|
|
||||||
tags: list[Tag] = db.relationship("Tag", secondary=drink_tag_association, cascade="save-update, merge")
|
_type_id = db.Column("type_id", db.Integer, db.ForeignKey("drink_type.id"))
|
||||||
type_id_ = db.Column("type_id", db.Integer, db.ForeignKey("drink_type.id"))
|
|
||||||
type: DrinkType = db.relationship("DrinkType")
|
|
||||||
|
|
||||||
volumes: [DrinkPriceVolume] = db.relationship(DrinkPriceVolume)
|
tags: list[Tag] = db.relationship("Tag", secondary=drink_tag_association, cascade="save-update, merge")
|
||||||
|
type: DrinkType = db.relationship("DrinkType", foreign_keys=[_type_id])
|
||||||
|
volumes: list[DrinkPriceVolume] = db.relationship(DrinkPriceVolume)
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
|
from __future__ import annotations # TODO: Remove if python requirement is >= 3.10
|
||||||
import inspect
|
import inspect
|
||||||
import argparse
|
import argparse
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
import pkg_resources
|
import pkg_resources
|
||||||
|
|
||||||
from flaschengeist.config import config
|
from flaschengeist.config import config
|
||||||
|
@ -27,7 +29,8 @@ class PrefixMiddleware(object):
|
||||||
class InterfaceGenerator:
|
class InterfaceGenerator:
|
||||||
known = []
|
known = []
|
||||||
classes = {}
|
classes = {}
|
||||||
mapper = {"str": "string", "int": "number", "float": "number", "date": "Date", "datetime": "Date", "NoneType": "null"}
|
mapper = {"str": "string", "int": "number", "float": "number", "date": "Date", "datetime": "Date",
|
||||||
|
"NoneType": "null"}
|
||||||
|
|
||||||
def __init__(self, namespace, filename):
|
def __init__(self, namespace, filename):
|
||||||
self.basename = ""
|
self.basename = ""
|
||||||
|
@ -36,51 +39,65 @@ class InterfaceGenerator:
|
||||||
self.this_type = None
|
self.this_type = None
|
||||||
|
|
||||||
def pytype(self, cls):
|
def pytype(self, cls):
|
||||||
if isinstance(cls, list):
|
a = self._pytype(cls)
|
||||||
return "", "Array<{}>".format(self.pytype(cls[0])[1])
|
print(f"{cls} -> {a}")
|
||||||
if sys.version_info >= (3, 8):
|
return a
|
||||||
import typing
|
|
||||||
|
|
||||||
if isinstance(cls, typing.ForwardRef):
|
def _pytype(self, cls):
|
||||||
return "", "this" if cls.__forward_arg__ == self.this_type else cls.__forward_arg__
|
import typing
|
||||||
if typing.get_origin(cls) == typing.Union:
|
origin = typing.get_origin(cls)
|
||||||
types = typing.get_args(cls)
|
arguments = typing.get_args(cls)
|
||||||
if len(types) == 2 and types[-1] is type(None):
|
|
||||||
return "?", self.pytype(types[0])[1]
|
if origin is typing.ForwardRef: # isinstance(cls, typing.ForwardRef):
|
||||||
else:
|
return "", "this" if cls.__forward_arg__ == self.this_type else cls.__forward_arg__
|
||||||
return "", "|".join([self.pytype(pt)[1] for pt in types])
|
if origin is typing.Union:
|
||||||
if hasattr(cls, "__name__"):
|
print(f"A1: {arguments[1]}")
|
||||||
if cls.__name__ in self.mapper:
|
if len(arguments) == 2 and arguments[1] is type(None):
|
||||||
return "", self.mapper[cls.__name__]
|
return "?", self.pytype(arguments[0])[1]
|
||||||
else:
|
else:
|
||||||
return "", cls.__name__
|
return "", "|".join([self.pytype(pt)[1] for pt in arguments])
|
||||||
|
if origin is list:
|
||||||
|
return "", "Array<{}>".format("|".join([self.pytype(a_type)[1] for a_type in arguments]))
|
||||||
|
|
||||||
|
name = cls.__name__ if hasattr(cls, "__name__") else cls if isinstance(cls, str) else None
|
||||||
|
if name is not None:
|
||||||
|
if name in self.mapper:
|
||||||
|
return "", self.mapper[name]
|
||||||
|
else:
|
||||||
|
return "", name
|
||||||
print(
|
print(
|
||||||
"WARNING: This python version might not detect all types (try >= 3.8). Could not identify >{}<".format(cls)
|
"WARNING: This python version might not detect all types (try >= 3.9). Could not identify >{}<".format(cls)
|
||||||
)
|
)
|
||||||
return "?", "any"
|
return "?", "any"
|
||||||
|
|
||||||
def walker(self, module):
|
def walker(self, module):
|
||||||
|
if sys.version_info < (3, 9):
|
||||||
|
raise RuntimeError("Python >= 3.9 is required to export API")
|
||||||
|
import typing
|
||||||
|
|
||||||
if (
|
if (
|
||||||
inspect.ismodule(module[1])
|
inspect.ismodule(module[1])
|
||||||
and module[1].__name__.startswith(self.basename)
|
and module[1].__name__.startswith(self.basename)
|
||||||
and module[1].__name__ not in self.known
|
and module[1].__name__ not in self.known
|
||||||
):
|
):
|
||||||
self.known.append(module[1].__name__)
|
self.known.append(module[1].__name__)
|
||||||
for cls in inspect.getmembers(module[1], lambda x: inspect.isclass(x) or inspect.ismodule(x)):
|
for cls in inspect.getmembers(module[1], lambda x: inspect.isclass(x) or inspect.ismodule(x)):
|
||||||
self.walker(cls)
|
self.walker(cls)
|
||||||
elif (
|
elif (
|
||||||
inspect.isclass(module[1])
|
inspect.isclass(module[1])
|
||||||
and module[1].__module__.startswith(self.basename)
|
and module[1].__module__.startswith(self.basename)
|
||||||
and module[0] not in self.classes
|
and module[0] not in self.classes
|
||||||
and not module[0].startswith("_")
|
and not module[0].startswith("_")
|
||||||
and hasattr(module[1], "__annotations__")
|
and hasattr(module[1], "__annotations__")
|
||||||
):
|
):
|
||||||
self.this_type = module[0]
|
self.this_type = module[0]
|
||||||
d = {
|
print("\n\n" + module[0] + "\n")
|
||||||
param: self.pytype(ptype)
|
d = {}
|
||||||
for param, ptype in module[1].__annotations__.items()
|
for param, ptype in typing.get_type_hints(module[1], globalns=None, localns=None).items():
|
||||||
if not param.startswith("_") and not param.endswith("_")
|
if not param.startswith("_") and not param.endswith("_"):
|
||||||
}
|
print(f"{param} ::: {ptype}")
|
||||||
|
d[param] = self.pytype(ptype)
|
||||||
|
|
||||||
if len(d) == 1:
|
if len(d) == 1:
|
||||||
key, value = d.popitem()
|
key, value = d.popitem()
|
||||||
self.classes[module[0]] = value[1]
|
self.classes[module[0]] = value[1]
|
||||||
|
|
Loading…
Reference in New Issue