Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
58abb5785c | ||
|
|
509e75eaff | ||
|
|
0c50eedb2a | ||
|
|
c38ff90081 | ||
|
|
4c029e973f | ||
|
|
21cf9029e8 | ||
|
|
4a640b8dcd | ||
|
|
9471bc8921 | ||
|
|
7fe06c64fc | ||
|
|
d13d70fd56 | ||
|
|
58ec56180a | ||
|
|
32a88f1bad | ||
|
|
99ef42940c | ||
|
|
c152710617 |
@@ -0,0 +1,36 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
What command line or API call were you trying to run?
|
||||
|
||||
```bash
|
||||
ocrmypdf ...arguments... input.pdf output.pdf
|
||||
```
|
||||
|
||||
Run with verbosity or higher `-v1` to see more detailed logging. This information may be helpful.
|
||||
|
||||
**Example file**
|
||||
Please include an example *input* PDF (or image). The input file is more helpful.
|
||||
|
||||
If possible, use an input file with no personal or confidential information. At your option you may GPG-encrypt the file for OCRmyPDF's author only.
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**System**
|
||||
- OS: [e.g. Linux, Windows, macOS]
|
||||
- OCRmyPDF Version: ``ocrmypdf --version``
|
||||
- How did you install ocrmypdf? Did you use a system package manager, `pip`, or a Docker image?
|
||||
@@ -0,0 +1,17 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: enhancement
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
||||
@@ -51,6 +51,14 @@ Forking a child process to call ``ocrmypdf.ocr()`` is suggested. That
|
||||
way your application will survive and remain interactive even if
|
||||
OCRmyPDF does not.
|
||||
|
||||
.. warning::
|
||||
|
||||
On Windows, the script that calls ``ocrmypdf.ocr()`` must be protected
|
||||
by an "ifmain" guard (``if __name__ == '__main__'``) or you must use
|
||||
``ocrmypdf.ocr(...use_threads=True)``. If you do not take at least one
|
||||
of these steps, Windows fork semantics will prevent OCRmyPDF from working
|
||||
correct.
|
||||
|
||||
Logging
|
||||
-------
|
||||
|
||||
|
||||
@@ -202,6 +202,13 @@ Alternatives
|
||||
- `Watchman <https://facebook.github.io/watchman/>`__ is a more
|
||||
powerful alternative to ``watchmedo``.
|
||||
|
||||
AWS Lambda is not viable
|
||||
------------------------
|
||||
|
||||
AWS Lambda and its equivalents have low limits on execution time and payload
|
||||
size, relative to OCRmyPDF's needs. As of this writing, the request/response
|
||||
payload for AWS Lambda was 6 MB, which means many PDFs will not fit.
|
||||
|
||||
macOS Automator
|
||||
===============
|
||||
|
||||
|
||||
+2
-4
@@ -90,10 +90,8 @@ Docker volume:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
docker run --rm -v $(pwd):/data ocrmypdf /data/input.pdf /data/output.pdf
|
||||
|
||||
(However, when done this way, ``output.pdf`` may be owned by the root
|
||||
user.)
|
||||
alias docker_ocrmypdf='docker run --rm -i --user "$(id -u):$(id -g)" --workdir /data -v "$PWD:/data" ocrmypdf'
|
||||
docker_ocrmypdf /data/input.pdf /data/output.pdf
|
||||
|
||||
.. _docker-lang-packs:
|
||||
|
||||
|
||||
@@ -13,6 +13,19 @@ Note that it is licensed under GPLv3, so scripts that
|
||||
``import ocrmypdf`` and are released publicly should probably also be
|
||||
licensed under GPLv3.
|
||||
|
||||
v9.7.2
|
||||
======
|
||||
|
||||
- Fixed an issue with ``ocrmypdf.ocr(...language=)`` not accepting a list of
|
||||
languages as documented.
|
||||
- Updated setup.py to confirm that pdfminer.six version 20200402 is supported.
|
||||
|
||||
v9.7.1
|
||||
======
|
||||
|
||||
- Fixed version check failing when used with qpdf 10.0.0.
|
||||
- Added some missing type annotations.
|
||||
- Updated documentation to warn about need for "ifmain" guard and Windows.
|
||||
|
||||
v9.7.0
|
||||
======
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
# installation
|
||||
cffi == 1.14.0
|
||||
img2pdf == 0.3.3
|
||||
pdfminer.six == 20200124
|
||||
pdfminer.six == 20200402
|
||||
pikepdf == 1.10.2
|
||||
Pillow == 7.0.0
|
||||
reportlab == 3.5.34
|
||||
|
||||
@@ -98,7 +98,7 @@ setup(
|
||||
'chardet >= 3.0.4, < 4', # unlisted requirement of pdfminer.six 20181108
|
||||
'cffi >= 1.9.1', # must be a setup and install requirement
|
||||
'img2pdf >= 0.3.0, < 0.4', # pure Python, so track HEAD closely
|
||||
'pdfminer.six >= 20181108, <= 20200124',
|
||||
'pdfminer.six >= 20181108, <= 20200402',
|
||||
'pikepdf >= 1.8.1, < 2',
|
||||
'Pillow >= 6.2.0',
|
||||
'reportlab >= 3.3.0', # oldest released version with sane image handling
|
||||
|
||||
+15
-5
@@ -21,7 +21,7 @@ import sys
|
||||
from contextlib import suppress
|
||||
from enum import IntEnum
|
||||
from pathlib import Path
|
||||
from typing import Dict, List
|
||||
from typing import Dict, Iterable
|
||||
|
||||
from tqdm import tqdm
|
||||
|
||||
@@ -67,7 +67,11 @@ class Verbosity(IntEnum):
|
||||
debug_all = 2 #: More detailed debugging from ocrmypdf and dependent modules
|
||||
|
||||
|
||||
def configure_logging(verbosity, progress_bar_friendly=True, manage_root_logger=False):
|
||||
def configure_logging(
|
||||
verbosity: Verbosity,
|
||||
progress_bar_friendly: bool = True,
|
||||
manage_root_logger: bool = False,
|
||||
):
|
||||
"""Set up logging.
|
||||
|
||||
Library users may wish to use this function if they want their log output to be
|
||||
@@ -128,7 +132,7 @@ def configure_logging(verbosity, progress_bar_friendly=True, manage_root_logger=
|
||||
return log
|
||||
|
||||
|
||||
def create_options(*, input_file, output_file, **kwargs):
|
||||
def create_options(*, input_file: os.PathLike, output_file: os.PathLike, **kwargs):
|
||||
cmdline = []
|
||||
deferred = []
|
||||
|
||||
@@ -150,6 +154,12 @@ def create_options(*, input_file, output_file, **kwargs):
|
||||
cmdline.append(f"--{cmd_style_arg}")
|
||||
continue
|
||||
|
||||
if isinstance(val, Iterable) and not isinstance(val, str):
|
||||
for elem in val:
|
||||
cmdline.append(f"--{cmd_style_arg}")
|
||||
cmdline.append(elem)
|
||||
continue
|
||||
|
||||
# We have a parameter
|
||||
cmdline.append(f"--{cmd_style_arg}")
|
||||
if isinstance(val, (int, float)):
|
||||
@@ -180,7 +190,7 @@ def ocr( # pylint: disable=unused-argument
|
||||
input_file: os.PathLike,
|
||||
output_file: os.PathLike,
|
||||
*,
|
||||
language: List[str] = None,
|
||||
language: Iterable[str] = None,
|
||||
image_dpi: int = None,
|
||||
output_type=None,
|
||||
sidecar: os.PathLike = None,
|
||||
@@ -210,7 +220,7 @@ def ocr( # pylint: disable=unused-argument
|
||||
jbig2_page_group_size: int = None,
|
||||
pages: str = None,
|
||||
max_image_mpixels: float = None,
|
||||
tesseract_config: List[str] = None,
|
||||
tesseract_config: Iterable[str] = None,
|
||||
tesseract_pagesegmode: int = None,
|
||||
tesseract_oem: int = None,
|
||||
pdf_renderer=None,
|
||||
|
||||
@@ -23,6 +23,7 @@ import re
|
||||
import shutil
|
||||
import sys
|
||||
from collections.abc import Mapping
|
||||
from distutils.version import LooseVersion
|
||||
from functools import lru_cache
|
||||
from subprocess import PIPE, STDOUT, CalledProcessError
|
||||
from subprocess import run as subprocess_run
|
||||
@@ -270,7 +271,15 @@ def check_external_program(
|
||||
raise MissingDependencyError()
|
||||
return
|
||||
|
||||
if found_version < need_version:
|
||||
def remove_leading_v(s):
|
||||
if s.startswith('v'):
|
||||
return s[1:]
|
||||
return s
|
||||
|
||||
found_version = remove_leading_v(found_version)
|
||||
need_version = remove_leading_v(need_version)
|
||||
|
||||
if LooseVersion(found_version) < LooseVersion(need_version):
|
||||
_error_old_version(program, package, need_version, found_version, required_for)
|
||||
if not recommended:
|
||||
raise MissingDependencyError()
|
||||
|
||||
@@ -28,7 +28,7 @@ from pathlib import Path
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def safe_symlink(input_file, soft_link_name, *args, **kwargs):
|
||||
def safe_symlink(input_file: os.PathLike, soft_link_name: os.PathLike, *args, **kwargs):
|
||||
"""
|
||||
Helper function: relinks soft symbolic link if necessary
|
||||
"""
|
||||
@@ -76,12 +76,12 @@ def is_iterable_notstr(thing):
|
||||
return isinstance(thing, Iterable) and not isinstance(thing, str)
|
||||
|
||||
|
||||
def monotonic(L):
|
||||
def monotonic(L: Iterable):
|
||||
"""Does list increase monotonically?"""
|
||||
return all(b > a for a, b in zip(L, L[1:]))
|
||||
|
||||
|
||||
def page_number(input_file):
|
||||
def page_number(input_file: os.PathLike):
|
||||
"""Get one-based page number implied by filename (000002.pdf -> 2)"""
|
||||
return int(os.path.basename(os.fspath(input_file))[0:6])
|
||||
|
||||
@@ -97,7 +97,7 @@ def available_cpu_count():
|
||||
return 1
|
||||
|
||||
|
||||
def is_file_writable(test_file):
|
||||
def is_file_writable(test_file: os.PathLike):
|
||||
"""Intentionally racy test if target is writable.
|
||||
|
||||
We intend to write to the output file if and only if we succeed and
|
||||
|
||||
@@ -22,7 +22,7 @@ from collections import defaultdict, namedtuple
|
||||
from decimal import Decimal
|
||||
from enum import Enum
|
||||
from math import hypot, isclose
|
||||
from os import fspath
|
||||
from os import PathLike, fspath
|
||||
from pathlib import Path
|
||||
from warnings import warn
|
||||
|
||||
@@ -40,7 +40,7 @@ logger = logging.getLogger()
|
||||
Colorspace = Enum('Colorspace', 'gray rgb cmyk lab icc index sep devn pattern jpeg2000')
|
||||
|
||||
Encoding = Enum(
|
||||
'Encoding', 'ccitt jpeg jpeg2000 jbig2 asciihex ascii85 lzw flate ' + 'runlength'
|
||||
'Encoding', 'ccitt jpeg jpeg2000 jbig2 asciihex ascii85 lzw flate runlength'
|
||||
)
|
||||
|
||||
FRIENDLY_COLORSPACE = {
|
||||
@@ -558,7 +558,7 @@ def simplify_textboxes(miner, textbox_getter):
|
||||
yield TextboxInfo(box.bbox, visible, corrupt)
|
||||
|
||||
|
||||
def _pdf_get_pageinfo(pdf, pageno: int, infile, xmltext):
|
||||
def _pdf_get_pageinfo(pdf, pageno: int, infile: PathLike, xmltext: str):
|
||||
pageinfo = {}
|
||||
pageinfo['pageno'] = pageno
|
||||
pageinfo['images'] = []
|
||||
|
||||
@@ -59,3 +59,10 @@ def test_tqdm_console():
|
||||
|
||||
log.info("done")
|
||||
assert not before_pbar("done")
|
||||
|
||||
|
||||
def test_language_list():
|
||||
with pytest.raises(
|
||||
(ocrmypdf.exceptions.InputFileError, ocrmypdf.exceptions.MissingDependencyError)
|
||||
):
|
||||
ocrmypdf.ocr('doesnotexist.pdf', '_.pdf', language=['eng', 'deu'])
|
||||
|
||||
@@ -176,3 +176,37 @@ def test_language_warning(caplog):
|
||||
vd.check_options_languages(opts)
|
||||
assert opts.language == ['eng']
|
||||
assert 'assuming --language' in caplog.text
|
||||
|
||||
|
||||
def test_version_comparison():
|
||||
vd.check_external_program(
|
||||
program="dummy_basic",
|
||||
package="dummy",
|
||||
version_checker=lambda: '9.0',
|
||||
need_version='8.0.2',
|
||||
)
|
||||
vd.check_external_program(
|
||||
program="dummy_doubledigit",
|
||||
package="dummy",
|
||||
version_checker=lambda: '10.0',
|
||||
need_version='8.0.2',
|
||||
)
|
||||
vd.check_external_program(
|
||||
program="tesseract",
|
||||
package="tesseract",
|
||||
version_checker=lambda: '4.0.0-beta.1',
|
||||
need_version='4.0.0',
|
||||
)
|
||||
vd.check_external_program(
|
||||
program="tesseract",
|
||||
package="tesseract",
|
||||
version_checker=lambda: 'v5.0.0-alpha.20200201',
|
||||
need_version='4.0.0',
|
||||
)
|
||||
with pytest.raises(MissingDependencyError):
|
||||
vd.check_external_program(
|
||||
program="dummy_fails",
|
||||
package="dummy",
|
||||
version_checker=lambda: '1.0',
|
||||
need_version='2.0',
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user