inventory/inventory/__init__.py
2025-10-07 09:52:08 -05:00

109 lines
3.3 KiB
Python

from __future__ import annotations
import os
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
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.ProdConfig)
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
from .routes.reports import bp_reports
_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.User,
_models.WorkLog,
_models.WorkNote,
])
app.register_blueprint(bp_reports)
init_entry_routes(app)
init_index_routes(app)
init_listing_routes(app)
init_search_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", True):
# 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