Source code for cadrumo.adapters.outbound.aeat.sede.errors
"""Exception hierarchy for :mod:`adapters.outbound.aeat.sede`.Defines the base :exc:`SedeError` plus the narrowly-scoped subclassesraised by the sede navigation, parsing, and fetch helpers. Everysubclass extends :exc:`core.errors.hierarchy.CadrumoError` so callers cantrap the whole AEAT integration surface with a single``except CadrumoError``."""from__future__importannotationsfromcollections.abcimportMappingfromenumimportStrEnumfrom.....application.live.errorsimportLiveIvaAcquisitionFailureModefrom.....core.errors.hierarchyimportCadrumoError,CoreError
[docs]classSedeError(CadrumoError):"""Base class for post-auth AEAT sede errors. Extends :exc:`core.errors.hierarchy.CadrumoError` so callers tracking cross-package errors can catch the whole AEAT surface uniformly. """def__init__(self,message:str|None=None,*,failure_mode:SedeFailureMode|str|None=None,context:Mapping[str,object]|None=None,translated_message:str|None=None,)->None:"""Construct a Sede error with optional stable failure-mode context."""enriched_context=dict(context)ifcontextisnotNoneelse{}iffailure_modeisnotNone:failure_mode_value=failure_mode.valueifisinstance(failure_mode,SedeFailureMode)elsestr(failure_mode)enriched_context["failure_mode"]=failure_mode_valueself.failure_mode:str|None=failure_mode_valueelse:self.failure_mode=Nonesuper().__init__(message,context=enriched_contextorNone,translated_message=translated_message,)@propertydeflive_iva_failure_mode(self)->LiveIvaAcquisitionFailureMode:"""Translate the Sede taxonomy into the live application contract."""ifself.failure_mode==SedeFailureMode.AUTH_GATE_DETECTED.value:context=self.contextifisinstance(self.context,dict)else{}required_provider=str(context.get("required_auth_provider")or"").casefold()ifrequired_providerin{"certificate","certificado"}:returnLiveIvaAcquisitionFailureMode.CERTIFICATE_REQUIREDreturnLiveIvaAcquisitionFailureMode.AEAT_403ifself.failure_mode==SedeFailureMode.EXTERNAL_SHAPE_CHANGED.value:returnLiveIvaAcquisitionFailureMode.DOM_DRIFTifself.failure_mode==SedeFailureMode.LIVE_NAVIGATION_FAILED.value:returnLiveIvaAcquisitionFailureMode.LIVE_NAVIGATION_FAILEDreturnLiveIvaAcquisitionFailureMode.UNKNOWN
[docs]classSedeFailureMode(StrEnum):"""Closed post-auth Sede failure modes surfaced by live browser adapters."""LIVE_NAVIGATION_FAILED="live_navigation_failed"SITE_HEALTH_FAILED="site_health_failed"BROWSER_BACKEND_FAILED="browser_backend_failed"EXTERNAL_SHAPE_CHANGED="external_shape_changed"# Surface that requires AEAT authentication (cl@ve / certificate)# which the live driver does not hold. The form navigation succeeds# at HTTP 200 but redirects to AEAT's standard 4033 / 403 error page.AUTH_GATE_DETECTED="auth_gate_detected"
[docs]classSedeNavigationError(SedeError):"""Raised when a navigation step fails (goto, click, wait)."""
[docs]classSedeParseError(SedeError):"""Raised when the captured HTML cannot be parsed to a record."""
[docs]classExpedienteNotFoundError(SedeError):"""Raised when no expediente matches the requested filter."""
[docs]classJustificanteFetchError(SedeError):"""Raised when the CSV-keyed PDF download fails or is malformed."""
[docs]classSedeValidationError(SedeError):"""Raised when data captured from Sede violates expected shape or invariants. Pydantic callbacks translate this registered error to a plain ``ValueError`` at their narrow boundary; direct sede adapter helpers keep the registered type. """
[docs]classBrowserAdapterTypeError(CoreError):"""Raised when ``BrowserContext.new_page()`` returns an unexpected type. All three sede live-adapter entry points (Renta WEB Open, NIF-IVA check, GROI check) guard the ``BrowserContext.new_page()`` return value against Playwright version skew or mock-adapter misuse. This shared error class replaces the three bare ``TypeError`` raises so callers can catch a typed, registered envelope instead of the built-in exception. """