Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8fca0c71dc | ||
|
|
944d99bdc1 | ||
|
|
5bb6e1c5d7 | ||
|
|
8d7a8f0f98 | ||
|
|
b9dd0a5e3c | ||
|
|
6949ad2c5d | ||
|
|
b3324c3b4e | ||
|
|
b38cac6931 | ||
|
|
bb4c47e707 | ||
|
|
5e1e2497ab | ||
|
|
cd910fbf21 | ||
|
|
1225269a4b |
+32
-10
@@ -19,8 +19,10 @@ jobs:
|
|||||||
test_linux:
|
test_linux:
|
||||||
name: Test ${{ matrix.os }} with Python ${{ matrix.python }}
|
name: Test ${{ matrix.os }} with Python ${{ matrix.python }}
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
|
continue-on-error: ${{ matrix.experimental }}
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
|
experimental: [false]
|
||||||
include:
|
include:
|
||||||
- os: ubuntu-22.04
|
- os: ubuntu-22.04
|
||||||
python: "3.10"
|
python: "3.10"
|
||||||
@@ -34,6 +36,9 @@ jobs:
|
|||||||
tesseract5: true
|
tesseract5: true
|
||||||
- os: ubuntu-latest
|
- os: ubuntu-latest
|
||||||
python: "pypy3.10"
|
python: "pypy3.10"
|
||||||
|
- os: ubuntu-22.04
|
||||||
|
python: "3.13"
|
||||||
|
experimental: true
|
||||||
|
|
||||||
env:
|
env:
|
||||||
OS: ${{ matrix.os }}
|
OS: ${{ matrix.os }}
|
||||||
@@ -49,6 +54,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
python-version: ${{ matrix.python }}
|
python-version: ${{ matrix.python }}
|
||||||
cache: "pip"
|
cache: "pip"
|
||||||
|
allow-prereleases: ${{ matrix.experimental }}
|
||||||
|
|
||||||
- name: Install Tesseract 5
|
- name: Install Tesseract 5
|
||||||
if: matrix.tesseract5
|
if: matrix.tesseract5
|
||||||
@@ -258,29 +264,45 @@ jobs:
|
|||||||
|
|
||||||
create_release:
|
create_release:
|
||||||
name: Create GitHub release
|
name: Create GitHub release
|
||||||
needs: [wheel_sdist_linux, test_linux, test_macos, test_windows]
|
needs: [upload_pypi]
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags/v')
|
if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags/v')
|
||||||
permissions:
|
permissions:
|
||||||
# Required to create a release
|
# Required to create a release
|
||||||
contents: write
|
contents: write
|
||||||
|
id-token: write
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/download-artifact@v4
|
- uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: artifact
|
name: artifact
|
||||||
path: dist
|
path: dist
|
||||||
|
|
||||||
- name: Create Release
|
- name: Sign the dists with Sigstore
|
||||||
id: create-release
|
uses: sigstore/gh-action-sigstore-python@v2.1.1
|
||||||
uses: shogo82148/actions-create-release@v1
|
|
||||||
|
|
||||||
- name: Upload Assets
|
|
||||||
uses: shogo82148/actions-upload-release-asset@v1
|
|
||||||
with:
|
with:
|
||||||
upload_url: ${{ steps.create-release.outputs.upload_url }}
|
inputs: >-
|
||||||
asset_path: |
|
|
||||||
./dist/*.whl
|
|
||||||
./dist/*.tar.gz
|
./dist/*.tar.gz
|
||||||
|
./dist/*.whl
|
||||||
|
|
||||||
|
- name: Create GitHub Release
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ github.token }}
|
||||||
|
run: >-
|
||||||
|
gh release create
|
||||||
|
'${{ github.ref_name }}'
|
||||||
|
--repo '${{ github.repository }}'
|
||||||
|
--notes ""
|
||||||
|
|
||||||
|
- name: Upload artifact signatures to GitHub Release
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ github.token }}
|
||||||
|
# Upload to GitHub Release using the `gh` CLI.
|
||||||
|
# `dist/` contains the built packages, and the
|
||||||
|
# sigstore-produced signatures and certificates.
|
||||||
|
run: >-
|
||||||
|
gh release upload
|
||||||
|
'${{ github.ref_name }}' dist/**
|
||||||
|
--repo '${{ github.repository }}'
|
||||||
|
|
||||||
docker_ubuntu:
|
docker_ubuntu:
|
||||||
name: Build Ubuntu-based Docker image
|
name: Build Ubuntu-based Docker image
|
||||||
|
|||||||
@@ -44,3 +44,4 @@ docs/_build/
|
|||||||
docs/_static/
|
docs/_static/
|
||||||
docs/_templates/
|
docs/_templates/
|
||||||
docs/Makefile
|
docs/Makefile
|
||||||
|
src/ocrmypdf/_version.py
|
||||||
+1
-1
@@ -135,7 +135,7 @@ Users may need to customize the script to meet their requirements.
|
|||||||
"OCR_ON_SUCCESS_ARCHIVE", "This will move the processed original file to ``OCR_ARCHIVE_DIRECTORY`` if the exit code is 0 (OK). Note that ``OCR_ON_SUCCESS_DELETE`` takes precedence over this option, i.e. if both options are set, the input file will be deleted."
|
"OCR_ON_SUCCESS_ARCHIVE", "This will move the processed original file to ``OCR_ARCHIVE_DIRECTORY`` if the exit code is 0 (OK). Note that ``OCR_ON_SUCCESS_DELETE`` takes precedence over this option, i.e. if both options are set, the input file will be deleted."
|
||||||
"OCR_OUTPUT_DIRECTORY_YEAR_MONTH", "This will place files in the output in ``{output}/{year}/{month}/{filename}``"
|
"OCR_OUTPUT_DIRECTORY_YEAR_MONTH", "This will place files in the output in ``{output}/{year}/{month}/{filename}``"
|
||||||
"OCR_DESKEW", "Apply deskew to crooked input PDFs"
|
"OCR_DESKEW", "Apply deskew to crooked input PDFs"
|
||||||
"OCR_JSON_SETTINGS", "A JSON string specifying any other arguments for ``ocrmypdf.ocr``, e.g. ``'OCR_JSON_SETTINGS={""rotate_pages"": true}'``."
|
"OCR_JSON_SETTINGS", "A JSON string specifying any other arguments for ``ocrmypdf.ocr``, e.g. ``'OCR_JSON_SETTINGS={""rotate_pages"": true, ""optimize"": "3"}'``."
|
||||||
"OCR_POLL_NEW_FILE_SECONDS", "Polling interval"
|
"OCR_POLL_NEW_FILE_SECONDS", "Polling interval"
|
||||||
"OCR_LOGLEVEL", "Level of log messages to report"
|
"OCR_LOGLEVEL", "Level of log messages to report"
|
||||||
|
|
||||||
|
|||||||
@@ -640,8 +640,7 @@ environment:
|
|||||||
|
|
||||||
pip install git+https://github.com/ocrmypdf/OCRmyPDF.git
|
pip install git+https://github.com/ocrmypdf/OCRmyPDF.git
|
||||||
|
|
||||||
Or, to install in `development
|
Or, to install in editable mode
|
||||||
mode <https://packaging.python.org/en/latest/guides/distributing-packages-using-setuptools/#working-in-development-mode>`__,
|
|
||||||
allowing customization of OCRmyPDF, use the ``-e`` flag:
|
allowing customization of OCRmyPDF, use the ``-e`` flag:
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|||||||
@@ -38,12 +38,13 @@ on ARM and x86_64. Performance may be poor on other processor architectures.
|
|||||||
Versioning scheme
|
Versioning scheme
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
OCRmyPDF uses setuptools-scm for versioning, which derives the version from
|
OCRmyPDF uses hatch-vcs for versioning, which derives the version from
|
||||||
Git as a single source of truth. This may be unsuitable for some distributions, e.g.
|
Git as a single source of truth. This may be unsuitable for some distributions, e.g.
|
||||||
to indicate that your distribution modifies OCRmyPDF in some way.
|
to indicate that your distribution modifies OCRmyPDF in some way.
|
||||||
|
|
||||||
You can patch the ``__version__`` variable in ``src/ocrmypdf/_version.py`` if
|
You can patch the ``__version__`` variable in ``src/ocrmypdf/_version.py`` if
|
||||||
necessary.
|
necessary, or set the environment variable ``SETUPTOOLS_SCM_PRETEND_VERSION``
|
||||||
|
to the required version, if you need to override versioning for some reason.
|
||||||
|
|
||||||
jbig2enc
|
jbig2enc
|
||||||
--------
|
--------
|
||||||
|
|||||||
+9
-12
@@ -29,6 +29,9 @@ conventions. Note that: plugins installed with as setuptools entrypoints are
|
|||||||
not checked currently, because OCRmyPDF assumes you may not want to enable
|
not checked currently, because OCRmyPDF assumes you may not want to enable
|
||||||
plugins for all files.
|
plugins for all files.
|
||||||
|
|
||||||
|
See [OCRmyPDF-EasyOCR](https://github.com/ocrmypdf/OCRmyPDF-EasyOCR) for an
|
||||||
|
example of a straightforward, fully working plugin.
|
||||||
|
|
||||||
Script plugins
|
Script plugins
|
||||||
==============
|
==============
|
||||||
|
|
||||||
@@ -70,14 +73,15 @@ similar to ``pytest`` packages such as ``pytest-cov`` (the package) and
|
|||||||
module), just like pytest plugins. At the same time, please make it clear
|
module), just like pytest plugins. At the same time, please make it clear
|
||||||
that your package is not official.
|
that your package is not official.
|
||||||
|
|
||||||
Setuptools plugins
|
Plugins
|
||||||
==================
|
=======
|
||||||
|
|
||||||
You can also create a plugin that OCRmyPDF will always automatically load if both are
|
You can also create a plugin that OCRmyPDF will always automatically load if both are
|
||||||
installed in the same virtual environment, using a setuptools entrypoint.
|
installed in the same virtual environment, using a project entrypoint.
|
||||||
|
OCRmyPDF uses the entrypoint namespace "ocrmypdf".
|
||||||
|
|
||||||
Your package's ``pyproject.toml`` would need to contain the following, for a plugin
|
For example, ``pyproject.toml`` would need to contain the following, for a plugin named
|
||||||
named ``ocrmypdf-exampleplugin``:
|
``ocrmypdf-exampleplugin``:
|
||||||
|
|
||||||
.. code-block:: toml
|
.. code-block:: toml
|
||||||
|
|
||||||
@@ -87,13 +91,6 @@ named ``ocrmypdf-exampleplugin``:
|
|||||||
[project.entry-points."ocrmypdf"]
|
[project.entry-points."ocrmypdf"]
|
||||||
exampleplugin = "exampleplugin.pluginmodule"
|
exampleplugin = "exampleplugin.pluginmodule"
|
||||||
|
|
||||||
.. code-block:: ini
|
|
||||||
|
|
||||||
# equivalent setup.cfg
|
|
||||||
[options.entry_points]
|
|
||||||
ocrmypdf =
|
|
||||||
exampleplugin = exampleplugin.pluginmodule
|
|
||||||
|
|
||||||
Plugin requirements
|
Plugin requirements
|
||||||
===================
|
===================
|
||||||
|
|
||||||
|
|||||||
@@ -30,6 +30,17 @@ OCRmyPDF typically supports the three most recent Python versions.
|
|||||||
|
|
||||||
.. |OCRmyPDF PyPI| image:: https://img.shields.io/pypi/v/ocrmypdf.svg
|
.. |OCRmyPDF PyPI| image:: https://img.shields.io/pypi/v/ocrmypdf.svg
|
||||||
|
|
||||||
|
v16.5.0
|
||||||
|
=======
|
||||||
|
|
||||||
|
- Fixed issue with interpreting PDFs that have images with array masks.
|
||||||
|
:issue:`1377`
|
||||||
|
- Enabled testing on Python 3.13.
|
||||||
|
- Fixed a test that did not work correctly but still passed. :issue:`1382`
|
||||||
|
- Improved "PDF/A conversion failed" warning message to better describe implications.
|
||||||
|
- Updated documentation to better explain OCR_JSON_SETTINGS in batch processing.
|
||||||
|
- Build backend changed from setuptools to hatchling.
|
||||||
|
|
||||||
v16.4.3
|
v16.4.3
|
||||||
=======
|
=======
|
||||||
|
|
||||||
|
|||||||
+7
-9
@@ -1,8 +1,8 @@
|
|||||||
# SPDX-FileCopyrightText: 2022 James R. Barlow
|
# SPDX-FileCopyrightText: 2022 James R. Barlow
|
||||||
# SPDX-License-Identifier: MPL-2.0
|
# SPDX-License-Identifier: MPL-2.0
|
||||||
[build-system]
|
[build-system]
|
||||||
requires = ["setuptools >= 61", "setuptools_scm[toml] >= 7.0.5", "wheel"]
|
requires = ["hatchling", "hatch-vcs"]
|
||||||
build-backend = "setuptools.build_meta"
|
build-backend = "hatchling.build"
|
||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "ocrmypdf"
|
name = "ocrmypdf"
|
||||||
@@ -46,6 +46,7 @@ keywords = ["PDF", "OCR", "optical character recognition", "PDF/A", "scanning"]
|
|||||||
Documentation = "https://ocrmypdf.readthedocs.io/"
|
Documentation = "https://ocrmypdf.readthedocs.io/"
|
||||||
Source = "https://github.com/ocrmypdf/OCRmyPDF"
|
Source = "https://github.com/ocrmypdf/OCRmyPDF"
|
||||||
Tracker = "https://github.com/ocrmypdf/OCRmyPDF/issues"
|
Tracker = "https://github.com/ocrmypdf/OCRmyPDF/issues"
|
||||||
|
Changelog = "https://github.com/ocrmypdf/OCRmyPDF/docs/release_notes.rst"
|
||||||
|
|
||||||
[project.optional-dependencies]
|
[project.optional-dependencies]
|
||||||
docs = ["sphinx", "sphinx-issues", "sphinx-rtd-theme"]
|
docs = ["sphinx", "sphinx-issues", "sphinx-rtd-theme"]
|
||||||
@@ -67,14 +68,11 @@ webservice = ["Flask>=2.0.1"]
|
|||||||
[project.scripts]
|
[project.scripts]
|
||||||
ocrmypdf = "ocrmypdf.__main__:run"
|
ocrmypdf = "ocrmypdf.__main__:run"
|
||||||
|
|
||||||
[tool.setuptools.package-data]
|
[tool.hatch.version]
|
||||||
ocrmypdf = ["data/sRGB.icc", "py.typed"]
|
source = "vcs"
|
||||||
|
|
||||||
[tool.setuptools.packages.find]
|
[tool.hatch.build.hooks.vcs]
|
||||||
where = ["src"]
|
version-file = "src/ocrmypdf/_version.py"
|
||||||
namespaces = false
|
|
||||||
|
|
||||||
[tool.setuptools_scm]
|
|
||||||
|
|
||||||
[tool.distutils.bdist_wheel]
|
[tool.distutils.bdist_wheel]
|
||||||
python-tag = "py310"
|
python-tag = "py310"
|
||||||
|
|||||||
@@ -9,11 +9,12 @@ from pluggy import HookimplMarker as _HookimplMarker
|
|||||||
|
|
||||||
from ocrmypdf import helpers, hocrtransform, pdfa, pdfinfo
|
from ocrmypdf import helpers, hocrtransform, pdfa, pdfinfo
|
||||||
from ocrmypdf._concurrent import Executor
|
from ocrmypdf._concurrent import Executor
|
||||||
|
from ocrmypdf._defaults import PROGRAM_NAME
|
||||||
from ocrmypdf._jobcontext import PageContext, PdfContext
|
from ocrmypdf._jobcontext import PageContext, PdfContext
|
||||||
from ocrmypdf._pipelines._common import (
|
from ocrmypdf._pipelines._common import (
|
||||||
configure_debug_logging,
|
configure_debug_logging,
|
||||||
)
|
)
|
||||||
from ocrmypdf._version import PROGRAM_NAME, __version__
|
from ocrmypdf._version import __version__
|
||||||
from ocrmypdf.api import (
|
from ocrmypdf.api import (
|
||||||
Verbosity,
|
Verbosity,
|
||||||
configure_logging,
|
configure_logging,
|
||||||
@@ -37,7 +38,6 @@ from ocrmypdf.pluginspec import OcrEngine, OrientationConfidence
|
|||||||
|
|
||||||
hookimpl = _HookimplMarker('ocrmypdf')
|
hookimpl = _HookimplMarker('ocrmypdf')
|
||||||
|
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
'__version__',
|
'__version__',
|
||||||
'BadArgsError',
|
'BadArgsError',
|
||||||
|
|||||||
@@ -6,3 +6,5 @@ DEFAULT_LANGUAGE = 'eng'
|
|||||||
|
|
||||||
# Default rotation threshold
|
# Default rotation threshold
|
||||||
DEFAULT_ROTATE_PAGES_THRESHOLD = 14.0
|
DEFAULT_ROTATE_PAGES_THRESHOLD = 14.0
|
||||||
|
|
||||||
|
PROGRAM_NAME = 'OCRmyPDF'
|
||||||
|
|||||||
@@ -15,8 +15,8 @@ from pikepdf import Dictionary, Name, Pdf
|
|||||||
from pikepdf import __version__ as PIKEPDF_VERSION
|
from pikepdf import __version__ as PIKEPDF_VERSION
|
||||||
from pikepdf.models.metadata import PdfMetadata, encode_pdf_date
|
from pikepdf.models.metadata import PdfMetadata, encode_pdf_date
|
||||||
|
|
||||||
|
from ocrmypdf._defaults import PROGRAM_NAME
|
||||||
from ocrmypdf._jobcontext import PdfContext
|
from ocrmypdf._jobcontext import PdfContext
|
||||||
from ocrmypdf._version import PROGRAM_NAME
|
|
||||||
from ocrmypdf._version import __version__ as OCRMYPF_VERSION
|
from ocrmypdf._version import __version__ as OCRMYPF_VERSION
|
||||||
from ocrmypdf.languages import iso_639_2_from_3
|
from ocrmypdf.languages import iso_639_2_from_3
|
||||||
|
|
||||||
|
|||||||
@@ -441,7 +441,8 @@ def report_output_pdf(options, start_input_file, optimize_messages) -> ExitCode:
|
|||||||
log.info("Output file is a %s (as expected)", pdfa_info['conformance'])
|
log.info("Output file is a %s (as expected)", pdfa_info['conformance'])
|
||||||
else:
|
else:
|
||||||
log.warning(
|
log.warning(
|
||||||
"Output file is okay but is not PDF/A (seems to be %s)",
|
"Output file is a valid PDF, but conversion to PDF/A did not "
|
||||||
|
"succeed (issue: %s)",
|
||||||
pdfa_info['conformance'],
|
pdfa_info['conformance'],
|
||||||
)
|
)
|
||||||
return ExitCode.pdfa_conversion_failed
|
return ExitCode.pdfa_conversion_failed
|
||||||
|
|||||||
@@ -1,16 +0,0 @@
|
|||||||
# SPDX-FileCopyrightText: 2022 James R. Barlow
|
|
||||||
# SPDX-License-Identifier: MPL-2.0
|
|
||||||
|
|
||||||
"""Get version by introspecting package information.
|
|
||||||
|
|
||||||
OCRmyPDF uses setuptools_scm to derive version from git tags.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
from importlib.metadata import version as _package_version
|
|
||||||
|
|
||||||
PROGRAM_NAME = 'ocrmypdf'
|
|
||||||
|
|
||||||
# Official PEP 396
|
|
||||||
__version__ = _package_version('ocrmypdf')
|
|
||||||
+1
-1
@@ -10,7 +10,7 @@ from collections.abc import Callable, Mapping
|
|||||||
from typing import Any, TypeVar
|
from typing import Any, TypeVar
|
||||||
|
|
||||||
from ocrmypdf._defaults import DEFAULT_ROTATE_PAGES_THRESHOLD
|
from ocrmypdf._defaults import DEFAULT_ROTATE_PAGES_THRESHOLD
|
||||||
from ocrmypdf._version import PROGRAM_NAME as _PROGRAM_NAME
|
from ocrmypdf._defaults import PROGRAM_NAME as _PROGRAM_NAME
|
||||||
from ocrmypdf._version import __version__ as _VERSION
|
from ocrmypdf._version import __version__ as _VERSION
|
||||||
|
|
||||||
T = TypeVar('T', int, float)
|
T = TypeVar('T', int, float)
|
||||||
|
|||||||
@@ -382,8 +382,12 @@ class ImageInfo:
|
|||||||
self._height = max(smask.get(Name.Height, 0), self._height)
|
self._height = max(smask.get(Name.Height, 0), self._height)
|
||||||
if (mask := pim.obj.get(Name.Mask, None)) is not None:
|
if (mask := pim.obj.get(Name.Mask, None)) is not None:
|
||||||
# If the image has a /Mask entry, it has an explicit mask.
|
# If the image has a /Mask entry, it has an explicit mask.
|
||||||
self._width = max(mask.get(Name.Width, 0), self._width)
|
# /Mask can be a Stream or an Array. If it's a Stream,
|
||||||
self._height = max(mask.get(Name.Height, 0), self._height)
|
# use its /Width and /Height if they are larger than the main
|
||||||
|
# image's.
|
||||||
|
if isinstance(mask, Stream):
|
||||||
|
self._width = max(mask.get(Name.Width, 0), self._width)
|
||||||
|
self._height = max(mask.get(Name.Height, 0), self._height)
|
||||||
|
|
||||||
# If /ImageMask is true, then this image is a stencil mask
|
# If /ImageMask is true, then this image is a stencil mask
|
||||||
# (Images that draw with this stencil mask will have a reference to
|
# (Images that draw with this stencil mask will have a reference to
|
||||||
|
|||||||
@@ -239,7 +239,9 @@ def make_rotate_test(imagefile, outdir, prefix, image_angle, page_angle):
|
|||||||
@pytest.mark.parametrize('image_angle', (0, 90, 180, 270))
|
@pytest.mark.parametrize('image_angle', (0, 90, 180, 270))
|
||||||
def test_rotate_page_level(image_angle, page_angle, resources, outdir, caplog):
|
def test_rotate_page_level(image_angle, page_angle, resources, outdir, caplog):
|
||||||
reference = make_rotate_test(resources / 'typewriter.png', outdir, 'ref', 0, 0)
|
reference = make_rotate_test(resources / 'typewriter.png', outdir, 'ref', 0, 0)
|
||||||
test = make_rotate_test(resources, outdir, 'test', image_angle, page_angle)
|
test = make_rotate_test(
|
||||||
|
resources / 'typewriter.png', outdir, 'test', image_angle, page_angle
|
||||||
|
)
|
||||||
out = test.with_suffix('.out.pdf')
|
out = test.with_suffix('.out.pdf')
|
||||||
|
|
||||||
exitcode = run_ocrmypdf_api(
|
exitcode = run_ocrmypdf_api(
|
||||||
|
|||||||
Reference in New Issue
Block a user