Convert to object oriented ruffus syntax (does not run)

I experimented with the idea of using asyncio-based processing but
realized that that does not solve the import time binding problem
that is the real issue. Therefore the simpler refactoring is to convert
to ruffus-oo syntax and get things working again.

build_pipeline() is really ugly at the moment. The old syntax had its
advantages.

This test reproduces the complete pipeline graph but does not work
otherwise.
This commit is contained in:
James R. Barlow
2016-11-30 23:58:26 -08:00
parent de939951d4
commit 401b21864f
+291 -224
View File
@@ -20,8 +20,11 @@ from PIL import Image
from functools import partial
from ruffus import transform, suffix, merge, active_if, regex, jobs_limit, \
formatter, follows, split, collate, check_if_uptodate, graphviz, posttask
# from ruffus import transform, suffix, merge, active_if, regex, \
# formatter, split, collate, graphviz, \
# posttask, Pipeline
from ruffus import formatter, regex, Pipeline, suffix
import ruffus.ruffus_exceptions as ruffus_exceptions
import ruffus.cmdline as cmdline
import ruffus.proxy_logger as proxy_logger
@@ -44,6 +47,9 @@ BASEDIR = os.path.dirname(os.path.realpath(__file__))
VECTOR_PAGE_DPI = 400
_log = None
# -------------
# External dependencies
@@ -281,86 +287,87 @@ debugging.add_argument(
'-g', '--debug-rendering', action='store_true',
help="render each page twice with debug information on second page")
options = parser.parse_args()
if 0:
options = parser.parse_args()
# ----------
# Languages
# ----------
# Languages
if not options.language:
options.language = ['eng'] # Enforce English hegemony
if not options.language:
options.language = ['eng'] # Enforce English hegemony
# Support v2.x "eng+deu" language syntax
if '+' in options.language[0]:
options.language = options.language[0].split('+')
# Support v2.x "eng+deu" language syntax
if '+' in options.language[0]:
options.language = options.language[0].split('+')
if not set(options.language).issubset(tesseract.languages()):
complain(
"The installed version of tesseract does not have language "
"data for the following requested languages: ")
for lang in (set(options.language) - tesseract.languages()):
complain(lang)
sys.exit(ExitCode.bad_args)
# ----------
# Arguments
options.verbose_abbreviated_path = 1
if options.pdf_renderer == 'auto':
options.pdf_renderer = 'hocr'
if options.pdf_renderer == 'tesseract' and tesseract.version() < '3.04.01' \
and os.environ.get('OCRMYPDF_SHARP_TTF', '') != '1':
complain(
"WARNING: Your version of tesseract has problems with PDF output. "
"Some PDF viewers will fail to find searchable text.\n"
"--pdf-renderer=tesseract is not recommended.")
if any((options.clean, options.clean_final)):
try:
from . import unpaper
if unpaper.version() < '6.1':
complain(
"The installed 'unpaper' is not supported. "
"Install version 6.1 or newer.")
sys.exit(ExitCode.missing_dependency)
except FileNotFoundError:
if not set(options.language).issubset(tesseract.languages()):
complain(
"Install the 'unpaper' program to use --deskew or --clean.")
sys.exit(ExitCode.missing_dependency)
else:
unpaper = None
"The installed version of tesseract does not have language "
"data for the following requested languages: ")
for lang in (set(options.language) - tesseract.languages()):
complain(lang)
sys.exit(ExitCode.bad_args)
if options.debug_rendering and options.pdf_renderer == 'tesseract':
complain(
"Ignoring --debug-rendering because it is not supported with"
"--pdf-renderer=tesseract.")
if options.force_ocr and options.skip_text:
complain(
"Error: --force-ocr and --skip-text are mutually incompatible.")
sys.exit(ExitCode.bad_args)
# ----------
# Arguments
if options.clean and not options.clean_final \
and options.pdf_renderer == 'tesseract':
complain(
"Tesseract PDF renderer cannot render --clean pages without "
"also performing --clean-final, so --clean-final is assumed.")
options.verbose_abbreviated_path = 1
if set(options.language) & {'chi_sim', 'chi_tra'} \
and (options.pdf_renderer == 'hocr' or options.output_type == 'pdfa'):
complain(
"Your settings are known to cause problems with OCR of Chinese text. "
"Try adding these arguments: "
" ocrmypdf --pdf-renderer tesseract --output-type pdf")
if options.pdf_renderer == 'auto':
options.pdf_renderer = 'hocr'
lossless_reconstruction = False
if options.pdf_renderer == 'hocr':
if not options.deskew and not options.clean_final and \
not options.force_ocr and not options.remove_background:
lossless_reconstruction = True
if options.pdf_renderer == 'tesseract' and tesseract.version() < '3.04.01' \
and os.environ.get('OCRMYPDF_SHARP_TTF', '') != '1':
complain(
"WARNING: Your version of tesseract has problems with PDF output. "
"Some PDF viewers will fail to find searchable text.\n"
"--pdf-renderer=tesseract is not recommended.")
if any((options.clean, options.clean_final)):
try:
from . import unpaper
if unpaper.version() < '6.1':
complain(
"The installed 'unpaper' is not supported. "
"Install version 6.1 or newer.")
sys.exit(ExitCode.missing_dependency)
except FileNotFoundError:
complain(
"Install the 'unpaper' program to use --deskew or --clean.")
sys.exit(ExitCode.missing_dependency)
else:
unpaper = None
if options.debug_rendering and options.pdf_renderer == 'tesseract':
complain(
"Ignoring --debug-rendering because it is not supported with"
"--pdf-renderer=tesseract.")
if options.force_ocr and options.skip_text:
complain(
"Error: --force-ocr and --skip-text are mutually incompatible.")
sys.exit(ExitCode.bad_args)
if options.clean and not options.clean_final \
and options.pdf_renderer == 'tesseract':
complain(
"Tesseract PDF renderer cannot render --clean pages without "
"also performing --clean-final, so --clean-final is assumed.")
if set(options.language) & {'chi_sim', 'chi_tra'} \
and (options.pdf_renderer == 'hocr' or options.output_type == 'pdfa'):
complain(
"Your settings are known to cause problems with OCR of Chinese text. "
"Try adding these arguments: "
" ocrmypdf --pdf-renderer tesseract --output-type pdf")
lossless_reconstruction = False
if options.pdf_renderer == 'hocr':
if not options.deskew and not options.clean_final and \
not options.force_ocr and not options.remove_background:
lossless_reconstruction = True
# ----------
@@ -383,9 +390,6 @@ def logging_factory(logger_name, listargs):
root_logger.addHandler(handler)
return root_logger
_logger, _logger_mutex = proxy_logger.make_shared_logger_and_proxy(
logging_factory, __name__, [None, options.verbose])
class WrappedLogger:
@@ -417,14 +421,18 @@ class WrappedLogger:
with self.mutex:
self.logger.critical(*args, **kwargs)
_log = WrappedLogger(_logger, _logger_mutex)
_log.debug('ocrmypdf ' + VERSION)
def re_symlink(input_file, soft_link_name, log=_log):
"""
Helper function: relinks soft symbolic link if necessary
"""
if log is None:
class Blackhole:
def debug(self, msg):
pass
log = Blackhole()
# Guard against soft linking to oneself
if input_file == soft_link_name:
log.debug("Warning: No symbolic link made. You are using " +
@@ -543,12 +551,6 @@ def triage_image_file(input_file, output_file, log):
sys.exit(ExitCode.input_file)
@posttask(partial(done_task, 'triage'))
@transform(
input=os.path.join(work_folder, 'origin'),
filter=formatter('(?i)'),
output=os.path.join(work_folder, 'origin.pdf'),
extras=[_log])
def triage(
input_file,
output_file,
@@ -566,13 +568,6 @@ def triage(
triage_image_file(input_file, output_file, log)
@posttask(partial(done_task, 'repair_pdf'))
@transform(
input=triage,
filter=suffix('.pdf'),
output='.repaired.pdf',
output_dir=work_folder,
extras=[_log, _pdfinfo, _pdfinfo_lock])
def repair_pdf(
input_file,
output_file,
@@ -660,11 +655,6 @@ def is_ocr_required(pageinfo, log):
return ocr_required
@posttask(partial(done_task, 'split_pages'))
@split(
repair_pdf,
os.path.join(work_folder, '*.page.pdf'),
extras=[_log, _pdfinfo, _pdfinfo_lock])
def split_pages(
input_files,
output_files,
@@ -703,14 +693,6 @@ def split_pages(
os.path.basename(filename)[0:6] + alt_suffix))
@posttask(partial(done_task, 'rasterize_preview'))
@active_if(options.rotate_pages)
@transform(
input=split_pages,
filter=suffix('.page.pdf'),
output='.preview.jpg',
output_dir=work_folder,
extras=[_log, _pdfinfo, _pdfinfo_lock])
def rasterize_preview(
input_file,
output_file,
@@ -726,12 +708,6 @@ def rasterize_preview(
log=log)
@posttask(partial(done_task, 'orient_page'))
@collate(
input=[split_pages, rasterize_preview],
filter=regex(r".*/(\d{6})(\.ocr|\.skip)(?:\.page\.pdf|\.preview\.jpg)"),
output=os.path.join(work_folder, r'\1\2.oriented.pdf'),
extras=[_log, _pdfinfo, _pdfinfo_lock])
def orient_page(
infiles,
output_file,
@@ -801,13 +777,6 @@ def orient_page(
pdfinfo[pageno] = pageinfo
@posttask(partial(done_task, 'rasterize_with_ghostscript'))
@transform(
input=orient_page,
filter=suffix('.ocr.oriented.pdf'),
output='.page.png',
output_dir=work_folder,
extras=[_log, _pdfinfo, _pdfinfo_lock])
def rasterize_with_ghostscript(
input_file,
output_file,
@@ -838,12 +807,6 @@ def rasterize_with_ghostscript(
log=log)
@posttask(partial(done_task, 'preprocess_remove_background'))
@transform(
input=rasterize_with_ghostscript,
filter=suffix(".page.png"),
output=".pp-background.png",
extras=[_log, _pdfinfo, _pdfinfo_lock])
def preprocess_remove_background(
input_file,
output_file,
@@ -865,12 +828,6 @@ def preprocess_remove_background(
re_symlink(input_file, output_file, log)
@posttask(partial(done_task, 'preprocess_deskew'))
@transform(
input=preprocess_remove_background,
filter=suffix(".pp-background.png"),
output=".pp-deskew.png",
extras=[_log, _pdfinfo, _pdfinfo_lock])
def preprocess_deskew(
input_file,
output_file,
@@ -888,12 +845,6 @@ def preprocess_deskew(
leptonica.deskew(input_file, output_file, dpi)
@posttask(partial(done_task, 'preprocess_clean'))
@transform(
input=preprocess_deskew,
filter=suffix(".pp-deskew.png"),
output=".pp-clean.png",
extras=[_log, _pdfinfo, _pdfinfo_lock])
def preprocess_clean(
input_file,
output_file,
@@ -911,14 +862,6 @@ def preprocess_clean(
unpaper.clean(input_file, output_file, dpi, log)
@posttask(partial(done_task, 'ocr_tesseract_hocr'))
@active_if(options.pdf_renderer == 'hocr')
@transform(
input=preprocess_clean,
filter=suffix(".pp-clean.png"),
output=".hocr",
extras=[_log, _pdfinfo, _pdfinfo_lock])
@graphviz(fillcolor='"#00cc66"')
def ocr_tesseract_hocr(
input_file,
output_file,
@@ -939,14 +882,6 @@ def ocr_tesseract_hocr(
)
@posttask(partial(done_task, 'select_image_for_pdf'))
@collate(
input=[rasterize_with_ghostscript, preprocess_remove_background,
preprocess_deskew, preprocess_clean],
filter=regex(r".*/(\d{6})(?:\.page|\.pp-.*)\.png"),
output=os.path.join(work_folder, r'\1.image'),
extras=[_log, _pdfinfo, _pdfinfo_lock])
@graphviz(shape='diamond')
def select_image_for_pdf(
infiles,
output_file,
@@ -983,14 +918,6 @@ def select_image_for_pdf(
re_symlink(image, output_file)
@posttask(partial(done_task, 'select_image_layer'))
@active_if(options.pdf_renderer == 'hocr')
@collate(
input=[select_image_for_pdf, orient_page],
filter=regex(r".*/(\d{6})(?:\.image|\.ocr\.oriented\.pdf)"),
output=os.path.join(work_folder, r'\1.image-layer.pdf'),
extras=[_log, _pdfinfo, _pdfinfo_lock])
@graphviz(fillcolor='"#00cc66"', shape='diamond')
def select_image_layer(
infiles,
output_file,
@@ -1021,14 +948,6 @@ def select_image_layer(
log.debug('{:4d}: convert done'.format(page_number(page_pdf)))
@posttask(partial(done_task, 'render_hocr_page'))
@active_if(options.pdf_renderer == 'hocr')
@transform(
input=ocr_tesseract_hocr,
filter=suffix('.hocr'),
output='.hocr.pdf',
extras=[_log, _pdfinfo, _pdfinfo_lock])
@graphviz(fillcolor='"#00cc66"')
def render_hocr_page(
input_file,
output_file,
@@ -1044,15 +963,6 @@ def render_hocr_page(
showBoundingboxes=False, invisibleText=True)
@posttask(partial(done_task, 'render_hocr_debug_page'))
@active_if(options.pdf_renderer == 'hocr')
@active_if(options.debug_rendering)
@collate(
input=[select_image_for_pdf, ocr_tesseract_hocr],
filter=regex(r".*/(\d{6})(?:\.image|\.hocr)"),
output=os.path.join(work_folder, r'\1.debug.pdf'),
extras=[_log, _pdfinfo, _pdfinfo_lock])
@graphviz(fillcolor='"#00cc66"')
def render_hocr_debug_page(
infiles,
output_file,
@@ -1074,14 +984,6 @@ class PdfMergeFailedError(Exception):
pass
@posttask(partial(done_task, 'add_text_layer'))
@active_if(options.pdf_renderer == 'hocr')
@collate(
input=[render_hocr_page, select_image_layer],
filter=regex(r".*/(\d{6})(?:\.hocr\.pdf|\.image-layer\.pdf)"),
output=os.path.join(work_folder, r'\1.rendered.pdf'),
extras=[_log, _pdfinfo, _pdfinfo_lock])
@graphviz(fillcolor='"#00cc66"')
def add_text_layer(
infiles,
output_file,
@@ -1153,14 +1055,6 @@ def add_text_layer(
pdf_output.write(out)
@posttask(partial(done_task, 'tesseract_ocr_and_render_pdf'))
@active_if(options.pdf_renderer == 'tesseract')
@collate(
input=[select_image_for_pdf, orient_page],
filter=regex(r".*/(\d{6})(?:\.image|\.ocr\.oriented\.pdf)"),
output=os.path.join(work_folder, r'\1.rendered.pdf'),
extras=[_log, _pdfinfo, _pdfinfo_lock])
@graphviz(fillcolor='"#66ccff"')
def tesseract_ocr_and_render_pdf(
input_files,
output_file,
@@ -1219,13 +1113,6 @@ def get_pdfmark(base_pdf):
return pdfmark
@posttask(partial(done_task, 'generate_postscript_stub'))
@active_if(options.output_type == 'pdfa')
@transform(
input=repair_pdf,
filter=formatter(r'\.repaired\.pdf'),
output=os.path.join(work_folder, 'pdfa_def.ps'),
extras=[_log])
def generate_postscript_stub(
input_file,
output_file,
@@ -1236,13 +1123,6 @@ def generate_postscript_stub(
generate_pdfa_def(output_file, pdfmark)
@posttask(partial(done_task, 'skip_page'))
@transform(
input=orient_page,
filter=suffix('.skip.oriented.pdf'),
output='.done.pdf',
output_dir=work_folder,
extras=[_log])
def skip_page(
input_file,
output_file,
@@ -1254,13 +1134,6 @@ def skip_page(
re_symlink(input_file, output_file, log)
@posttask(partial(done_task, 'merge_pages_ghostscript'))
@active_if(options.output_type == 'pdfa')
@merge(
input=[add_text_layer, render_hocr_debug_page, skip_page,
tesseract_ocr_and_render_pdf, generate_postscript_stub],
output=os.path.join(work_folder, 'merged.pdf'),
extras=[_log, _pdfinfo, _pdfinfo_lock])
def merge_pages_ghostscript(
input_files,
output_file,
@@ -1286,13 +1159,6 @@ def merge_pages_ghostscript(
ghostscript.generate_pdfa(pdf_pages, output_file, options.jobs or 1)
@posttask(partial(done_task, 'merge_pages_qpdf'))
@active_if(options.output_type == 'pdf')
@merge(
input=[add_text_layer, render_hocr_debug_page, skip_page,
tesseract_ocr_and_render_pdf, repair_pdf],
output=os.path.join(work_folder, 'merged.pdf'),
extras=[_log, _pdfinfo, _pdfinfo_lock])
def merge_pages_qpdf(
input_files,
output_file,
@@ -1333,11 +1199,6 @@ def merge_pages_qpdf(
qpdf.merge(pdf_pages, output_file)
@posttask(partial(done_task, 'copy_final'))
@merge(
input=[merge_pages_ghostscript, merge_pages_qpdf],
output=options.output_file,
extras=[_log, _pdfinfo, _pdfinfo_lock])
def copy_final(
input_files,
output_file,
@@ -1451,6 +1312,212 @@ def traverse_ruffus_exception(e_args):
return traverse_ruffus_exception(exc)
def build_pipeline():
import sys
sys.argv = ['ocrmypdf', 'file1.pdf', 'file2.pdf']
options = parser.parse_args()
_logger, _logger_mutex = proxy_logger.make_shared_logger_and_proxy(
logging_factory, __name__, [None, options.verbose])
_log = WrappedLogger(_logger, _logger_mutex)
_log.debug('ocrmypdf ' + VERSION)
main_pipeline = Pipeline.pipelines['main']
# Triage
task_triage = main_pipeline.transform(
task_func=triage,
input=os.path.join(work_folder, 'origin'),
filter=formatter('(?i)'),
output=os.path.join(work_folder, 'origin.pdf'),
extras=[_log])
task_repair_pdf = main_pipeline.transform(
task_func=repair_pdf,
input=task_triage,
filter=suffix('.pdf'),
output='.repaired.pdf',
output_dir=work_folder,
extras=[_log, _pdfinfo, _pdfinfo_lock])
# Split
task_split_pages = main_pipeline.split(
split_pages,
task_repair_pdf,
os.path.join(work_folder, '*.page.pdf'),
extras=[_log, _pdfinfo, _pdfinfo_lock])
# Rasterize preview
task_rasterize_preview = main_pipeline.transform(
task_func=rasterize_preview,
input=task_split_pages,
filter=suffix('.page.pdf'),
output='.preview.jpg',
output_dir=work_folder,
extras=[_log, _pdfinfo, _pdfinfo_lock])
task_rasterize_preview.active_if(options.rotate_pages)
# Orient
task_orient_page = main_pipeline.collate(
task_func=orient_page,
input=[task_split_pages, task_rasterize_preview],
filter=regex(r".*/(\d{6})(\.ocr|\.skip)(?:\.page\.pdf|\.preview\.jpg)"),
output=os.path.join(work_folder, r'\1\2.oriented.pdf'),
extras=[_log, _pdfinfo, _pdfinfo_lock])
# Rasterize actual
task_rasterize_with_ghostscript = main_pipeline.transform(
task_func=rasterize_with_ghostscript,
input=task_orient_page,
filter=suffix('.ocr.oriented.pdf'),
output='.page.png',
output_dir=work_folder,
extras=[_log, _pdfinfo, _pdfinfo_lock])
# Preprocessing subpipeline
task_preprocess_remove_background = main_pipeline.transform(
task_func=preprocess_remove_background,
input=task_rasterize_with_ghostscript,
filter=suffix(".page.png"),
output=".pp-background.png",
extras=[_log, _pdfinfo, _pdfinfo_lock])
task_preprocess_deskew = main_pipeline.transform(
task_func=preprocess_deskew,
input=task_preprocess_remove_background,
filter=suffix(".pp-background.png"),
output=".pp-deskew.png",
extras=[_log, _pdfinfo, _pdfinfo_lock])
task_preprocess_clean = main_pipeline.transform(
task_func=preprocess_clean,
input=task_preprocess_deskew,
filter=suffix(".pp-deskew.png"),
output=".pp-clean.png",
extras=[_log, _pdfinfo, _pdfinfo_lock])
# HOCR OCR
task_ocr_tesseract_hocr = main_pipeline.transform(
task_func=ocr_tesseract_hocr,
input=task_preprocess_clean,
filter=suffix(".pp-clean.png"),
output=".hocr",
extras=[_log, _pdfinfo, _pdfinfo_lock])
task_ocr_tesseract_hocr.graphviz(fillcolor='"#00cc66"')
task_ocr_tesseract_hocr.active_if(options.pdf_renderer == 'hocr')
task_select_image_for_pdf = main_pipeline.collate(
task_func=select_image_for_pdf,
input=[task_rasterize_with_ghostscript,
task_preprocess_remove_background,
task_preprocess_deskew,
task_preprocess_clean],
filter=regex(r".*/(\d{6})(?:\.page|\.pp-.*)\.png"),
output=os.path.join(work_folder, r'\1.image'),
extras=[_log, _pdfinfo, _pdfinfo_lock])
task_select_image_for_pdf.graphviz(shape='diamond')
task_select_image_layer = main_pipeline.collate(
task_func=select_image_layer,
input=[task_select_image_for_pdf, task_orient_page],
filter=regex(r".*/(\d{6})(?:\.image|\.ocr\.oriented\.pdf)"),
output=os.path.join(work_folder, r'\1.image-layer.pdf'),
extras=[_log, _pdfinfo, _pdfinfo_lock])
task_select_image_layer.graphviz(
fillcolor='"#00cc66"', shape='diamond')
task_select_image_layer.active_if(options.pdf_renderer == 'hocr')
task_render_hocr_page = main_pipeline.transform(
task_func=render_hocr_page,
input=task_ocr_tesseract_hocr,
filter=suffix('.hocr'),
output='.hocr.pdf',
extras=[_log, _pdfinfo, _pdfinfo_lock])
task_render_hocr_page.graphviz(fillcolor='"#00cc66"')
task_render_hocr_page.active_if(options.pdf_renderer == 'hocr')
task_render_hocr_debug_page = main_pipeline.transform(
task_func=render_hocr_debug_page,
input=[task_select_image_for_pdf, task_ocr_tesseract_hocr],
filter=regex(r".*/(\d{6})(?:\.image|\.hocr)"),
output=os.path.join(work_folder, r'\1.debug.pdf'),
extras=[_log, _pdfinfo, _pdfinfo_lock])
task_render_hocr_debug_page.graphviz(fillcolor='"#00cc66"')
task_render_hocr_debug_page.active_if(options.pdf_renderer == 'hocr')
task_render_hocr_debug_page.active_if(options.debug_rendering)
task_add_text_layer = main_pipeline.collate(
task_func=add_text_layer,
input=[task_render_hocr_page, task_select_image_layer],
filter=regex(r".*/(\d{6})(?:\.hocr\.pdf|\.image-layer\.pdf)"),
output=os.path.join(work_folder, r'\1.rendered.pdf'),
extras=[_log, _pdfinfo, _pdfinfo_lock])
task_add_text_layer.graphviz(fillcolor='"#00cc66"')
task_add_text_layer.active_if(options.pdf_renderer == 'hocr')
# Tesseract OCR
task_tesseract_ocr_and_render_pdf = main_pipeline.collate(
task_func=tesseract_ocr_and_render_pdf,
input=[task_select_image_for_pdf, task_orient_page],
filter=regex(r".*/(\d{6})(?:\.image|\.ocr\.oriented\.pdf)"),
output=os.path.join(work_folder, r'\1.rendered.pdf'),
extras=[_log, _pdfinfo, _pdfinfo_lock])
task_tesseract_ocr_and_render_pdf.graphviz(fillcolor='"#66ccff"')
task_tesseract_ocr_and_render_pdf.active_if(options.pdf_renderer == 'tesseract')
# PDF/A
task_generate_postscript_stub = main_pipeline.transform(
task_func=generate_postscript_stub,
input=task_repair_pdf,
filter=formatter(r'\.repaired\.pdf'),
output=os.path.join(work_folder, 'pdfa_def.ps'),
extras=[_log])
task_generate_postscript_stub.active_if(options.output_type == 'pdfa')
# Bypass valve
task_skip_page = main_pipeline.transform(
task_func=skip_page,
input=task_orient_page,
filter=suffix('.skip.oriented.pdf'),
output='.done.pdf',
output_dir=work_folder,
extras=[_log])
# Merge pages
task_merge_pages_ghostscript = main_pipeline.merge(
task_func=merge_pages_ghostscript,
input=[task_add_text_layer,
task_render_hocr_debug_page,
task_skip_page,
task_tesseract_ocr_and_render_pdf,
task_generate_postscript_stub],
output=os.path.join(work_folder, 'merged.pdf'),
extras=[_log, _pdfinfo, _pdfinfo_lock])
task_merge_pages_ghostscript.active_if(options.output_type == 'pdfa')
task_merge_pages_qpdf = main_pipeline.merge(
task_func=merge_pages_qpdf,
input=[task_add_text_layer,
task_render_hocr_debug_page,
task_skip_page,
task_tesseract_ocr_and_render_pdf,
task_repair_pdf],
output=os.path.join(work_folder, 'merged.pdf'),
extras=[_log, _pdfinfo, _pdfinfo_lock])
task_merge_pages_qpdf.active_if(options.output_type == 'pdf')
# Finalize
task_copy_final = main_pipeline.merge(
task_func=copy_final,
input=[task_merge_pages_ghostscript, task_merge_pages_qpdf],
output=options.output_file,
extras=[_log, _pdfinfo, _pdfinfo_lock])
def run_pipeline():
# Any changes to options will not take effect for options that are already
# bound to function parameters in the pipeline. (For example