# SPDX-FileCopyrightText: 2022 James R. Barlow # SPDX-License-Identifier: MPL-2.0 [build-system] requires = ["hatchling"] build-backend = "hatchling.build" [project] name = "ocrmypdf" version = "17.8.1" description = "OCRmyPDF adds an OCR text layer to scanned PDF files, allowing them to be searched" readme = "README.md" license = "MPL-2.0" requires-python = ">=3.11" dependencies = [ "fpdf2>=2.8.0", "img2pdf>=0.5", "packaging>=20", "pdfminer.six>=20260107", # fixes parsing of tokens split across the read buffer/streams (gh #1361) "pi-heif", # Heif image format - maintainers: if this is removed, it will NOT break "pikepdf>=10", "Pillow>=10.0.1", "pluggy>=1", "pydantic>=2.12.5", "pypdfium2>=5.0.0", "rich>=13", "typing-extensions>=4.12; python_version < '3.13'", "uharfbuzz>=0.53.2", ] authors = [{ name = "James R. Barlow", email = "james@purplerock.ca" }] classifiers = [ "Development Status :: 5 - Production/Stable", "Environment :: Console", "Intended Audience :: End Users/Desktop", "Intended Audience :: Science/Research", "Intended Audience :: System Administrators", "Operating System :: MacOS", "Operating System :: Microsoft :: Windows", "Operating System :: POSIX", "Operating System :: POSIX :: BSD", "Operating System :: POSIX :: Linux", "Programming Language :: Python :: 3", "Topic :: Scientific/Engineering :: Image Recognition", "Topic :: Text Processing :: Indexing", "Topic :: Text Processing :: Linguistic", ] keywords = ["PDF", "OCR", "optical character recognition", "PDF/A", "scanning"] [project.urls] Documentation = "https://ocrmypdf.readthedocs.io/" Source = "https://github.com/ocrmypdf/OCRmyPDF" Tracker = "https://github.com/ocrmypdf/OCRmyPDF/issues" Changelog = "https://github.com/ocrmypdf/OCRmyPDF/tree/main/docs/releasenotes" [project.optional-dependencies] # User-installable features - use `uv sync --extra ` or `pip install ocrmypdf[name]` watcher = ["watchdog>=1.0.2", "cyclopts>=3", "python-dotenv"] webservice = ["streamlit>=1.41.0"] [project.scripts] ocrmypdf = "ocrmypdf.__main__:run" [tool.distutils.bdist_wheel] python-tag = "py311" [tool.coverage.run] branch = true parallel = true concurrency = ["multiprocessing", "thread"] sigterm = true [tool.coverage.paths] source = ["src/ocrmypdf"] [tool.coverage.report] # Regexes for lines to exclude from consideration exclude_lines = [ # Have to re-enable the standard pragma "pragma: no cover", # Don't complain if tests don't hit defensive assertion code: "raise AssertionError", "raise NotImplementedError", # Don't complain if non-runnable code isn't run: "if 0:", "if False:", "if __name__ == .__main__.:", "if TYPE_CHECKING:", ] [tool.pytest.ini_options] minversion = "6.0" testpaths = ["tests"] addopts = "-n auto" markers = ["slow"] filterwarnings = [ "ignore:.*XMLParser.*:DeprecationWarning", "ignore:.*ast.NameConstant.*:DeprecationWarning:reportlab", "ignore:.*distutils.*:DeprecationWarning:libxmp", ] [tool.mypy] check_untyped_defs = true [[tool.mypy.overrides]] module = [ 'img2pdf', 'pdfminer.*', 'reportlab.*', 'fitz', 'libxmp.utils', 'pypdfium2', 'uharfbuzz', 'pi_heif', ] ignore_missing_imports = true [[tool.mypy.overrides]] # Test functions are not required to annotate their return type (almost # always None); it's a low-value hint that would just be noise here. module = 'tests.*' disallow_untyped_defs = false disallow_incomplete_defs = false [tool.ruff] target-version = "py311" exclude = ["src/ocrmypdf/_version.py"] # Autogenerated [tool.ruff.lint] "select" = [ "D", # pydocstyle "E", # pycodestyle "W", # pycodestyle "F", # pyflakes "I", # isort "UP", # pyupgrade "SIM", # simplify "B", # flake8-bugbear "ICN", # flake8-import-conventions "PTH", # flake8-use-pathlib ] ignore = [ "B028", # warning with no explicit stacklevel # rule is key in dict instead of key in dict.keys(); but pikepdf semantics differ "SIM118", ] [tool.ruff.lint.isort] known-first-party = ["ocrmypdf"] required-imports = ["from __future__ import annotations"] [tool.ruff.lint.flake8-import-conventions] # Prohibit explicit imports from the 'datetime' module banned-from = ["datetime"] # Optionally, suggest an alias for 'import datetime' (e.g., as dt) extend-aliases = { "datetime" = "dt" } [tool.ruff.lint.pydocstyle] convention = "google" [tool.ruff.lint.per-file-ignores] "docs/conf.py" = ["D100", "D101", "D105"] "tests/*.py" = ["D100", "D101", "D102", "D103", "D105", "E501"] "misc/*.py" = ["D103", "D101", "D102"] "src/ocrmypdf/builtin_plugins/*.py" = ["D103", "D102", "D105"] [tool.ruff.format] quote-style = "preserve" [dependency-groups] # Developer-only tools - use `uv sync --group ` dev = [ "mypy>=1.13.0", "ruff>=0.14.11", "prek>=0.4.8", "ipykernel>=6.29.5", "reportlab>=4.4.4", "cyclopts>=4.5.1", "pygithub>=2.9.1", ] test = [ # Core testing framework "coverage[toml]>=6.2", "hypothesis>=6.36.0", "pytest>=6.2.5", "pytest-cov>=3.0.0", "pytest-xdist>=2.5.0", # Test dependencies "python-xmp-toolkit==2.0.1", # also requires apt-get install libexempi3 "reportlab>=3.6.8", # Type stubs for testing "types-humanfriendly", # Extended test capabilities (merged from extended_test) "pymupdf>=1.24.14", ] docs = [ "myst-parser>=4.0.1", "sphinx", "sphinx-issues", "sphinx-reredirects", "sphinx-rtd-theme", "sphinxcontrib-mermaid", ] streamlit-dev = ["streamlit>=1.40.2", "streamlit-pdf-viewer>=0.0.19"]