diff --git a/elodie/media/photo.py b/elodie/media/photo.py index 1ccd3ff6..4152eac1 100644 --- a/elodie/media/photo.py +++ b/elodie/media/photo.py @@ -29,7 +29,7 @@ class Photo(Media): __name__ = 'Photo' #: Valid extensions for photo files. - extensions = ('arw', 'cr2', 'dng', 'gif', 'heic', 'jpeg', 'jpg', 'nef', 'png', 'rw2') + extensions = ('arw', 'cr2', 'dng', 'gif', 'heic', 'jpeg', 'jpg', 'nef', 'png', 'rw2', 'tif', 'tiff') def __init__(self, source=None): super(Photo, self).__init__(source) @@ -94,10 +94,10 @@ def is_valid(self): """ source = self.source - # HEIC is not well supported yet so we special case it. + # HEIC and RAW formats are not well supported by Pillow so we special case them. # https://github.com/python-pillow/Pillow/issues/2806 extension = os.path.splitext(source)[1][1:].lower() - if(extension != 'heic'): + if(extension not in ('arw', 'cr2', 'dng', 'heic', 'nef', 'rw2')): # gh-4 This checks if the source file is an image. # Use Pillow to validate the image format. if(self.pillow is None): diff --git a/elodie/tests/media/photo_test.py b/elodie/tests/media/photo_test.py index 4b65d9d7..d5b326cf 100644 --- a/elodie/tests/media/photo_test.py +++ b/elodie/tests/media/photo_test.py @@ -10,6 +10,7 @@ import time import pytest +from unittest.mock import patch sys.path.insert(0, os.path.abspath(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))))) sys.path.insert(0, os.path.abspath(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) @@ -37,11 +38,21 @@ def test_photo_extensions(): assert 'nef' in extensions assert 'png' in extensions assert 'rw2' in extensions + assert 'tif' in extensions + assert 'tiff' in extensions valid_extensions = Photo.get_valid_extensions() assert extensions == valid_extensions, valid_extensions +@pytest.mark.parametrize('extension', ('tif', 'tiff')) +def test_is_valid_tiff_extensions_using_pillow(extension): + with tempfile.NamedTemporaryFile(suffix=f'.{extension}') as ntf: + photo = Photo(ntf.name) + with patch.object(photo.pillow, 'open') as mock_open: + mock_open.return_value.format = 'TIFF' + assert photo.is_valid() + def test_empty_album(): photo = Photo(helper.get_file('plain.jpg')) assert photo.get_album() is None @@ -57,6 +68,15 @@ def test_is_valid(): assert photo.is_valid() +def test_is_valid_raw_formats(): + # Verify that RAW and HEIC formats are accepted even if they are not + # valid images (bypassing Pillow). + # We use a dummy file for each extension. + for ext in ('arw', 'cr2', 'dng', 'heic', 'nef', 'rw2'): + with tempfile.NamedTemporaryFile(suffix=f'.{ext}') as ntf: + photo = Photo(ntf.name) + assert photo.is_valid(), f'Failed for extension {ext}' + def test_is_not_valid(): photo = Photo(helper.get_file('text.txt'))