", 413
@app.route("/", methods=["GET", "POST"])
def index():
today = datetime.now(timezone.utc).date().isoformat()
values = {"amount": "12.50", "base": "EUR", "quote": "USD", "day": today}
errors, error, result, status = {}, None, None, 200
token = session.setdefault("csrf", secrets.token_urlsafe(32))
if request.method == "POST":
# example:inputs
values = {
"amount": request.form.get("amount", ""),
"base": request.form.get("base", ""),
"quote": request.form.get("quote", ""),
"day": request.form.get("day", ""),
}
# /example:inputs
submitted = request.form.get("csrf", "")
if not submitted.isascii() or not hmac.compare_digest(submitted, token):
error, status = "This form expired. Refresh the page and try again.", 403
else:
amount_text = values["amount"].strip()
if not re.fullmatch(r"-?(?:0|[1-9][0-9]{0,8})(?:\.[0-9]{1,4})?", amount_text):
errors["amount"] = "Enter an amount with up to nine whole digits and four decimal places."
for field in ("base", "quote"):
if values[field] not in CURRENCIES:
errors[field] = "Choose one of the listed currencies."
try:
day = date.fromisoformat(values["day"])
if day.isoformat() != values["day"] or values["day"] > today:
raise ValueError()
except ValueError:
errors["day"] = "Choose a real date on or before today."
if errors:
status = 422
else:
key = os.environ.get("PARSEAPI_KEY", "").strip()
if not key or key.startswith(("parse_public_", "parse_app_")):
error, status = "The converter is unavailable. Please try again later.", 503
else:
base, quote = values["base"], values["quote"]
try:
# One interactive attempt, with one reused official SDK client.
with ParseAPI(api_key=key, timeout=10.0, retries=0) as parse:
# example:request
exchange = parse.currency.rate(base, quote, date=day.isoformat())
# /example:request
if (not isinstance(exchange, dict) or exchange.get("base") != base
or exchange.get("quote") != quote
or type(exchange.get("rate")) not in (int, float)
or not math.isfinite(exchange["rate"]) or exchange["rate"] <= 0):
raise ValueError("Unexpected rate response.")
applied = date.fromisoformat(exchange.get("date", ""))
if applied.isoformat() != exchange["date"] or applied > day:
raise ValueError("Unexpected rate date.")
# example:precision
currency = parse.currency(quote)
# /example:precision
if (not isinstance(currency, dict) or currency.get("currency") != quote
or type(currency.get("digits")) is not int or not 0 <= currency["digits"] <= 6):
raise ValueError("Currency precision is unavailable.")
# example:fields
rate = Decimal(str(exchange["rate"]))
rate_date = exchange["date"]
digits = currency["digits"]
# /example:fields
amount = Decimal(amount_text)
with localcontext() as context:
context.prec = 50
# example:convert
converted = (amount * rate).quantize(
Decimal(1).scaleb(-digits), rounding=ROUND_HALF_EVEN
)
# /example:convert
if converted == 0:
converted = abs(converted)
result = {"amount": format(amount, "f"), "base": base, "quote": quote,
"converted": format(converted, "f"), "rate": format(rate, "f"),
"rate_date": rate_date}
except ParseAPIError as failure:
if failure.status == 404:
error, status = "No reference rate is available for this pair and date. Try another date.", 422
else:
error, status = "The rate could not be checked. Please try again later.", 503
except httpx.RequestError:
error, status = "The rate could not be checked. Please try again later.", 503
except (ValueError, InvalidOperation, OverflowError, TypeError):
error, status = "The rate response could not be used. Please try again later.", 503
return render_template_string(PAGE, values=values, errors=errors, error=error, result=result,
currencies=CURRENCIES, today=today, csrf=token), status
if __name__ == "__main__":
app.run(host="127.0.0.1", port=int(os.environ.get("PORT", "8000")), debug=False, use_reloader=False)