Source code for aeat.adapters.outbound.fx._ecb_refresh
"""Refresh the bundled ECB euro reference-rate snapshot.Maintenance utility (not on the runtime path) that re-acquires the EuropeanCentral Bank ``eurofxref-hist.xml`` full history and writes it to the bundleddata file the runtime reads offline. Fetch and write are separated so thewrite/validate path is testable without a network round-trip.See the ``ledger-fx-conversion`` ADR: the runtime stays offline against aversioned bundled snapshot; this utility updates that snapshot on release."""from__future__importannotationsimporturllib.requestfrompathlibimportPathfromurllib.parseimporturlparsefrom....core.external_constantsimportUTF_8_ENCODINGfrom._ecb_providerimport_BUNDLED_RATES,_parse_eurofxrefECB_HIST_URL="https://www.ecb.europa.eu/stats/eurofxref/eurofxref-hist.xml"
[docs]defrefresh_bundled_ecb_rates(*,source_xml:str|None=None,url:str=ECB_HIST_URL,dest:Path|None=None,)->int:"""Validate and write a fresh ECB eurofxref snapshot to the bundled file. When ``source_xml`` is given it is used directly (testable path); otherwise the history is fetched from ``url`` (must be https). The XML is parsed to confirm it is a usable eurofxref document before it overwrites the bundle. Returns the number of dated rate sets written. """xml=source_xmlifsource_xmlisnotNoneelse_fetch(url)target=destor_BUNDLED_RATES# Validate by parsing before persisting; a malformed download must not# clobber a working bundle.tmp=target.with_suffix(".xml.tmp")tmp.write_text(xml,encoding=UTF_8_ENCODING)parsed=_parse_eurofxref(tmp)ifnotparsed:tmp.unlink(missing_ok=True)raiseValueError("refreshed ECB document contained no dated rate sets")target.write_text(xml,encoding=UTF_8_ENCODING)tmp.unlink(missing_ok=True)returnlen(parsed)
def_fetch(url:str)->str:parsed=urlparse(url)if(parsed.scheme!="https"orparsed.netloc!="www.ecb.europa.eu"orparsed.path!="/stats/eurofxref/eurofxref-hist.xml"):raiseValueError(f"refusing non-https or non-ECB eurofxref URL: {url!r}")# URL is constrained to the canonical ECB eurofxref HTTPS endpoint above.withurllib.request.urlopen(url,timeout=30)asresponse:# nosemgrepreturnresponse.read().decode(UTF_8_ENCODING)__all__=["ECB_HIST_URL","refresh_bundled_ecb_rates"]