diff --git a/ocrmypdf/__init__.py b/ocrmypdf/__init__.py index e69de29b..4098e60c 100644 --- a/ocrmypdf/__init__.py +++ b/ocrmypdf/__init__.py @@ -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 diff --git a/ocrmypdf/main.py b/ocrmypdf/main.py index 77ce047e..3841c5ac 100755 --- a/ocrmypdf/main.py +++ b/ocrmypdf/main.py @@ -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 diff --git a/ocrmypdf/tesseract.py b/ocrmypdf/tesseract.py index 9a542019..dfeac879 100644 --- a/ocrmypdf/tesseract.py +++ b/ocrmypdf/tesseract.py @@ -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:]) diff --git a/tests/test_main.py b/tests/test_main.py index 3935349b..62b5f195 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -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 +