import os from pathlib import Path from flask import Flask from config import CONFIGS from .extensions import csrf, db, login_manager, migrate def create_app(config_name: str | None = None) -> Flask: """Create and configure an isolated Steady application instance.""" app = Flask(__name__, instance_relative_config=True) selected_config = config_name or os.environ.get("STEADY_ENV", "development") try: app.config.from_object(CONFIGS[selected_config]) except KeyError as exc: valid_names = ", ".join(sorted(CONFIGS)) raise ValueError( f"Unknown configuration {selected_config!r}; choose {valid_names}." ) from exc Path(app.instance_path).mkdir(parents=True, exist_ok=True) _validate_config(app) _initialize_extensions(app) _register_blueprints(app) return app def _validate_config(app: Flask) -> None: if not app.config.get("SECRET_KEY"): raise RuntimeError("SECRET_KEY must be set outside development and testing.") def _initialize_extensions(app: Flask) -> None: db.init_app(app) migrate.init_app(app, db) login_manager.init_app(app) csrf.init_app(app) login_manager.login_view = "auth.login" login_manager.login_message_category = "info" def _register_blueprints(app: Flask) -> None: # Imports stay local so feature modules do not create circular imports. from .auth import bp as auth_blueprint from .core import bp as core_blueprint from .tasks import bp as tasks_blueprint app.register_blueprint(core_blueprint) app.register_blueprint(auth_blueprint, url_prefix="/auth") app.register_blueprint(tasks_blueprint, url_prefix="/tasks")