diff --git a/requirements/main.txt b/requirements/main.txt index 2b6f1fca..d6c25b7b 100644 --- a/requirements/main.txt +++ b/requirements/main.txt @@ -4,7 +4,7 @@ cffi == 1.13.2 img2pdf == 0.3.3 pdfminer.six == 20191110 -pikepdf == 1.7.0 +pikepdf == 1.8.1 Pillow >= 6.2.0 reportlab == 3.5.32 tqdm == 4.37.0 diff --git a/setup.py b/setup.py index 214bc62f..a79337c6 100644 --- a/setup.py +++ b/setup.py @@ -98,7 +98,7 @@ setup( 'cffi >= 1.9.1', # must be a setup and install requirement 'img2pdf >= 0.3.0, < 0.4', # pure Python, so track HEAD closely 'pdfminer.six >= 20181108, <= 20191110', - 'pikepdf >= 1.7.0, < 2', + 'pikepdf >= 1.8.1, < 2', 'Pillow >= 6.2.0', 'reportlab >= 3.3.0', # oldest released version with sane image handling 'tqdm >= 4', diff --git a/src/ocrmypdf/exec/qpdf.py b/src/ocrmypdf/exec/qpdf.py index 9be8692b..d46baf1c 100644 --- a/src/ocrmypdf/exec/qpdf.py +++ b/src/ocrmypdf/exec/qpdf.py @@ -17,35 +17,45 @@ """Interface to qpdf executable""" -from functools import lru_cache -from os import fspath -from subprocess import PIPE, STDOUT, CalledProcessError +from io import StringIO -from . import get_version, run +import pikepdf -@lru_cache(maxsize=1) def version(): - return get_version('qpdf', regex=r'qpdf version (.+)') + return pikepdf.__libqpdf_version__ def check(input_file, log=None): - args_qpdf = ['qpdf', '--check', fspath(input_file)] - - if log is None: - import logging as log - + pdf = None try: - run(args_qpdf, stderr=STDOUT, stdout=PIPE, universal_newlines=True, check=True) - except CalledProcessError as e: - if e.returncode == 2: - log.error("%s: not a valid PDF, and could not repair it.", input_file) - log.error("Details:") - log.error(e.output) - elif e.returncode == 3: - log.info("qpdf --check returned warnings:") - log.info(e.output) - else: - log.warning(e.output) + pdf = pikepdf.open(input_file) + except pikepdf.PdfError as e: + if log: + log.error(e) return False - return True + else: + messages = pdf.check() + for msg in messages: + if 'error' in msg.lower(): + log.error(msg) + else: + log.warning(msg) + + sio = StringIO() + linearize = None + try: + pdf.check_linearization(sio) + except RuntimeError: + pass + else: + linearize = sio.getvalue() + if linearize: + log.warning(linearize) + + if not messages and not linearize: + return True + return False + finally: + if pdf: + pdf.close()