Skip to content

refactor(document): consolidate five forked PDF extractors onto one canonical path #13886

Closed as not planned

Description

@mrveiss

Five independent PDF text extractors exist; three are live and two are fully orphaned (728 lines, zero callers).

Location Lib Wired
autobot-backend/api/knowledge.py:1065 pypdf live - KB upload
autobot-backend/media/document/pipeline.py:104 pypdf live - via media/manager.py:40
autobot-backend/knowledge/connectors/content_extraction.py:39 PyPDF2 live - gdrive.py:40, onedrive.py:44
autobot-backend/utils/document_parser.py:124 pypdf orphaned - 0 callers
autobot-backend/utils/document_extractors.py:126 pypdf orphaned - 0 callers

SECURITY-ADJACENT: the connector fork runs PyPDF2 (unmaintained) while requirements.txt:23 pins pypdf>=6.15.0 with the comment SECURITY UPDATE (improved permission checks). Google Drive and OneDrive ingestion runs on the library we upgraded away from.

Verified orphan status: grep -rn document_parser|document_extractors --include=*.py outside those two files returns nothing, not even tests.

Per the no-deletion rule the two orphans are WIRED IN, not removed: document_parser.py carries format breadth (DOC/DOCX/XLSX/PPT/PPTX/ODT/ODS/ODP/ODG) the live paths lack, and document_extractors.py carries directory-batch logic. Fold both into the survivor.

Survivor should be media/document/pipeline.py - it already returns structured ProcessingResult with confidence, page_count, document_info and an unavailable-vs-error distinction.

Blocks #13884 (empty-layer detection) and the OCR fallback from shipping five times.

Activity

  1. mrveiss commented on Aug 31, 2026

    @mrveiss
    OwnerAuthor

    Duplicate of #13893, which shipped this exact consolidation and is merged (0b913d1f59, PR #13924).

    Verification against current Dev_new_gui tree (2026-08-31):

    • autobot-backend/media/document/extraction.py is the single canonical extractor (extract_pdf, extract_docx, extract_document).
    • All five forks now delegate to it:
      • api/knowledge.py:1095 — _extract_pdf_document calls media.document.extraction.extract_pdf
      • media/document/pipeline.py — imports extract_pdf/extract_docx from media.document.extraction
      • knowledge/connectors/content_extraction.py:16 — imports extract_pdf/extract_docx from media.document.extraction
      • utils/document_parser.py:15,124,142 — _parse_pdf/_parse_docx delegate to media.document.extraction
      • utils/document_extractors.py:40,140,182 — delegates to media.document.extraction
    • grep -rn "PyPDF2" --include=*.py . → only historical comments/docstrings, no live import.
    • grep -n "PyPDF2" autobot-backend/requirements.txt → only a comment noting its removal (refactor(document): consolidate five forked PDF extractors onto one canonical path #13893), no dependency line.
    • test_only_the_canonical_module_constructs_a_pdf_reader and test_pypdf2_is_not_imported_anywhere (autobot-backend/tests/test_document_extraction_canonical_13893.py) pin exactly this as a structural guard against the fork regrowing.
    • Both orphans named in this issue's body are wired in, not deleted: document_parser.py still carries the DOC/DOCX/XLSX/PPT/PPTX/ODT/ODS/ODP/ODG format breadth (called from knowledge/documents.py), document_extractors.py's directory-batch logic is called from knowledge/documents.py::DocumentExtractor.

    Gate 2: pipeline-scripts/check-issue-close-refs.sh 13886 → clear, no forward-tracking references.

    Closing as a duplicate; #13893 carries the acceptance criteria and evidence.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions