From 396c5e3669cec97ae511bcfeac85d4cef6b3cc3d Mon Sep 17 00:00:00 2001 From: Michal Stolarczyk Date: Fri, 30 Aug 2024 10:24:39 +0200 Subject: [PATCH] warn on unicode decoding errors in PDF annotations in some cases the the annotations may contain some junk that hinders annotations processing altogether. This allows to ignore the error and warn instead, which is configurable via warn_unicode_error arguments in the PDF initializer and/or open() method. --- pdfplumber/page.py | 8 +++++++- pdfplumber/pdf.py | 4 ++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/pdfplumber/page.py b/pdfplumber/page.py index 096ee1b..96515db 100644 --- a/pdfplumber/page.py +++ b/pdfplumber/page.py @@ -13,6 +13,7 @@ from typing import ( Union, ) from unicodedata import normalize as normalize_unicode +from warnings import warn from pdfminer.converter import PDFPageAggregator from pdfminer.layout import ( @@ -306,7 +307,12 @@ class Page(Container): try: extras[k] = v.decode("utf-8") except UnicodeDecodeError: - extras[k] = v.decode("utf-16") + try: + extras[k] = v.decode("utf-16") + except UnicodeDecodeError: + if not self.pdf.warn_unicode_error: + raise + warn(f"Could not decode {k} for annotation. {k} will be missing.") parsed = { "page_number": self.page_number, diff --git a/pdfplumber/pdf.py b/pdfplumber/pdf.py index 9b6ea71..b00a6a2 100644 --- a/pdfplumber/pdf.py +++ b/pdfplumber/pdf.py @@ -35,6 +35,7 @@ class PDF(Container): password: Optional[str] = None, strict_metadata: bool = False, unicode_norm: Optional[Literal["NFC", "NFKC", "NFD", "NFKD"]] = None, + warn_unicode_error: bool = False, ): self.stream = stream self.stream_is_external = stream_is_external @@ -43,6 +44,7 @@ class PDF(Container): self.laparams = None if laparams is None else LAParams(**laparams) self.password = password self.unicode_norm = unicode_norm + self.warn_unicode_error = warn_unicode_error self.doc = PDFDocument(PDFParser(stream), password=password or "") self.rsrcmgr = PDFResourceManager() @@ -76,6 +78,7 @@ class PDF(Container): repair: bool = False, gs_path: Optional[Union[str, pathlib.Path]] = None, repair_setting: T_repair_setting = "default", + warn_unicode_error: bool = False, ) -> "PDF": stream: Union[BufferedReader, BytesIO] @@ -107,6 +110,7 @@ class PDF(Container): strict_metadata=strict_metadata, unicode_norm=unicode_norm, stream_is_external=stream_is_external, + warn_unicode_error=warn_unicode_error, ) except PSException: