import logging import os import sys import warnings from flask import Flask from tofu_api.api import TofuApiBlueprint from tofu_api.common.config import Config from tofu_api.common.json import JSONProvider from tofu_api.common.rest import RestApiErrorHandler from tofu_api.dependencies import Dependencies # Enable deprecation warnings in dev environment if not sys.warnoptions and os.getenv('FLASK_DEBUG'): warnings.filterwarnings('default', module='tofu_api.*') class App(Flask): """ Flask application for Tofu API. """ # Override Flask classes config_class = Config json_provider_class = JSONProvider # Set type hint for config config: Config # Dependencies container dependencies: Dependencies def __init__(self): # Set instance path to the project root directory project_root_dir = os.path.abspath('.') # Create and configure the app super().__init__( 'tofu_api', instance_path=project_root_dir, instance_relative_config=True, ) # Load app configuration from YAML file self.config.from_yaml(os.getenv('FLASK_CONFIG_FILE', default='config.yml')) # Configure logging and error handling self.configure_logging() self.configure_error_handling() # Initialize DI container self.dependencies = Dependencies() # Initialize dependencies self.init_database() # Register blueprints self.register_blueprint(TofuApiBlueprint(self)) def configure_logging(self) -> None: """ Configures the logging system. """ logging.basicConfig( level=logging.DEBUG if self.debug else logging.INFO, format='{asctime}.{msecs:03.0f} {levelname:>8} [{name}] {message}', datefmt='%Y-%m-%d %H:%M:%S', style='{', ) def configure_error_handling(self) -> None: """ Registers error handlers to the app. """ error_handler = RestApiErrorHandler(debug_mode=self.debug) error_handler.register_error_handlers(self) def init_database(self) -> None: """ Initialize database connection and models. """ # Initialize SQLAlchemy, create the database engine based on the app config db = self.dependencies.get_sqlalchemy() db.init_database(self) # Import models to populate the database metadata import tofu_api.models # noqa (unused import) def create_app() -> App: """ App factory, returns a Flask app object. """ return App()