diff --git a/requirements.txt b/requirements.txt index 6c4fba73..c1993ac5 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,3 +12,5 @@ ffmpeg-python>=0.1.17 Sphinx>=2.0.1 sphinx_rtd_theme>=0.4.3 PyNaCl>=1.3.0 +werkzeug>=0.15.4 +flask>=1.0.3 diff --git a/royalnet/royalgamesweb.py b/royalnet/royalgamesweb.py new file mode 100644 index 00000000..3600844f --- /dev/null +++ b/royalnet/royalgamesweb.py @@ -0,0 +1,15 @@ +import os +from .web import create_app +from .web.blueprints import helloworld, testing + + +class TestConfig: + DB_PATH = os.environ["DB_PATH"] + REQUIRED_TABLES = set() + + +app = create_app(TestConfig, [helloworld, testing]) + + +if __name__ == "__main__": + app.run() diff --git a/royalnet/web/__init__.py b/royalnet/web/__init__.py new file mode 100644 index 00000000..35cb06a7 --- /dev/null +++ b/royalnet/web/__init__.py @@ -0,0 +1,5 @@ +from .flaskserver import create_app +from .royalprint import Royalprint +from . import blueprints + +__all__ = ["create_app", "Royalprint", "blueprints"] diff --git a/royalnet/web/alchemyhandler.py b/royalnet/web/alchemyhandler.py new file mode 100644 index 00000000..6cf2aa8e --- /dev/null +++ b/royalnet/web/alchemyhandler.py @@ -0,0 +1,21 @@ +import flask as f +from werkzeug.local import LocalProxy + + +alchemy = f.current_app.config["ALCHEMY"] + + +def get_alchemy_session(): + if "alchemy_session" not in f.g: + f.g.alchemy_session = alchemy.Session() + return f.g.alchemy_session + + +@f.current_app.teardown_appcontext +def teardown_alchemy_session(*_, **__): + _alchemy_session = f.g.pop("alchemy_session", None) + if _alchemy_session is not None: + _alchemy_session.close() + + +alchemy_session = LocalProxy(get_alchemy_session) diff --git a/royalnet/web/blueprints/__init__.py b/royalnet/web/blueprints/__init__.py new file mode 100644 index 00000000..24f425d8 --- /dev/null +++ b/royalnet/web/blueprints/__init__.py @@ -0,0 +1,4 @@ +from .helloworld import bp as helloworld +from .testing import bp as testing + +__all__ = ["helloworld", "testing"] diff --git a/royalnet/web/blueprints/helloworld.py b/royalnet/web/blueprints/helloworld.py new file mode 100644 index 00000000..cd8e77aa --- /dev/null +++ b/royalnet/web/blueprints/helloworld.py @@ -0,0 +1,11 @@ +import flask as f +from .. import Royalprint + + +bp = Royalprint("helloworld", __name__, url_prefix="/helloworld") + + +@bp.route("/") +def helloworld(): + return "Hello world!" + diff --git a/royalnet/web/blueprints/testing.py b/royalnet/web/blueprints/testing.py new file mode 100644 index 00000000..989b95af --- /dev/null +++ b/royalnet/web/blueprints/testing.py @@ -0,0 +1,13 @@ +import flask as f +from .. import Royalprint +from ...database.tables import Royal + + +bp = Royalprint("testing", __name__, url_prefix="/testing", required_tables={Royal}) + + +@bp.route("/listroyals") +def listroyals(): + from ..alchemyhandler import alchemy, alchemy_session + royals = alchemy_session.query(alchemy.Royal).all() + return f'
' diff --git a/royalnet/web/flaskserver.py b/royalnet/web/flaskserver.py new file mode 100644 index 00000000..ed22c245 --- /dev/null +++ b/royalnet/web/flaskserver.py @@ -0,0 +1,15 @@ +import typing +import flask as f +from ..database import Alchemy +from .royalprint import Royalprint + + +def create_app(config_obj: typing.Type, blueprints: typing.List[Royalprint]): + app = f.Flask(__name__) + app.config.from_object(config_obj) + required_tables = set() + for blueprint in blueprints: + required_tables = required_tables.union(blueprint.required_tables) + app.register_blueprint(blueprint) + app.config["ALCHEMY"] = Alchemy(app.config["DB_PATH"], required_tables) + return app diff --git a/royalnet/web/royalprint.py b/royalnet/web/royalprint.py new file mode 100644 index 00000000..d4b1fb14 --- /dev/null +++ b/royalnet/web/royalprint.py @@ -0,0 +1,16 @@ +import typing +import flask as f + + +class Royalprint(f.Blueprint): + def __init__(self, name, import_name, static_folder=None, + static_url_path=None, template_folder=None, + url_prefix=None, subdomain=None, url_defaults=None, + root_path=None, required_tables: typing.Optional[set] = None): + super().__init__(name, import_name, static_folder=static_folder, + static_url_path=static_url_path, template_folder=template_folder, + url_prefix=url_prefix, subdomain=subdomain, url_defaults=url_defaults, + root_path=root_path) + self.required_tables = required_tables + if self.required_tables is None: + self.required_tables = set()