Skip to content

Installation and setup⚓︎

PyPDFForm is available on PyPI and can be installed using any preferred package manager, such as pip, Poetry, or uv.

Prerequisites⚓︎

PyPDFForm officially supports Python 3.10 and newer versions that are currently in their active life cycles. This typically includes the minimum supported version and the four major versions above it. For details on Python version life cycles, refer to this page.

Info

While official support is limited to active Python versions, PyPDFForm generally avoids features specific to particular major Python versions. It is expected to be functional with Python 3.7+ (due to its use of Postponed Evaluation of Annotations for type hints, introduced in Python 3.7), though these versions are not actively tested.

Install using pip⚓︎

It is highly recommended to create a virtual environment before installation. Then, run the following command to install PyPDFForm:

pip install PyPDFForm
pip install -U PyPDFForm

Create a PDF wrapper⚓︎

The main user interface of the library is the PdfWrapper class. It implements most PyPDFForm APIs and accepts various optional parameters, the most important of which is the PDF form template.

For example, to use this PDF as a template, instantiate the PdfWrapper object as follows:

from PyPDFForm import PdfWrapper

pdf = PdfWrapper("sample_template.pdf")
from PyPDFForm import PdfWrapper

with open("sample_template.pdf", "rb+") as template:
    pdf = PdfWrapper(template)
from PyPDFForm import PdfWrapper

with open("sample_template.pdf", "rb+") as template:
    pdf = PdfWrapper(template.read())
Tip

PyPDFForm provides an adapter for different file interaction methods in Python, which allows you to pass your PDF form to PdfWrapper as a file path, an open file object, or a bytes file stream. This file adaptation applies to all PyPDFForm APIs. You can replace file path parameters with file objects or streams throughout the documentation.

Handling appearance streams⚓︎

For a PDF viewer to display content in a form field (especially text fields), it needs an "appearance stream." This stream defines how the field's content is rendered. PyPDFForm offers two ways to handle this, set via flags during PdfWrapper instantiation.

Set need_appearances=True to instruct the PDF viewer to generate appearance streams. This is often the best choice when you expect the PDF to be opened in powerful, proprietary software like Adobe Acrobat, which has sophisticated rendering capabilities.

from PyPDFForm import PdfWrapper

pdf = PdfWrapper("sample_template.pdf", need_appearances=True)

Set generate_appearance_streams=True to use PyPDFForm's built-in generator. This is a good fallback if the PDF viewer lacks the ability to generate its own appearance streams.

from PyPDFForm import PdfWrapper

pdf = PdfWrapper("sample_template.pdf", generate_appearance_streams=True)
Warning

PyPDFForm's internal appearance stream generation relies on qpdf and shares its limitations. Some known limitations include:

  • Limited to ASCII text: Only ASCII characters are supported.
  • Single-line text fields only: It does not support multi-line text fields.
  • No text alignment handling: Text alignment (left, center, right) is not preserved or applied.

Use full name for PDF form fields⚓︎

According to section 12.7.3.2 of the PDF standard, PDF form fields can have fully qualified names constructed using the pattern <parent_field_name>.<field_name>.

PyPDFForm allows you to access fields by their full names by setting use_full_widget_name to True when instantiating PdfWrapper. For example, to use this PDF:

from PyPDFForm import PdfWrapper

pdf = PdfWrapper("sample_template_with_full_key.pdf", use_full_widget_name=True)

This enables accessing fields by their full names. For instance, you can access the checkbox labeled Gain de 2 classes using its full name Gain de 2 classes.0 instead of its partial name 0.

Warning

When using full names, the update_widget_key and commit_widget_key_updates methods of PdfWrapper are disabled and raise a NotImplementedError because full names involve both the field and its parent.

Write to a file⚓︎

The PdfWrapper acts as a file-like object, enabling you to write the processed PDF to another file-like object:

from PyPDFForm import PdfWrapper

pdf = PdfWrapper("sample_template.pdf")

with open("output.pdf", "wb+") as output:
    output.write(pdf.read())
from io import BytesIO
from PyPDFForm import PdfWrapper

pdf = PdfWrapper("sample_template.pdf")

with BytesIO() as output:
    output.write(pdf.read())

Additionally, PdfWrapper offers a convenient write method to save the PDF directly.

from PyPDFForm import PdfWrapper

pdf = PdfWrapper("sample_template.pdf")
pdf.write("output.pdf")
from io import BytesIO
from PyPDFForm import PdfWrapper

buff = BytesIO()

pdf = PdfWrapper("sample_template.pdf")
pdf.write(buff)

buff.seek(0)