Skip to content

Commit

Permalink
File: Should Ghostscript go astray, our fallback saves the day.
Browse files Browse the repository at this point in the history
TYPE: Bugfix
LINK: OGC-1911
  • Loading branch information
cyrillkuettel authored Nov 20, 2024
1 parent 1e8ddc1 commit 6859eff
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 3 deletions.
22 changes: 21 additions & 1 deletion src/onegov/file/filters.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import os
import shlex
import logging
import subprocess

from depot.fields.interfaces import FileFilter
from depot.io.utils import file_from_content
from io import BytesIO

from onegov.core.utils import module_path
from onegov.file.utils import IMAGE_MIME_TYPES, get_image_size
from pathlib import Path
from PIL import Image
Expand All @@ -16,6 +20,9 @@
from depot.fields.upload import UploadedFile


log = logging.getLogger('onegov.file')


class ConditionalFilter(FileFilter):
""" A depot filter that's only run if a condition is met. The condition
is defined by overriding the :meth:``meets_condition`` returns True.
Expand Down Expand Up @@ -192,4 +199,17 @@ def generate_thumbnail(
# FIXME: This is kinda slow. We should be able to render the
# PDF directly at the thumbnail size. Maybe we should
# use pdf2image rather than roll our own?
return super().generate_thumbnail(self.generate_preview(fp))
try:
return super().generate_thumbnail(self.generate_preview(fp))
except Exception as e:
log.warning(f'Thumbnail generation failed: {e!s}')
fallback = BytesIO()
icon_path = (
module_path('onegov.org', 'static/pdf_preview')
+ os.sep
+ 'thumbnail_medium_pdf_preview_fallback.png'
)
with open(icon_path, 'rb') as f:
fallback.write(f.read())
fallback.seek(0)
return super().generate_thumbnail(fallback)
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 0 additions & 1 deletion tests/onegov/file/conftest.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import pytest

from depot.manager import DepotManager


Expand Down
40 changes: 39 additions & 1 deletion tests/onegov/file/test_models.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import os

import sedate
import transaction
import pytest
Expand All @@ -8,6 +10,7 @@
from onegov.core.orm.abstract import associated
from onegov.core.utils import module_path
from onegov.file import File, FileSet, AssociatedFiles, NamedFile
from onegov.file.filters import WithPDFThumbnailFilter
from onegov.file.models.fileset import file_to_set_associations
from tests.shared.utils import create_image
from pathlib import Path
Expand Down Expand Up @@ -193,7 +196,7 @@ def test_pdf_preview_creation(session):
transaction.commit()

pdf = session.query(File).one()
pdf.reference['thumbnail_medium']
assert pdf.reference.get('thumbnail_medium', None) is not None

# our example file contains a blue backgorund so we can verify that
# the thumbnail for the pdf is generated correctly
Expand All @@ -212,6 +215,41 @@ def test_pdf_preview_creation(session):
assert w in (362, 396)


def test_pdf_preview_creation_with_erroneous_pdf(session, monkeypatch):
# There was a pdf which made ghostscript fail with stderr: "circular
# reference to indirect object".
# However, we can't upload the original pdf due to sensitive information.
# So we have to kind of mock the error here.
mock = Mock(side_effect=ValueError)
monkeypatch.setattr(
WithPDFThumbnailFilter,
'generate_preview',
mock
)

filname = 'example.pdf'
path = module_path('tests.onegov.file', f'fixtures/{filname}')

with open(path, 'rb') as f:
session.add(File(name=f'{filname}', reference=f))
transaction.commit()
pdf = session.query(File).one()
assert pdf.reference.get('thumbnail_medium', None) is not None
thumb = DepotManager.get().get(pdf.reference['thumbnail_medium']['id'])

# expect to be the default one

thumbnail_medium_pdf_preview_fallback = BytesIO(
Path(
module_path('onegov.org', 'static/pdf_preview')
+ os.sep
+ 'thumbnail_medium_pdf_preview_fallback.png'
).read_bytes()
)

assert thumb.read() == thumbnail_medium_pdf_preview_fallback.read()


def test_max_image_size(session):
session.add(File(name='unchanged.png', reference=create_image(2048, 2048)))
session.add(File(name='limited.png', reference=create_image(2049, 2048)))
Expand Down

0 comments on commit 6859eff

Please sign in to comment.