Convert all tesseract cache usages to plugin
This commit is contained in:
@@ -167,7 +167,6 @@ def get_orientation(input_file: Path, engine_mode, timeout: float, tesseract_env
|
||||
except TimeoutExpired:
|
||||
return OrientationConfidence(angle=0, confidence=0.0)
|
||||
except CalledProcessError as e:
|
||||
# breakpoint()
|
||||
tesseract_log_output(e.stdout)
|
||||
tesseract_log_output(e.stderr)
|
||||
if (
|
||||
@@ -191,15 +190,17 @@ def get_orientation(input_file: Path, engine_mode, timeout: float, tesseract_env
|
||||
return oc
|
||||
|
||||
|
||||
def tesseract_log_output(stdout):
|
||||
def tesseract_log_output(stream):
|
||||
tlog = TesseractLoggerAdapter(
|
||||
log, extra=log.extra if hasattr(log, 'extra') else None
|
||||
)
|
||||
|
||||
if not stream:
|
||||
return
|
||||
try:
|
||||
text = stdout.decode()
|
||||
text = stream.decode()
|
||||
except UnicodeDecodeError:
|
||||
text = stdout.decode('utf-8', 'ignore')
|
||||
text = stream.decode('utf-8', 'ignore')
|
||||
|
||||
lines = text.splitlines()
|
||||
for line in lines:
|
||||
|
||||
@@ -169,13 +169,6 @@ def spoof(tmp_path_factory, **kwargs):
|
||||
return env
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def spoof_tesseract_cache(tmp_path_factory):
|
||||
if running_in_docker():
|
||||
return os.environ.copy()
|
||||
return spoof(tmp_path_factory, tesseract="tesseract_cache.py")
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def resources():
|
||||
return Path(TESTS_ROOT) / 'resources'
|
||||
|
||||
@@ -19,6 +19,31 @@
|
||||
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
"""Cache output of tesseract to speed up test suite
|
||||
|
||||
The cache is keyed by by the input test file The input arguments are slugged
|
||||
into a hideous filename that more or less represents them literally. Joined
|
||||
together, this becomes the name of the cache folder. A few name files like
|
||||
stdout, stderr, hocr, pdf, describe the output to reproduce.
|
||||
|
||||
Changes to tests/resources/ or image processing algorithms don't trigger a
|
||||
cache miss. By design, an input image that varies according to platform
|
||||
differences (e.g. JPEG decoders are allowed to produce differing outputs,
|
||||
and in practice they do) will still be a cache hit. By design, an
|
||||
invocation of tesseract with the same parameters from a different test case
|
||||
will be a hit. It's fragile.
|
||||
|
||||
The tests/cache/manifest.jsonl is a JSON lines file that contains
|
||||
information about the system that produced the results used when cache was
|
||||
generated. This mainly a log to answer questions about how the files
|
||||
were produced.
|
||||
|
||||
Certain operations are not cached and routed to Tesseract OCR directly.
|
||||
|
||||
Assumes Tesseract 4.0.0-alpha or higher.
|
||||
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import logging
|
||||
@@ -147,6 +172,7 @@ def cached_run(options, run_args, **run_kwargs):
|
||||
json.dump(manifest, f)
|
||||
f.write('\n')
|
||||
f.flush()
|
||||
return p
|
||||
|
||||
|
||||
class CacheOcrEngine(TesseractOcrEngine):
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
"""Tesseract no-op spoof
|
||||
"""Tesseract no-op plugin
|
||||
|
||||
To quickly run tests where getting OCR output is not necessary.
|
||||
|
||||
|
||||
@@ -1,198 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# © 2016 James R. Barlow: github.com/jbarlow83
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a
|
||||
# copy of this software and associated documentation files (the
|
||||
# "Software"), to deal in the Software without restriction, including
|
||||
# without limitation the rights to use, copy, modify, merge, publish,
|
||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
||||
# permit persons to whom the Software is furnished to do so, subject to
|
||||
# the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included
|
||||
# in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
"""Cache output of tesseract to speed up test suite
|
||||
|
||||
The cache is keyed by an environment variable that slips the input test file
|
||||
from tests/resources/ to us. The input arguments are slugged into a hideous
|
||||
filename that more or less represents them literally. Joined together, this
|
||||
becomes the name of the cache folder. A few name files like stdout, stderr,
|
||||
hocr, pdf, describe the output to reproduce.
|
||||
|
||||
Changes to tests/resources/ or image processing algorithms don't trigger a
|
||||
cache miss. By design, an input image that varies according to platform
|
||||
differences (e.g. JPEG decoders are allowed to produce differing outputs,
|
||||
and in practice they do) will still be a cache hit. By design, an
|
||||
invocation of tesseract with the same parameters from a different test case
|
||||
will be a hit. It's fragile.
|
||||
|
||||
The tests/cache/manifest.jsonl is a JSON lines file that contains
|
||||
information about the system that produced the results used when cache was
|
||||
generated. This mainly a log to answer questions about how the files
|
||||
were produced.
|
||||
|
||||
For performance reasons, especially the slow performance of Tesseract on
|
||||
machines with AVX2, the cache is now bundled.
|
||||
|
||||
Certain operations are not cached and routed to tesseract directly.
|
||||
|
||||
Assumes Tesseract 4.0.0-alpha or higher.
|
||||
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import os
|
||||
import platform
|
||||
import re
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
__version__ = subprocess.check_output(
|
||||
['tesseract', '--version'], stderr=subprocess.STDOUT
|
||||
).decode()
|
||||
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
prog='tesseract-cache', description='cache output of tesseract'
|
||||
)
|
||||
parser.add_argument('-l', '--language', action='append')
|
||||
parser.add_argument('imagename')
|
||||
parser.add_argument('outputbase')
|
||||
parser.add_argument('configfiles', nargs='*')
|
||||
parser.add_argument('--user-words', type=str)
|
||||
parser.add_argument('--user-patterns', type=str)
|
||||
parser.add_argument('-c', action='append')
|
||||
parser.add_argument('--psm', type=int)
|
||||
parser.add_argument('--oem', type=int)
|
||||
|
||||
TESTS_ROOT = Path(__file__).resolve().parent.parent
|
||||
CACHE_ROOT = TESTS_ROOT / 'cache'
|
||||
|
||||
|
||||
def real_tesseract():
|
||||
tess_args = ['tesseract'] + sys.argv[1:]
|
||||
os.execvp("tesseract", tess_args)
|
||||
return # Not reachable
|
||||
|
||||
|
||||
def main():
|
||||
if any(
|
||||
opt in sys.argv[1:]
|
||||
for opt in ('--print-parameters', '--list-langs', '--version')
|
||||
):
|
||||
real_tesseract() # jump into real tesseract, replacing this process
|
||||
|
||||
# Convert non-standard but supported -psm to --psm
|
||||
sys.argv = ['--psm' if arg == '-psm' else arg for arg in sys.argv]
|
||||
|
||||
if '_OCRMYPDF_TEST_INFILE' not in os.environ:
|
||||
real_tesseract() # test not properly set up
|
||||
source = os.environ['_OCRMYPDF_TEST_INFILE'] # required
|
||||
args = parser.parse_args()
|
||||
|
||||
cache_disabled = os.environ.get('_OCRMYPDF_CACHE_DISABLED', False)
|
||||
|
||||
if args.imagename == 'stdin':
|
||||
real_tesseract()
|
||||
|
||||
def slugs():
|
||||
yield '' # so we don't start with a '-' which makes rm difficult
|
||||
for arg in sys.argv[1:]:
|
||||
if arg == args.imagename:
|
||||
yield Path(args.imagename).name
|
||||
elif arg == args.outputbase:
|
||||
yield Path(args.outputbase).name
|
||||
elif arg == '-c' or arg.startswith('textonly'):
|
||||
pass
|
||||
else:
|
||||
yield arg
|
||||
|
||||
argv_slug = '__'.join(slugs())
|
||||
argv_slug = argv_slug.replace('/', '___')
|
||||
|
||||
cache_folder = Path(CACHE_ROOT) / Path(source).stem / argv_slug
|
||||
cache_folder.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
print(f"Tesseract cache folder {cache_folder} - ", end='', file=sys.stderr)
|
||||
|
||||
if (cache_folder / 'stderr.bin').exists() and not cache_disabled:
|
||||
# Cache hit
|
||||
print("HIT", file=sys.stderr)
|
||||
|
||||
# Replicate stdout/err
|
||||
sys.stdout.buffer.write((cache_folder / 'stdout.bin').read_bytes())
|
||||
sys.stderr.buffer.write((cache_folder / 'stderr.bin').read_bytes())
|
||||
if args.outputbase != 'stdout':
|
||||
if not args.configfiles:
|
||||
args.configfiles.append('txt')
|
||||
for configfile in args.configfiles:
|
||||
# cp cache -> output
|
||||
tessfile = args.outputbase + '.' + configfile
|
||||
shutil.copy(str(cache_folder / configfile) + '.bin', tessfile)
|
||||
sys.exit(0)
|
||||
|
||||
# Cache miss
|
||||
print("MISS", file=sys.stderr)
|
||||
|
||||
# Call tesseract
|
||||
print(sys.argv[1:])
|
||||
p = subprocess.run(
|
||||
['tesseract'] + sys.argv[1:], stdout=subprocess.PIPE, stderr=subprocess.PIPE
|
||||
)
|
||||
sys.stdout.buffer.write(p.stdout)
|
||||
sys.stderr.buffer.write(p.stderr)
|
||||
|
||||
if p.returncode != 0:
|
||||
# Do not cache errors or crashes
|
||||
print("Tesseract error", file=sys.stderr)
|
||||
return p.returncode
|
||||
|
||||
(cache_folder / 'stdout.bin').write_bytes(p.stdout)
|
||||
|
||||
if args.outputbase != 'stdout':
|
||||
if not args.configfiles:
|
||||
args.configfiles.append('txt')
|
||||
|
||||
for configfile in args.configfiles:
|
||||
if configfile not in ('hocr', 'pdf', 'txt'):
|
||||
continue
|
||||
# cp pwd/{outputbase}.{configfile} -> {cache}/{configfile}
|
||||
tessfile = args.outputbase + '.' + configfile
|
||||
shutil.copy(tessfile, str(cache_folder / configfile) + '.bin')
|
||||
|
||||
(cache_folder / 'stderr.bin').write_bytes(p.stderr)
|
||||
|
||||
manifest = {}
|
||||
manifest['tesseract_version'] = __version__.replace('\n', ' ')
|
||||
manifest['platform'] = platform.platform()
|
||||
manifest['python'] = platform.python_version()
|
||||
manifest['argv_slug'] = argv_slug
|
||||
manifest['sourcefile'] = str(Path(source).relative_to(TESTS_ROOT))
|
||||
|
||||
def clean_sys_argv():
|
||||
for arg in sys.argv[1:]:
|
||||
yield re.sub(r'.*/com.github.ocrmypdf[^/]+[/](.*)', r'$TMPDIR/\1', arg)
|
||||
|
||||
manifest['args'] = list(clean_sys_argv())
|
||||
|
||||
# pylint: disable=E1101
|
||||
with (Path(CACHE_ROOT) / 'manifest.jsonl').open('a') as f:
|
||||
json.dump(manifest, f)
|
||||
f.write('\n')
|
||||
f.flush()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
+54
-26
@@ -52,7 +52,7 @@ def test_quick(resources, outpdf):
|
||||
|
||||
|
||||
@pytest.mark.parametrize('renderer', RENDERERS)
|
||||
def test_oversample(spoof_tesseract_cache, renderer, resources, outpdf):
|
||||
def test_oversample(renderer, resources, outpdf):
|
||||
oversampled_pdf = check_ocrmypdf(
|
||||
resources / 'skew.pdf',
|
||||
outpdf,
|
||||
@@ -61,7 +61,8 @@ def test_oversample(spoof_tesseract_cache, renderer, resources, outpdf):
|
||||
'-f',
|
||||
'--pdf-renderer',
|
||||
renderer,
|
||||
env=spoof_tesseract_cache,
|
||||
'--plugin',
|
||||
'tests/plugins/tesseract_cache.py',
|
||||
)
|
||||
|
||||
pdfinfo = PdfInfo(oversampled_pdf)
|
||||
@@ -75,17 +76,25 @@ def test_repeat_ocr(resources, no_outpdf):
|
||||
assert result == ExitCode.already_done_ocr
|
||||
|
||||
|
||||
def test_force_ocr(spoof_tesseract_cache, resources, outpdf):
|
||||
def test_force_ocr(resources, outpdf):
|
||||
out = check_ocrmypdf(
|
||||
resources / 'graph_ocred.pdf', outpdf, '-f', env=spoof_tesseract_cache
|
||||
resources / 'graph_ocred.pdf',
|
||||
outpdf,
|
||||
'-f',
|
||||
'--plugin',
|
||||
'tests/plugins/tesseract_cache.py',
|
||||
)
|
||||
pdfinfo = PdfInfo(out)
|
||||
assert pdfinfo[0].has_text
|
||||
|
||||
|
||||
def test_skip_ocr(spoof_tesseract_cache, resources, outpdf):
|
||||
def test_skip_ocr(resources, outpdf):
|
||||
out = check_ocrmypdf(
|
||||
resources / 'graph_ocred.pdf', outpdf, '-s', env=spoof_tesseract_cache
|
||||
resources / 'graph_ocred.pdf',
|
||||
outpdf,
|
||||
'-s',
|
||||
'--plugin',
|
||||
'tests/plugins/tesseract_cache.py',
|
||||
)
|
||||
pdfinfo = PdfInfo(out)
|
||||
assert pdfinfo[0].has_text
|
||||
@@ -136,9 +145,14 @@ def test_ocr_timeout(renderer, resources, outpdf):
|
||||
assert not pdfinfo[0].has_text
|
||||
|
||||
|
||||
def test_skip_big(spoof_tesseract_cache, resources, outpdf):
|
||||
def test_skip_big(resources, outpdf):
|
||||
out = check_ocrmypdf(
|
||||
resources / 'jbig2.pdf', outpdf, '--skip-big', '1', env=spoof_tesseract_cache
|
||||
resources / 'jbig2.pdf',
|
||||
outpdf,
|
||||
'--skip-big',
|
||||
'1',
|
||||
'--plugin',
|
||||
'tests/plugins/tesseract_cache.py',
|
||||
)
|
||||
pdfinfo = PdfInfo(out)
|
||||
assert not pdfinfo[0].has_text
|
||||
@@ -146,9 +160,7 @@ def test_skip_big(spoof_tesseract_cache, resources, outpdf):
|
||||
|
||||
@pytest.mark.parametrize('renderer', RENDERERS)
|
||||
@pytest.mark.parametrize('output_type', ['pdf', 'pdfa'])
|
||||
def test_maximum_options(
|
||||
spoof_tesseract_cache, renderer, output_type, resources, outpdf
|
||||
):
|
||||
def test_maximum_options(renderer, output_type, resources, outpdf):
|
||||
check_ocrmypdf(
|
||||
resources / 'multipage.pdf',
|
||||
outpdf,
|
||||
@@ -169,7 +181,8 @@ def test_maximum_options(
|
||||
renderer,
|
||||
'--output-type',
|
||||
output_type,
|
||||
env=spoof_tesseract_cache,
|
||||
'--plugin',
|
||||
'tests/plugins/tesseract_cache.py',
|
||||
)
|
||||
|
||||
|
||||
@@ -208,7 +221,7 @@ def test_force_ocr_on_pdf_with_no_images(resources, no_outpdf):
|
||||
pytest.helpers.is_macos() and pytest.helpers.running_in_travis(),
|
||||
reason="takes too long to install language packs in Travis macOS homebrew",
|
||||
)
|
||||
def test_german(spoof_tesseract_cache, resources, outdir):
|
||||
def test_german(resources, outdir):
|
||||
# Produce a sidecar too - implicit test that system locale is set up
|
||||
# properly. It is fine that we are testing -l deu on a French file because
|
||||
# we are exercising the functionality not going for accuracy.
|
||||
@@ -221,7 +234,8 @@ def test_german(spoof_tesseract_cache, resources, outdir):
|
||||
'deu', # more commonly installed
|
||||
'--sidecar',
|
||||
sidecar,
|
||||
env=spoof_tesseract_cache,
|
||||
'--plugin',
|
||||
'tests/plugins/tesseract_cache.py',
|
||||
)
|
||||
except MissingDependencyError:
|
||||
if 'deu' not in tesseract.get_languages():
|
||||
@@ -290,7 +304,7 @@ def test_encrypted(resources, caplog, no_outpdf):
|
||||
|
||||
|
||||
@pytest.mark.parametrize('renderer', RENDERERS)
|
||||
def test_pagesegmode(renderer, spoof_tesseract_cache, resources, outpdf):
|
||||
def test_pagesegmode(renderer, resources, outpdf):
|
||||
check_ocrmypdf(
|
||||
resources / 'skew.pdf',
|
||||
outpdf,
|
||||
@@ -300,7 +314,8 @@ def test_pagesegmode(renderer, spoof_tesseract_cache, resources, outpdf):
|
||||
'1',
|
||||
'--pdf-renderer',
|
||||
renderer,
|
||||
env=spoof_tesseract_cache,
|
||||
'--plugin',
|
||||
'tests/plugins/tesseract_cache.py',
|
||||
)
|
||||
|
||||
|
||||
@@ -362,7 +377,7 @@ def test_algo4(resources, outpdf):
|
||||
assert p.returncode == ExitCode.encrypted_pdf
|
||||
|
||||
|
||||
def test_jbig2_passthrough(spoof_tesseract_cache, resources, outpdf):
|
||||
def test_jbig2_passthrough(resources, outpdf):
|
||||
out = check_ocrmypdf(
|
||||
resources / 'jbig2.pdf',
|
||||
outpdf,
|
||||
@@ -370,7 +385,8 @@ def test_jbig2_passthrough(spoof_tesseract_cache, resources, outpdf):
|
||||
'pdf',
|
||||
'--pdf-renderer',
|
||||
'hocr',
|
||||
env=spoof_tesseract_cache,
|
||||
'--plugin',
|
||||
'tests/plugins/tesseract_cache.py',
|
||||
)
|
||||
out_pageinfo = PdfInfo(out)
|
||||
assert out_pageinfo[0].images[0].enc == Encoding.jbig2
|
||||
@@ -391,9 +407,14 @@ def test_linearized_pdf_and_indirect_object(resources, outpdf):
|
||||
)
|
||||
|
||||
|
||||
def test_very_high_dpi(spoof_tesseract_cache, resources, outpdf):
|
||||
def test_very_high_dpi(resources, outpdf):
|
||||
"Checks for a Decimal quantize error with high DPI, etc"
|
||||
check_ocrmypdf(resources / '2400dpi.pdf', outpdf, env=spoof_tesseract_cache)
|
||||
check_ocrmypdf(
|
||||
resources / '2400dpi.pdf',
|
||||
outpdf,
|
||||
'--plugin',
|
||||
'tests/plugins/tesseract_cache.py',
|
||||
)
|
||||
pdfinfo = PdfInfo(outpdf)
|
||||
|
||||
image = pdfinfo[0].images[0]
|
||||
@@ -673,7 +694,7 @@ def test_compression_changed(ocrmypdf_exec, resources, image, compression, outpd
|
||||
im.close()
|
||||
|
||||
|
||||
def test_sidecar_pagecount(spoof_tesseract_cache, resources, outpdf):
|
||||
def test_sidecar_pagecount(resources, outpdf):
|
||||
sidecar = outpdf.with_suffix('.txt')
|
||||
check_ocrmypdf(
|
||||
resources / '3small.pdf',
|
||||
@@ -681,7 +702,8 @@ def test_sidecar_pagecount(spoof_tesseract_cache, resources, outpdf):
|
||||
'--skip-text',
|
||||
'--sidecar',
|
||||
sidecar,
|
||||
env=spoof_tesseract_cache,
|
||||
'--plugin',
|
||||
'tests/plugins/tesseract_cache.py',
|
||||
)
|
||||
|
||||
pdfinfo = PdfInfo(resources / '3small.pdf')
|
||||
@@ -697,10 +719,15 @@ def test_sidecar_pagecount(spoof_tesseract_cache, resources, outpdf):
|
||||
), "Sidecar page count does not match PDF page count"
|
||||
|
||||
|
||||
def test_sidecar_nonempty(spoof_tesseract_cache, resources, outpdf):
|
||||
def test_sidecar_nonempty(resources, outpdf):
|
||||
sidecar = outpdf.with_suffix('.txt')
|
||||
check_ocrmypdf(
|
||||
resources / 'ccitt.pdf', outpdf, '--sidecar', sidecar, env=spoof_tesseract_cache
|
||||
resources / 'ccitt.pdf',
|
||||
outpdf,
|
||||
'--sidecar',
|
||||
sidecar,
|
||||
'--plugin',
|
||||
'tests/plugins/tesseract_cache.py',
|
||||
)
|
||||
|
||||
with open(sidecar, 'r', encoding='utf-8') as f:
|
||||
@@ -709,7 +736,7 @@ def test_sidecar_nonempty(spoof_tesseract_cache, resources, outpdf):
|
||||
|
||||
|
||||
@pytest.mark.parametrize('pdfa_level', ['1', '2', '3'])
|
||||
def test_pdfa_n(spoof_tesseract_cache, pdfa_level, resources, outpdf):
|
||||
def test_pdfa_n(pdfa_level, resources, outpdf):
|
||||
if pdfa_level == '3' and ghostscript.version() < '9.19':
|
||||
pytest.xfail(reason='Ghostscript >= 9.19 required')
|
||||
|
||||
@@ -718,7 +745,8 @@ def test_pdfa_n(spoof_tesseract_cache, pdfa_level, resources, outpdf):
|
||||
outpdf,
|
||||
'--output-type',
|
||||
'pdfa-' + pdfa_level,
|
||||
env=spoof_tesseract_cache,
|
||||
'--plugin',
|
||||
'tests/plugins/tesseract_cache.py',
|
||||
)
|
||||
|
||||
pdfa_info = file_claims_pdfa(outpdf)
|
||||
|
||||
@@ -58,7 +58,7 @@ def test_list_range():
|
||||
assert _pages_from_ranges([0, 1, 2]) == {0, 1, 2}
|
||||
|
||||
|
||||
def test_limited_pages(resources, outpdf, spoof_tesseract_cache):
|
||||
def test_limited_pages(resources, outpdf):
|
||||
multi = resources / 'multipage.pdf'
|
||||
ocrmypdf.ocr(
|
||||
multi,
|
||||
@@ -66,7 +66,7 @@ def test_limited_pages(resources, outpdf, spoof_tesseract_cache):
|
||||
pages='5-6',
|
||||
optimize=0,
|
||||
output_type='pdf',
|
||||
tesseract_env=spoof_tesseract_cache,
|
||||
plugins=['tests/plugins/tesseract_cache.py'],
|
||||
)
|
||||
pi = PdfInfo(outpdf)
|
||||
assert not pi.pages[0].has_text
|
||||
|
||||
@@ -102,9 +102,7 @@ def test_remove_background(resources, outdir):
|
||||
)
|
||||
@pytest.mark.parametrize("renderer", ['sandwich', 'hocr'])
|
||||
@pytest.mark.parametrize("output_type", ['pdf', 'pdfa'])
|
||||
def test_exotic_image(
|
||||
spoof_tesseract_cache, pdf, renderer, output_type, resources, outdir
|
||||
):
|
||||
def test_exotic_image(pdf, renderer, output_type, resources, outdir):
|
||||
outfile = outdir / f'test_{pdf}_{renderer}.pdf'
|
||||
check_ocrmypdf(
|
||||
resources / pdf,
|
||||
@@ -118,14 +116,15 @@ def test_exotic_image(
|
||||
'--skip-text',
|
||||
'--pdf-renderer',
|
||||
renderer,
|
||||
env=spoof_tesseract_cache,
|
||||
'--plugin',
|
||||
'tests/plugins/tesseract_cache.py',
|
||||
)
|
||||
|
||||
assert outfile.with_suffix('.pdf.txt').exists()
|
||||
|
||||
|
||||
@pytest.mark.parametrize('renderer', RENDERERS)
|
||||
def test_non_square_resolution(renderer, spoof_tesseract_cache, resources, outpdf):
|
||||
def test_non_square_resolution(renderer, resources, outpdf):
|
||||
# Confirm input image is non-square resolution
|
||||
in_pageinfo = PdfInfo(resources / 'aspect.pdf')
|
||||
assert in_pageinfo[0].dpi.x != in_pageinfo[0].dpi.y
|
||||
@@ -135,7 +134,8 @@ def test_non_square_resolution(renderer, spoof_tesseract_cache, resources, outpd
|
||||
outpdf,
|
||||
'--pdf-renderer',
|
||||
renderer,
|
||||
env=spoof_tesseract_cache,
|
||||
'--plugin',
|
||||
'tests/plugins/tesseract_cache.py',
|
||||
)
|
||||
|
||||
out_pageinfo = PdfInfo(outpdf)
|
||||
@@ -145,9 +145,7 @@ def test_non_square_resolution(renderer, spoof_tesseract_cache, resources, outpd
|
||||
|
||||
|
||||
@pytest.mark.parametrize('renderer', RENDERERS)
|
||||
def test_convert_to_square_resolution(
|
||||
renderer, spoof_tesseract_cache, resources, outpdf
|
||||
):
|
||||
def test_convert_to_square_resolution(renderer, resources, outpdf):
|
||||
# Confirm input image is non-square resolution
|
||||
in_pageinfo = PdfInfo(resources / 'aspect.pdf')
|
||||
assert in_pageinfo[0].dpi.x != in_pageinfo[0].dpi.y
|
||||
@@ -159,7 +157,8 @@ def test_convert_to_square_resolution(
|
||||
'--force-ocr',
|
||||
'--pdf-renderer',
|
||||
renderer,
|
||||
env=spoof_tesseract_cache,
|
||||
'--plugin',
|
||||
'tests/plugins/tesseract_cache.py',
|
||||
)
|
||||
|
||||
out_pageinfo = PdfInfo(outpdf)
|
||||
|
||||
@@ -97,7 +97,7 @@ def test_monochrome_correlation(resources, outdir):
|
||||
|
||||
@pytest.mark.slow
|
||||
@pytest.mark.parametrize('renderer', RENDERERS)
|
||||
def test_autorotate(spoof_tesseract_cache, renderer, resources, outdir):
|
||||
def test_autorotate(renderer, resources, outdir):
|
||||
# cardinal.pdf contains four copies of an image rotated in each cardinal
|
||||
# direction - these ones are "burned in" not tagged with /Rotate
|
||||
out = check_ocrmypdf(
|
||||
@@ -108,7 +108,8 @@ def test_autorotate(spoof_tesseract_cache, renderer, resources, outdir):
|
||||
'1',
|
||||
'--pdf-renderer',
|
||||
renderer,
|
||||
env=spoof_tesseract_cache,
|
||||
'--plugin',
|
||||
'tests/plugins/tesseract_cache.py',
|
||||
)
|
||||
for n in range(1, 4 + 1):
|
||||
correlation = check_monochrome_correlation(
|
||||
@@ -128,9 +129,7 @@ def test_autorotate(spoof_tesseract_cache, renderer, resources, outdir):
|
||||
('99', 'correlation < 0.10'), # High thres -> never rotate -> low corr
|
||||
],
|
||||
)
|
||||
def test_autorotate_threshold(
|
||||
spoof_tesseract_cache, threshold, correlation_test, resources, outdir
|
||||
):
|
||||
def test_autorotate_threshold(threshold, correlation_test, resources, outdir):
|
||||
out = check_ocrmypdf(
|
||||
resources / 'cardinal.pdf',
|
||||
outdir / 'out.pdf',
|
||||
@@ -139,7 +138,8 @@ def test_autorotate_threshold(
|
||||
'-r',
|
||||
# '-v',
|
||||
# '1',
|
||||
env=spoof_tesseract_cache,
|
||||
'--plugin',
|
||||
'tests/plugins/tesseract_cache.py',
|
||||
)
|
||||
|
||||
correlation = check_monochrome_correlation(
|
||||
|
||||
@@ -31,7 +31,6 @@ from ocrmypdf.exec import tesseract
|
||||
|
||||
check_ocrmypdf = pytest.helpers.check_ocrmypdf
|
||||
run_ocrmypdf = pytest.helpers.run_ocrmypdf
|
||||
spoof = pytest.helpers.spoof
|
||||
|
||||
|
||||
@pytest.mark.parametrize('basename', ['graph_ocred.pdf', 'cardinal.pdf'])
|
||||
|
||||
@@ -31,7 +31,6 @@ from ocrmypdf.exceptions import ExitCode, MissingDependencyError
|
||||
|
||||
check_ocrmypdf = pytest.helpers.check_ocrmypdf
|
||||
run_ocrmypdf = pytest.helpers.run_ocrmypdf
|
||||
spoof = pytest.helpers.spoof
|
||||
have_unpaper = pytest.helpers.have_unpaper
|
||||
|
||||
|
||||
|
||||
+15
-5
@@ -25,7 +25,6 @@ from ocrmypdf.pdfinfo import PdfInfo
|
||||
check_ocrmypdf = pytest.helpers.check_ocrmypdf
|
||||
run_ocrmypdf = pytest.helpers.run_ocrmypdf
|
||||
run_ocrmypdf_api = pytest.helpers.run_ocrmypdf_api
|
||||
spoof = pytest.helpers.spoof
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@@ -39,15 +38,26 @@ def test_userunit_ghostscript_fails(poster, no_outpdf, caplog):
|
||||
assert 'not supported by Ghostscript' in caplog.text
|
||||
|
||||
|
||||
def test_userunit_pdf_passes(spoof_tesseract_cache, poster, outpdf):
|
||||
def test_userunit_pdf_passes(poster, outpdf):
|
||||
before = PdfInfo(poster)
|
||||
check_ocrmypdf(poster, outpdf, '--output-type=pdf', env=spoof_tesseract_cache)
|
||||
check_ocrmypdf(
|
||||
poster,
|
||||
outpdf,
|
||||
'--output-type=pdf',
|
||||
'--plugin',
|
||||
'tests/plugins/tesseract_cache.py',
|
||||
)
|
||||
|
||||
after = PdfInfo(outpdf)
|
||||
assert isclose(before[0].width_inches, after[0].width_inches)
|
||||
|
||||
|
||||
def test_rotate_interaction(spoof_tesseract_cache, poster, outpdf):
|
||||
def test_rotate_interaction(poster, outpdf):
|
||||
check_ocrmypdf(
|
||||
poster, outpdf, '--output-type=pdf', '--rotate-pages', env=spoof_tesseract_cache
|
||||
poster,
|
||||
outpdf,
|
||||
'--output-type=pdf',
|
||||
'--rotate-pages',
|
||||
'--plugin',
|
||||
'tests/plugins/tesseract_cache.py',
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user