Issues (157)

elodie/tests/media/photo_test.py (6 issues)

1
# -*- coding: utf-8
2
# Project imports
3
from __future__ import unicode_literals
4
import os
5
import sys
6
7
from datetime import datetime
8
import shutil
9
import tempfile
10
import time
11
12
from nose.plugins.skip import SkipTest
13
14
sys.path.insert(0, os.path.abspath(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))))))
15
sys.path.insert(0, os.path.abspath(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))))
16
17
import helper
18
from elodie.media.media import Media
19
from elodie.media.photo import Photo
20
21
os.environ['TZ'] = 'GMT'
22
23
setup_module = helper.setup_module
24
teardown_module = helper.teardown_module
25
26
def test_photo_extensions():
27
    photo = Photo()
28
    extensions = photo.extensions
29
30
    assert 'arw' in extensions
31
    assert 'cr2' in extensions
32
    assert 'dng' in extensions
33
    assert 'gif' in extensions
34
    assert 'heic' in extensions
35
    assert 'jpg' in extensions
36
    assert 'jpeg' in extensions
37
    assert 'nef' in extensions
38
    assert 'png' in extensions
39
    assert 'rw2' in extensions
40
41
    valid_extensions = Photo.get_valid_extensions()
42
43
    assert extensions == valid_extensions, valid_extensions
44
45
def test_empty_album():
46
    photo = Photo(helper.get_file('plain.jpg'))
47
    assert photo.get_album() is None
48
49
def test_has_album():
50
    photo = Photo(helper.get_file('with-album.jpg'))
51
    album = photo.get_album()
52
53
    assert album == 'Test Album', album
54
55
def test_is_valid():
56
    photo = Photo(helper.get_file('plain.jpg'))
57
58
    assert photo.is_valid()
59
60
def test_is_not_valid():
61
    photo = Photo(helper.get_file('text.txt'))
62
63
    assert not photo.is_valid()
64
65
def test_get_metadata_of_invalid_photo():
66
    photo = Photo(helper.get_file('invalid.jpg'))
67
    metadata = photo.get_metadata()
68
69
    assert metadata is None
70
71
def test_get_coordinate_default():
72
    photo = Photo(helper.get_file('with-location.jpg'))
73
    coordinate = photo.get_coordinate()
74
75
    assert helper.isclose(coordinate,37.3667027222), coordinate
76
77
def test_get_coordinate_latitude():
78
    photo = Photo(helper.get_file('with-location.jpg'))
79
    coordinate = photo.get_coordinate('latitude')
80
81
    assert helper.isclose(coordinate,37.3667027222), coordinate
82
83
def test_get_coordinate_latitude_minus():
84
    photo = Photo(helper.get_file('with-location-inv.jpg'))
85
    coordinate = photo.get_coordinate('latitude')
86
87
    assert helper.isclose(coordinate,-37.3667027222), coordinate
88
89
def test_get_coordinate_longitude():
90
    photo = Photo(helper.get_file('with-location.jpg'))
91
    coordinate = photo.get_coordinate('longitude')
92
93
    assert helper.isclose(coordinate,-122.033383611), coordinate
94
95
def test_get_coordinate_longitude_plus():
96
    photo = Photo(helper.get_file('with-location-inv.jpg'))
97
    coordinate = photo.get_coordinate('longitude')
98
99
    assert helper.isclose(coordinate,122.033383611), coordinate
100
101
def test_get_coordinates_without_exif():
102
    photo = Photo(helper.get_file('no-exif.jpg'))
103
    latitude = photo.get_coordinate('latitude')
104
    longitude = photo.get_coordinate('longitude')
105
106
    assert latitude is None, latitude
107
    assert longitude is None, longitude
108
109
def test_get_coordinates_with_zero_coordinate():
110
    photo = Photo(helper.get_file('with-location-zero-coordinate.jpg'))
111
    latitude = photo.get_coordinate('latitude')
112
    longitude = photo.get_coordinate('longitude')
113
114
    assert helper.isclose(latitude,51.55325), latitude
115
    assert helper.isclose(longitude,-0.00417777777778), longitude
116
117
def test_get_coordinates_with_null_coordinate():
118
    photo = Photo(helper.get_file('with-null-coordinates.jpg'))
