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:
James R. Barlow
2015-08-11 00:17:02 -07:00
parent 8d848284df
commit 1cb5f6a90d
4 changed files with 44 additions and 21 deletions
+11
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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