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.
88 lines
3.1 KiB
Python
88 lines
3.1 KiB
Python
"""
|
||
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:]}%"
|