119
    latitude = photo.get_coordinate('latitude')
120
    longitude = photo.get_coordinate('longitude')
121
122
    assert latitude is None, latitude
123
    assert longitude is None, longitude
124
125
def test_get_date_taken():
126
    photo = Photo(helper.get_file('plain.jpg'))
127
    date_taken = photo.get_date_taken()
128
129
    #assert date_taken == (2015, 12, 5, 0, 59, 26, 5, 339, 0), date_taken
130
    assert date_taken == helper.time_convert((2015, 12, 5, 0, 59, 26, 5, 339, 0)), date_taken
131
132
def test_get_date_taken_without_exif():
133
    source = helper.get_file('no-exif.jpg')
134
    photo = Photo(source)
135
    date_taken = photo.get_date_taken()
136
137
    date_taken_from_file = time.gmtime(min(os.path.getmtime(source), os.path.getctime(source)))
138
139
    assert date_taken == date_taken_from_file, date_taken
140
141
def test_get_camera_make():
142
    photo = Photo(helper.get_file('with-location.jpg'))
143
    make = photo.get_camera_make()
144
145
    assert make == 'Canon', make
146
147
def test_get_camera_make_not_set():
148
    photo = Photo(helper.get_file('no-exif.jpg'))
149
    make = photo.get_camera_make()
150
151
    assert make is None, make
152
153
def test_get_camera_model():
154
    photo = Photo(helper.get_file('with-location.jpg'))
155
    model = photo.get_camera_model()
156
157
    assert model == 'Canon EOS REBEL T2i', model
158
159
def test_get_camera_model_not_set():
160
    photo = Photo(helper.get_file('no-exif.jpg'))
161
    model = photo.get_camera_model()
162
163
    assert model is None, model
164
165
def test_is_valid():
166
    photo = Photo(helper.get_file('with-location.jpg'))
167
168
    assert photo.is_valid()
169
170
def test_is_not_valid():
171
    photo = Photo(helper.get_file('text.txt'))
172
173
    assert not photo.is_valid()
174
175
def test_is_valid_fallback_using_pillow():
176
    photo = Photo(helper.get_file('imghdr-error.jpg'))
177
178
    assert photo.is_valid()
179
180
def test_pillow_not_loaded():
181
    photo = Photo(helper.get_file('imghdr-error.jpg'))
182
    photo.pillow = None
183
184
    assert photo.is_valid() == False
185
186 View Code Duplication
def test_set_album():
0 ignored issues
show
This code seems to be duplicated in your project.
Loading history...
187
    temporary_folder, folder = helper.create_working_folder()
188
189
    origin = '%s/photo.jpg' % folder
190
    shutil.copyfile(helper.get_file('plain.jpg'), origin)
191
192
    photo = Photo(origin)
193
    metadata = photo.get_metadata()
194
195
    assert metadata['album'] is None, metadata['album']
196
197
    status = photo.set_album('Test Album')
198
199
    assert status == True, status
200
201
    photo_new = Photo(origin)
202
    metadata_new = photo_new.get_metadata()
203
204
    shutil.rmtree(folder)
205
206
    assert metadata_new['album'] == 'Test Album', metadata_new['album']
207
208
def test_set_date_taken_with_missing_datetimeoriginal():
209
    # When datetimeoriginal (or other key) is missing we have to add it gh-74
210
    # https://github.com/jmathai/elodie/issues/74
211
    temporary_folder, folder = helper.create_working_folder()
212
213
    origin = '%s/photo.jpg' % folder
214
    shutil.copyfile(helper.get_file('no-exif.jpg'), origin)
215
216
    photo = Photo(origin)
217
    status = photo.set_date_taken(datetime(2013, 9, 30, 7, 6, 5))
218
219
    assert status == True, status
220
221
    photo_new = Photo(origin)
222
    metadata = photo_new.get_metadata()
223
224
    date_taken = metadata['date_taken']
225
226
    shutil.rmtree(folder)
227
228
    #assert date_taken == (2013, 9, 30, 7, 6, 5, 0, 273, 0), metadata['date_taken']
229
    assert date_taken == helper.time_convert((2013, 9, 30, 7, 6, 5, 0, 273, 0)), metadata['date_taken']
