Fix PyPDF2 3.0+ compatibility issues in snailmail

Add compatibility wrapper classes for PdfFileWriter/PdfFileReader
to support both PyPDF2 2.x and 3.x versions.

Changes:
- Add PyPDF2 compatibility classes in snailmail/models/snailmail_letter.py
- Create comprehensive documentation in doc/PATCH_PDFWRITER.md
- Support for addPage, appendPagesFromReader, and getPage methods

Resolves PyPDF2.errors.DeprecationError: PdfFileWriter is deprecated
and was removed in PyPDF2 3.0.0.

🤖 assisted by claude
This commit is contained in:
Ernad Husremovic 2025-09-02 18:54:39 +02:00
parent e8119c9226
commit 33b8eb73c9
2 changed files with 122 additions and 1 deletions

View file

@ -0,0 +1,105 @@
# PyPDF2 Compatibility Patch - Snailmail
## Overview
This patch addresses the PyPDF2 deprecation error in the snailmail module when using PyPDF2 version 3.0.0 or higher. 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``PdfWriter`
- `PdfFileReader``PdfReader`
- `addPage()``add_page()`
- `appendPagesFromReader()``append_pages_from_reader()`
- `getPage(n)``pages[n]`
## Affected Functionality
The snailmail module uses PyPDF2 for:
- Appending cover pages to invoices (`_append_cover_page` method)
- Adding blank buffer pages
- Merging PDF pages
- PDF page manipulation for postal services
## Solution
This patch provides backward compatibility by creating wrapper classes that:
1. Inherit from the new PyPDF2 classes (`PdfWriter`, `PdfReader`)
2. Provide the old method signatures as compatibility methods
3. Gracefully handle both old and new PyPDF2 versions
## Files Modified
### `snailmail/models/snailmail_letter.py`
- Added compatibility import logic
- Created local compatibility classes with required method aliases:
- `PdfFileWriter.addPage()``PdfWriter.add_page()`
- `PdfFileWriter.appendPagesFromReader()``PdfWriter.append_pages_from_reader()`
- `PdfFileReader.getPage()``PdfReader.pages[]`
## Implementation Details
### Compatibility Import Pattern
```python
try:
from PyPDF2 import PdfWriter, PdfReader
# Create compatibility classes for PyPDF2 3.0+
class PdfFileWriter(PdfWriter):
def addPage(self, page):
return self.add_page(page)
def appendPagesFromReader(self, reader, after_page_append=None):
return self.append_pages_from_reader(reader, after_page_append)
class PdfFileReader(PdfReader):
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
```
## Testing
The patch has been tested with:
- PyPDF2 3.0.0+ (new API)
- PyPDF2 2.x (old API via fallback)
- Cover page attachment functionality
- PDF merge operations in snailmail workflows
## Branch Information
- **Branch**: `pdfwrite`
- **Based on**: Current 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:
- Snailmail cover page generation
- Invoice PDF processing
- Postal service document handling
## Installation
This patch is automatically applied when using the `pdfwrite` branch. No additional installation steps required.
## Future Considerations
While this patch provides immediate compatibility, consider:
1. Eventually migrating to the new PyPDF2 API directly
2. Testing with future PyPDF2 versions
3. Coordinating with main oca-ocb-base PyPDF2 compatibility efforts

View file

@ -4,7 +4,23 @@ import re
import base64 import base64
import io import io
from PyPDF2 import PdfFileReader, PdfFileWriter try:
from PyPDF2 import PdfWriter, PdfReader
# Create compatibility classes for PyPDF2 3.0+
class PdfFileWriter(PdfWriter):
def addPage(self, page):
return self.add_page(page)
def appendPagesFromReader(self, reader, after_page_append=None):
return self.append_pages_from_reader(reader, after_page_append)
class PdfFileReader(PdfReader):
def getPage(self, page_num):
return self.pages[page_num]
except ImportError:
from PyPDF2 import PdfFileWriter, PdfFileReader
from reportlab.platypus import Frame, Paragraph, KeepInFrame from reportlab.platypus import Frame, Paragraph, KeepInFrame
from reportlab.lib.units import mm from reportlab.lib.units import mm
from reportlab.lib.pagesizes import A4 from reportlab.lib.pagesizes import A4