From 183335833e366aada6c2d212cd6ee5f1a29729b6 Mon Sep 17 00:00:00 2001 From: Antony Lee Date: Tue, 30 Mar 2021 16:10:36 +0200 Subject: [PATCH] Access pdf annotations while inside pikepdf.Pdf context manager. Depending on the exact way the pdf file is written, iterating over Annots can fail after the file has been closed. This is not the case for matplotlib-generated pdfs, but is the case for mplcairo-generated ones. As a simple repro of the different behavior between "in-the-contextmanager" and "out-of-the-contextmanager": ``` from matplotlib import pyplot as plt plt.figtext(.5, .5, "hello, world", url="https://www.google.com") plt.savefig("/tmp/test.pdf", backend="pdf") import pikepdf with pikepdf.Pdf.open("/tmp/test.pdf") as pdf: page = pdf.pages[0] print(repr(page.Annots)) # within contextmanager: ok with pikepdf.Pdf.open("/tmp/test.pdf") as pdf: page = pdf.pages[0] print(repr(page.Annots)) # after contextmanager: AttributeError ``` --- lib/matplotlib/tests/test_backend_pdf.py | 30 ++++++++++++++---------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/lib/matplotlib/tests/test_backend_pdf.py b/lib/matplotlib/tests/test_backend_pdf.py index 31d50ac1302f..06bfe1cdb1ab 100644 --- a/lib/matplotlib/tests/test_backend_pdf.py +++ b/lib/matplotlib/tests/test_backend_pdf.py @@ -227,13 +227,15 @@ def test_text_urls(): with pikepdf.Pdf.open(fd) as pdf: annots = pdf.pages[0].Annots - for y, fragment in [('0.1', 'plain'), ('0.4', 'mathtext')]: - annot = next( - (a for a in annots if a.A.URI == f'{test_url}{fragment}'), - None) - assert annot is not None - # Positions in points (72 per inch.) - assert annot.Rect[1] == decimal.Decimal(y) * 72 + # Iteration over Annots must occur within the context manager, + # otherwise it may fail depending on the pdf structure. + for y, fragment in [('0.1', 'plain'), ('0.4', 'mathtext')]: + annot = next( + (a for a in annots if a.A.URI == f'{test_url}{fragment}'), + None) + assert annot is not None + # Positions in points (72 per inch.) + assert annot.Rect[1] == decimal.Decimal(y) * 72 @needs_usetex @@ -251,12 +253,14 @@ def test_text_urls_tex(): with pikepdf.Pdf.open(fd) as pdf: annots = pdf.pages[0].Annots - annot = next( - (a for a in annots if a.A.URI == f'{test_url}tex'), - None) - assert annot is not None - # Positions in points (72 per inch.) - assert annot.Rect[1] == decimal.Decimal('0.7') * 72 + # Iteration over Annots must occur within the context manager, + # otherwise it may fail depending on the pdf structure. + annot = next( + (a for a in annots if a.A.URI == f'{test_url}tex'), + None) + assert annot is not None + # Positions in points (72 per inch.) + assert annot.Rect[1] == decimal.Decimal('0.7') * 72 def test_pdfpages_fspath():