import importlib import logging import os from inspect import isclass from pathlib import Path from pkgutil import iter_modules from typing import final from flask import Blueprint, Flask from starfall.config import Config from starfall.db import db from starfall.types import SnapshotQueue from starfall.web.blueprints.base import BaseBlueprint @final class WebUI: def __init__(self): self.config: Config | None = None self.queue: SnapshotQueue | None = None self.app: Flask | None = None self.blueprint: Blueprint = Blueprint("main", __name__) def run(self, config: Config, queue: SnapshotQueue): self.config = config self.queue = queue logging.getLogger("web").debug("Hello from %r", type(self)) self.app = Flask(__name__) self.app.config.update( SECRET_KEY=str(self.config.get("web.secret_key")), SQLALCHEMY_DATABASE_URI=str(self.config.get("web.database_url")), ) self.app.root_path = os.path.realpath(".") self.app.static_folder = os.path.realpath("./web/static") self.app.template_folder = "web" db.init_app(self.app) self.import_blueprints() self.app.register_blueprint(self.blueprint, options={"queue": self.queue}) self.app.run(host=self.config.get("web.host"), port=self.config.get("web.port")) def import_blueprints(self): path = os.path.realpath(os.path.dirname(__file__) + os.sep + "blueprints") for _, module_name, _ in iter_modules([path], f"{__name__}.blueprints."): if module_name.endswith("base"): continue module = importlib.import_module(module_name) for attribute_name in dir(module): attribute = getattr(module, attribute_name) if isclass(attribute) and issubclass(attribute, BaseBlueprint): globals()[attribute_name] = attribute globals()[attribute_name](self.blueprint)