230
231 View Code Duplication
def test_set_date_taken():
0 ignored issues
show
This code seems to be duplicated in your project.
Loading history...
232
    temporary_folder, folder = helper.create_working_folder()
233
234
    origin = '%s/photo.jpg' % folder
235
    shutil.copyfile(helper.get_file('plain.jpg'), origin)
236
237
    photo = Photo(origin)
238
    status = photo.set_date_taken(datetime(2013, 9, 30, 7, 6, 5))
239
240
    assert status == True, status
241
242
    photo_new = Photo(origin)
243
    metadata = photo_new.get_metadata()
244
245
    date_taken = metadata['date_taken']
246
247
    shutil.rmtree(folder)
248
249
    #assert date_taken == (2013, 9, 30, 7, 6, 5, 0, 273, 0), metadata['date_taken']
250
    assert date_taken == helper.time_convert((2013, 9, 30, 7, 6, 5, 0, 273, 0)), metadata['date_taken']
251
252 View Code Duplication
def test_set_location():
0 ignored issues
show
This code seems to be duplicated in your project.
Loading history...
253
    temporary_folder, folder = helper.create_working_folder()
254
255
    origin = '%s/photo.jpg' % folder
256
    shutil.copyfile(helper.get_file('plain.jpg'), origin)
257
258
    photo = Photo(origin)
259
    origin_metadata = photo.get_metadata()
260
261
    # Verify that original photo has different location info that what we
262
    #   will be setting and checking
263
    assert not helper.isclose(origin_metadata['latitude'], 11.1111111111), origin_metadata['latitude']
264
    assert not helper.isclose(origin_metadata['longitude'], 99.9999999999), origin_metadata['longitude']
265
266
    status = photo.set_location(11.1111111111, 99.9999999999)
267
268
    assert status == True, status
269
270
    photo_new = Photo(origin)
271
    metadata = photo_new.get_metadata()
272
273
    shutil.rmtree(folder)
274
275
    assert helper.isclose(metadata['latitude'], 11.1111111111), metadata['latitude']
276
    assert helper.isclose(metadata['longitude'], 99.9999999999), metadata['longitude']
277
278 View Code Duplication
def test_set_location_minus():
0 ignored issues
show
This code seems to be duplicated in your project.
Loading history...
279
    temporary_folder, folder = helper.create_working_folder()
280
281
    origin = '%s/photo.jpg' % folder
282
    shutil.copyfile(helper.get_file('plain.jpg'), origin)
283
284
    photo = Photo(origin)
285
    origin_metadata = photo.get_metadata()
286
287
    # Verify that original photo has different location info that what we
288
    #   will be setting and checking
289
    assert not helper.isclose(origin_metadata['latitude'], 11.1111111111), origin_metadata['latitude']
290
    assert not helper.isclose(origin_metadata['longitude'], 99.9999999999), origin_metadata['longitude']
291
292
    status = photo.set_location(-11.1111111111, -99.9999999999)
293
294
    assert status == True, status
295
296
    photo_new = Photo(origin)
297
    metadata = photo_new.get_metadata()
298
299
    shutil.rmtree(folder)
300
301
    assert helper.isclose(metadata['latitude'], -11.1111111111), metadata['latitude']
302
    assert helper.isclose(metadata['longitude'], -99.9999999999), metadata['longitude']
303
304 View Code Duplication
def test_set_title():
0 ignored issues
show
This code seems to be duplicated in your project.
Loading history...
305
    temporary_folder, folder = helper.create_working_folder()
306
307
    origin = '%s/photo.jpg' % folder
308
    shutil.copyfile(helper.get_file('plain.jpg'), origin)
309
310
    photo = Photo(origin)
311
    origin_metadata = photo.get_metadata()
312
313
    status = photo.set_title('my photo title')
314
315
    assert status == True, status
316
317
    photo_new = Photo(origin)
318
    metadata = photo_new.get_metadata()
319
320
    shutil.rmtree(folder)
321
322
    assert metadata['title'] == 'my photo title', metadata['title']
323
324 View Code Duplication
def test_set_title_non_ascii():
0 ignored issues
show
This code seems to be duplicated in your project.
Loading history...
325
    temporary_folder, folder = helper.create_working_folder()
