feat: add locale formatting config and update notebook outputs
Add configurable locale/display formatting environment variables (`PALLADIUM_CURRENCY_SYMBOL`, `PALLADIUM_THOUSANDS_SEP`, `PALLADIUM_DECIMAL_SEP`) to support regional number formatting in the Streamlit app. Update `.env.example` with documentation for these new variables. Also refresh `00_setup.ipynb` with current execution outputs reflecting a live Athena connection with report templates, a selected client (Global Guardian Insurance, ID=2), and resolved NameError in assumption override cells.
This commit is contained in:
87
app/locale.py
Normal file
87
app/locale.py
Normal file
@@ -0,0 +1,87 @@
|
||||
"""
|
||||
Locale / formatting settings for the Palladium Streamlit app.
|
||||
|
||||
All settings are read from environment variables (via .env) so the same
|
||||
codebase can be deployed for different regions without code changes.
|
||||
|
||||
Environment variables
|
||||
---------------------
|
||||
PALLADIUM_CURRENCY_SYMBOL Default: "$"
|
||||
Prefix shown before monetary values (e.g. "$", "€", "£", "CAD ").
|
||||
|
||||
PALLADIUM_THOUSANDS_SEP Default: ","
|
||||
Thousands separator used in number display (e.g. "," for Americas,
|
||||
"." for continental Europe, " " for some locales).
|
||||
|
||||
PALLADIUM_DECIMAL_SEP Default: "."
|
||||
Decimal separator (e.g. "." for Americas/UK, "," for continental Europe).
|
||||
|
||||
Note: Streamlit's NumberColumn ``format`` uses printf-style strings.
|
||||
The ``%,`` flag (thousands separator) is supported in Streamlit ≥ 1.31.
|
||||
For non-standard separators (e.g. European "." thousands / "," decimal)
|
||||
the values are pre-formatted as strings and displayed in TextColumns.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
|
||||
|
||||
def _env(key: str, default: str) -> str:
|
||||
return os.environ.get(key, default).strip()
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Resolved settings (read once at import time; restart app to pick up changes)
|
||||
# ---------------------------------------------------------------------------
|
||||
CURRENCY_SYMBOL: str = _env("PALLADIUM_CURRENCY_SYMBOL", "$")
|
||||
THOUSANDS_SEP: str = _env("PALLADIUM_THOUSANDS_SEP", ",")
|
||||
DECIMAL_SEP: str = _env("PALLADIUM_DECIMAL_SEP", ".")
|
||||
|
||||
# True when the locale uses standard printf-compatible separators
|
||||
# (i.e. "," thousands + "." decimal — the C/POSIX default).
|
||||
# When False, we pre-format values as strings instead of relying on printf.
|
||||
_STANDARD_LOCALE: bool = THOUSANDS_SEP == "," and DECIMAL_SEP == "."
|
||||
|
||||
|
||||
def currency_fmt() -> str:
|
||||
"""Return a Streamlit NumberColumn ``format`` string for currency.
|
||||
|
||||
For standard locales returns e.g. ``"$%,.0f"`` (thousands-separated,
|
||||
no decimal places). For non-standard locales returns ``"%s"`` and
|
||||
callers should use :func:`fmt_currency` to pre-format the value.
|
||||
"""
|
||||
if _STANDARD_LOCALE:
|
||||
return f"{CURRENCY_SYMBOL}%,.0f"
|
||||
return "%s"
|
||||
|
||||
|
||||
def pct_fmt() -> str:
|
||||
"""Return a Streamlit NumberColumn ``format`` string for percentages.
|
||||
|
||||
Stores the value as a fraction (0–1) and displays as e.g. ``"20.00%"``.
|
||||
Streamlit's ``%%`` in format strings renders a literal ``%``.
|
||||
"""
|
||||
if _STANDARD_LOCALE:
|
||||
return "%.2f%%"
|
||||
return "%s"
|
||||
|
||||
|
||||
def fmt_currency(value: float) -> str:
|
||||
"""Format *value* as a currency string using the configured locale."""
|
||||
if _STANDARD_LOCALE:
|
||||
return f"{CURRENCY_SYMBOL}{value:,.0f}"
|
||||
# Non-standard: build manually
|
||||
integer_part = f"{int(abs(value)):,}".replace(",", THOUSANDS_SEP)
|
||||
sign = "-" if value < 0 else ""
|
||||
return f"{sign}{CURRENCY_SYMBOL}{integer_part}"
|
||||
|
||||
|
||||
def fmt_pct(value: float) -> str:
|
||||
"""Format *value* (0–1 fraction) as a percentage string."""
|
||||
pct = value * 100
|
||||
if _STANDARD_LOCALE:
|
||||
return f"{pct:.2f}%"
|
||||
integer_part = f"{int(pct)}"
|
||||
decimal_part = f"{abs(pct) % 1:.2f}"[1:] # ".xx"
|
||||
return f"{integer_part}{DECIMAL_SEP}{decimal_part[1:]}%"
|
||||
Reference in New Issue
Block a user