"""Closed taxonomy of evidence-document shapes derived from content bytes.Replaces the two-member ``MediaKind`` (``PDF`` / ``IMAGE``) that was derivedfrom a *declared* MIME type. That derivation could not see inside a document,so a ZUGFeRD / Factur-X invoice -- a PDF that carries a complete machine-readable EN16931 XML payload as an embedded file -- was indistinguishable froma scan of a paper receipt. Both answered ``PDF``, and the most exactly readabledocument in the corpus was read as rendered prose.The shape is therefore derived from the bytes themselves. It exists so a readercan ask *what can be recovered exactly from this document* before choosing astrategy, and so the routing order is inspectable: a document carrying astructured record reaches no model at all."""from__future__importannotationsfromenumimportStrEnum__all__=["PDF_CONTAINER_SHAPES","STRUCTURED_DOCUMENT_SHAPES","DocumentShape"]
[docs]classDocumentShape(StrEnum):"""What a resolved evidence document actually is, by content. Members are ordered from most to least exactly readable. The three ``XML_*`` members and :attr:`PDF_EMBEDDED_XML` all carry a structured record; everything below them requires text extraction or a model. """XML_CII="xml_cii""""Standalone EN16931 Cross Industry Invoice (UN/CEFACT syntax)."""XML_UBL="xml_ubl""""Standalone EN16931 UBL invoice (OASIS syntax)."""XML_FACTURAE="xml_facturae""""Standalone Facturae 3.2.x invoice (the Spanish national format)."""PDF_EMBEDDED_XML="pdf_embedded_xml""""PDF carrying a structured invoice as an embedded file (ZUGFeRD / Factur-X)."""XML_AEAT_SII="xml_aeat_sii""""AEAT SII submission: a BATCH of ledger records, not one invoice document. Deliberately not a member of :data:`STRUCTURED_DOCUMENT_SHAPES`. That set routes a document into the single-invoice reader, and one SII file declares its record collections at ``maxOccurs=10000``; routing a batch into a singular reader would silently keep the first record and discard the rest. Which family each record belongs to -- facturas emitidas, recibidas, a baja, or one of the twelve non-invoice families -- is classified per RECORD, never per file. """XML_AEAT_VERIFACTU="xml_aeat_verifactu""""VERI*FACTU submission: a batch of registro de facturacion records. Not a member of :data:`STRUCTURED_DOCUMENT_SHAPES`, for the same reason as :attr:`XML_AEAT_SII`. Its ``RegistroFactura`` is a CHOICE of ``RegistroAlta`` or ``RegistroAnulacion`` repeated to ``maxOccurs=1000``, so a single submission may MIX registrations and cancellations and cannot be classified from the file alone. """PDF_TEXT_LAYER="pdf_text_layer""""PDF with an extractable text layer but no structured record."""PDF_SCAN="pdf_scan""""PDF whose pages carry no extractable text; readable only by rasterising."""IMAGE="image""""A bare image of a document."""UNKNOWN="unknown""""Bytes matching no recognised shape. Never guessed at, always refused."""
STRUCTURED_DOCUMENT_SHAPES:frozenset[DocumentShape]=frozenset({DocumentShape.XML_CII,DocumentShape.XML_UBL,DocumentShape.XML_FACTURAE,DocumentShape.PDF_EMBEDDED_XML,},)"""Shapes carrying a structured SINGLE-INVOICE record, readable with no model.Membership means "one document, one invoice, readable by``parse_einvoice_document``". The AEAT record-batch shapes are excluded onpurpose: they are equally structured and equally model-free, but they carry aCOLLECTION of ledger records, so admitting them here would route a batch into areader that returns one invoice and silently drop every record after the first.No single-invoice reader accepts them: the evidence path leaves them outsidethis set and refuses them as filing artefacts until a dedicated reconciliationreader exists. A future reader would need a collection return type rather thansilently discarding records.Hand-listed rather than derived, so adding a structured member forces adeliberate decision about which of the two readers it belongs to."""PDF_CONTAINER_SHAPES:frozenset[DocumentShape]=frozenset({DocumentShape.PDF_EMBEDDED_XML,DocumentShape.PDF_TEXT_LAYER,DocumentShape.PDF_SCAN,},)"""Shapes whose bytes are a PDF, whatever the PDF turns out to carry.The read paths that rasterise pages, or try a text layer before falling back tovision, need exactly this question: is this a PDF container? They previouslyasked it of ``MediaKind``, which is derived from the STORED MIME TYPE -- a labelthe producer attached, which cannot see inside the document. That is the sameblindness the shape probe exists to remove, so asking the label was the oneremaining way a caller could be told "PDF" by something that never opened it.Hand-listed for the same reason as the sets above: a new PDF-carrying shapeshould force a decision about whether page rasterisation is meaningful for it,rather than being swept in by a name prefix."""