jenkins-bot has submitted this change. (
https://gerrit.wikimedia.org/r/c/pywikibot/core/+/1324317?usp=email )
Change subject: reflinks: Pass PDF bytes directly to pdfinfo
......................................................................
reflinks: Pass PDF bytes directly to pdfinfo
PDF responses are decoded as text before being written to a temporary
stream positioned at EOF. This can corrupt binary data and prevent
pdfinfo from extracting document metadata.
Pass the original response bytes through the documented pdfinfo stdin
interface and remove the temporary-file lifecycle. Add a regression test
for byte preservation and title parsing.
Change-Id: I3d95a9e3eeefad76e60e6d4f2231feca599fa4f4
---
M scripts/reflinks.py
M tests/reflinks_tests.py
2 files changed, 32 insertions(+), 16 deletions(-)
Approvals:
jenkins-bot: Verified
Xqt: Looks good to me, approved
diff --git a/scripts/reflinks.py b/scripts/reflinks.py
index 47721cd..3927a2b 100755
--- a/scripts/reflinks.py
+++ b/scripts/reflinks.py
@@ -53,10 +53,8 @@
import http.client as httplib
import itertools
-import os
import re
import subprocess
-import tempfile
from contextlib import suppress
from enum import IntEnum
from functools import partial
@@ -498,18 +496,14 @@
@staticmethod
def getPDFTitle(ref, response) -> None:
"""Use pdfinfo to retrieve title from a PDF."""
- # pdfinfo is Unix-only
pywikibot.info('Reading PDF file...')
- infile = None
try:
- fd, infile = tempfile.mkstemp()
- urlobj = os.fdopen(fd, 'w+')
- urlobj.write(response.text)
- pdfinfo_out = subprocess.Popen([r'pdfinfo', '/dev/stdin'],
- stdin=urlobj,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE,
- shell=False).communicate()[0]
+ pdfinfo_out = subprocess.run(
+ ['pdfinfo', '-'],
+ input=response.content,
+ capture_output=True,
+ check=False,
+ ).stdout
except ValueError:
pywikibot.info('pdfinfo value error.')
except OSError:
@@ -527,10 +521,6 @@
pywikibot.info('title: ' + ref.title)
break
pywikibot.info('PDF done.')
- finally:
- if infile is not None:
- urlobj.close()
- os.unlink(infile)
def setup(self) -> None:
"""Read dead links from file."""
diff --git a/tests/reflinks_tests.py b/tests/reflinks_tests.py
index c75d103..6864723 100755
--- a/tests/reflinks_tests.py
+++ b/tests/reflinks_tests.py
@@ -8,6 +8,8 @@
from __future__ import annotations
import unittest
+from types import SimpleNamespace
+from unittest.mock import patch
from scripts.reflinks import ReferencesRobot, XmlDumpPageGenerator, main
from tests import join_xml_data_path
@@ -15,6 +17,30 @@
from tests.utils import empty_sites
+class TestPDFTitle(TestCase):
+
+ """Tests for PDF title extraction."""
+
+ net = False
+
+ def test_pdf_bytes_passed_to_pdfinfo(self) -> None:
+ """Test that pdfinfo receives the unchanged PDF content."""
+ content = b'%PDF-1.7\x00\xff'
+ process = SimpleNamespace(
+ stdout=b'Pages: 1\nTitle: Example document\n')
+ ref = SimpleNamespace(title='')
+ response = SimpleNamespace(content=content)
+
+ with patch('scripts.reflinks.subprocess.run',
+ return_value=process) as run:
+ ReferencesRobot.getPDFTitle(ref, response)
+
+ self.assertEqual(ref.title, 'Example document')
+ run.assert_called_once_with(
+ ['pdfinfo', '-'], input=content,
+ capture_output=True, check=False)
+
+
class TestXMLPageGenerator(TestCase):
"""Test XML Page generator."""
--
To view, visit
https://gerrit.wikimedia.org/r/c/pywikibot/core/+/1324317?usp=email
To unsubscribe, or for help writing mail filters, visit
https://gerrit.wikimedia.org/r/settings?usp=email
Gerrit-MessageType: merged
Gerrit-Project: pywikibot/core
Gerrit-Branch: master
Gerrit-Change-Id: I3d95a9e3eeefad76e60e6d4f2231feca599fa4f4
Gerrit-Change-Number: 1324317
Gerrit-PatchSet: 3
Gerrit-Owner: Mahveotm <[email protected]>
Gerrit-Reviewer: Xqt <[email protected]>
Gerrit-Reviewer: jenkins-bot
_______________________________________________
Pywikibot-commits mailing list -- [email protected]
To unsubscribe send an email to [email protected]