326
327
    origin = '%s/photo.jpg' % folder
328
    shutil.copyfile(helper.get_file('plain.jpg'), origin)
329
330
    photo = Photo(origin)
331
    origin_metadata = photo.get_metadata()
332
333
    unicode_title = u'形声字 / 形聲字'
334
335
    status = photo.set_title(unicode_title)
336
    assert status == True, status
337
338
    photo_new = Photo(origin)
339
    metadata = photo_new.get_metadata()
340
341
    shutil.rmtree(folder)
342
343
    assert metadata['title'] == unicode_title, metadata['title']
344
345
# This is a test generator that will test reading and writing to
346
# various RAW formats. Each sample file has a different date which
347
# is the only information which needs to be added to run the tests
348
# for that file type.
349
# https://nose.readthedocs.io/en/latest/writing_tests.html#test-generators
350
def test_various_types():
351
    types = Photo.extensions
352
    #extensions = ('arw', 'cr2', 'dng', 'gif', 'jpeg', 'jpg', 'nef', 'rw2')
353
    dates = {
354
        'arw': (2007, 4, 8, 17, 41, 18, 6, 98, 0),
355
        'cr2': (2005, 10, 29, 16, 14, 44, 5, 302, 0),
356
        'dng': (2009, 10, 20, 9, 10, 46, 1, 293, 0),
357
        'heic': (2019, 5, 26, 10, 33, 20, 6, 146, 0),
358
        'nef': (2008, 10, 24, 9, 12, 56, 4, 298, 0),
359
        'png': (2015, 1, 18, 12, 1, 1, 6, 18, 0),
360
        'rw2': (2014, 11, 19, 23, 7, 44, 2, 323, 0)
361
    }
362
363
    for type in types:
364
        if type in dates:
365
            yield (_test_photo_type_get, type, dates[type])
366
            yield (_test_photo_type_set, type, dates[type])
367
368
def _test_photo_type_get(type, date):
369
    temporary_folder, folder = helper.create_working_folder()
370
371
    photo_name = 'photo.{}'.format(type)
372
    photo_file = helper.get_file(photo_name)
373
    origin = '{}/{}'.format(folder, photo_name)
374
375
    if not photo_file:
376
        photo_file = helper.download_file(photo_name, folder)
377
        if not photo_file or not os.path.isfile(photo_file):
378
            raise SkipTest('{} file not downlaoded'.format(type))
379
380
        # downloading for each test is costly so we save it in the working directory
381
        file_path_save_as = helper.get_file_path(photo_name)
382
        if os.path.isfile(photo_file):
383
            shutil.copyfile(photo_file, file_path_save_as)
384
385
    shutil.copyfile(photo_file, origin)
386
387
    photo = Photo(origin)
388
    metadata = photo.get_metadata()
389
390
    shutil.rmtree(folder)
391
392
    assert metadata['date_taken'] == helper.time_convert(date), '{} date {}'.format(type, metadata['date_taken'])
393
394
def _test_photo_type_set(type, date):
395
    temporary_folder, folder = helper.create_working_folder()
396
397
    photo_name = 'photo.{}'.format(type)
398
    photo_file = helper.get_file(photo_name)
399
    origin = '{}/{}'.format(folder, photo_name)
400
401
    if not photo_file:
402
        photo_file = helper.download_file(photo_name, folder)
403
        if not photo_file or not os.path.isfile(photo_file):
404
            raise SkipTest('{} file not downlaoded'.format(type))
405
406
    shutil.copyfile(photo_file, origin)
407
408
    photo = Photo(origin)
409
    origin_metadata = photo.get_metadata()
410
411
    status = photo.set_location(11.1111111111, 99.9999999999)
412
413
    assert status == True, status
414
415
    photo_new = Photo(origin)
416
    metadata = photo_new.get_metadata()
417
418
    shutil.rmtree(folder)
419
420
    assert metadata['date_taken'] == helper.time_convert(date), '{} date {}'.format(type, metadata['date_taken'])
421
    assert helper.isclose(metadata['latitude'], 11.1111111111), '{} lat {}'.format(type, metadata['latitude'])
422
    assert helper.isclose(metadata['longitude'], 99.9999999999), '{} lon {}'.format(type, metadata['latitude'])
423