tofu-api/tofu_api/app.py

95 lines
2.6 KiB
Python

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()