We’re happy to announce the release of GroupDocs.Watermark for Python v26.10, available as of October 2026. This release upgrades the underlying .NET engine from 26.6 to 26.9 and the embedded .NET runtime from 10.0.0 to 10.0.12. It introduces support for custom loggers, enforces stricter attribute assignment, and fixes critical issues with preview callbacks and page stream handling. Additionally, compatibility is extended to Python 3.5–3.14, and platform support is clarified via strict wheel tags.
What’s new in this release
- [Feature] Accept a Python object or function as
WatermarkerSettings.logger(WATERMARKPYTHON-65) - [Enhancement] Update GroupDocs.Watermark engine from 26.6 to 26.9 (WATERMARKPYTHON-66)
- [Enhancement] Update the embedded .NET runtime from 10.0.0 to 10.0.12 (WATERMARKPYTHON-67)
- [Enhancement] Raise
AttributeErrorwhen code assigns an attribute a class does not have (WATERMARKPYTHON-68) - [Fix] Cannot use the package on Python 3.5 – 3.7 (WATERMARKPYTHON-69)
- [Fix] pip installs the package on Linux and macOS versions that cannot run it (WATERMARKPYTHON-70)
- [Fix] Preview release callbacks receive
Noneinstead of the page stream (WATERMARKPYTHON-71) - [Fix] Page previews written to
io.BytesIOare empty (WATERMARKPYTHON-72) - [Fix] Spreadsheet page previews written through a release callback are truncated (WATERMARKPYTHON-73)
Public API changes
Upgrading requires using the new wheel (pip ≥ 20.3) and handling the new AttributeError for misspelled attributes; other API signatures remain unchanged.
New classes and members
Color: a constructor; it had none.get()on 4 indexed classes —ReadOnlyListBase,SpreadsheetHeaderFooterCollection,SpreadsheetHeaderFooterSectionCollection,WordProcessingHeaderFooterCollection— as an alternative tox[key]; theiritemproperty is removed.
New features
Custom logger for WatermarkerSettings
WatermarkerSettings.logger now accepts a Python object or a plain function. In 26.6 assigning any value raised
TypeError: _marshal_callback_or_handle: cannot wrap ... as GroupDocs.Watermark.Options.ILogger
The logger can be an object that implements trace(message), warning(message) and error(message, exception), or a callable fn(level, message, exception). The engine logs a trace when it opens a file and an error (with the .NET exception text) when it cannot load one; failures inside the logger are ignored.
from groupdocs.watermark import Watermarker, WatermarkerSettings
class PrintLogger:
def trace(self, message):
print("trace:", message)
def warning(self, message):
print("warning:", message)
def error(self, message, exception):
print("error:", message, exception)
settings = WatermarkerSettings()
settings.logger = PrintLogger() # object with the required methods
# or: settings.logger = lambda level, msg, exc: print(level, msg, exc)
with Watermarker("document.pdf", settings) as watermarker:
print(watermarker.get_document_info().page_count)
Strict attribute assignment
Assigning a misspelled or .NET-style property on a watermark wrapper now raises an AttributeError instead of silently creating a Python-only attribute. This prevents code from thinking it has changed the document when it has not.
from groupdocs.watermark import Watermarker
from groupdocs.watermark.watermarks import TextWatermark, Font
with Watermarker("document.pdf") as wm:
watermark = TextWatermark("CONFIDENTIAL", Font("Arial", 36))
# The following line raises an error because the property name is wrong
watermark.opacity_level = 0.5
The raised error is:
AttributeError: 'TextWatermark' object has no attribute 'opacity_level'; assigning it would not reach the .NET object. Did you mean: 'opacity'?
Existing correct property assignments continue to work unchanged.
Code example
See the Custom logger for WatermarkerSettings and Strict attribute assignment sections above.
How to get the update
PyPI
- Package: groupdocs-watermark-net 26.10.0
- Install command:
pip install groupdocs-watermark-net==26.10.0
Direct download
Download the wheels for Windows, Linux and macOS from the GroupDocs.Watermark for Python via .NET 26.10 page.