Source code for cadrumo.adapters.outbound.aeat.sede.declarations_remote
"""Remote-read guard and CSV-extraction helpers for the declarations fetch adapter.The read guards (``assert_read_http``, ``assert_read_browser_action``) areconsumed only by ``_declarations_fetch.py``, which delegates to them for itsown ``_assert_read_http`` / ``_assert_read_browser_action`` wrappers.``_walker.py`` — a separate declarations-register surface — declares its ownnon-delegating read guards and never imports from this module.``extract_csv_from_url`` is shared more widely, by ``_declarations.py`` and``_parse.py`` as well. External consumers import it from this defining module."""from__future__importannotationsfromurllib.parseimportparse_qs,urlsplitfrompydanticimportAnyUrlfrom.....core.aeat_csvimportis_aeat_csvfrom.....core.identity.aeat_csvimportAeatCsvfrom.....domain.calculations.registry.remote_state_guardimport(RemoteOperation,RemoteStateGuardPolicy,assert_remote_operation_allowed,)from.errorsimportSedeParseError
[docs]defassert_read_http(method:str,url:str,*,policy:RemoteStateGuardPolicy,)->None:"""Refuse an HTTP call the read-only remote-state policy does not permit."""assert_remote_operation_allowed(policy,RemoteOperation(kind="http",method=method,url=AnyUrl(url)),)
[docs]defassert_read_browser_action(action:str,*,policy:RemoteStateGuardPolicy,)->None:"""Refuse a browser action the read-only remote-state policy does not permit."""assert_remote_operation_allowed(policy,RemoteOperation(kind="browser_action",action=action),)
[docs]defextract_csv_from_url(url:str)->AeatCsv:"""Extract and shape-validate the ``CSV`` query parameter from a cotejo URL. The return names :data:`~cadrumo.core.identity.aeat_csv.AeatCsv` to document an invariant this function already enforces rather than to add one: the :func:`~cadrumo.core.aeat_csv.is_aeat_csv` guard below is the same 8-32 uppercase alphanumeric shape the alias constrains toward, so every value returned here is already in the alias's canonical form. A plain function's annotation runs no validator; the guard is what refuses, and the alias is what names the contract the guard implements. """parsed=urlsplit(url)qs=parse_qs(parsed.query)csv_values=qs.get("CSV",[])ifnotcsv_values:raiseSedeParseError(f"cotejo URL missing CSV query: {url!r}")iflen(csv_values)>1:raiseSedeParseError(f"cotejo URL has {len(csv_values)} CSV values; AEAT only emits one: {url!r}",)csv=csv_values[0]ifnotis_aeat_csv(csv):raiseSedeParseError(f"cotejo URL CSV {csv!r} does not match AEAT shape (expected 8-32 uppercase alphanumeric chars)",)returncsv