111 lines
3.4 KiB
Python
111 lines
3.4 KiB
Python
from __future__ import annotations
|
|
|
|
import os, logging, sys
|
|
|
|
from flask import Flask
|
|
from jinja_markdown import MarkdownExtension
|
|
from pathlib import Path
|
|
from sqlalchemy.engine import Engine
|
|
from sqlalchemy import event
|
|
from sqlalchemy.pool import Pool
|
|
from werkzeug.middleware.profiler import ProfilerMiddleware
|
|
|
|
import crudkit
|
|
|
|
from crudkit.integrations.flask import init_app
|
|
|
|
from .debug_pretty import init_pretty
|
|
|
|
from .routes.entry import init_entry_routes
|
|
from .routes.index import init_index_routes
|
|
from .routes.listing import init_listing_routes
|
|
from .routes.search import init_search_routes
|
|
from .routes.settings import init_settings_routes
|
|
from .routes.reports import init_reports_routes
|
|
|
|
def create_app(config_cls=crudkit.DevConfig) -> Flask:
|
|
app = Flask(__name__)
|
|
app.jinja_env.add_extension(MarkdownExtension)
|
|
|
|
init_pretty(app)
|
|
|
|
runtime = init_app(app, config=crudkit.DevConfig)
|
|
from sqlalchemy import event
|
|
|
|
engine = runtime.engine
|
|
|
|
# quick status endpoint you can hit while clicking around
|
|
@app.get("/_db_status")
|
|
def _db_status():
|
|
try:
|
|
return {"pool": engine.pool.status()}
|
|
except Exception as e:
|
|
return {"error": str(e)}, 500
|
|
|
|
crudkit.init_crud(app)
|
|
print(f"Effective DB URL: {str(runtime.engine.url)}")
|
|
|
|
from . import models as _models
|
|
_models.Base.metadata.create_all(bind=runtime.engine)
|
|
|
|
# ensure extensions carries the scoped_session from integrations.init_app
|
|
Session = app.extensions["crudkit"].get("Session")
|
|
if Session is not None:
|
|
# tell crud layer to use it for any future services
|
|
if hasattr(crudkit, "crud") and hasattr(crudkit.crud, "configure_session_factory"):
|
|
crudkit.crud.configure_session_factory(Session)
|
|
# patch any services already created before this point
|
|
try:
|
|
for svc in getattr(crudkit.crud, "_services", {}).values():
|
|
svc._session_factory = Session
|
|
except Exception:
|
|
pass
|
|
|
|
crudkit.crud.register_many([
|
|
_models.Area,
|
|
_models.Brand,
|
|
_models.DeviceType,
|
|
_models.Image,
|
|
_models.Inventory,
|
|
_models.RoomFunction,
|
|
_models.Room,
|
|
_models.Status,
|
|
_models.User,
|
|
_models.WorkLog,
|
|
_models.WorkNote,
|
|
])
|
|
|
|
init_entry_routes(app)
|
|
init_index_routes(app)
|
|
init_listing_routes(app)
|
|
init_search_routes(app)
|
|
init_settings_routes(app)
|
|
init_reports_routes(app)
|
|
|
|
@app.teardown_appcontext
|
|
def _remove_session(_exc):
|
|
sess = app.extensions["crudkit"].get("Session")
|
|
if hasattr(sess, "remove"):
|
|
try:
|
|
sess.remove()
|
|
except Exception:
|
|
pass
|
|
|
|
if app.config.get("PROFILE", False):
|
|
# Use an absolute dir under the instance path (always writable)
|
|
inst_dir = Path(app.instance_path)
|
|
inst_dir.mkdir(parents=True, exist_ok=True)
|
|
|
|
prof_dir = inst_dir / "profiler"
|
|
prof_dir.mkdir(parents=True, exist_ok=True)
|
|
|
|
# If you're using the dev reloader, guard so you don't wrap twice
|
|
if not app.debug or os.environ.get("WERKZEUG_RUN_MAIN") == "true":
|
|
app.wsgi_app = ProfilerMiddleware(
|
|
app.wsgi_app,
|
|
sort_by=("cumtime", "tottime"),
|
|
restrictions=[50],
|
|
profile_dir=str(prof_dir), # absolute path
|
|
)
|
|
|
|
return app
|