2025-05-24: V3 Announcements
This article provides important information about the upcoming v3.0.0 release.
TL; DR
PyPDFForm v3.0.0 is scheduled for release on June 24, 2025. This major release includes changes that will break compatibility with older code. To avoid issues, pin your version to <=2.5.0 as soon as possible.
Here's a list of the changes:
FormWrapper
has been removed. Its features have been moved toPdfWrapper
. Thefill
method ofPdfWrapper
will now work the same way it did inFormWrapper
.- The way to enable
adobe_mode
when filling has changed. Instead of passingadobe_mode
as an argument to thefill
method, you now pass it when creating aPdfWrapper
object. - Setting font properties for the entire document (e.g.,
PdfWrapper("sample_template.pdf", global_font_size=20)
) is no longer supported. You must now set font properties for each individual widget. register_font
is now a method of thePdfWrapper
object, not a general class method.PdfWrapper.preview
is removed.- You can no longer change the
button_style
of existing checkboxes or radio buttons. (Setting thebutton_style
when you create them is still supported.) - Render widgets flag
render_widgets
is removed.
Why these changes?
When I started this project about five years ago, I didn't have as much experience as I do now. I ran into some technical problems during the initial proof of concept. One problem was that filled text fields in Adobe Acrobat sometimes only appeared when the field was selected.
Because of this behavior in Adobe Acrobat, and because I wanted to support as many PDF viewers as possible, I decided to use a "watermark" approach. Instead of directly changing the form field data, this approach gathers information about each field, such as its location, font, size, and color. Then, it removes all the original form fields, creates a watermark of the PDF, draws the filled content onto the watermark, and combines the watermark with the original PDF. Even though this removes the original fields and makes the filled content look "flattened", it ensures that the filled PDFs only contain basic PDF data and can be viewed in any PDF application. The project has grown since then, adding features like custom form field styles and even the ability to create form fields. As of version 2.5.0, the PdfWrapper
still uses this watermark method as its core.
About a year ago, with the help of the community, I was finally able to solve the text field issue in Adobe Acrobat that had been present since the beginning of the project. This made it possible to directly modify the form field data when filling a PDF, which has several benefits: the form fields can remain editable after filling, there's no need for complicated calculations to determine coordinates and resolutions, and merging watermarks with the original PDF is no longer necessary, which greatly improves performance. However, the project had already developed significantly, and some features that relied on the watermark approach, such as changing font properties, couldn't be easily adapted to the new method, at least not initially. Therefore, instead of completely abandoning the watermark approach, I decided to create a new, simpler set of APIs that would support this new way of filling forms. This resulted in the FormWrapper
.
The FormWrapper
turned out to be a good addition, attracting even more users because it could truly "fill" a PDF form as if it were done by hand. Since then, PdfWrapper
and FormWrapper
have existed side-by-side. However, recent developments have made it necessary to introduce even more significant and fundamental changes to the project. First, I've noticed that many users, even when using features from PdfWrapper
like creating or renaming widgets, prefer to use FormWrapper
for the final step of filling the PDF. In these situations, I've had to advise them to first perform the necessary actions with PdfWrapper
, extract the stream from the PdfWrapper
object, and then use that as input for FormWrapper
to complete the filling process. This workflow doesn't seem very intuitive. Second, I've developed some extremely complex calculations to determine how form field data should be drawn when using the watermark method. However, I've reached a point where I can't figure out how to support landscape PDFs due to orientation issues. This makes abandoning the watermark approach even more desirable. Finally, my recent research has revealed clearer ways to implement features that were previously only achievable through the watermark method by directly manipulating form field data.
Considering everything mentioned above, I believe it's time to introduce the next major version of PyPDFForm: v3.0.0.
What are the changes?
In short, the goal of v3.0.0 can be summed up to:
- Merge
FormWrapper
intoPdfWrapper
. - Reimplement most, if not all,
PdfWrapper
features, especially thefill
method, by directly manipulating form field data. - Preserve as much backward compatibility as possible.
Let's talk more about backward compatibility. With changes as significant as those in this release, it's impossible to maintain complete backward compatibility. For instance, even if you use the fill
method in the same way as before, the filled PDF forms will now be editable because the watermark method is no longer used.
So, when I say I've tried to preserve as much backward compatibility as possible, I mean I've minimized the number of API changes. The appearance of your generated PDFs will be slightly different compared to the watermark approach, but you'll still be able to use most of PyPDFForm's APIs in the same way as before the release.
However, some unavoidable changes will break backward compatibility. This is why this release is a major version update, as defined by Semantic Versioning. I'll do my best to explain these changes and the reasons behind them in the list below:
- As mentioned earlier,
FormWrapper
has been merged intoPdfWrapper
and completely removed.FormWrapper
only provided basic PDF form filling features. After the merge, thefill
method ofPdfWrapper
will function identically to how it did inFormWrapper
. - The
adobe_mode
parameter has been moved from thefill
method to thePdfWrapper
object's constructor. This change is necessary because mostPdfWrapper
features now directly manipulate form field data and need to support Adobe Acrobat. Therefore, the setting applies to the entire object rather than just the filling method. - Previously, font properties could be set globally for each object using parameters like
global_font
,global_font_size
, andglobal_font_color
when creating the object. This is no longer possible. Font properties must now be set for each individual widget. Setting font properties globally made sense when they all needed to be applied to the same watermarks. Now that the project directly manipulates form fields, it's more logical to set them at the widget level. register_font
is now a method that belongs to eachPdfWrapper
object, rather than a general class method. This change should have been made earlier, and it's becoming more obvious with this release, as each registered font should only be used for a single PDF form.- The
preview
feature has been removed. It was initially an experimental feature and has proven to create messy, unreadable previews for PDFs with many fields. There are better ways to inspect a PDF form, such as usingschema
andsample_data
. - Modifying the
button_style
of existing checkboxes or radio buttons by directly manipulating form field data is difficult, as it involves complex stream creation that I'm currently unable to implement. Therefore, this feature has been removed for now but may be added back in the future. Note that this change doesn't affect the ability to set thebutton_style
when creating checkboxes or radio buttons. render_widgets
has been removed. This feature was originally added to maintain backward compatibility when the watermark approach first began supporting the rendering of widget borders and backgrounds. Since the watermark approach is no longer used, this feature is unnecessary.
What do you need to do?
First, I strongly recommend that you pin your PyPDFForm dependency version to <=2.5.0 as soon as possible, unless you're certain that these changes won't cause any problems for you.
After pinning your version, you have a couple of options:
- If any of the backward-incompatible changes affect your code, update your code accordingly, using the information provided above.
- If you prefer the old watermark approach, you can keep your version pinned to <=2.5.0 indefinitely, as those older versions will remain available.
Otherwise, once the release is made, you should have no problem upgrading to v3.0.0 and any future patches after the release.
When will this happen?
This announcement was written and should be published on May 24, 2025. After publication, the community will have one month to review this information and make any necessary adjustments.
Therefore, unless there's significant opposition from the community, PyPDFForm v3.0.0 will be released on June 24, 2025.