A Swiss-army knife for everyday PDF workflows.
Project description
pdf-tools
A Swiss-army knife for everyday PDF workflows - pure-Python, cross-platform, and fully typed.
Features
| Capability | Sub-command / API | Notes |
|---|---|---|
Convert images (.png, .jpg, .tiff, .bmp, ...) or Word (.doc, .docx) to PDF |
pdf-tools convert ... pdf_tools.convert_file_to_pdf() |
Uses Pillow + img2pdf for images and LibreOffice / unoserver for Word files. |
| Merge multiple PDFs or whole folders | pdf-tools merge ... pdf_tools.merge_pdfs() |
Preserves bookmarks; skips non-PDF inputs with a warning. |
| Process = convert then merge | pdf-tools process convert-and-merge-pdfs ... pdf_tools.convert_and_merge_pdfs() |
Converts supported inputs, passes existing PDFs through, and merges the result. |
| Watermark text stamps | pdf-tools watermark add-text ... pdf_tools.add_text_watermark() |
PyMuPDF-based text watermarking with configurable font, color, opacity, rotation, and position. |
| Async-friendly CLI | Built on Typer + AsyncTyper |
CLI callbacks can be async def. |
| Pydantic v2 models | File, Files, WatermarkOptions, ... |
JSON-serializable contracts for automation. |
Installation
The published Python package is pdf-toolchest; the installed command is pdf-tools.
pip install pdf-toolchest
pdf-tools --help
Word conversion requires LibreOffice plus a working unoserver / unoconvert install. Install unoserver with the Python environment that can import LibreOffice's uno module; for many Linux setups this is:
pipx install unoserver --system-site-packages
CLI Quick Start
# Convert a single Word file
pdf-tools convert file-to-pdf draft.docx
# Convert every supported file in a folder to PDFs in ./out
pdf-tools convert folder-to-pdfs assets/ --output-dir out/
# Merge selected PDFs
pdf-tools merge pdf-files a.pdf b.pdf c.pdf -o merged.pdf
# Merge all PDFs in a folder
pdf-tools merge pdfs-in-folder scans/ -o merged.pdf
# Convert images/docs and merge the PDFs
pdf-tools process convert-and-merge-pdfs image1.jpg doc1.docx doc2.docx -o final.pdf
# Add a diagonal red DRAFT watermark on every page
pdf-tools watermark add-text src.pdf stamped.pdf \
--text "DRAFT" --color "#FF0000" --font-size 72 --opacity 0.2 --rotation 45
Batch LibreOffice Listener
For repeated Word conversions, run one listener for the whole session. --port is the unoconvert XMLRPC port; --uno-port is the LibreOffice UNO port. Note that unoserver needs to have access to the uno package that ships with LibreOffice, so it needs to either be installed system-wide or, if using pipx for example, needs to have access to the system site packages.
unoserver --interface 127.0.0.1 --port 2003 --uno-port 2002 &
pdf-tools process convert-and-merge-pdfs doc1.docx doc2.docx -o final.pdf
kill %1
Python API
Common APIs are exported from pdf_tools. Functions accept str, Path, or File inputs.
from pathlib import Path
from pdf_tools import (
WatermarkOptions,
add_text_watermark,
convert_file_to_pdf,
merge_pdfs,
)
# Convert one image to out/diagram.pdf
img_pdf = convert_file_to_pdf("diagram.png", output_path=Path("out"))
# Merge PDFs
merged = merge_pdfs(
["intro.pdf", img_pdf.path],
output_path="bundle.pdf",
set_bookmarks=True,
)
# Watermark the first page
opts = WatermarkOptions(text="CONFIDENTIAL", font_size=36, all_pages=False)
add_text_watermark(src=merged.path, dst="bundle_wm.pdf", opts=opts)
Batch conversion returns structured information about converted and skipped files.
from pdf_tools import convert_files_to_pdfs
result = convert_files_to_pdfs(["photo.jpg", "notes.txt"], output_dir="out")
print(result.converted)
print(result.skipped)
For Word conversion from Python, start a listener before calling conversion helpers.
from pdf_tools import convert_and_merge_pdfs, unoserver_listener
with unoserver_listener():
convert_and_merge_pdfs(
files=["doc1.docx", "pic.jpg", "appendix.pdf"],
output_path="package.pdf",
)
Development
git clone https://github.com/your-org/pdf-tools.git
cd pdf-tools
poetry install --with dev
scripts/lint
pytest -q -m "not slow"
Slow Word-conversion tests require LibreOffice and working uno bindings.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pdf_toolchest-0.2.0.tar.gz.
File metadata
- Download URL: pdf_toolchest-0.2.0.tar.gz
- Upload date:
- Size: 20.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cd267a041328341dd43a550097009aeca70aef69bf94f9b6f91e1b7bf7482dbe
|
|
| MD5 |
d7720092774c5ae1e5ba1ae9531d071c
|
|
| BLAKE2b-256 |
c64c3522629c76b56c1e26f79c04e56f09671bd32c8d7060c2e9b42ef758333e
|
Provenance
The following attestation bundles were made for pdf_toolchest-0.2.0.tar.gz:
Publisher:
publish.yml on aswann45/pdf-tools
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pdf_toolchest-0.2.0.tar.gz -
Subject digest:
cd267a041328341dd43a550097009aeca70aef69bf94f9b6f91e1b7bf7482dbe - Sigstore transparency entry: 2012800303
- Sigstore integration time:
-
Permalink:
aswann45/pdf-tools@33ac0bf6195b5c68a2b39a3333c6579f4a1065e1 -
Branch / Tag:
refs/tags/0.2.0 - Owner: https://github.com/aswann45
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@33ac0bf6195b5c68a2b39a3333c6579f4a1065e1 -
Trigger Event:
release
-
Statement type:
File details
Details for the file pdf_toolchest-0.2.0-py3-none-any.whl.
File metadata
- Download URL: pdf_toolchest-0.2.0-py3-none-any.whl
- Upload date:
- Size: 28.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a517170e07670a684932dbbdc7e77f7d0b5b247a6f8697d85f40b09ff215ad26
|
|
| MD5 |
bd88590be75e24fe52392274d95c6202
|
|
| BLAKE2b-256 |
cb85d303d5330695527daeec5b550a18397f65924b3926df8c3f87fec5d661c6
|
Provenance
The following attestation bundles were made for pdf_toolchest-0.2.0-py3-none-any.whl:
Publisher:
publish.yml on aswann45/pdf-tools
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pdf_toolchest-0.2.0-py3-none-any.whl -
Subject digest:
a517170e07670a684932dbbdc7e77f7d0b5b247a6f8697d85f40b09ff215ad26 - Sigstore transparency entry: 2012800442
- Sigstore integration time:
-
Permalink:
aswann45/pdf-tools@33ac0bf6195b5c68a2b39a3333c6579f4a1065e1 -
Branch / Tag:
refs/tags/0.2.0 - Owner: https://github.com/aswann45
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@33ac0bf6195b5c68a2b39a3333c6579f4a1065e1 -
Trigger Event:
release
-
Statement type: