Passed
Push — master ( 9ddb09...7fc5b5 )
by Jaisen
01:14
created

elodie.tests.media.photo_test   A

Complexity

Total Complexity 40

Size/Duplication

Total Lines 397
Duplicated Lines 32.75 %

Importance

Changes 0
Metric Value
eloc 250
dl 130
loc 397
rs 9.2
c 0
b 0
f 0
wmc 40

29 Functions

Rating   Name   Duplication   Size   Complexity  
A test_get_date_taken() 0 6 1
A test_empty_album() 0 3 1
A test_set_location_minus() 25 25 1
A test_get_camera_make() 0 5 1
A test_is_valid() 0 4 1
A test_get_coordinate_longitude() 0 5 1
A _test_photo_type_set() 0 29 4
A test_get_coordinate_default() 0 5 1
A test_get_coordinates_without_exif() 0 7 1
A test_get_metadata_of_invalid_photo() 0 5 1
A test_has_album() 0 5 1
A test_get_coordinate_latitude() 0 5 1
A test_get_camera_make_not_set() 0 5 1
A test_set_title_non_ascii() 20 20 1
A test_various_types() 0 15 3
A test_get_camera_model_not_set() 0 5 1
A test_get_date_taken_without_exif() 0 8 1
A test_get_coordinates_with_zero_coordinate() 0 7 1
A test_set_location() 25 25 1
A test_get_coordinate_longitude_plus() 0 5 1
A test_photo_extensions() 0 16 1
A test_set_date_taken_with_missing_datetimeoriginal() 0 22 1
A test_is_not_valid() 0 4 1
A test_get_camera_model() 0 5 1
A test_get_coordinate_latitude_minus() 0 5 1
A test_set_date_taken() 20 20 1
A _test_photo_type_get() 0 25 5
A test_set_album() 21 21 1
A test_set_title() 19 19 1

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complexity

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like elodie.tests.media.photo_test often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

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