Refactor (Welle C): create_app()-Factory einführen
- App-Aufbau in create_app(config) gekapselt; Blueprint-Importe und -Registrierung, CSRF, DB-Init, Pfade/Version dort. - app = create_app() am Modulende -> 'from app import app, db' und die bestehenden 80 Tests bleiben unverändert grün. - create_app(config) erlaubt isolierte Test-Apps (z.B. TESTING, In-Memory-DB) ohne den FLASK_TESTING-Env-Hack. - DB-Check/Lektion-Laden in _load_lessons_or_exit() ausgelagert, weiterhin nur im Normalbetrieb. - Obsoletes app.py-E402-Ignore aus ruff.toml entfernt (Importe jetzt funktionslokal). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
814b3f45cb
commit
c2663c0801
2 changed files with 59 additions and 51 deletions
108
app.py
108
app.py
|
|
@ -17,54 +17,8 @@ logging.basicConfig(
|
|||
)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Flask App erstellen
|
||||
app = Flask(__name__)
|
||||
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///typewriter.db'
|
||||
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
|
||||
app.secret_key = helpers.get_or_create_secret_key()
|
||||
|
||||
# CSRF-Schutz aktivieren
|
||||
csrf = CSRFProtect(app)
|
||||
|
||||
# Datenbank initialisieren
|
||||
db.init_app(app)
|
||||
|
||||
# Initialisiere Pfade für helpers
|
||||
with app.app_context():
|
||||
helpers.initialize_paths(app.root_path)
|
||||
|
||||
# VERSION aus helpers laden
|
||||
VERSION = helpers.get_version()
|
||||
|
||||
# Globale Template-Variablen
|
||||
@app.context_processor
|
||||
def inject_globals():
|
||||
"""Stellt globale Variablen für alle Templates bereit"""
|
||||
return {'APP_VERSION': VERSION}
|
||||
|
||||
|
||||
# Blueprints importieren und registrieren
|
||||
from routes.main import main_bp
|
||||
from routes.training import training_bp
|
||||
from routes.statistics import statistics_bp
|
||||
from routes.settings import settings_bp
|
||||
from routes.session import session_bp
|
||||
from routes.utils import utils_bp, shutdown
|
||||
|
||||
app.register_blueprint(main_bp)
|
||||
app.register_blueprint(training_bp)
|
||||
app.register_blueprint(statistics_bp)
|
||||
app.register_blueprint(settings_bp)
|
||||
app.register_blueprint(session_bp)
|
||||
app.register_blueprint(utils_bp)
|
||||
|
||||
# CSRF-Ausnahme gezielt nur für die Shutdown-Route.
|
||||
# /repair_json und /recreate_lessons bleiben damit CSRF-geschützt.
|
||||
csrf.exempt(shutdown)
|
||||
|
||||
|
||||
# Datenbank-Status prüfen und Lektionen laden (nur wenn nicht im Test-Modus)
|
||||
if not app.config.get('TESTING', False) and os.environ.get('FLASK_TESTING') != 'true':
|
||||
def _load_lessons_or_exit(app: Flask) -> None:
|
||||
"""Prüft die Datenbank und lädt die Lektionen (nur im Normalbetrieb)."""
|
||||
with app.app_context():
|
||||
db_ready = helpers.check_database_status(db.engine)
|
||||
|
||||
|
|
@ -85,10 +39,66 @@ if not app.config.get('TESTING', False) and os.environ.get('FLASK_TESTING') != '
|
|||
logger.info(f"{len(helpers.lessons)} Lektionen geladen")
|
||||
|
||||
|
||||
def create_app(config: dict | None = None) -> Flask:
|
||||
"""Application-Factory: erstellt und konfiguriert die Flask-App.
|
||||
|
||||
Args:
|
||||
config: Optionale Config-Overrides (z.B. für Tests).
|
||||
"""
|
||||
app = Flask(__name__)
|
||||
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///typewriter.db'
|
||||
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
|
||||
app.secret_key = helpers.get_or_create_secret_key()
|
||||
|
||||
if config:
|
||||
app.config.update(config)
|
||||
|
||||
# CSRF-Schutz und Datenbank initialisieren
|
||||
csrf = CSRFProtect(app)
|
||||
db.init_app(app)
|
||||
|
||||
# Pfade und Version
|
||||
helpers.initialize_paths(app.root_path)
|
||||
app.config['APP_VERSION'] = helpers.get_version()
|
||||
|
||||
@app.context_processor
|
||||
def inject_globals():
|
||||
"""Stellt globale Variablen für alle Templates bereit"""
|
||||
return {'APP_VERSION': app.config['APP_VERSION']}
|
||||
|
||||
# Blueprints importieren und registrieren
|
||||
from routes.main import main_bp
|
||||
from routes.training import training_bp
|
||||
from routes.statistics import statistics_bp
|
||||
from routes.settings import settings_bp
|
||||
from routes.session import session_bp
|
||||
from routes.utils import utils_bp, shutdown
|
||||
|
||||
app.register_blueprint(main_bp)
|
||||
app.register_blueprint(training_bp)
|
||||
app.register_blueprint(statistics_bp)
|
||||
app.register_blueprint(settings_bp)
|
||||
app.register_blueprint(session_bp)
|
||||
app.register_blueprint(utils_bp)
|
||||
|
||||
# CSRF-Ausnahme gezielt nur für die Shutdown-Route.
|
||||
# /repair_json und /recreate_lessons bleiben damit CSRF-geschützt.
|
||||
csrf.exempt(shutdown)
|
||||
|
||||
# Datenbank-Status prüfen und Lektionen laden (nur im Normalbetrieb)
|
||||
if not app.config.get('TESTING', False) and os.environ.get('FLASK_TESTING') != 'true':
|
||||
_load_lessons_or_exit(app)
|
||||
|
||||
return app
|
||||
|
||||
|
||||
app = create_app()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
logger.info("=" * 50)
|
||||
logger.info("Tipptrainer gestartet")
|
||||
logger.info(f"Version: {VERSION}")
|
||||
logger.info(f"Version: {app.config['APP_VERSION']}")
|
||||
logger.info(f"Lektionen geladen: {len(helpers.lessons)}")
|
||||
logger.info("Debug-Info verfügbar unter: http://127.0.0.1:5000/debug")
|
||||
logger.info("=" * 50)
|
||||
|
|
|
|||
|
|
@ -15,5 +15,3 @@ ignore = ["E501"]
|
|||
[lint.per-file-ignores]
|
||||
# Tests setzen FLASK_TESTING bewusst VOR dem App-Import (E402)
|
||||
"tests/*" = ["E402"]
|
||||
# app.py registriert Blueprints bewusst nach App-/CSRF-Setup (E402)
|
||||
"app.py" = ["E402"]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue