from abc import ABC, abstractmethod from typing import Callable, Type, TYPE_CHECKING from flask import Blueprint from flask.views import View if TYPE_CHECKING: from tofu_api.app import App __all__ = [ 'BaseBlueprint', ] class BaseBlueprint(Blueprint, ABC): """ Base class for Flask blueprints. """ # Reference to the application object app: 'App' @property @abstractmethod def name(self) -> str: """ The name of the blueprint. Will be prepended to each endpoint name. """ raise NotImplementedError @property @abstractmethod def import_name(self) -> str: """ The name of the blueprint package. Should be set to `__name__`. """ raise NotImplementedError @property @abstractmethod def url_prefix(self) -> str: """ Prefix for all URLs. """ raise NotImplementedError def __init__(self, app: 'App'): """ Initialize blueprint. Needs the Flask application object. """ super().__init__( name=self.name, import_name=self.import_name, url_prefix=self.url_prefix, ) self.app = app self.init_blueprint() @abstractmethod def init_blueprint(self) -> None: """ Register child blueprints and URL rules. """ raise NotImplementedError @staticmethod def create_view_func(view_cls: Type[View], *args, **kwargs) -> Callable: """ Helper function to create a view function from a `View` class using `view_cls.as_view()`. All arguments are passed to the constructor of the view class. """ return view_cls.as_view(view_cls.__name__, *args, **kwargs)