Compare commits

...
10 Commits
11 changed files with 72 additions and 61 deletions
+3 -3
View File
@@ -19,16 +19,16 @@ repos:
language_version: python
exclude: ^src/ocrmypdf/lib/_leptonica.py
- repo: https://github.com/asottile/setup-cfg-fmt
rev: v1.17.0
rev: v1.19.0
hooks:
- id: setup-cfg-fmt
- repo: https://github.com/asottile/pyupgrade
rev: v2.26.0
rev: v2.29.0
hooks:
- id: pyupgrade
args: ["--py36-plus"]
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v0.910
rev: v0.910-1
hooks:
- id: mypy
additional_dependencies:
+15
View File
@@ -18,6 +18,21 @@ wish to use some of its features for working with PDFs.
for Python 3.6 around that time. The change will be marked with a major
release.
v12.7.2
=======
- Fixed "invalid version number" error for Tesseract packaging with nonstandard
version "5.0.0-rc1.20211030".
- Fixed use of deprecated ``importlib.resources.read_binary``.
- Replace some uses of string paths with ``pathlib.Path``.
- Fixed a leaked file handle when using ``--output-type none``.
- Removed shims to support versions of pikepdf that are no longer supported.
v12.7.1
=======
- Declare support for pdfminer.six v20211012.
v12.7.0
=======
+15 -21
View File
@@ -24,45 +24,39 @@
import logging
import os
import sys
from pathlib import Path
import ocrmypdf
# pylint: disable=logging-format-interpolation
# pylint: disable=logging-not-lazy
script_dir = os.path.dirname(os.path.realpath(__file__))
print(script_dir + '/batch.py: Start')
script_dir = Path(__file__).parent
if len(sys.argv) > 1:
start_dir = sys.argv[1]
start_dir = Path(sys.argv[1])
else:
start_dir = '.'
start_dir = Path('.')
if len(sys.argv) > 2:
log_file = sys.argv[2]
log_file = Path(sys.argv[2])
else:
log_file = script_dir + '/ocr-tree.log'
log_file = script_dir.with_name('ocr-tree.log')
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s %(message)s',
filename=log_file,
filemode='w',
filemode='a',
)
ocrmypdf.configure_logging(ocrmypdf.Verbosity.default)
for dir_name, _subdirs, file_list in os.walk(start_dir):
logging.info(dir_name + '\n')
os.chdir(dir_name)
for filename in file_list:
file_ext = os.path.splitext(filename)[1]
if file_ext == '.pdf':
full_path = dir_name + '/' + filename
print(full_path)
result = ocrmypdf.ocr(filename, filename, deskew=True)
if result == ocrmypdf.ExitCode.already_done_ocr:
print("Skipped document because it already contained text")
elif result == ocrmypdf.ExitCode.ok:
print("OCR complete")
logging.info(result)
for filename in start_dir.glob("**/*.py"):
logging.info(f"Processing {filename}")
result = ocrmypdf.ocr(filename, filename, deskew=True)
if result == ocrmypdf.ExitCode.already_done_ocr:
logging.error("Skipped document because it already contained text")
elif result == ocrmypdf.ExitCode.ok:
logging.info("OCR complete")
logging.info(result)
+7 -6
View File
@@ -28,6 +28,7 @@ classifiers =
Programming Language :: Python :: 3.7
Programming Language :: Python :: 3.8
Programming Language :: Python :: 3.9
Programming Language :: Python :: 3.10
Topic :: Scientific/Engineering :: Image Recognition
Topic :: Text Processing :: Indexing
Topic :: Text Processing :: Linguistic
@@ -49,14 +50,14 @@ install_requires =
cffi>=1.9.1 # must be a setup and install requirement
coloredlogs>=14.0 # strictly optional
img2pdf>=0.3.0,<0.5 # pure Python
importlib-metadata>=4;python_version<'3.8' # until Python 3.8
importlib-resources>=5;python_version<'3.9' # until Python 3.9
pdfminer.six!=20200720,>=20191110,<=20201018
pdfminer.six!=20200720,>=20191110,<=20211012
pikepdf>=2.10.0
pikepdf<3;implementation_name=="pypy" and python_version=='3.6'
pluggy>=0.13.0,<2
reportlab>=3.5.66
tqdm>=4
importlib-metadata>=4;python_version<'3.8' # until Python 3.8
importlib-resources>=5;python_version<'3.9' # until Python 3.9
pikepdf<3;implementation_name=="pypy" and python_version=='3.6'
python_requires = >=3.6
include_package_data = True
package_dir =
@@ -64,8 +65,8 @@ package_dir =
platforms = any
setup_requires =
cffi>=1.9.1 # to build the leptonica module
setuptools_scm
setuptools_scm_git_archive
setuptools-scm
setuptools-scm-git-archive
zip_safe = False
[options.packages.find]
+9 -11
View File
@@ -8,9 +8,7 @@
"""Interface to Tesseract executable"""
import logging
import os
import re
import shutil
from collections import namedtuple
from distutils.version import StrictVersion
from os import fspath
@@ -61,8 +59,8 @@ class TesseractVersion(StrictVersion):
r'''
^(\d+) \. (\d+) (\. (\d+))? # groups: 1/major, 2/minor, 3/[skip], 4/patch
[-]? # optional hyphen separator
(?:(alpha|beta|rc|dev)?[.\-\ ]?(\d+)?)? # 5/prerelease, 6/prerelease_num
(?:-(\d+)-g[0-9a-f]+)? # untagged git version
(?: ((?:alpha|beta|rc|dev)\d*)? [.\-\ ]? (\d+)? )? # 5/prerelease, 6/prerelease_num
(?:(?:-\d+)?-g[0-9a-f]+)? # untagged git version
$
''',
re.VERBOSE | re.ASCII,
@@ -73,7 +71,7 @@ class TesseractVersion(StrictVersion):
super().parse(vstring)
except TypeError as e:
if 'int() argument must be a string' in str(e):
super().parse(vstring + '0')
super().parse(vstring + '-0')
def version():
@@ -250,7 +248,7 @@ def generate_hocr(
# Reminder: test suite tesseract test plugins will break after any changes
# to the number of order parameters here
args_tesseract.extend([os.fspath(input_file), os.fspath(prefix), 'hocr', 'txt'])
args_tesseract.extend([fspath(input_file), fspath(prefix), 'hocr', 'txt'])
args_tesseract.extend(tessconfig)
try:
p = run(args_tesseract, stdout=PIPE, stderr=STDOUT, timeout=timeout, check=True)
@@ -273,7 +271,7 @@ def generate_hocr(
# The sidecar text file will get the suffix .txt; rename it to
# whatever caller wants it named
if prefix.with_suffix('.txt').exists():
shutil.move(prefix.with_suffix('.txt'), output_text)
prefix.with_suffix('.txt').replace(output_text)
def use_skip_page(output_pdf, output_text):
@@ -320,18 +318,18 @@ def generate_pdf(
if user_patterns:
args_tesseract.extend(['--user-patterns', user_patterns])
prefix = os.path.splitext(output_pdf)[0] # Tesseract appends suffixes
prefix = output_pdf.parent / Path(output_pdf.stem)
# Reminder: test suite tesseract test plugins might break after any changes
# to the number of order parameters here
args_tesseract.extend([os.fspath(input_file), os.fspath(prefix), 'pdf', 'txt'])
args_tesseract.extend([fspath(input_file), fspath(prefix), 'pdf', 'txt'])
args_tesseract.extend(tessconfig)
try:
p = run(args_tesseract, stdout=PIPE, stderr=STDOUT, timeout=timeout, check=True)
stdout = p.stdout
if os.path.exists(prefix + '.txt'):
shutil.move(prefix + '.txt', output_text)
if prefix.with_suffix('.txt').exists():
prefix.with_suffix('.txt').replace(output_text)
except TimeoutExpired:
page_timedout(timeout)
use_skip_page(output_pdf, output_text)
+3 -3
View File
@@ -290,10 +290,10 @@ def exec_concurrent(context: PdfContext, executor: Executor):
# Copy text file to destination
copy_final(text, options.sidecar, context)
if options.output_type != 'none':
# Merge layers to one single pdf
pdf = ocrgraft.finalize()
# Merge layers to one single pdf
pdf = ocrgraft.finalize()
if options.output_type != 'none':
# PDF/A and metadata
log.info("Postprocessing...")
pdf = post_process(pdf, context, executor)
+4 -2
View File
@@ -160,10 +160,12 @@ def _pages_from_ranges(ranges: str) -> Set[int]:
try:
new_pages = list(range(int(start) - 1, int(end)))
if not new_pages:
raise BadArgsError(f"invalid page subrange '{start}-{end}'")
raise BadArgsError(
f"invalid page subrange '{start}-{end}'"
) from None
pages.extend(new_pages)
except ValueError:
raise BadArgsError("invalid page range") from None
raise BadArgsError(f"invalid page subrange '{g}'") from None
if not pages:
raise BadArgsError(
+1 -9
View File
@@ -221,15 +221,7 @@ def check_pdf(input_file: Path) -> bool:
# If linearization is missing entirely, we do not complain. We do
# complain if linearization is present but incorrect.
pdf.check_linearization(sio)
except RuntimeError:
pass
except (
# Workaround for a problematic pikepdf version
# pragma: no cover
pikepdf.ForeignObjectError
if pikepdf.__version__ == '2.1.0'
else NeverRaise
):
except (RuntimeError, pikepdf.ForeignObjectError):
pass
else:
linearize_msgs = sio.getvalue()
+4 -1
View File
@@ -585,7 +585,10 @@ def optimize(
log.info(f"Optimize ratio: {ratio:.2f} savings: {(savings):.1%}")
if savings < 0:
log.info("Image optimization did not improve the file - discarded")
log.info(
"Image optimization did not improve the file - "
"optimizations will not be used"
)
# We still need to save the file
with Pdf.open(input_file) as pike:
pike.remove_unreferenced_resources()
+4 -5
View File
@@ -14,9 +14,10 @@ from pathlib import Path
from typing import Dict, Iterator, Union
try:
from importlib_resources import read_binary
from importlib_resources import files as package_files
except ImportError:
from importlib.resources import read_binary
from importlib.resources import files as package_files
import pikepdf
import pkg_resources # deprecated
@@ -107,9 +108,7 @@ def generate_pdfa_ps(target_filename: Path, icc: str = 'sRGB'):
if icc != 'sRGB':
raise NotImplementedError("Only supporting sRGB")
bytes_icc_profile = read_binary(
'ocrmypdf.data', SRGB_ICC_PROFILE_NAME
)
bytes_icc_profile = (package_files('ocrmypdf.data') / SRGB_ICC_PROFILE).read_bytes()
ps = '\n'.join(_make_postscript(icc, bytes_icc_profile, 3))
# We should have encoded everything to pure ASCII by this point, and
+7
View File
@@ -238,6 +238,13 @@ def test_version_comparison():
need_version='4.0.0',
version_parser=TesseractVersion,
)
vd.check_external_program(
program="tesseract",
package="tesseract",
version_checker=lambda: '5.0.0-rc1.20211030',
need_version='4.0.0',
version_parser=TesseractVersion,
)
vd.check_external_program(
program="tesseract",
package="tesseract",