How to Create Documents with the Generated Compatibility Module in Python

How to Create Documents with the Generated Compatibility Module in Python

Aspose.PDF FOSS for Python ships a generated compatibility subpackage (aspose_pdf.generated) that mirrors a stable subset of the main API surface — a Document class with the core lifecycle operations, plus UnsignedContent/UnsignedContentAbsorber and PdfAValidateOptions/PdfAValidationResult. It exists for callers that want this narrower surface explicitly rather than the full-featured top-level classes, and its classes are not imported automatically by import aspose_pdf — you import them from aspose_pdf.generated.* directly. The package is pure Python and is installed from PyPI with pip.

Step-by-Step Guide

Step 1: Install the Package

Install the Aspose.PDF FOSS package from PyPI:

git clone https://github.com/aspose-pdf-foss/Aspose-PDF-FOSS-for-Python.git
cd Aspose-PDF-FOSS-for-Python
pip install -e .

Verify the installation by importing the generated Document and printing a confirmation message:

import aspose_pdf
from aspose_pdf.generated.document import Document
print("aspose-pdf-foss-for-python is ready.")

Step 2: Import Required Classes

The generated compatibility classes live in aspose_pdf.generated.document, aspose_pdf.generated.forms, and aspose_pdf.generated.pdfa — import them explicitly by submodule:

import aspose_pdf
from aspose_pdf.generated.document import Document
from aspose_pdf.generated.forms import UnsignedContent, UnsignedContentAbsorber
from aspose_pdf.generated.pdfa import PdfAValidateOptions, PdfAValidationResult

Step 3: Create and Load a Document

Document(source) loads immediately when a source is supplied; calling Document() with no argument creates an empty instance you can load later with load_from. Both accept a file path, bytes, or a binary stream:

from aspose_pdf.generated.document import Document

document = Document("report.pdf")
print(f"Loaded {len(document.pages)} page(s)")

empty_doc = Document()
empty_doc.load_from("report.pdf")

Step 7: Extract Unsigned Form Content

UnsignedContentAbsorber extracts the pages, form fields, and annotations that have not been part of a digital signature. Call extract() to run the extraction, has_extracted() to check whether it has run, and get_extracted() to retrieve the result again without re-extracting:

from aspose_pdf.generated.forms import UnsignedContentAbsorber

absorber = UnsignedContentAbsorber()
unsigned = absorber.extract()
print(f"Unsigned pages: {len(unsigned.pages)}")
print(f"Unsigned form fields: {len(unsigned.form_fields)}")

if absorber.has_extracted():
    same_result = absorber.get_extracted()

Step 8: Build an UnsignedContent Container Manually

UnsignedContent is also a plain container you can populate yourself with add_page, add_form_field, and add_annotation — each has a matching remove_* method, and reset() clears all three collections at once:

from aspose_pdf.generated.forms import UnsignedContent

content = UnsignedContent()
content.add_page("page-1")
content.add_annotation("signature-placeholder")
print(content)  # UnsignedContent(pages=1, form_fields=0, annotations=1)

content.remove_annotation("signature-placeholder")
content.reset()

Step 9: Configure and Run PDF/A Validation

PdfAValidateOptions collects the inputs and settings for a validation run. add_input(source) registers an input, set_option(key, value) stores a named option, and get_options() returns a copy of the stored options. PdfAValidationResult holds the outcome — add_error(message) marks the result invalid and appends to errors, and to_dict() renders is_valid and errors as a plain dictionary:

from aspose_pdf.generated.pdfa import PdfAValidateOptions, PdfAValidationResult

options = PdfAValidateOptions()
options.add_input("report.pdf")
options.set_option("pdfa_version", "1b")
print(options.get_options())

result = PdfAValidationResult()
result.add_error("Font 'Arial' is not embedded")
print(result.is_valid)   # False
print(result.to_dict())

Common Issues and Fixes

ImportError or AttributeError when accessing aspose_pdf.generated

The generated subpackage is not re-exported by import aspose_pdf — import each class from its specific submodule, for example from aspose_pdf.generated.document import Document, rather than expecting aspose_pdf.generated.Document to work after a plain import aspose_pdf.

Confusing the generated Document with the main aspose_pdf.Document

aspose_pdf.Document (the top-level class re-exported by import aspose_pdf) has a larger surface — it adds methods such as validate_pdfa, iter_pages, and redact_text that aspose_pdf.generated.document.Document does not implement. If a method is missing on the generated Document, check whether it belongs to the top-level Document class instead.

save() raises AsposePdfException: Cannot save a disposed document

close()/dispose() releases the document’s internal state permanently — a disposed Document cannot be saved, optimized, or repaired afterward. Perform all remaining operations before calling close(), or reload from the source with a fresh Document(...) call.

change_passwords raises PdfSecurityException: Document is not encrypted

change_passwords only rotates a password on a document that is already encrypted. Call encrypt(password) first, or check document.is_encrypted before attempting to change the password.

PdfAValidationResult.add_error raises TypeError

add_error requires a str argument. Convert exception objects or other error details to a string (str(error)) before passing them to add_error.

Frequently Asked Questions

Why does aspose_pdf.generated exist alongside the main aspose_pdf.Document?

It mirrors a narrower, stable subset of the Aspose.PDF API for code written against that reduced surface. New code that does not specifically need this compatibility subset should generally use the top-level aspose_pdf.Document, which supports more operations (PDF/A conversion, page iteration, text redaction, and others).

Does UnsignedContentAbsorber.extract() accept a Document to scan?

extract() accepts positional and keyword arguments that are used to populate the returned UnsignedContent’s pages, form_fields, and annotations collections — pass the collections you want represented as keyword arguments (pages=, form_fields=, annotations=).

What happens if I call reset() on UnsignedContentAbsorber before extracting anything?

It clears any previously extracted result. get_extracted() then returns None and has_extracted() returns False until extract() is called again.

Can PdfAValidateOptions.add_input be called more than once?

Yes — each call appends another entry to the inputs list, and it returns self, so calls can be chained: options.add_input("a.pdf").add_input("b.pdf").

Is close() different from dispose() on the generated Document?

No — close() is a direct alias that calls dispose() with the same arguments; either name releases the document’s resources.

See Also