aeat.adapters.inbound.pdf._pdfplumber module¶
Shared pdfplumber-backed page-text extraction.
Backs the per-format extract_pages_text / extract_pages_text_from_bytes
public surfaces (borrador, declaracion, justificante). Each per-format
backend remains the public entry point and is responsible for binding
its own format identity to the primitive: it injects the format-specific
error class plus the diagnostic phrasing that error messages must carry.
Public surface¶
Three return-shape families are supported:
extract_pages_text_from_path()/extract_pages_text_from_bytes()— tuple-of-stripped-strings, empty-PDF guard raised aserror_class. Used by borrador and declaracion.extract_pages_text_concatenated()— singlestrjoined from the non-empty pages, no empty-PDF guard. Used by justificante where layout-sensitive parsing happens downstream.extract_pages_text_with_fast_path()— wraps the path-based primitive with an optional caller-supplied fast-path extractor (e.g. the pypdfium2 path used by declaracion). The fast-path runs first; if it returnsNonethe function falls back to pdfplumber.
All path-based diagnostics use the redacted <input-pdf> label. The bytes
entry point is for secure-storage flows that should never materialise source
PDF bytes as a plaintext temporary file.
The pdfminer logger level is governed centrally by
aeat.core.logging.configure_logging() dictConfig (WARNING).
- extract_pages_text_from_path(pdf_path, *, error_class, not_found_label, pdf_label)[source]¶
Read
pdf_pathpage-by-page and return one stripped string per page.- Parameters:
pdf_path (
Path) – Filesystem path of the PDF to read.error_class (
type[Exception]) – Format-specific exception class to raise on every failure mode (missing file, pdfplumber failure, empty PDF). Each per-format backend injects its own (e.g.BorradorParseError,DeclaracionParseError) so callers canexceptby their familiar concrete type.not_found_label (
str) – Prefix the file-not-found message uses (e.g."Modelo 100 PDF not found","declaración PDF not found").pdf_label (
str) – Article-prefixed phrase the empty-PDF message uses (e.g."PDF","the PDF") so the diagnostic reads naturally per format.
- Return type:
- Returns:
Tuple of stripped per-page text in page order. Empty pages preserve their slot as the empty string.
- Raises:
Exception – An instance of the supplied
error_classwhen the file does not exist, when pdfplumber cannot open it, or when every page is empty (suggesting a scan-only / XFA PDF without an embedded text layer).
- extract_pages_text_from_bytes(pdf_bytes, *, error_class, pdf_label, source_label='in-memory PDF')[source]¶
Extract text from PDF bytes without materialising a plaintext file.
- Parameters:
pdf_bytes (
bytes) – In-memory source PDF bytes, typically read from secure storage.error_class (
type[Exception]) – Format-specific exception class raised on pdfplumber failure or an all-empty text layer.pdf_label (
str) – Article-prefixed phrase for the empty-PDF diagnostic.source_label (
str) – Redacted source phrase used in errors. Defaults to"in-memory PDF".
- Return type:
- Returns:
Tuple of stripped per-page text in page order.
- extract_pages_text_concatenated(pdf_path, *, error_class)[source]¶
Return the concatenated text of
pdf_pathusing pdfplumber.Skips empty pages and joins the remaining
page.extract_text()output with newlines. Unlikeextract_pages_text_from_path(), this helper does NOT raise on an all-empty PDF; downstream layout-sensitive parsers (justificante) decide what an empty document means in their own domain terms.- Parameters:
- Return type:
- Returns:
Single string with every non-empty page’s text joined by newlines. May be empty if every page is empty.
- Raises:
Exception – An instance of the supplied
error_classwhen pdfplumber cannot open the file.
- extract_pages_text_with_fast_path(pdf_path, *, error_class, not_found_label, pdf_label, fast_path_extractor=None)[source]¶
Try
fast_path_extractorfirst, falling back to pdfplumber.The fast-path callable receives the same
pdf_pathand must return either a tuple of stripped per-page strings (consumed verbatim) orNoneto signal “fall through to pdfplumber”. Format-specific extractors (e.g. the pypdfium2 path used by declaracion with declaration-content canary regexes) live in the calling module so the canonical primitive stays content-neutral.When
fast_path_extractorisNonethis function is equivalent toextract_pages_text_from_path().