from __future__ import annotations import logging from datetime import timedelta from logging.handlers import RotatingFileHandler from pathlib import Path from flask import Flask from .services import Office365Service from .settings import Settings, load_settings from .tasks import BackgroundTaskManager def _configure_logging(app: Flask) -> None: log_dir = Path(app.root_path).parent / "logs" log_dir.mkdir(parents=True, exist_ok=True) log_path = log_dir / "office365_admin.log" root_logger = logging.getLogger() formatter = logging.Formatter("%(asctime)s [%(levelname)s] %(name)s - %(message)s") if not any(isinstance(handler, RotatingFileHandler) for handler in root_logger.handlers): file_handler = RotatingFileHandler( log_path, maxBytes=2 * 1024 * 1024, backupCount=5, encoding="utf-8", ) file_handler.setFormatter(formatter) root_logger.addHandler(file_handler) root_logger.setLevel(logging.INFO) app.logger.info("Logging initialized at %s", log_path) def create_app( settings_override: Settings | None = None, service_factory=None, task_manager_factory=None, ) -> Flask: settings = settings_override or load_settings() app = Flask(__name__, template_folder="templates", static_folder="static") app.config["SETTINGS"] = settings app.config["JSON_AS_ASCII"] = False app.secret_key = settings.session_secret app.permanent_session_lifetime = timedelta(hours=8) _configure_logging(app) if service_factory is None: service = Office365Service(settings) elif callable(service_factory): service = service_factory(settings) else: service = service_factory app.extensions["office365_service"] = service if task_manager_factory is None: task_manager = BackgroundTaskManager() elif callable(task_manager_factory): task_manager = task_manager_factory() else: task_manager = task_manager_factory app.extensions["task_manager"] = task_manager from .routes import bp app.register_blueprint(bp) return app