From 50ebda332a9ccc8b8cc147f356437c90de12dd0b Mon Sep 17 00:00:00 2001 From: Raphael Michel Date: Fri, 5 Aug 2022 09:53:32 +0200 Subject: [PATCH] Bump PyPDF to version 2 (#2755) --- src/pretix/base/pdf.py | 22 +++++++-------- src/pretix/base/settings.py | 2 ++ src/pretix/control/views/pdf.py | 10 +++---- src/pretix/plugins/badges/exporters.py | 28 +++++++++---------- .../plugins/ticketoutputpdf/exporters.py | 4 +-- .../plugins/ticketoutputpdf/ticketoutput.py | 4 +-- src/setup.py | 2 +- src/tests/plugins/badges/test_pdf.py | 10 +++---- .../ticketoutputpdf/test_ticketoutputpdf.py | 6 ++-- 9 files changed, 44 insertions(+), 44 deletions(-) diff --git a/src/pretix/base/pdf.py b/src/pretix/base/pdf.py index cc584072cc..cbc529a70c 100644 --- a/src/pretix/base/pdf.py +++ b/src/pretix/base/pdf.py @@ -57,7 +57,7 @@ from django.utils.html import conditional_escape from django.utils.timezone import now from django.utils.translation import gettext_lazy as _, pgettext from i18nfield.strings import LazyI18nString -from PyPDF2 import PdfFileReader +from PyPDF2 import PdfReader from pytz import timezone from reportlab.graphics import renderPDF from reportlab.graphics.barcode.qr import QrCodeWidget @@ -646,7 +646,7 @@ class Renderer: self.event = event if self.background_file: self.bg_bytes = self.background_file.read() - self.bg_pdf = PdfFileReader(BytesIO(self.bg_bytes), strict=False) + self.bg_pdf = PdfReader(BytesIO(self.bg_bytes), strict=False) else: self.bg_bytes = None self.bg_pdf = None @@ -861,7 +861,7 @@ class Renderer: canvas.restoreState() def draw_page(self, canvas: Canvas, order: Order, op: OrderPosition, show_page=True, only_page=None): - page_count = self.bg_pdf.getNumPages() + page_count = len(self.bg_pdf.pages) if not only_page and not show_page: raise ValueError("only_page=None and show_page=False cannot be combined") @@ -881,7 +881,7 @@ class Renderer: elif o['type'] == "poweredby": self._draw_poweredby(canvas, op, o) if self.bg_pdf: - canvas.setPageSize((self.bg_pdf.getPage(page).mediaBox[2], self.bg_pdf.getPage(page).mediaBox[3])) + canvas.setPageSize((self.bg_pdf.pages[0].mediabox[2], self.bg_pdf.pages[0].mediabox[3])) if show_page: canvas.showPage() @@ -905,17 +905,17 @@ class Renderer: with open(os.path.join(d, 'out.pdf'), 'rb') as f: return BytesIO(f.read()) else: - from PyPDF2 import PdfFileReader, PdfFileWriter + from PyPDF2 import PdfReader, PdfWriter buffer.seek(0) - new_pdf = PdfFileReader(buffer) - output = PdfFileWriter() + new_pdf = PdfReader(buffer) + output = PdfWriter() for i, page in enumerate(new_pdf.pages): - bg_page = copy.copy(self.bg_pdf.getPage(i)) - bg_page.mergePage(page) - output.addPage(bg_page) + bg_page = copy.copy(self.bg_pdf.pages[i]) + bg_page.merge_page(page) + output.add_page(bg_page) - output.addMetadata({ + output.add_metadata({ '/Title': str(title), '/Creator': 'pretix', }) diff --git a/src/pretix/base/settings.py b/src/pretix/base/settings.py index f3459a6e10..a0518ad21f 100644 --- a/src/pretix/base/settings.py +++ b/src/pretix/base/settings.py @@ -57,6 +57,7 @@ from django_countries.fields import Country from hierarkey.models import GlobalSettingsBase, Hierarkey from i18nfield.forms import I18nFormField, I18nTextarea, I18nTextInput from i18nfield.strings import LazyI18nString +from phonenumbers import PhoneNumber, parse from rest_framework import serializers from pretix.api.serializers.fields import ( @@ -3030,6 +3031,7 @@ settings_hierarkey.add_type(LazyI18nStringList, settings_hierarkey.add_type(RelativeDateWrapper, serialize=lambda rdw: rdw.to_string(), unserialize=lambda s: RelativeDateWrapper.from_string(s)) +settings_hierarkey.add_type(PhoneNumber, lambda pn: pn.as_international, lambda s: parse(s)) @settings_hierarkey.set_global(cache_namespace='global') diff --git a/src/pretix/control/views/pdf.py b/src/pretix/control/views/pdf.py index 5fbb79bd31..38553a7b34 100644 --- a/src/pretix/control/views/pdf.py +++ b/src/pretix/control/views/pdf.py @@ -39,8 +39,8 @@ from django.utils.crypto import get_random_string from django.utils.timezone import now from django.utils.translation import gettext as _ from django.views.generic import TemplateView -from PyPDF2 import PdfFileReader, PdfFileWriter -from PyPDF2.utils import PdfReadError +from PyPDF2 import PdfReader, PdfWriter +from PyPDF2.errors import PdfReadError from reportlab.lib.units import mm from pretix.base.i18n import language @@ -153,9 +153,9 @@ class BaseEditorView(EventPermissionRequiredMixin, TemplateView): def post(self, request, *args, **kwargs): if "emptybackground" in request.POST: - p = PdfFileWriter() + p = PdfWriter() try: - p.addBlankPage( + p.add_blank_page( width=float(request.POST.get('width')) * mm, height=float(request.POST.get('height')) * mm, ) @@ -203,7 +203,7 @@ class BaseEditorView(EventPermissionRequiredMixin, TemplateView): try: bg_bytes = c.file.read() - PdfFileReader(BytesIO(bg_bytes), strict=False) + PdfReader(BytesIO(bg_bytes), strict=False) except PdfReadError as e: return JsonResponse({ "status": "error", diff --git a/src/pretix/plugins/badges/exporters.py b/src/pretix/plugins/badges/exporters.py index c324cc10a3..76469a7161 100644 --- a/src/pretix/plugins/badges/exporters.py +++ b/src/pretix/plugins/badges/exporters.py @@ -48,6 +48,7 @@ from django.db.models import Exists, OuterRef, Q from django.db.models.functions import Coalesce from django.utils.timezone import make_aware from django.utils.translation import gettext as _, gettext_lazy +from PyPDF2 import Transformation from reportlab.lib import pagesizes from reportlab.lib.units import mm from reportlab.pdfgen import canvas @@ -157,7 +158,7 @@ OPTIONS = OrderedDict([ def render_pdf(event, positions, opt): - from PyPDF2 import PdfFileReader, PdfFileWriter + from PyPDF2 import PdfReader, PdfWriter Renderer._register_fonts() renderermap = { @@ -168,7 +169,7 @@ def render_pdf(event, positions, opt): default_renderer = _renderer(event, event.badge_layouts.get(default=True)) except BadgeLayout.DoesNotExist: default_renderer = None - output_pdf_writer = PdfFileWriter() + output_pdf_writer = PdfWriter() any = False npp = opt['cols'] * opt['rows'] @@ -189,22 +190,19 @@ def render_pdf(event, positions, opt): p.showPage() p.save() buffer.seek(0) - canvas_pdf_reader = PdfFileReader(buffer) - empty_pdf_page = output_pdf_writer.addBlankPage( - width=opt['pagesize'][0] if opt['pagesize'] else positions[0][1].bg_pdf.getPage(0).mediaBox[2], - height=opt['pagesize'][1] if opt['pagesize'] else positions[0][1].bg_pdf.getPage(0).mediaBox[3], + canvas_pdf_reader = PdfReader(buffer) + empty_pdf_page = output_pdf_writer.add_blank_page( + width=opt['pagesize'][0] if opt['pagesize'] else positions[0][1].bg_pdf.pages[0].mediabox[2], + height=opt['pagesize'][1] if opt['pagesize'] else positions[0][1].bg_pdf.pages[0].mediabox[3], ) for i, (op, r) in enumerate(positions): - bg_page = copy.copy(r.bg_pdf.getPage(0)) - bg_page.trimBox = bg_page.mediaBox + bg_page = copy.copy(r.bg_pdf.pages[0]) + bg_page.trimbox = bg_page.mediabox offsetx = opt['margins'][3] + (i % opt['cols']) * opt['offsets'][0] offsety = opt['margins'][2] + (opt['rows'] - 1 - i // opt['cols']) * opt['offsets'][1] - empty_pdf_page.mergeTranslatedPage( - bg_page, - tx=offsetx, - ty=offsety - ) - empty_pdf_page.mergePage(canvas_pdf_reader.getPage(0)) + bg_page.add_transformation(Transformation().translate(offsetx, offsety)) + empty_pdf_page.merge_page(bg_page) + empty_pdf_page.merge_page(canvas_pdf_reader.pages[0]) pagebuffer = [] outbuffer = BytesIO() @@ -221,7 +219,7 @@ def render_pdf(event, positions, opt): if pagebuffer: render_page(pagebuffer) - output_pdf_writer.addMetadata({ + output_pdf_writer.add_metadata({ '/Title': 'Badges', '/Creator': 'pretix', }) diff --git a/src/pretix/plugins/ticketoutputpdf/exporters.py b/src/pretix/plugins/ticketoutputpdf/exporters.py index f686f63000..cc1545b485 100644 --- a/src/pretix/plugins/ticketoutputpdf/exporters.py +++ b/src/pretix/plugins/ticketoutputpdf/exporters.py @@ -43,7 +43,7 @@ from django.db.models import Q from django.db.models.functions import Coalesce from django.utils.timezone import make_aware from django.utils.translation import gettext as _, gettext_lazy -from PyPDF2.merger import PdfFileMerger +from PyPDF2 import PdfMerger from pretix.base.exporter import BaseExporter from pretix.base.i18n import language @@ -105,7 +105,7 @@ class AllTicketsPDF(BaseExporter): return d def render(self, form_data): - merger = PdfFileMerger() + merger = PdfMerger() qs = OrderPosition.objects.filter( order__event__in=self.events ).prefetch_related( diff --git a/src/pretix/plugins/ticketoutputpdf/ticketoutput.py b/src/pretix/plugins/ticketoutputpdf/ticketoutput.py index b05a8517ca..dd99310e73 100644 --- a/src/pretix/plugins/ticketoutputpdf/ticketoutput.py +++ b/src/pretix/plugins/ticketoutputpdf/ticketoutput.py @@ -44,7 +44,7 @@ from django.http import HttpRequest from django.template.loader import get_template from django.utils.functional import cached_property from django.utils.translation import gettext_lazy as _ -from PyPDF2 import PdfFileMerger +from PyPDF2 import PdfMerger from pretix.base.i18n import language from pretix.base.models import Order, OrderPosition @@ -112,7 +112,7 @@ class PdfTicketOutput(BaseTicketOutput): return renderer.render_background(buffer, _('Ticket')) def generate_order(self, order: Order): - merger = PdfFileMerger() + merger = PdfMerger() with language(order.locale, self.event.settings.region): for op in order.positions_with_tickets: layout = override_layout.send_chained( diff --git a/src/setup.py b/src/setup.py index 8dabe00617..e4214688d8 100644 --- a/src/setup.py +++ b/src/setup.py @@ -211,7 +211,7 @@ setup( 'psycopg2-binary', 'pycountry', 'pycparser==2.21', - 'PyPDF2==1.27.9', + 'PyPDF2==2.9.*', 'python-bidi==0.4.*', # Support for Arabic in reportlab 'python-dateutil==2.8.*', 'python-u2flib-server==4.*', diff --git a/src/tests/plugins/badges/test_pdf.py b/src/tests/plugins/badges/test_pdf.py index 6a1f354b7f..82cd64a3ca 100644 --- a/src/tests/plugins/badges/test_pdf.py +++ b/src/tests/plugins/badges/test_pdf.py @@ -39,7 +39,7 @@ from io import BytesIO import pytest from django.utils.timezone import now from django_scopes import scope -from PyPDF2 import PdfFileReader +from PyPDF2 import PdfReader from pretix.base.models import ( Event, Item, ItemVariation, Order, OrderPosition, Organizer, @@ -100,8 +100,8 @@ def test_generate_pdf(env): 'include_pending': True }) assert ftype == 'application/pdf' - pdf = PdfFileReader(BytesIO(buf)) - assert pdf.numPages == 2 + pdf = PdfReader(BytesIO(buf)) + assert len(pdf.pages) == 2 @pytest.mark.django_db @@ -115,5 +115,5 @@ def test_generate_pdf_multi(env): 'include_pending': True }) assert ftype == 'application/pdf' - pdf = PdfFileReader(BytesIO(buf)) - assert pdf.numPages == 1 + pdf = PdfReader(BytesIO(buf)) + assert len(pdf.pages) == 1 diff --git a/src/tests/plugins/ticketoutputpdf/test_ticketoutputpdf.py b/src/tests/plugins/ticketoutputpdf/test_ticketoutputpdf.py index c20186b237..c98bdddb76 100644 --- a/src/tests/plugins/ticketoutputpdf/test_ticketoutputpdf.py +++ b/src/tests/plugins/ticketoutputpdf/test_ticketoutputpdf.py @@ -26,7 +26,7 @@ from io import BytesIO import pytest from django.utils.timezone import now from django_scopes import scope -from PyPDF2 import PdfFileReader +from PyPDF2 import PdfReader from pretix.base.models import ( Event, Item, ItemVariation, Order, OrderPosition, Organizer, @@ -70,5 +70,5 @@ def test_generate_pdf(env0): o = PdfTicketOutput(event) fname, ftype, buf = o.generate(order.positions.first()) assert ftype == 'application/pdf' - pdf = PdfFileReader(BytesIO(buf)) - assert pdf.numPages == 1 + pdf = PdfReader(BytesIO(buf)) + assert len(pdf.pages) == 1