Compare commits

...
12 Commits
Author SHA1 Message Date
James R. Barlow 8fca0c71dc v16.5.0 release notes 2024-08-31 02:12:07 -07:00
James R. Barlow 944d99bdc1 Fix PROGRAM_NAME 2024-08-31 01:23:55 -07:00
James R. Barlow 5bb6e1c5d7 Modify GitHub release strategy to use sigstore 2024-08-31 01:17:51 -07:00
James R. Barlow 8d7a8f0f98 Update documentation to transition from setuptools to hatchling 2024-08-31 01:14:51 -07:00
James R. Barlow b9dd0a5e3c Use hatchling and hatch-vcs as build backend 2024-08-31 01:08:23 -07:00
James R. Barlow 6949ad2c5d pyproject: link changelog 2024-08-31 00:45:46 -07:00
James R. Barlow b3324c3b4e Don't assume /Mask is always a Stream
Fixes #1377
2024-08-31 00:37:52 -07:00
James R. Barlow b38cac6931 Drop wheel from build requires
Not usually needed anymore
2024-08-28 01:31:56 -07:00
Elliott Sales de AndradeandGitHub bb4c47e707 Fix broken test_rotate_page_level (#1382)
Before 42ff7fc842, `make_rotate_test`
always used `resources / 'typewriter.png'`, but after the change the
second call accidentally used just `resources`, which is a directory,
and fails to open.
2024-08-21 01:25:07 -07:00
James R. Barlow 5e1e2497ab Enable Python 3.13 experimental 2024-08-15 01:32:33 -07:00
James R. Barlow cd910fbf21 Improve "PDF/A conversion failed" message 2024-08-10 01:34:02 -07:00
James R. Barlow 1225269a4b Clarify opporutnities available with OCR_JSON_SETTINGS 2024-08-10 01:02:05 -07:00
16 changed files with 83 additions and 61 deletions
+32 -10
View File
@@ -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
+1
View File
@@ -44,3 +44,4 @@ docs/_build/
docs/_static/ docs/_static/
docs/_templates/ docs/_templates/
docs/Makefile docs/Makefile
src/ocrmypdf/_version.py
+1 -1
View File
@@ -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"
+1 -2
View File
@@ -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
+3 -2
View File
@@ -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
View File
@@ -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
=================== ===================
+11
View File
@@ -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
View File
@@ -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"
+2 -2
View File
@@ -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',
+2
View File
@@ -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'
+1 -1
View File
@@ -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
+2 -1
View File
@@ -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
-16
View File
@@ -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
View File
@@ -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)
+6 -2
View File
@@ -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
+3 -1
View File
@@ -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(