Added explicit page copying after cloneReaderDocumentRoot() calls because
PyPDF2 3.x only copies document structure, not content pages.
🤖 assisted by claude
4.6 KiB
PyPDF2 Compatibility Patch
Overview
This patch addresses the PyPDF2 deprecation error that occurs when using PyPDF2 version 3.0.0 or higher with Odoo. The original error was:
PyPDF2.errors.DeprecationError: PdfFileWriter is deprecated and was removed in PyPDF2 3.0.0. Use PdfWriter instead.
Problem
In PyPDF2 3.0.0, several classes and methods were deprecated and removed:
PdfFileWriter→PdfWriterPdfFileReader→PdfReaderaddPage()→add_page()addMetadata()→add_metadata()getNumPages()→len(pages)getPage(n)→pages[n]appendPagesFromReader()→append_pages_from_reader()_addObject()→_add_object()cloneReaderDocumentRoot()→clone_reader_document_root()
Solution
This patch provides backward compatibility by creating wrapper classes that:
- Inherit from the new PyPDF2 classes (
PdfWriter,PdfReader) - Provide the old method signatures as compatibility methods
- Gracefully handle both old and new PyPDF2 versions
Files Modified
1. odoo/tools/pdf.py
- Added compatibility wrapper classes
PdfFileWriterandPdfFileReader - Updated import logic to handle both PyPDF2 2.x and 3.x
- Added method aliases for deprecated methods
- Updated
BrandedFileWriterclass to use new API with fallback
2. odoo/addons/base/models/ir_actions_report.py
- Added compatibility import logic
- Created local compatibility classes with required method aliases
- Added support for
numPagesproperty and related methods
Implementation Details
Critical PyPDF2 3.x Fix - Page Content Copying
In PyPDF2 3.x, cloneReaderDocumentRoot() only copies document structure, NOT content pages. This was causing 327-byte PDFs with no actual content. Modules using this method now include explicit page copying:
writer.cloneReaderDocumentRoot(reader)
# Copy all pages from the reader to the writer (required for PyPDF2 3.x)
for page_num in range(reader.getNumPages()):
page = reader.getPage(page_num)
writer.addPage(page)
Compatibility Import Pattern
try:
from PyPDF2 import PdfReader, PdfWriter
# Create compatibility classes
class PdfFileWriter(PdfWriter):
def addPage(self, page):
return self.add_page(page)
def addMetadata(self, metadata):
return self.add_metadata(metadata)
def _addObject(self, obj):
return self._add_object(obj)
class PdfFileReader(PdfReader):
def getNumPages(self):
return len(self.pages)
def getPage(self, page_num):
return self.pages[page_num]
except ImportError:
# Fallback to old API for older PyPDF2 versions
from PyPDF2 import PdfFileWriter, PdfFileReader
Method Compatibility Mapping
| Old Method (PyPDF2 < 3.0) | New Method (PyPDF2 ≥ 3.0) | Compatibility Method |
|---|---|---|
PdfFileWriter.addPage() |
PdfWriter.add_page() |
✅ Wrapped |
PdfFileWriter.addMetadata() |
PdfWriter.add_metadata() |
✅ Wrapped |
PdfFileWriter._addObject() |
PdfWriter._add_object() |
✅ Wrapped |
PdfFileReader.getNumPages() |
len(PdfReader.pages) |
✅ Wrapped |
PdfFileReader.getPage() |
PdfReader.pages[] |
✅ Wrapped |
PdfFileWriter.appendPagesFromReader() |
PdfWriter.append_pages_from_reader() |
✅ Wrapped |
PdfFileWriter.cloneReaderDocumentRoot() |
PdfWriter.clone_reader_document_root() |
✅ Wrapped |
Testing
The patch has been tested with:
- PyPDF2 3.0.0+ (new API)
- PyPDF2 2.x (old API via fallback)
OdooPdfFileWriterinstantiation- PDF generation workflows
- Report generation (original error case)
Branch Information
- Branch:
pdfwrite - Based on: Current main/master branch
- Type: Compatibility patch
- Impact: Backward compatible - no breaking changes
Author
- Developer: Ernad Husremović (hernad@bring.out.ba)
- Company: bring.out.doo Sarajevo
- Date: 2025-09-02
Related Issues
This patch resolves the PyPDF2 deprecation error encountered in:
- Report generation (
/report/pdf/endpoints) - PDF merge operations
- PDF attachment handling
- Account EDI PDF operations
Future Considerations
While this patch provides immediate compatibility, consider:
- Eventually migrating to the new PyPDF2 API directly
- Monitoring PyPDF2 changelog for future deprecations
- Testing with future PyPDF2 versions
Installation
This patch is automatically applied when using the pdfwrite branch. No additional installation steps required.