# SPDX-FileCopyrightText: 2023 James R. Barlow # SPDX-License-Identifier: MPL-2.0 from __future__ import annotations import pikepdf import pytest from pikepdf import Name import ocrmypdf from ocrmypdf.pdfinfo import PdfInfo def test_block_tagged(resources): with pytest.raises(ocrmypdf.exceptions.TaggedPDFError): ocrmypdf.ocr(resources / 'tagged.pdf', '_.pdf') def test_detect_structure_tree(resources): assert PdfInfo(resources / 'tagged.pdf').has_structure_tree is True def test_structure_tree_without_markinfo_blocks(resources, tmp_path): """A PDF with a structure tree but no /MarkInfo flag is still blocked.""" untagged = tmp_path / 'struct_only.pdf' with pikepdf.open(resources / 'tagged.pdf') as pdf: del pdf.Root.MarkInfo pdf.save(untagged) info = PdfInfo(untagged) assert info.is_tagged is False assert info.has_structure_tree is True with pytest.raises(ocrmypdf.exceptions.TaggedPDFError): ocrmypdf.ocr(untagged, '_.pdf') def test_force_tagged_warns(resources, outpdf, caplog): caplog.set_level('WARNING') ocrmypdf.ocr( resources / 'tagged.pdf', outpdf, force_ocr=True, plugins=['tests/plugins/tesseract_noop.py'], ) assert 'structural markup' in caplog.text def test_tagged_pdf_mode_ignore_with_skip_text(resources, outpdf, caplog): """Ignore tagged_pdf_mode should warn but not error, and keep structure.""" caplog.set_level('WARNING') ocrmypdf.ocr( resources / 'tagged.pdf', outpdf, tagged_pdf_mode='ignore', skip_text=True, # Tagged PDF has text, so skip pages with text # output_type=pdf avoids the Ghostscript PDF/A step, whose treatment of # the structure tree is version-dependent (Ghostscript >= 10 discards it, # 9.x preserves it). We only want to assert OCRmyPDF's own behavior here. output_type='pdf', plugins=['tests/plugins/tesseract_noop.py'], ) assert 'structural markup' in caplog.text # skip-text leaves the text pages untouched, so OCRmyPDF keeps the structure tree with pikepdf.open(outpdf) as pdf: assert Name.StructTreeRoot in pdf.Root def test_tagged_pdf_mode_ignore_with_force(resources, outpdf, caplog): """Ignore tagged_pdf_mode with force mode should warn and discard structure.""" caplog.set_level('WARNING') ocrmypdf.ocr( resources / 'tagged.pdf', outpdf, tagged_pdf_mode='ignore', force_ocr=True, plugins=['tests/plugins/tesseract_noop.py'], ) assert 'structural markup' in caplog.text # force-ocr rasterizes every page, destroying the MCIDs the tree relies on with pikepdf.open(outpdf) as pdf: assert Name.StructTreeRoot not in pdf.Root assert Name.MarkInfo not in pdf.Root def test_tagged_pdf_mode_ignore_with_redo(resources, outpdf): """Redo mode rewrites the text layer, so structure is discarded.""" ocrmypdf.ocr( resources / 'tagged.pdf', outpdf, tagged_pdf_mode='ignore', redo_ocr=True, plugins=['tests/plugins/tesseract_noop.py'], ) with pikepdf.open(outpdf) as pdf: assert Name.StructTreeRoot not in pdf.Root assert Name.MarkInfo not in pdf.Root