Refactor exit codes; test for missing tessdata
Some versions of tesseract installed by homebrew end up without a functional tessdata folder, and tesseract is not helpful in this situation, so add a new test to make sure our output is at least indicative of the problem. In the process of properly handling return codes I discovered test_override_metadata triggers a NPE inside JHOVE probably due to the Unicode character checking. This could be specific to my JRE (1.6.0_65, Oracle) but it's probably JHOVE's fault. A valid PDF/A (per Acrobat) is still generated.
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
from enum import IntEnum
|
||||
|
||||
|
||||
class ExitCode(IntEnum):
|
||||
bad_args = 1
|
||||
input_file = 2
|
||||
missing_dependency = 3
|
||||
invalid_output_pdfa = 4
|
||||
file_access_error = 5
|
||||
already_done_ocr = 6
|
||||
other_error = 15
|
||||
|
||||
+9
-16
@@ -33,7 +33,7 @@ from .pageinfo import pdf_get_all_pageinfo
|
||||
from .pdfa import generate_pdfa_def
|
||||
from . import ghostscript
|
||||
from . import tesseract
|
||||
|
||||
from . import ExitCode
|
||||
|
||||
warnings.simplefilter('ignore', pypdf.utils.PdfReadWarning)
|
||||
|
||||
@@ -43,13 +43,6 @@ JHOVE_PATH = os.path.realpath(os.path.join(BASEDIR, 'jhove'))
|
||||
JHOVE_JAR = os.path.join(JHOVE_PATH, 'bin', 'JhoveApp.jar')
|
||||
JHOVE_CFG = os.path.join(JHOVE_PATH, 'conf', 'jhove.conf')
|
||||
|
||||
EXIT_BAD_ARGS = 1
|
||||
EXIT_BAD_INPUT_FILE = 2
|
||||
EXIT_MISSING_DEPENDENCY = 3
|
||||
EXIT_INVALID_OUTPUT_PDFA = 4
|
||||
EXIT_FILE_ACCESS_ERROR = 5
|
||||
EXIT_ALREADY_DONE_OCR = 6
|
||||
EXIT_OTHER_ERROR = 15
|
||||
|
||||
# -------------
|
||||
# External dependencies
|
||||
@@ -66,7 +59,7 @@ if tesseract.version() < MINIMUM_TESS_VERSION:
|
||||
"Please install tesseract {0} or newer "
|
||||
"(currently installed version is {1})".format(
|
||||
MINIMUM_TESS_VERSION, tesseract.version()))
|
||||
sys.exit(EXIT_MISSING_DEPENDENCY)
|
||||
sys.exit(ExitCode.missing_dependency)
|
||||
|
||||
|
||||
# -------------
|
||||
@@ -184,7 +177,7 @@ if not set(options.language).issubset(tesseract.languages()):
|
||||
"data for the following requested languages: ")
|
||||
for lang in (set(options.language) - tesseract.languages()):
|
||||
complain(lang, file=sys.stderr)
|
||||
sys.exit(EXIT_BAD_ARGS)
|
||||
sys.exit(ExitCode.bad_args)
|
||||
|
||||
|
||||
# ----------
|
||||
@@ -197,7 +190,7 @@ if any((options.deskew, options.clean, options.clean_final)):
|
||||
except ImportError:
|
||||
complain(
|
||||
"Install the 'unpaper' program to use --deskew or --clean.")
|
||||
sys.exit(EXIT_BAD_ARGS)
|
||||
sys.exit(ExitCode.bad_args)
|
||||
else:
|
||||
unpaper = None
|
||||
|
||||
@@ -209,7 +202,7 @@ if options.debug_rendering and options.pdf_renderer == 'tesseract':
|
||||
if options.force_ocr and options.skip_text:
|
||||
complain(
|
||||
"Error: --force-ocr and --skip-text are mutually incompatible.")
|
||||
sys.exit(EXIT_BAD_ARGS)
|
||||
sys.exit(ExitCode.bad_args)
|
||||
|
||||
if options.clean and not options.clean_final \
|
||||
and options.pdf_renderer == 'tesseract':
|
||||
@@ -357,7 +350,7 @@ def is_ocr_required(pageinfo, log):
|
||||
if not options.force_ocr and not options.skip_text:
|
||||
log.error(s.format(page,
|
||||
"aborting (use --force-ocr to force OCR)"))
|
||||
sys.exit(EXIT_ALREADY_DONE_OCR)
|
||||
sys.exit(ExitCode.already_done_ocr)
|
||||
elif options.force_ocr:
|
||||
log.info(s.format(page,
|
||||
"rasterizing text and running OCR anyway"))
|
||||
@@ -850,14 +843,14 @@ def run_pipeline():
|
||||
|
||||
pdf_is_valid, pdf_is_pdfa = validate_pdfa(options.output_file, _log)
|
||||
|
||||
returncode = EXIT_OTHER_ERROR # Assume error
|
||||
returncode = ExitCode.other_error # Assume error
|
||||
|
||||
if not pdf_is_valid:
|
||||
_log.warning('Output file: The generated PDF/A file is INVALID')
|
||||
returncode = EXIT_INVALID_OUTPUT_PDFA
|
||||
returncode = ExitCode.invalid_output_pdfa
|
||||
elif pdf_is_valid and not pdf_is_pdfa:
|
||||
_log.warning('Output file: Generated file is VALID PDF but not PDF/A')
|
||||
returncode = EXIT_INVALID_OUTPUT_PDFA
|
||||
returncode = ExitCode.invalid_output_pdfa
|
||||
elif pdf_is_valid and pdf_is_pdfa:
|
||||
_log.info('Output file: The generated PDF/A file is VALID')
|
||||
returncode = 0
|
||||
|
||||
+12
-4
@@ -6,6 +6,7 @@ import sys
|
||||
import os
|
||||
import re
|
||||
from functools import lru_cache
|
||||
from . import ExitCode
|
||||
|
||||
|
||||
@lru_cache(maxsize=1)
|
||||
@@ -20,7 +21,7 @@ def version():
|
||||
stderr=STDOUT)
|
||||
except CalledProcessError:
|
||||
print("Could not find Tesseract executable on system PATH.")
|
||||
sys.exit(1)
|
||||
sys.exit(ExitCode.missing_dependency)
|
||||
|
||||
tesseract_version = re.match(r'tesseract\s(.+)', versions).group(1)
|
||||
return tesseract_version
|
||||
@@ -32,9 +33,16 @@ def languages():
|
||||
'tesseract',
|
||||
'--list-langs'
|
||||
]
|
||||
langs = check_output(
|
||||
args_tess, close_fds=True, universal_newlines=True,
|
||||
stderr=STDOUT)
|
||||
try:
|
||||
langs = check_output(
|
||||
args_tess, close_fds=True, universal_newlines=True,
|
||||
stderr=STDOUT)
|
||||
except CalledProcessError as e:
|
||||
print("Tesseract failed to report available languages.")
|
||||
print("Output from Tesseract:")
|
||||
print("-" * 40)
|
||||
print(e.output)
|
||||
sys.exit(ExitCode.missing_dependency)
|
||||
return set(lang.strip() for lang in langs.splitlines()[1:])
|
||||
|
||||
|
||||
|
||||
+12
-1
@@ -11,6 +11,7 @@ from unittest.mock import patch, create_autospec
|
||||
import pytest
|
||||
from ocrmypdf.pageinfo import pdf_get_all_pageinfo
|
||||
import PyPDF2 as pypdf
|
||||
from ocrmypdf import ExitCode
|
||||
|
||||
|
||||
if sys.version_info.major < 3:
|
||||
@@ -243,4 +244,14 @@ def test_ghostscript_pdfa_fails(break_ghostscript_pdfa):
|
||||
|
||||
p, out, err = run_ocrmypdf_env(
|
||||
'graph_ocred.pdf', 'not_a_pdfa.pdf', env, '-v', '1', '--skip-text')
|
||||
assert p.returncode == 4, err # not PDFA
|
||||
assert p.returncode == ExitCode.invalid_output_pdfa, err # not PDFA
|
||||
|
||||
|
||||
def test_tesseract_missing_tessdata():
|
||||
env = os.environ
|
||||
env['TESSDATA_PREFIX'] = '/tmp'
|
||||
|
||||
p, _, err = run_ocrmypdf_env(
|
||||
'graph_ocred.pdf', 'not_a_pdfa.pdf', env, '-v', '1', '--skip-text')
|
||||
assert p.returncode == ExitCode.missing_dependency, err
|
||||
|
||||
|
||||
Reference in New Issue
Block a user