Files
allmende-payment-system/src/allmende_payment_system/tools.py
2026-06-29 16:28:22 +02:00

111 lines
3.3 KiB
Python

import locale
import numbers
import os
from starlette.templating import Jinja2Templates
TRANSACTION_TYPE_DE = {
"deposit": "Einzahlung",
"withdrawal": "Auszahlung",
"expense": "Auslage",
"order": "Einkauf",
}
UNITS_OF_MEASURE = {"piece": "Stück"}
def format_number(value: float):
try:
return f"{value:.2f}".replace(".", ",")
except TypeError:
return value
def get_jinja_renderer() -> Jinja2Templates:
renderer = Jinja2Templates(directory="src/allmende_payment_system/templates")
renderer.env.filters["transaction_type_de"] = lambda x: TRANSACTION_TYPE_DE[x]
renderer.env.filters["units_of_measure_de"] = lambda x: UNITS_OF_MEASURE.get(x, x)
renderer.env.filters["format_number"] = format_number
renderer.env.filters["timestamp_de"] = lambda x: x.strftime("%d.%m.%Y %H:%M")
renderer.env.globals["production_mode"] = "APS_PRODUCTION_MODE" in os.environ
renderer.env.globals["read_only_mode"] = "APS_READ_ONLY" in os.environ
return renderer
def timer_context(name: str):
import time
class Timer:
def __enter__(self):
self.start = time.perf_counter()
def __exit__(self, exc_type, exc_val, exc_tb):
end = time.perf_counter()
print(f"{name} took {end - self.start:.4f} seconds")
return Timer()
import cProfile
import io
import pstats
from contextlib import contextmanager
@contextmanager
def profile(top_n: int = 20, sort_by: str = "cumulative", min_time: float = 0.001):
pr = cProfile.Profile()
pr.enable()
try:
yield
finally:
pr.disable()
s = io.StringIO()
ps = pstats.Stats(pr, stream=s).strip_dirs()
ps.sort_stats(sort_by)
ps.print_stats()
rows = []
for line in s.getvalue().splitlines():
parts = line.split(None, 5)
if len(parts) < 6:
continue
try:
cum = float(parts[3])
if cum >= min_time:
rows.append(
(
int(parts[0].split("/")[0]),
float(parts[1]),
cum,
float(parts[4]),
parts[5].strip(),
)
)
except (ValueError, IndexError):
continue
rows = rows[:top_n]
if not rows:
print("[profiler] nothing exceeded min_time threshold")
return
w = 55
print(f"\n── profile ({sort_by}, ≥{min_time}s) ──────────────────────────────")
print(f"{'calls':>7} {'tot':>8} {'cum':>8} {'percall':>8} {'function':<{w}}")
print("" * (7 + 8 + 8 + 8 + w + 6))
for calls, tot, cum, percall, loc in rows:
c = (
f"\033[91m{cum:8.4f}\033[0m"
if cum > 1
else f"\033[93m{cum:8.4f}\033[0m" if cum > 0.1 else f"{cum:8.4f}"
)
print(
f"{calls:>7} {tot:8.4f} {c} {percall:8.4f} {loc[-w:] if len(loc) > w else loc:<{w}}"
)
print(f"" * (7 + 8 + 8 + 8 + w + 6))
print(
f" {len(rows)} functions | tot accounted: {sum(r[1] for r in rows):.4f}s\n"
)