Fix tests and cleanup

This commit is contained in:
Cédric Leporcq 2021-08-08 21:43:37 +02:00
parent d7ca7f8321
commit a2cc3a6f0c
58 changed files with 62 additions and 4813 deletions

View File

View File

@ -1,154 +0,0 @@
from builtins import range
from past.utils import old_div
import hashlib
import os
import random
import string
import tempfile
import re
import time
import urllib
from datetime import datetime
from datetime import timedelta
from elodie.external.pyexiftool import ExifTool
from elodie.dependencies import get_exiftool
from elodie import constants
ELODIE_PATH = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
def create_working_folder(format=None):
temporary_folder = tempfile.gettempdir()
folder = tempfile.TemporaryDirectory(prefix='elodie-').name
folder = os.path.join(folder, random_string(10, format))
os.makedirs(folder)
return (temporary_folder, folder)
def download_file(name, destination):
try:
url_to_file = 'https://s3.amazonaws.com/jmathai/github/elodie/{}'.format(name)
# urlretrieve works differently for python 2 and 3
if constants.python_version < 3:
final_name = '{}/{}{}'.format(destination, random_string(10), os.path.splitext(name)[1])
urllib.urlretrieve(
url_to_file,
final_name
)
else:
final_name, headers = urllib.request.urlretrieve(url_to_file)
return final_name
except Exception as e:
return False
def get_file(name):
file_path = get_file_path(name)
if not os.path.isfile(file_path):
return False
return file_path
def get_file_path(name):
return os.path.join(ELODIE_PATH, 'samples', name)
def get_test_location():
return (61.013710, 99.196656, 'Siberia')
def populate_folder(number_of_files, include_invalid=False):
temporary_folder, folder = create_working_folder()
for x in range(0, number_of_files):
ext = 'jpg' if x % 2 == 0 else 'txt'
fname = '%s/%s.%s' % (folder, x, ext)
with open(fname, 'a'):
os.utime(fname, None)
if include_invalid:
fname = '%s/%s' % (folder, 'invalid.invalid')
with open(fname, 'a'):
os.utime(fname, None)
return folder
def random_string(length, format=None):
format_choice = string.ascii_uppercase + string.digits
if format == 'int':
format_choice = string.digits
elif format == 'str':
format_choice = string.asci_uppercase
return ''.join(random.SystemRandom().choice(format_choice) for _ in range(length))
def random_decimal():
return random.random()
def random_coordinate(coordinate, precision):
# Here we add to the decimal section of the coordinate by a given precision
return coordinate + ((old_div(10.0, (10.0**precision))) * random_decimal())
def temp_dir():
return tempfile.gettempdir()
def is_windows():
return os.name == 'nt'
# path_tz_fix(file_name)
# Change timestamp in file_name by the offset
# between UTC and local time, i.e.
# 2015-12-05_00-59-26-with-title-some-title.jpg ->
# 2015-12-04_20-59-26-with-title-some-title.jpg
# (Windows only)
def path_tz_fix(file_name):
if is_windows():
# Calculate the offset between UTC and local time
tz_shift = old_div((datetime.fromtimestamp(0) -
datetime.utcfromtimestamp(0)).seconds,3600)
# replace timestamp in file_name
m = re.search('(\d{4}-\d{2}-\d{2}_\d{2}-\d{2}-\d{2})',file_name)
t_date = datetime.fromtimestamp(time.mktime(time.strptime(m.group(0), '%Y-%m-%d_%H-%M-%S')))
s_date_fix = (t_date-timedelta(hours=tz_shift)).strftime('%Y-%m-%d_%H-%M-%S')
return re.sub('\d{4}-\d{2}-\d{2}_\d{2}-\d{2}-\d{2}',s_date_fix,file_name)
else:
return file_name
# time_convert(s_time)
# Change s_time (struct_time) by the offset
# between UTC and local time
# (Windows only)
def time_convert(s_time):
if is_windows():
return time.gmtime((time.mktime(s_time)))
else:
return s_time
# isclose(a,b,rel_tol)
# To compare float coordinates a and b
# with relative tolerance c
def isclose(a, b, rel_tol = 1e-8):
if not isinstance(a, (int, float)) or not isinstance(b, (int, float)):
return False
diff = abs(a - b)
return (diff <= abs(rel_tol * a) and
diff <= abs(rel_tol * b))
def get_hash_db(photo_path):
return os.path.join(photo_path, '.elodie',constants.hash_db)
def get_location_db(photo_path):
return os.path.join(photo_path, '.elodie', constants.location_db)
def setup_module():
exiftool_addedargs = [
u'-config',
u'"{}"'.format(constants.exiftool_config)
]
ExifTool(executable_=get_exiftool(), addedargs=exiftool_addedargs).start()
def teardown_module():
ExifTool().terminate

View File

@ -1,208 +0,0 @@
# -*- coding: utf-8
# Project imports
import os
import sys
import shutil
import tempfile
import time
from datetime import datetime
sys.path.insert(0, os.path.abspath(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))))
import helper
from elodie.media.media import Media
from elodie.media.video import Video
from elodie.media.audio import Audio
from elodie.external.pyexiftool import ExifTool
from elodie.dependencies import get_exiftool
from elodie import constants
os.environ['TZ'] = 'GMT'
def setup_module():
exiftool_addedargs = [
u'-config',
u'"{}"'.format(constants.exiftool_config)
]
ExifTool(executable_=get_exiftool(), addedargs=exiftool_addedargs).start()
def teardown_module():
ExifTool().terminate
def test_audio_extensions():
audio = Audio()
extensions = audio.extensions
assert 'm4a' in extensions
valid_extensions = Audio.get_valid_extensions()
assert extensions == valid_extensions, valid_extensions
def test_get_coordinate():
audio = Audio(helper.get_file('audio.m4a'))
coordinate = audio.get_coordinate()
assert helper.isclose(coordinate, 29.758938), coordinate
def test_get_camera_make():
audio = Audio(helper.get_file('audio.m4a'))
coordinate = audio.get_camera_make()
assert coordinate is None, coordinate
def test_get_camera_model():
audio = Audio(helper.get_file('audio.m4a'))
coordinate = audio.get_camera_model()
assert coordinate is None, coordinate
def test_get_coordinate_latitude():
audio = Audio(helper.get_file('audio.m4a'))
coordinate = audio.get_coordinate('latitude')
assert helper.isclose(coordinate, 29.758938), coordinate
def test_get_coordinate_longitude():
audio = Audio(helper.get_file('audio.m4a'))
coordinate = audio.get_coordinate('longitude')
assert helper.isclose(coordinate, -95.3677), coordinate
def test_get_date_original():
audio = Audio(helper.get_file('audio.m4a'))
date_created = audio.get_date_attribute(audio.date_original)
assert date_created.strftime('%Y-%m-%d %H:%M:%S') == '2016-01-03 21:23:39', date_created
def test_get_exiftool_attributes():
audio = Video(helper.get_file('audio.m4a'))
exif = audio.get_exiftool_attributes()
assert exif is not None, exif
assert exif is not False, exif
def test_is_valid():
audio = Audio(helper.get_file('audio.m4a'))
assert audio.is_valid()
def test_is_not_valid():
audio = Audio(helper.get_file('photo.png'))
assert not audio.is_valid()
def test_set_date_original():
temporary_folder, folder = helper.create_working_folder()
origin = '%s/audio.m4a' % folder
shutil.copyfile(helper.get_file('audio.m4a'), origin)
audio = Audio(origin)
date = datetime(2013, 9, 30, 7, 6, 5)
status = audio.set_date_original(date, origin)
assert status == True, status
audio_new = Audio(origin)
metadata = audio_new.get_metadata(update_cache=True)
date_original = metadata['date_original']
shutil.rmtree(folder)
assert date_original == date, date_original
def test_set_location():
temporary_folder, folder = helper.create_working_folder()
origin = '%s/audio.m4a' % folder
shutil.copyfile(helper.get_file('audio.m4a'), origin)
audio = Audio(origin)
origin_metadata = audio.get_metadata()
# Verify that original audio has different location info that what we
# will be setting and checking
assert not helper.isclose(origin_metadata['latitude'], 11.1111111111), origin_metadata['latitude']
assert not helper.isclose(origin_metadata['longitude'], 99.9999999999), origin_metadata['longitude']
status = audio.set_location(11.1111111111, 99.9999999999, origin)
assert status == True, status
audio_new = Audio(origin)
metadata = audio_new.get_metadata(update_cache=True)
shutil.rmtree(folder)
assert helper.isclose(metadata['latitude'], 11.1111111111), metadata['latitude']
assert helper.isclose(metadata['longitude'], 99.9999999999), metadata['longitude']
def test_set_location_minus():
temporary_folder, folder = helper.create_working_folder()
origin = '%s/audio.m4a' % folder
shutil.copyfile(helper.get_file('audio.m4a'), origin)
audio = Audio(origin)
origin_metadata = audio.get_metadata()
# Verify that original audio has different location info that what we
# will be setting and checking
assert not helper.isclose(origin_metadata['latitude'], 11.111111), origin_metadata['latitude']
assert not helper.isclose(origin_metadata['longitude'], 99.999999), origin_metadata['longitude']
status = audio.set_location(-11.111111, -99.999999, origin)
assert status == True, status
audio_new = Audio(origin)
metadata = audio_new.get_metadata(update_cache=True)
shutil.rmtree(folder)
assert helper.isclose(metadata['latitude'], -11.111111), metadata['latitude']
assert helper.isclose(metadata['longitude'], -99.999999), metadata['longitude']
def test_set_title():
temporary_folder, folder = helper.create_working_folder()
origin = '%s/audio.m4a' % folder
shutil.copyfile(helper.get_file('audio.m4a'), origin)
audio = Audio(origin)
origin_metadata = audio.get_metadata()
status = audio.set_title('my audio title', origin)
assert status == True, status
audio_new = Audio(origin)
metadata = audio_new.get_metadata()
shutil.rmtree(folder)
assert metadata['title'] == 'my audio title', metadata['title']
def test_set_title_non_ascii():
temporary_folder, folder = helper.create_working_folder()
origin = '%s/audio.m4a' % folder
shutil.copyfile(helper.get_file('audio.m4a'), origin)
audio = Audio(origin)
origin_metadata = audio.get_metadata()
unicode_title = u'形声字 / 形聲字'
status = audio.set_title(unicode_title, origin)
assert status == True, status
audio_new = Audio(origin)
metadata = audio_new.get_metadata(update_cache=True)
shutil.rmtree(folder)
assert metadata['title'] == unicode_title, metadata['title']

View File

@ -1,271 +0,0 @@
# Project imports
import os
import sys
import hashlib
import random
import re
import shutil
import string
import tempfile
import time
import unittest
sys.path.insert(0, os.path.abspath(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))))
import helper
from elodie.media.media import Media, get_all_subclasses
from elodie.media.audio import Audio
from elodie.media.photo import Photo
from elodie.media.video import Video
os.environ['TZ'] = 'GMT'
setup_module = helper.setup_module
teardown_module = helper.teardown_module
def test_get_all_subclasses():
subclasses = get_all_subclasses(Media)
expected = {Media, Photo, Video, Audio}
assert subclasses == expected, subclasses
# def test_get_media_class(_file):
# pass
def test_get_class_by_file_without_extension():
base_file = helper.get_file('withoutextension')
cls = Media.get_class_by_file(base_file, [Audio, Photo, Video])
assert cls is not None, cls
def test_get_exiftool_attribute():
file_path = helper.get_file('invalid.jpg')
ignore_tags = ('File:FileModifyDate', 'File:FileAccessDate')
media = Media.get_class_by_file(file_path, [Photo], ignore_tags)
exif = media.get_exiftool_attributes()
for tag in ignore_tags:
assert tag not in exif
def test_get_original_name():
temporary_folder, folder = helper.create_working_folder()
origin = '%s/%s' % (folder, 'with-original-name.jpg')
file = helper.get_file('with-original-name.jpg')
shutil.copyfile(file, origin)
media = Media.get_class_by_file(origin, [Photo])
original_name = media.get_original_name()
assert original_name == 'originalfilename.jpg', original_name
def test_get_original_name_invalid_file():
temporary_folder, folder = helper.create_working_folder()
origin = '%s/%s' % (folder, 'invalid.jpg')
file = helper.get_file('invalid.jpg')
shutil.copyfile(file, origin)
media = Media.get_class_by_file(origin, [Photo])
original_name = media.get_original_name()
assert original_name is None, original_name
def test_set_album_from_folder_invalid_file():
temporary_folder, folder = helper.create_working_folder()
base_file = helper.get_file('invalid.jpg')
origin = '%s/invalid.jpg' % folder
shutil.copyfile(base_file, origin)
media = Media(origin)
status = media.set_album_from_folder(origin)
assert status == False, status
def test_set_album_from_folder():
temporary_folder, folder = helper.create_working_folder()
origin = '%s/photo.jpg' % folder
shutil.copyfile(helper.get_file('plain.jpg'), origin)
media = Media(origin)
metadata = media.get_metadata()
assert metadata['album'] is None, metadata['album']
new_album_name = os.path.split(folder)[1]
status = media.set_album_from_folder(origin)
assert status == True, status
media_new = Media(origin)
metadata_new = media_new.get_metadata(update_cache=True)
shutil.rmtree(folder)
assert metadata_new['album'] == new_album_name, metadata_new['album']
def test_set_metadata():
temporary_folder, folder = helper.create_working_folder()
origin = '%s/photo.jpg' % folder
shutil.copyfile(helper.get_file('plain.jpg'), origin)
media = Media(origin)
metadata = media.get_metadata()
assert metadata['title'] == None, metadata['title']
new_title = 'Some Title'
media.set_metadata(title = new_title)
new_metadata = media.get_metadata()
assert new_metadata['title'] == new_title, new_metadata['title']
def test_set_metadata_basename():
temporary_folder, folder = helper.create_working_folder()
origin = '%s/photo.jpg' % folder
shutil.copyfile(helper.get_file('plain.jpg'), origin)
media = Media(origin)
metadata = media.get_metadata()
assert metadata['base_name'] == 'photo', metadata['base_name']
new_basename = 'Some Base Name'
media.set_metadata_basename(new_basename)
new_metadata = media.get_metadata()
assert new_metadata['base_name'] == new_basename, new_metadata['base_name']
def test_get_file_path():
media = Media(helper.get_file('plain.jpg'))
path = media.get_file_path()
assert 'plain.jpg' in path, path
def test_get_class_by_file_photo():
media = Media.get_class_by_file(helper.get_file('plain.jpg'), [Photo, Video])
assert media.__name__ == 'Photo'
def test_get_class_by_file_video():
media = Media.get_class_by_file(helper.get_file('video.mov'), [Photo, Video])
assert media.__name__ == 'Video'
def test_get_class_by_file_unsupported():
media = Media.get_class_by_file(helper.get_file('text.txt'), [Photo, Video])
assert media is not None, media
def test_get_class_by_file_ds_store():
media = Media.get_class_by_file(helper.get_file('.DS_Store'),
[Photo, Video, Audio])
assert media is None, media
def test_get_class_by_file_invalid_type():
media = Media.get_class_by_file(None,
[Photo, Video, Audio])
assert media is None
media = Media.get_class_by_file(False,
[Photo, Video, Audio])
assert media is None
media = Media.get_class_by_file(True,
[Photo, Video, Audio])
assert media is None
def test_set_original_name_when_exists():
temporary_folder, folder = helper.create_working_folder()
origin = '%s/%s' % (folder, 'with-original-name.jpg')
file = helper.get_file('with-original-name.jpg')
shutil.copyfile(file, origin)
media = Media.get_class_by_file(origin, [Photo])
result = media.set_original_name(origin)
assert result is None, result
def test_set_original_name_when_does_not_exist():
temporary_folder, folder = helper.create_working_folder()
origin = '%s/%s' % (folder, 'plain.jpg')
file = helper.get_file('plain.jpg')
shutil.copyfile(file, origin)
media = Media.get_class_by_file(origin, [Photo])
metadata_before = media.get_metadata()
result = media.set_original_name(origin)
metadata_after = media.get_metadata(update_cache=True)
assert metadata_before['original_name'] is None, metadata_before
assert metadata_after['original_name'] == 'plain.jpg', metadata_after
assert result is True, result
def test_set_original_name_with_arg():
temporary_folder, folder = helper.create_working_folder()
origin = '%s/%s' % (folder, 'plain.jpg')
file = helper.get_file('plain.jpg')
shutil.copyfile(file, origin)
new_name = helper.random_string(15)
media = Media.get_class_by_file(origin, [Photo])
metadata_before = media.get_metadata()
result = media.set_original_name(origin, name=new_name)
metadata_after = media.get_metadata(update_cache=True)
assert metadata_before['original_name'] is None, metadata_before
assert metadata_after['original_name'] == new_name, metadata_after
assert result is True, result
def test_set_original_name():
files = ['plain.jpg', 'audio.m4a', 'photo.nef', 'video.mov']
for file in files:
ext = os.path.splitext(file)[1]
temporary_folder, folder = helper.create_working_folder()
random_file_name = '%s%s' % (helper.random_string(10), ext)
origin = '%s/%s' % (folder, random_file_name)
file_path = helper.get_file(file)
if file_path is False:
file_path = helper.download_file(file, folder)
shutil.copyfile(file_path, origin)
media = Media.get_class_by_file(origin, [Audio, Photo, Video])
metadata = media.get_metadata()
media.set_original_name(origin)
metadata_updated = media.get_metadata(update_cache=True)
shutil.rmtree(folder)
assert metadata['original_name'] is None, metadata['original_name']
assert metadata_updated['original_name'] == random_file_name, metadata_updated['original_name']
def is_valid():
media = Media()
assert not media.is_valid()

View File

@ -1,403 +0,0 @@
# -*- coding: utf-8
# Project imports
import os
import sys
from datetime import datetime
import shutil
import tempfile
import time
from nose.plugins.skip import SkipTest
sys.path.insert(0, os.path.abspath(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))))
import helper
from elodie.media.media import Media
from elodie.media.photo import Photo
os.environ['TZ'] = 'GMT'
setup_module = helper.setup_module
teardown_module = helper.teardown_module
def test_photo_extensions():
photo = Photo()
extensions = photo.extensions
assert 'arw' in extensions
assert 'cr2' in extensions
assert 'dng' in extensions
assert 'gif' in extensions
assert 'heic' in extensions
assert 'jpg' in extensions
assert 'jpeg' in extensions
assert 'nef' in extensions
assert 'png' in extensions
assert 'rw2' in extensions
valid_extensions = Photo.get_valid_extensions()
assert extensions == valid_extensions, valid_extensions
def test_empty_album():
photo = Photo(helper.get_file('plain.jpg'))
assert photo.get_album() is None
def test_has_album():
photo = Photo(helper.get_file('with-album.jpg'))
album = photo.get_album()
assert album == 'Test Album', album
def test_is_valid():
photo = Photo(helper.get_file('plain.jpg'))
assert photo.is_valid()
def test_is_not_valid():
photo = Photo(helper.get_file('video.mov'))
assert not photo.is_valid()
def test_get_metadata_of_invalid_photo():
photo = Photo(helper.get_file('invalid.jpg'))
metadata = photo.get_metadata()
assert metadata is None
def test_get_coordinate_default():
photo = Photo(helper.get_file('with-location.jpg'))
coordinate = photo.get_coordinate()
assert helper.isclose(coordinate,37.3667027222), coordinate
def test_get_coordinate_latitude():
photo = Photo(helper.get_file('with-location.jpg'))
coordinate = photo.get_coordinate('latitude')
assert helper.isclose(coordinate,37.3667027222), coordinate
def test_get_coordinate_latitude_minus():
photo = Photo(helper.get_file('with-location-inv.jpg'))
coordinate = photo.get_coordinate('latitude')
assert helper.isclose(coordinate,-37.3667027222), coordinate
def test_get_coordinate_longitude():
photo = Photo(helper.get_file('with-location.jpg'))
coordinate = photo.get_coordinate('longitude')
assert helper.isclose(coordinate,-122.033383611), coordinate
def test_get_coordinate_longitude_plus():
photo = Photo(helper.get_file('with-location-inv.jpg'))
coordinate = photo.get_coordinate('longitude')
assert helper.isclose(coordinate,122.033383611), coordinate
def test_get_coordinates_without_exif():
photo = Photo(helper.get_file('no-exif.jpg'))
latitude = photo.get_coordinate('latitude')
longitude = photo.get_coordinate('longitude')
assert latitude is None, latitude
assert longitude is None, longitude
def test_get_coordinates_with_zero_coordinate():
photo = Photo(helper.get_file('with-location-zero-coordinate.jpg'))
latitude = photo.get_coordinate('latitude')
longitude = photo.get_coordinate('longitude')
assert helper.isclose(latitude,51.55325), latitude
assert helper.isclose(longitude,-0.00417777777778), longitude
def test_get_coordinates_with_null_coordinate():
photo = Photo(helper.get_file('with-null-coordinates.jpg'))
latitude = photo.get_coordinate('latitude')
longitude = photo.get_coordinate('longitude')
assert latitude is None, latitude
assert longitude is None, longitude
def test_get_date_original():
photo = Photo(helper.get_file('plain.jpg'))
date_original = photo.get_date_attribute(['EXIF:DateTimeOriginal'])
#assert date_original == (2015, 12, 5, 0, 59, 26, 5, 339, 0), date_original
assert date_original == datetime(2015, 12, 5, 0, 59, 26), date_original
def test_get_camera_make():
photo = Photo(helper.get_file('with-location.jpg'))
make = photo.get_camera_make()
assert make == 'Canon', make
def test_get_camera_make_not_set():
photo = Photo(helper.get_file('no-exif.jpg'))
make = photo.get_camera_make()
assert make is None, make
def test_get_camera_model():
photo = Photo(helper.get_file('with-location.jpg'))
model = photo.get_camera_model()
assert model == 'Canon EOS REBEL T2i', model
def test_get_camera_model_not_set():
photo = Photo(helper.get_file('no-exif.jpg'))
model = photo.get_camera_model()
assert model is None, model
def test_is_valid_fallback_using_pillow():
photo = Photo(helper.get_file('imghdr-error.jpg'))
assert photo.is_valid()
def test_pillow_not_loaded():
photo = Photo(helper.get_file('imghdr-error.jpg'))
photo.pillow = None
assert photo.is_valid() == False
def test_set_album():
temporary_folder, folder = helper.create_working_folder()
origin = '%s/photo.jpg' % folder
shutil.copyfile(helper.get_file('plain.jpg'), origin)
photo = Photo(origin)
metadata = photo.get_metadata()
assert metadata['album'] is None, metadata['album']
status = photo.set_album('Test Album', origin)
assert status == True, status
photo_new = Photo(origin)
metadata_new = photo_new.get_metadata(update_cache=True)
shutil.rmtree(folder)
assert metadata_new['album'] == 'Test Album', metadata_new['album']
def test_set_date_original_with_missing_datetimeoriginal():
# When datetimeoriginal (or other key) is missing we have to add it gh-74
# https://github.com/jmathai/elodie/issues/74
temporary_folder, folder = helper.create_working_folder()
origin = '%s/photo.jpg' % folder
shutil.copyfile(helper.get_file('no-exif.jpg'), origin)
photo = Photo(origin)
time = datetime(2013, 9, 30, 7, 6, 5)
status = photo.set_date_original(time, origin)
assert status == True, status
photo_new = Photo(origin)
metadata = photo_new.get_metadata(update_cache=True)
date_original = metadata['date_original']
shutil.rmtree(folder)
#assert date_original == (2013, 9, 30, 7, 6, 5, 0, 273, 0), metadata['date_original']
# assert date_original == helper.time_convert((2013, 9, 30, 7, 6, 5, 0, 273, 0)), metadata['date_original']
assert date_original == time, metadata['date_original']
def test_set_date_original():
temporary_folder, folder = helper.create_working_folder()
origin = '%s/photo.jpg' % folder
shutil.copyfile(helper.get_file('plain.jpg'), origin)
photo = Photo(origin)
status = photo.set_date_original(datetime(2013, 9, 30, 7, 6, 5), origin)
assert status == True, status
photo_new = Photo(origin)
metadata = photo_new.get_metadata(update_cache=True)
date_original = metadata['date_original']
shutil.rmtree(folder)
#assert date_original == (2013, 9, 30, 7, 6, 5, 0, 273, 0), metadata['date_original']
assert date_original == datetime(2013, 9, 30, 7, 6, 5), metadata['date_original']
def test_set_location():
temporary_folder, folder = helper.create_working_folder()
origin = '%s/photo.jpg' % folder
shutil.copyfile(helper.get_file('plain.jpg'), origin)
photo = Photo(origin)
origin_metadata = photo.get_metadata()
# Verify that original photo has different location info that what we
# will be setting and checking
assert not helper.isclose(origin_metadata['latitude'], 11.1111111111), origin_metadata['latitude']
assert not helper.isclose(origin_metadata['longitude'], 99.9999999999), origin_metadata['longitude']
status = photo.set_location(11.1111111111, 99.9999999999, origin)
assert status == True, status
photo_new = Photo(origin)
metadata = photo_new.get_metadata(update_cache=True)
shutil.rmtree(folder)
assert helper.isclose(metadata['latitude'], 11.1111111111), metadata['latitude']
assert helper.isclose(metadata['longitude'], 99.9999999999), metadata['longitude']
def test_set_location_minus():
temporary_folder, folder = helper.create_working_folder()
origin = '%s/photo.jpg' % folder
shutil.copyfile(helper.get_file('plain.jpg'), origin)
photo = Photo(origin)
origin_metadata = photo.get_metadata()
# Verify that original photo has different location info that what we
# will be setting and checking
assert not helper.isclose(origin_metadata['latitude'], 11.1111111111), origin_metadata['latitude']
assert not helper.isclose(origin_metadata['longitude'], 99.9999999999), origin_metadata['longitude']
status = photo.set_location(-11.1111111111, -99.9999999999, origin)
assert status == True, status
photo_new = Photo(origin)
metadata = photo_new.get_metadata(update_cache=True)
shutil.rmtree(folder)
assert helper.isclose(metadata['latitude'], -11.1111111111), metadata['latitude']
assert helper.isclose(metadata['longitude'], -99.9999999999), metadata['longitude']
def test_set_title():
temporary_folder, folder = helper.create_working_folder()
origin = '%s/photo.jpg' % folder
shutil.copyfile(helper.get_file('plain.jpg'), origin)
photo = Photo(origin)
origin_metadata = photo.get_metadata()
status = photo.set_title('my photo title', origin)
assert status == True, status
photo_new = Photo(origin)
metadata = photo_new.get_metadata(update_cache=True)
shutil.rmtree(folder)
assert metadata['title'] == 'my photo title', metadata['title']
def test_set_title_non_ascii():
temporary_folder, folder = helper.create_working_folder()
origin = '%s/photo.jpg' % folder
shutil.copyfile(helper.get_file('plain.jpg'), origin)
photo = Photo(origin)
origin_metadata = photo.get_metadata()
unicode_title = u'形声字 / 形聲字'
status = photo.set_title(unicode_title, origin)
assert status == True, status
photo_new = Photo(origin)
metadata = photo_new.get_metadata(update_cache=True)
shutil.rmtree(folder)
assert metadata['title'] == unicode_title, metadata['title']
# This is a test generator that will test reading and writing to
# various RAW formats. Each sample file has a different date which
# is the only information which needs to be added to run the tests
# for that file type.
# https://nose.readthedocs.io/en/latest/writing_tests.html#test-generators
def test_various_types():
types = Photo.extensions
#extensions = ('arw', 'cr2', 'dng', 'gif', 'jpeg', 'jpg', 'nef', 'rw2')
dates = {
'arw': datetime(2007, 4, 8, 17, 41, 18),
'cr2': datetime(2005, 10, 29, 16, 14, 44),
'dng': datetime(2009, 10, 20, 9, 10, 46),
'heic': datetime(2019, 5, 26, 10, 33, 20),
'nef': datetime(2008, 10, 24, 9, 12, 56),
'png': datetime(2015, 1, 18, 12, 1, 1),
'rw2': datetime(2014, 11, 19, 23, 7, 44)
}
for type in types:
if type in dates:
yield (_test_photo_type_get, type, dates[type])
yield (_test_photo_type_set, type, dates[type])
def _test_photo_type_get(type, date):
temporary_folder, folder = helper.create_working_folder()
photo_name = 'photo.{}'.format(type)
photo_file = helper.get_file(photo_name)
origin = '{}/{}'.format(folder, photo_name)
if not photo_file:
photo_file = helper.download_file(photo_name, folder)
if not photo_file or not os.path.isfile(photo_file):
raise SkipTest('{} file not downloaded'.format(type))
# downloading for each test is costly so we save it in the working directory
file_path_save_as = helper.get_file_path(photo_name)
if os.path.isfile(photo_file):
shutil.copyfile(photo_file, file_path_save_as)
shutil.copyfile(photo_file, origin)
photo = Photo(origin)
metadata = photo.get_metadata()
shutil.rmtree(folder)
assert metadata['date_original'] == date, metadata['date_original']
def _test_photo_type_set(type, date):
temporary_folder, folder = helper.create_working_folder()
photo_name = 'photo.{}'.format(type)
photo_file = helper.get_file(photo_name)
origin = '{}/{}'.format(folder, photo_name)
if not photo_file:
photo_file = helper.download_file(photo_name, folder)
if not photo_file or not os.path.isfile(photo_file):
raise SkipTest('{} file not downloaded'.format(type))
shutil.copyfile(photo_file, origin)
photo = Photo(origin)
origin_metadata = photo.get_metadata()
status = photo.set_location(11.1111111111, 99.9999999999, origin)
assert status == True, status
photo_new = Photo(origin)
metadata = photo_new.get_metadata(update_cache=True)
shutil.rmtree(folder)
assert metadata['date_original'] == date, metadata['date_original']
assert helper.isclose(metadata['latitude'], 11.1111111111), '{} lat {}'.format(type, metadata['latitude'])
assert helper.isclose(metadata['longitude'], 99.9999999999), '{} lon {}'.format(type, metadata['latitude'])

View File

@ -1,200 +0,0 @@
# -*- coding: utf-8
# Project imports
import os
import sys
import shutil
import tempfile
import time
from datetime import datetime
from dateutil.parser import parse
sys.path.insert(0, os.path.abspath(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))))
import helper
from elodie.media.media import Media
from elodie.media.video import Video
os.environ['TZ'] = 'GMT'
def test_video_extensions():
video = Video()
extensions = video.extensions
assert 'avi' in extensions
assert 'm4v' in extensions
assert 'mov' in extensions
assert 'm4v' in extensions
assert '3gp' in extensions
valid_extensions = Video.get_valid_extensions()
assert extensions == valid_extensions, valid_extensions
def test_empty_album():
video = Video(helper.get_file('video.mov'))
assert video.get_album() is None
def test_get_camera_make():
video = Video(helper.get_file('video.mov'))
print(video.get_metadata())
make = video.get_camera_make()
assert make == 'Apple', make
def test_get_camera_model():
video = Video(helper.get_file('video.mov'))
model = video.get_camera_model()
assert model == 'iPhone 5', model
def test_get_coordinate():
video = Video(helper.get_file('video.mov'))
coordinate = video.get_coordinate()
assert coordinate == 38.1893, coordinate
def test_get_coordinate_latitude():
video = Video(helper.get_file('video.mov'))
coordinate = video.get_coordinate('latitude')
assert coordinate == 38.1893, coordinate
def test_get_coordinate_longitude():
video = Video(helper.get_file('video.mov'))
coordinate = video.get_coordinate('longitude')
assert coordinate == -119.9558, coordinate
def test_get_date_original():
media = Media(helper.get_file('video.mov'))
date_original = media.get_date_attribute(['QuickTime:ContentCreateDate'])
date = parse('2015-01-19 12:45:11-08:00')
assert date_original == date, date_original
def test_get_exiftool_attributes():
video = Video(helper.get_file('video.mov'))
exif = video.get_exiftool_attributes()
assert exif is not None, exif
assert exif is not False, exif
def test_is_valid():
video = Video(helper.get_file('video.mov'))
assert video.is_valid()
def test_is_not_valid():
video = Video(helper.get_file('photo.png'))
assert not video.is_valid()
def test_set_album():
temporary_folder, folder = helper.create_working_folder()
origin = '%s/video.mov' % folder
shutil.copyfile(helper.get_file('video.mov'), origin)
video = Video(origin)
metadata = video.get_metadata()
assert metadata['album'] is None, metadata['album']
status = video.set_album('Test Album', origin)
assert status == True, status
video_new = Video(origin)
metadata_new = video_new.get_metadata()
shutil.rmtree(folder)
assert metadata_new['album'] == 'Test Album', metadata_new['album']
def test_set_date_original():
temporary_folder, folder = helper.create_working_folder()
origin = '%s/video.mov' % folder
shutil.copyfile(helper.get_file('video.mov'), origin)
media = Media(origin)
status = media.set_date_original(datetime(2013, 9, 30, 7, 6, 5), origin)
assert status == True, status
media_new = Media(origin)
metadata = media_new.get_metadata()
date_original = metadata['date_original']
shutil.rmtree(folder)
assert date_original == datetime(2013, 9, 30, 7, 6, 5), metadata['date_original']
temporary_folder, folder = helper.create_working_folder()
origin = '%s/video.mov' % folder
shutil.copyfile(helper.get_file('video.mov'), origin)
video = Video(origin)
origin_metadata = video.get_metadata()
# Verify that original video has different location info that what we
# will be setting and checking
assert not helper.isclose(origin_metadata['latitude'], 11.1111111111), origin_metadata['latitude']
assert not helper.isclose(origin_metadata['longitude'], 99.9999999999), origin_metadata['longitude']
status = video.set_location(11.1111111111, 99.9999999999, origin)
assert status == True, status
video_new = Video(origin)
metadata = video_new.get_metadata()
shutil.rmtree(folder)
assert helper.isclose(metadata['latitude'], 11.1111111111), metadata['latitude']
assert helper.isclose(metadata['longitude'], 99.9999999999), metadata['longitude']
def test_set_title():
temporary_folder, folder = helper.create_working_folder()
origin = '%s/video.mov' % folder
shutil.copyfile(helper.get_file('video.mov'), origin)
video = Video(origin)
origin_metadata = video.get_metadata()
status = video.set_title('my video title', origin)
assert status == True, status
video_new = Video(origin)
metadata = video_new.get_metadata()
shutil.rmtree(folder)
assert metadata['title'] == 'my video title', metadata['title']
def test_set_title_non_ascii():
temporary_folder, folder = helper.create_working_folder()
origin = '%s/video.mov' % folder
shutil.copyfile(helper.get_file('video.mov'), origin)
video = Video(origin)
origin_metadata = video.get_metadata()
unicode_title = u'形声字 / 形聲字'
status = video.set_title(unicode_title, origin)
assert status == True, status
video_new = Video(origin)
metadata = video_new.get_metadata()
shutil.rmtree(folder)
assert metadata['title'] == unicode_title, metadata['title']

View File

@ -1,189 +0,0 @@
# Project imports
import mock
import os
import sys
from tempfile import gettempdir
sys.path.insert(0, os.path.abspath(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__)))))
import helper
from elodie.config import load_config
from elodie.plugins.googlephotos.googlephotos import GooglePhotos
from elodie.media.audio import Audio
from elodie.media.photo import Photo
# Globals to simplify mocking configs
auth_file = helper.get_file('plugins/googlephotos/auth_file.json')
secrets_file = helper.get_file('plugins/googlephotos/secrets_file.json')
config_string = """
[Plugins]
plugins=GooglePhotos
[PluginGooglePhotos]
auth_file={}
secrets_file={}
"""
config_string_fmt = config_string.format(
auth_file,
secrets_file
)
setup_module = helper.setup_module
teardown_module = helper.teardown_module
@mock.patch('elodie.constants.CONFIG_FILE', '%s/config.ini-googlephotos-set-session' % gettempdir())
def test_googlephotos_set_session():
with open('%s/config.ini-googlephotos-set-session' % gettempdir(), 'w') as f:
f.write(config_string_fmt)
if hasattr(load_config, 'config'):
del load_config.config
gp = GooglePhotos()
if hasattr(load_config, 'config'):
del load_config.config
assert gp.session is None, gp.session
gp.set_session()
assert gp.session is not None, gp.session
@mock.patch('elodie.constants.CONFIG_FILE', '%s/config.ini-googlephotos-after-supported' % gettempdir())
def test_googlephotos_after_supported():
with open('%s/config.ini-googlephotos-after-supported' % gettempdir(), 'w') as f:
f.write(config_string_fmt)
if hasattr(load_config, 'config'):
del load_config.config
sample_photo = Photo(helper.get_file('plain.jpg'))
sample_metadata = sample_photo.get_metadata()
sample_metadata['original_name'] = 'foobar'
final_file_path = helper.get_file('plain.jpg')
gp = GooglePhotos()
gp.after('', '', final_file_path, sample_metadata)
db_row = gp.db.get(final_file_path)
if hasattr(load_config, 'config'):
del load_config.config
assert db_row == 'foobar', db_row
@mock.patch('elodie.constants.CONFIG_FILE', '%s/config.ini-googlephotos-after-unsupported' % gettempdir())
def test_googlephotos_after_unsupported():
with open('%s/config.ini-googlephotos-after-unsupported' % gettempdir(), 'w') as f:
f.write(config_string_fmt)
if hasattr(load_config, 'config'):
del load_config.config
final_file_path = helper.get_file('audio.m4a')
sample_photo = Audio(final_file_path)
sample_metadata = sample_photo.get_metadata()
sample_metadata['original_name'] = 'foobar'
gp = GooglePhotos()
gp.after('', '', final_file_path, sample_metadata)
db_row = gp.db.get(final_file_path)
if hasattr(load_config, 'config'):
del load_config.config
assert db_row == None, db_row
@mock.patch('elodie.constants.CONFIG_FILE', '%s/config.ini-googlephotos-upload' % gettempdir())
def test_googlephotos_upload():
with open('%s/config.ini-googlephotos-upload' % gettempdir(), 'w') as f:
f.write(config_string_fmt)
if hasattr(load_config, 'config'):
del load_config.config
gp = GooglePhotos()
if hasattr(load_config, 'config'):
del load_config.config
gp.set_session()
status = gp.upload(helper.get_file('plain.jpg'))
assert status is not None, status
@mock.patch('elodie.constants.CONFIG_FILE', '%s/config.ini-googlephotos-upload-session-fail' % gettempdir())
def test_googlephotos_upload_session_fail():
with open('%s/config.ini-googlephotos-upload-session-fail' % gettempdir(), 'w') as f:
f.write(config_string)
if hasattr(load_config, 'config'):
del load_config.config
gp = GooglePhotos()
if hasattr(load_config, 'config'):
del load_config.config
gp.set_session()
status = gp.upload(helper.get_file('plain.jpg'))
assert status is None, status
@mock.patch('elodie.constants.CONFIG_FILE', '%s/config.ini-googlephotos-upload-invalid-empty' % gettempdir())
def test_googlephotos_upload_invalid_empty():
with open('%s/config.ini-googlephotos-upload-invalid-empty' % gettempdir(), 'w') as f:
f.write(config_string_fmt)
if hasattr(load_config, 'config'):
del load_config.config
gp = GooglePhotos()
if hasattr(load_config, 'config'):
del load_config.config
gp.set_session()
status = gp.upload(helper.get_file('invalid.jpg'))
assert status is None, status
@mock.patch('elodie.constants.CONFIG_FILE', '%s/config.ini-googlephotos-upload-dne' % gettempdir())
def test_googlephotos_upload_dne():
with open('%s/config.ini-googlephotos-upload-dne' % gettempdir(), 'w') as f:
f.write(config_string_fmt)
if hasattr(load_config, 'config'):
del load_config.config
gp = GooglePhotos()
if hasattr(load_config, 'config'):
del load_config.config
gp.set_session()
status = gp.upload('/file/does/not/exist')
assert status is None, status
@mock.patch('elodie.constants.CONFIG_FILE', '%s/config.ini-googlephotos-batch' % gettempdir())
def test_googlephotos_batch():
with open('%s/config.ini-googlephotos-batch' % gettempdir(), 'w') as f:
f.write(config_string_fmt)
if hasattr(load_config, 'config'):
del load_config.config
sample_photo = Photo(helper.get_file('plain.jpg'))
sample_metadata = sample_photo.get_metadata()
sample_metadata['original_name'] = 'foobar'
final_file_path = helper.get_file('plain.jpg')
gp = GooglePhotos()
gp.after('', '', final_file_path, sample_metadata)
db_row = gp.db.get(final_file_path)
assert db_row == 'foobar', db_row
status, count = gp.batch()
db_row_after = gp.db.get(final_file_path)
assert status == True, status
assert count == 1, count
assert db_row_after is None, db_row_after
if hasattr(load_config, 'config'):
del load_config.config
gp.set_session()
status = gp.upload(helper.get_file('invalid.jpg'))
assert status is None, status

View File

@ -1,4 +0,0 @@
-r ../../requirements.txt
flake8==2.6.2
mock==1.3.0
nose==1.3.7

View File

@ -1,128 +0,0 @@
# Project imports
import os
import sys
import unittest
from mock import patch
from tempfile import gettempdir
from elodie import constants
from elodie.config import load_config, load_plugin_config
@patch('elodie.constants.CONFIG_FILE', '%s/config.ini-singleton-success' % gettempdir())
def test_load_config_singleton_success():
with open('%s/config.ini-singleton-success' % gettempdir(), 'w') as f:
f.write("""
[Geolocation]
mapquest_key=your-api-key-goes-here
prefer_english_names=False
""")
if hasattr(load_config, 'config'):
del load_config.config
config = load_config(constants.CONFIG_FILE)
assert config['Geolocation']['mapquest_key'] == 'your-api-key-goes-here', config.get('Geolocation', 'mapquest_key')
config.set('Geolocation', 'mapquest_key', 'new-value')
config = load_config(constants.CONFIG_FILE)
if hasattr(load_config, 'config'):
del load_config.config
assert config['Geolocation']['mapquest_key'] == 'new-value', config.get('Geolocation', 'mapquest_key')
@patch('elodie.constants.CONFIG_FILE', '%s/config.ini-does-not-exist' % gettempdir())
def test_load_config_singleton_no_file():
if hasattr(load_config, 'config'):
del load_config.config
config = load_config(constants.CONFIG_FILE)
if hasattr(load_config, 'config'):
del load_config.config
assert config == {}, config
@patch('elodie.constants.CONFIG_FILE', '%s/config.ini-load-plugin-config-unset-backwards-compat' % gettempdir())
def test_load_plugin_config_unset_backwards_compat():
with open('%s/config.ini-load-plugin-config-unset-backwards-compat' % gettempdir(), 'w') as f:
f.write("""
""")
if hasattr(load_config, 'config'):
del load_config.config
plugins = load_plugin_config(constants.CONFIG_FILE)
if hasattr(load_config, 'config'):
del load_config.config
assert plugins == [], plugins
@patch('elodie.constants.CONFIG_FILE', '%s/config.ini-load-plugin-config-exists-not-set' % gettempdir())
def test_load_plugin_config_exists_not_set():
with open('%s/config.ini-load-plugin-config-exists-not-set' % gettempdir(), 'w') as f:
f.write("""
[Plugins]
""")
if hasattr(load_config, 'config'):
del load_config.config
plugins = load_plugin_config(constants.CONFIG_FILE)
if hasattr(load_config, 'config'):
del load_config.config
assert plugins == [], plugins
@patch('elodie.constants.CONFIG_FILE', '%s/config.ini-load-plugin-config-one' % gettempdir())
def test_load_plugin_config_one():
with open('%s/config.ini-load-plugin-config-one' % gettempdir(), 'w') as f:
f.write("""
[Plugins]
plugins=Dummy
""")
if hasattr(load_config, 'config'):
del load_config.config
plugins = load_plugin_config(constants.CONFIG_FILE)
if hasattr(load_config, 'config'):
del load_config.config
assert plugins == ['Dummy'], plugins
@patch('elodie.constants.CONFIG_FILE', '%s/config.ini-load-plugin-config-one-with-invalid' % gettempdir())
def test_load_plugin_config_one_with_invalid():
with open('%s/config.ini-load-plugin-config-one' % gettempdir(), 'w') as f:
f.write("""
[Plugins]
plugins=DNE
""")
if hasattr(load_config, 'config'):
del load_config.config
plugins = load_plugin_config(constants.CONFIG_FILE)
if hasattr(load_config, 'config'):
del load_config.config
assert plugins == [], plugins
@patch('elodie.constants.CONFIG_FILE', '%s/config.ini-load-plugin-config-many' % gettempdir())
def test_load_plugin_config_many():
with open('%s/config.ini-load-plugin-config-many' % gettempdir(), 'w') as f:
f.write("""
[Plugins]
plugins=GooglePhotos,Dummy
""")
if hasattr(load_config, 'config'):
del load_config.config
plugins = load_plugin_config(constants.CONFIG_FILE)
if hasattr(load_config, 'config'):
del load_config.config
assert plugins == ['GooglePhotos','Dummy'], plugins

View File

@ -1,110 +0,0 @@
# Project imports
import os
import sys
import unittest
try:
reload # Python 2.7
except NameError:
try:
from importlib import reload # Python 3.4+
except ImportError:
from imp import reload # Python 3.0 - 3.3
from mock import patch
from elodie import constants
def test_debug():
# This seems pointless but on Travis we explicitly modify the file to be True
assert constants.debug == constants.debug, constants.debug
def test_application_directory_default():
if('ELODIE_APPLICATION_DIRECTORY' in os.environ):
del os.environ['ELODIE_APPLICATION_DIRECTORY']
reload(constants)
expected_path = '{}/.elodie'.format(os.path.expanduser('~'))
assert constants.application_directory == expected_path, constants.application_directory
def test_application_directory_override_invalid():
os.environ['ELODIE_APPLICATION_DIRECTORY'] = '/foo/bar'
reload(constants)
directory_to_check = constants.application_directory
# reset
if('ELODIE_APPLICATION_DIRECTORY' in os.environ):
del os.environ['ELODIE_APPLICATION_DIRECTORY']
reload(constants)
expected_path = '{}/.elodie'.format(os.path.expanduser('~'))
assert directory_to_check == expected_path, constants.application_directory
def test_application_directory_override_valid():
cwd = os.getcwd()
os.environ['ELODIE_APPLICATION_DIRECTORY'] = cwd
reload(constants)
directory_to_check = constants.application_directory
hash_db_to_check = os.path.join(cwd, constants.hash_db)
# reset
if('ELODIE_APPLICATION_DIRECTORY' in os.environ):
del os.environ['ELODIE_APPLICATION_DIRECTORY']
reload(constants)
assert directory_to_check == cwd, constants.application_directory
assert cwd in hash_db_to_check, hash_db_to_check
def test_hash_db():
assert constants.hash_db == os.path.split(constants.hash_db)[1]
def test_location_db():
assert constants.location_db == os.path.split(constants.location_db)[1]
def test_script_directory():
path = os.path.dirname(os.path.dirname(__file__))
assert path == constants.script_directory, constants.script_directory
def test_exiftool_config():
path = constants.script_directory
assert '{}/configs/ExifTool_config'.format(path) == constants.exiftool_config, constants.exiftool_config
def test_mapquest_base_url_default():
assert constants.mapquest_base_url == 'https://open.mapquestapi.com', constants.mapquest_base_url
def test_mapquest_base_url_override():
os.environ['ELODIE_MAPQUEST_BASE_URL'] = 'foobar'
reload(constants)
url_to_check = constants.mapquest_base_url
# reset
if('ELODIE_MAPQUEST_BASE_URL' in os.environ):
del os.environ['ELODIE_MAPQUEST_BASE_URL']
reload(constants)
assert url_to_check == 'foobar', constants.mapquest_base_url
def test_mapquest_key_default():
if('ELODIE_MAPQUEST_KEY' in os.environ):
os.environ['ELODIE_MAPQUEST_KEY'] = None
reload(constants)
assert constants.mapquest_key == None, constants.mapquest_key
def test_mapquest_key_override():
os.environ['ELODIE_MAPQUEST_KEY'] = 'foobar'
reload(constants)
key_to_check = constants.mapquest_key
# reset
if('ELODIE_MAPQUEST_KEY' in os.environ):
del os.environ['ELODIE_MAPQUEST_KEY']
reload(constants)
assert key_to_check == 'foobar', key_to_check
def test_accepted_language():
assert constants.accepted_language == 'en', constants.accepted_language
def test_python_version():
assert constants.python_version == sys.version_info.major, constants.python_version

View File

@ -1,18 +0,0 @@
import mock
from elodie.dependencies import get_exiftool
@mock.patch('elodie.dependencies.find_executable')
@mock.patch('elodie.dependencies.os')
def test_exiftool(mock_os, mock_find_executable):
mock_find_executable.return_value = '/path/to/exiftool'
assert get_exiftool() == '/path/to/exiftool'
mock_find_executable.return_value = None
mock_os.path.isfile.return_value = True
mock_os.path.access.return_value = True
assert get_exiftool() == '/usr/local/bin/exiftool'
mock_os.path.isfile.return_value = False
assert get_exiftool() is None

View File

@ -1,678 +0,0 @@
# Project imports
from imp import load_source
import mock
import os
import sys
import shutil
from click.testing import CliRunner
from nose.plugins.skip import SkipTest
from nose.tools import assert_raises
from six import text_type, unichr as six_unichr
from tempfile import gettempdir
from datetime import datetime
import unittest
import helper
elodie = load_source('elodie', os.path.abspath('{}/../elodie.py'.format(os.path.dirname(os.path.realpath(__file__)))))
from elodie.config import load_config
from elodie.localstorage import Db
from elodie.media.audio import Audio
from elodie.media.photo import Photo
from elodie.media.video import Video
from elodie.plugins.plugins import Plugins
from elodie.plugins.googlephotos.googlephotos import GooglePhotos
os.environ['TZ'] = 'GMT'
def test_import_file_audio():
temporary_folder, folder = helper.create_working_folder()
temporary_folder_destination, folder_destination = helper.create_working_folder()
origin = '%s/audio.m4a' % folder
shutil.copyfile(helper.get_file('audio.m4a'), origin)
db = Db(folder)
dest_path = elodie.import_file(origin, folder_destination, db, False,
'copy', False, False)
shutil.rmtree(folder)
shutil.rmtree(folder_destination)
assert helper.path_tz_fix(os.path.join('2016-01-Jan','Houston','2016-01-03_21-23-39-audio.m4a')) in dest_path, dest_path
def test_import_file_photo():
temporary_folder, folder = helper.create_working_folder()
temporary_folder_destination, folder_destination = helper.create_working_folder()
origin = '%s/plain.jpg' % folder
shutil.copyfile(helper.get_file('plain.jpg'), origin)
db = Db(folder)
dest_path = elodie.import_file(origin, folder_destination, db, False,
'copy', False, False)
shutil.rmtree(folder)
shutil.rmtree(folder_destination)
assert helper.path_tz_fix(os.path.join('2015-12-Dec','Unknown Location','2015-12-05_00-59-26-plain.jpg')) in dest_path, dest_path
def test_import_file_video():
temporary_folder, folder = helper.create_working_folder()
temporary_folder_destination, folder_destination = helper.create_working_folder()
origin = '%s/video.mov' % folder
shutil.copyfile(helper.get_file('video.mov'), origin)
db = Db(folder)
dest_path = elodie.import_file(origin, folder_destination, db, False,
'copy', False, False)
shutil.rmtree(folder)
shutil.rmtree(folder_destination)
assert helper.path_tz_fix(os.path.join('2015-01-Jan','California','2015-01-19_12-45-11-video.mov')) in dest_path, dest_path
def test_import_file_path_unicode_checkmark():
temporary_folder, folder = helper.create_working_folder()
temporary_folder_destination, folder_destination = helper.create_working_folder()
origin = text_type(folder)+u'/unicode\u2713filename.png'
shutil.copyfile(helper.get_file('photo.png'), origin)
db = Db(folder)
dest_path = elodie.import_file(origin, folder_destination, db, False,
'copy', False, False)
shutil.rmtree(folder)
shutil.rmtree(folder_destination)
assert helper.path_tz_fix(os.path.join('2015-01-Jan','Unknown Location',
u'2015-01-18_12-01-01-unicode\u2713filename.png')) in dest_path, dest_path
def test_import_file_path_unicode_latin_nbsp():
temporary_folder, folder = helper.create_working_folder()
temporary_folder_destination, folder_destination = helper.create_working_folder()
origin = text_type(folder)+u'/unicode'+six_unichr(160)+u'filename.png'
shutil.copyfile(helper.get_file('photo.png'), origin)
db = Db(folder)
dest_path = elodie.import_file(origin, folder_destination, db, False,
'copy', False, False)
shutil.rmtree(folder)
shutil.rmtree(folder_destination)
assert helper.path_tz_fix(os.path.join('2015-01-Jan','Unknown Location',
u'2015-01-18_12-01-01-unicode\xa0filename.png')) in dest_path, dest_path
def test_import_file_allow_duplicate_false():
temporary_folder, folder = helper.create_working_folder()
temporary_folder_destination, folder_destination = helper.create_working_folder()
origin = '%s/with-original-name.jpg' % folder
shutil.copyfile(helper.get_file('with-original-name.jpg'), origin)
db = Db(folder)
dest_path1 = elodie.import_file(origin, folder_destination, db, False,
'copy', False, False)
dest_path2 = elodie.import_file(origin, folder_destination, db, False,
'copy', False, False)
shutil.rmtree(folder)
shutil.rmtree(folder_destination)
assert dest_path1 is not None
assert dest_path2 is None
def test_import_file_allow_duplicate_true():
temporary_folder, folder = helper.create_working_folder()
temporary_folder_destination, folder_destination = helper.create_working_folder()
origin = '%s/with-original-name.jpg' % folder
shutil.copyfile(helper.get_file('with-original-name.jpg'), origin)
db = Db(folder)
dest_path1 = elodie.import_file(origin, folder_destination, db, False,
'copy', False, True)
dest_path2 = elodie.import_file(origin, folder_destination, db, False,
'copy', False, True)
shutil.rmtree(folder)
shutil.rmtree(folder_destination)
assert dest_path1 is not None
assert dest_path2 is not None
assert dest_path1 == dest_path2
def test_import_file_send_to_trash_false():
temporary_folder, folder = helper.create_working_folder()
temporary_folder_destination, folder_destination = helper.create_working_folder()
origin = '%s/photo.png' % folder
shutil.copyfile(helper.get_file('photo.png'), origin)
db = Db(folder)
dest_path = elodie.import_file(origin, folder_destination, db, False,
'copy', False, False)
assert os.path.isfile(origin), origin
shutil.rmtree(folder)
shutil.rmtree(folder_destination)
assert dest_path is not None
def test_import_file_send_to_trash_true():
raise SkipTest("Temporarily disable send2trash test gh-230")
temporary_folder, folder = helper.create_working_folder()
temporary_folder_destination, folder_destination = helper.create_working_folder()
origin = '%s/photo.png' % folder
shutil.copyfile(helper.get_file('photo.png'), origin)
db = Db(folder)
dest_path = elodie.import_file(origin, folder_destination, db, False,
'copy', True, False)
assert not os.path.isfile(origin), origin
shutil.rmtree(folder)
shutil.rmtree(folder_destination)
assert dest_path is not None
def test_import_destination_in_source():
temporary_folder, folder = helper.create_working_folder()
folder_destination = '{}/destination'.format(folder)
os.mkdir(folder_destination)
origin = '%s/plain.jpg' % folder
shutil.copyfile(helper.get_file('plain.jpg'), origin)
db = Db(folder)
dest_path = elodie.import_file(origin, folder_destination, db, False,
'copy', False, False)
shutil.rmtree(folder)
assert dest_path is None, dest_path
def test_import_destination_in_source_gh_287():
temporary_folder, folder = helper.create_working_folder()
folder_destination = '{}-destination'.format(folder)
os.mkdir(folder_destination)
origin = '%s/video.mov' % folder
shutil.copyfile(helper.get_file('video.mov'), origin)
db = Db(folder)
dest_path = elodie.import_file(origin, folder_destination, db, False,
'copy', False, False)
shutil.rmtree(folder)
assert dest_path is not None, dest_path
@unittest.skip("Invalid file disabled")
def test_import_invalid_file_exit_code():
temporary_folder, folder = helper.create_working_folder()
temporary_folder_destination, folder_destination = helper.create_working_folder()
# use a good and bad
origin_invalid = '%s/invalid.jpg' % folder
shutil.copyfile(helper.get_file('invalid.jpg'), origin_invalid)
origin_valid = '%s/photo.png' % folder
shutil.copyfile(helper.get_file('plain.jpg'), origin_valid)
runner = CliRunner()
result = runner.invoke(elodie._import, ['--destination', folder_destination, '--allow-duplicates', origin_invalid, origin_valid])
shutil.rmtree(folder)
shutil.rmtree(folder_destination)
assert result.exit_code == 1, result.exit_code
def test_import_file_with_single_exclude():
temporary_folder, folder = helper.create_working_folder()
temporary_folder_destination, folder_destination = helper.create_working_folder()
origin_valid = '%s/photo.png' % folder
shutil.copyfile(helper.get_file('plain.jpg'), origin_valid)
runner = CliRunner()
result = runner.invoke(elodie._import, ['--destination', folder_destination, '--exclude-regex', origin_valid[0:5], '--allow-duplicates', origin_valid])
assert 'Success 0' in result.output, result.output
assert 'Error 0' in result.output, result.output
def test_import_file_with_multiple_exclude():
temporary_folder, folder = helper.create_working_folder()
temporary_folder_destination, folder_destination = helper.create_working_folder()
origin_valid = '%s/photo.png' % folder
shutil.copyfile(helper.get_file('plain.jpg'), origin_valid)
runner = CliRunner()
result = runner.invoke(elodie._import, ['--destination', folder_destination, '--exclude-regex', 'does not exist in path', '--exclude-regex', origin_valid[0:5], '--allow-duplicates', origin_valid])
assert 'Success 0' in result.output, result.output
assert 'Error 0' in result.output, result.output
def test_import_file_with_non_matching_exclude():
temporary_folder, folder = helper.create_working_folder()
temporary_folder_destination, folder_destination = helper.create_working_folder()
origin_valid = '%s/photo.png' % folder
shutil.copyfile(helper.get_file('plain.jpg'), origin_valid)
runner = CliRunner()
result = runner.invoke(elodie._import, ['--destination', folder_destination, '--exclude-regex', 'does not exist in path', '--allow-duplicates', origin_valid])
assert 'Success 1' in result.output, result.output
assert 'Error 0' in result.output, result.output
@unittest.skip('to fix')
def test_import_directory_with_matching_exclude():
temporary_folder, folder = helper.create_working_folder()
temporary_folder_destination, folder_destination = helper.create_working_folder()
origin_valid = '%s/photo.png' % folder
shutil.copyfile(helper.get_file('plain.jpg'), origin_valid)
exclude_regex_list = (os.path.basename(os.path.dirname(folder)))
exclude_regex_list = (os.path.dirname(folder))
runner = CliRunner()
result = runner.invoke(elodie._import, ['--destination',
folder_destination, '--source', folder, '--exclude-regex',
exclude_regex_list, '--allow-duplicates'])
assert 'Success 0' in result.output, result.output
assert 'Error 0' in result.output, result.output
def test_import_directory_with_non_matching_exclude():
temporary_folder, folder = helper.create_working_folder()
temporary_folder_destination, folder_destination = helper.create_working_folder()
origin_valid = '%s/photo.png' % folder
shutil.copyfile(helper.get_file('plain.jpg'), origin_valid)
runner = CliRunner()
result = runner.invoke(elodie._import, ['--destination', folder_destination, '--source', folder, '--exclude-regex', 'non-matching', '--allow-duplicates'])
assert 'Success 1' in result.output, result.output
assert 'Error 0' in result.output, result.output
@mock.patch('elodie.constants.CONFIG_FILE', '%s/config.ini-import-file-with-single-config-exclude' % gettempdir())
def test_import_file_with_single_config_exclude():
config_string = """
[Exclusions]
name1=photo
"""
with open('%s/config.ini-import-file-with-single-config-exclude' % gettempdir(), 'w') as f:
f.write(config_string)
if hasattr(load_config, 'config'):
del load_config.config
temporary_folder, folder = helper.create_working_folder()
temporary_folder_destination, folder_destination = helper.create_working_folder()
origin_valid = '%s/photo.png' % folder
shutil.copyfile(helper.get_file('plain.jpg'), origin_valid)
runner = CliRunner()
result = runner.invoke(elodie._import, ['--destination', folder_destination, '--allow-duplicates', origin_valid, '--debug'])
if hasattr(load_config, 'config'):
del load_config.config
assert 'Success 0' in result.output, result.output
assert 'Error 0' in result.output, result.output
@mock.patch('elodie.constants.CONFIG_FILE', '%s/config.ini-import-file-with-multiple-config-exclude' % gettempdir())
def test_import_file_with_multiple_config_exclude():
config_string = """
[Exclusions]
name1=notvalidatall
name2=photo
"""
with open('%s/config.ini-import-file-with-multiple-config-exclude' % gettempdir(), 'w') as f:
f.write(config_string)
if hasattr(load_config, 'config'):
del load_config.config
temporary_folder, folder = helper.create_working_folder()
temporary_folder_destination, folder_destination = helper.create_working_folder()
origin_valid = '%s/photo.png' % folder
shutil.copyfile(helper.get_file('plain.jpg'), origin_valid)
runner = CliRunner()
result = runner.invoke(elodie._import, ['--destination', folder_destination, '--allow-duplicates', origin_valid, '--debug'])
if hasattr(load_config, 'config'):
del load_config.config
assert 'Success 0' in result.output, result.output
assert 'Error 0' in result.output, result.output
def test_get_all_files_in_paths():
pass
def test_update_location_on_audio():
temporary_folder, folder = helper.create_working_folder()
temporary_folder_destination, folder_destination = helper.create_working_folder()
origin = '%s/audio.m4a' % folder
shutil.copyfile(helper.get_file('audio.m4a'), origin)
audio = Audio(origin)
metadata = audio.get_metadata()
db = Db(folder)
status = elodie.update_location(audio, origin, 'Sunnyvale, CA', db)
audio_processed = Audio(origin)
metadata_processed = audio_processed.get_metadata()
shutil.rmtree(folder)
shutil.rmtree(folder_destination)
assert status == True, status
assert metadata['latitude'] != metadata_processed['latitude'], metadata_processed['latitude']
assert helper.isclose(metadata_processed['latitude'], 37.36883), metadata_processed['latitude']
assert helper.isclose(metadata_processed['longitude'], -122.03635), metadata_processed['longitude']
def test_update_location_on_photo():
temporary_folder, folder = helper.create_working_folder()
temporary_folder_destination, folder_destination = helper.create_working_folder()
origin = '%s/plain.jpg' % folder
shutil.copyfile(helper.get_file('plain.jpg'), origin)
photo = Photo(origin)
metadata = photo.get_metadata()
db = Db(folder)
status = elodie.update_location(photo, origin, 'Sunnyvale, CA', db)
photo_processed = Photo(origin)
metadata_processed = photo_processed.get_metadata()
shutil.rmtree(folder)
shutil.rmtree(folder_destination)
assert status == True, status
assert metadata['latitude'] != metadata_processed['latitude']
assert helper.isclose(metadata_processed['latitude'], 37.36883), metadata_processed['latitude']
assert helper.isclose(metadata_processed['longitude'], -122.03635), metadata_processed['longitude']
def test_update_location_on_video():
temporary_folder, folder = helper.create_working_folder()
temporary_folder_destination, folder_destination = helper.create_working_folder()
origin = '%s/video.mov' % folder
shutil.copyfile(helper.get_file('video.mov'), origin)
video = Video(origin)
metadata = video.get_metadata()
db = Db(folder)
status = elodie.update_location(video, origin, 'Sunnyvale, CA', db)
video_processed = Video(origin)
metadata_processed = video_processed.get_metadata()
shutil.rmtree(folder)
shutil.rmtree(folder_destination)
assert status == True, status
assert metadata['latitude'] != metadata_processed['latitude']
assert helper.isclose(metadata_processed['latitude'], 37.36883), metadata_processed['latitude']
assert helper.isclose(metadata_processed['longitude'], -122.03635), metadata_processed['longitude']
def test_update_time_on_audio():
temporary_folder, folder = helper.create_working_folder()
temporary_folder_destination, folder_destination = helper.create_working_folder()
origin = '%s/audio.m4a' % folder
shutil.copyfile(helper.get_file('audio.m4a'), origin)
audio = Audio(origin)
metadata = audio.get_metadata()
status = elodie.update_time(audio, origin, '2000-01-01 12:00:00')
audio_processed = Audio(origin)
metadata_processed = audio_processed.get_metadata()
shutil.rmtree(folder)
shutil.rmtree(folder_destination)
assert status == True, status
assert metadata['date_original'] != metadata_processed['date_original']
assert metadata_processed['date_original'] == datetime(2000, 1, 1, 12, 0)
def test_update_time_on_photo():
temporary_folder, folder = helper.create_working_folder()
temporary_folder_destination, folder_destination = helper.create_working_folder()
origin = '%s/plain.jpg' % folder
shutil.copyfile(helper.get_file('plain.jpg'), origin)
photo = Photo(origin)
metadata = photo.get_metadata()
status = elodie.update_time(photo, origin, '2000-01-01 12:00:00')
photo_processed = Photo(origin)
metadata_processed = photo_processed.get_metadata()
shutil.rmtree(folder)
shutil.rmtree(folder_destination)
assert status == True, status
assert metadata['date_original'] != metadata_processed['date_original']
assert metadata_processed['date_original'] == datetime(2000, 1, 1, 12, 0)
def test_update_time_on_video():
temporary_folder, folder = helper.create_working_folder()
temporary_folder_destination, folder_destination = helper.create_working_folder()
origin = '%s/video.mov' % folder
shutil.copyfile(helper.get_file('video.mov'), origin)
video = Video(origin)
metadata = video.get_metadata()
status = elodie.update_time(video, origin, '2000-01-01 12:00:00')
video_processed = Video(origin)
metadata_processed = video_processed.get_metadata()
shutil.rmtree(folder)
shutil.rmtree(folder_destination)
assert status == True, status
assert metadata['date_original'] != metadata_processed['date_original']
assert metadata_processed['date_original'] == datetime(2000, 1, 1, 12, 0)
def test_update_with_directory_passed_in():
temporary_folder, folder = helper.create_working_folder()
temporary_folder_destination, folder_destination = helper.create_working_folder()
origin = '%s/photo.png' % folder
shutil.copyfile(helper.get_file('photo.png'), origin)
runner = CliRunner()
result = runner.invoke(elodie._import, ['--destination', folder_destination, folder])
runner2 = CliRunner()
result = runner2.invoke(elodie._update, ['--album', 'test', folder_destination])
updated_file_path = "{}/2015-01-Jan/test/2015-01-18_12-01-01-photo.png".format(folder_destination)
updated_file_exists = os.path.isfile(updated_file_path)
shutil.rmtree(folder)
shutil.rmtree(folder_destination)
assert updated_file_exists, updated_file_path
@unittest.skip("Invalid file disabled")
def test_update_invalid_file_exit_code():
temporary_folder, folder = helper.create_working_folder()
temporary_folder_destination, folder_destination = helper.create_working_folder()
# use a good and bad
origin_invalid = '%s/invalid.jpg' % folder
shutil.copyfile(helper.get_file('invalid.jpg'), origin_invalid)
origin_valid = '%s/photo.png' % folder
shutil.copyfile(helper.get_file('plain.jpg'), origin_valid)
runner = CliRunner()
result = runner.invoke(elodie._update, ['--album', 'test', origin_invalid, origin_valid])
# bugfix deleted by elodie._update....
# shutil.rmtree(folder)
shutil.rmtree(folder_destination)
assert result.exit_code == 1, result.exit_code
def test_regenerate_db_invalid_source():
runner = CliRunner()
result = runner.invoke(elodie._generate_db, ['--path', '/invalid/path'])
assert result.exit_code == 1, result.exit_code
def test_regenerate_valid_source():
temporary_folder, folder = helper.create_working_folder()
origin = '%s/photo.png' % folder
shutil.copyfile(helper.get_file('photo.png'), origin)
runner = CliRunner()
result = runner.invoke(elodie._generate_db, ['--path', folder])
db = Db(folder)
shutil.rmtree(folder)
assert result.exit_code == 0, result.exit_code
assert '66ca09b5533aba8b4ccdc7243435f2c4638c1a6762940ab9dbe66da185b3513e' in db.hash_db, db.hash_db
@unittest.skip("Invalid file disabled")
def test_regenerate_valid_source_with_invalid_files():
temporary_folder, folder = helper.create_working_folder()
origin_valid = '%s/photo.png' % folder
shutil.copyfile(helper.get_file('photo.png'), origin_valid)
origin_invalid = '%s/invalid.invalid' % folder
shutil.copyfile(helper.get_file('invalid.invalid'), origin_invalid)
runner = CliRunner()
result = runner.invoke(elodie._generate_db, ['--path', folder])
db = Db(folder)
shutil.rmtree(folder)
assert result.exit_code == 0, result.exit_code
assert '3c19a5d751cf19e093b7447297731124d9cc987d3f91a9d1872c3b1c1b15639a' in db.hash_db, db.hash_db
assert 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855' not in db.hash_db, db.hash_db
def test_verify_ok():
temporary_folder, folder = helper.create_working_folder()
origin = '%s/photo.png' % folder
shutil.copyfile(helper.get_file('photo.png'), origin)
runner = CliRunner()
runner.invoke(elodie._generate_db, ['--path', folder])
result = runner.invoke(elodie._verify, ['--path', folder])
shutil.rmtree(folder)
assert 'Success 1' in result.output, result.output
assert 'Error 0' in result.output, result.output
def test_verify_error():
temporary_folder, folder = helper.create_working_folder()
origin = '%s/photo.png' % folder
shutil.copyfile(helper.get_file('photo.png'), origin)
runner = CliRunner()
runner.invoke(elodie._generate_db, ['--path', folder])
with open(origin, 'w') as f:
f.write('changed text')
result = runner.invoke(elodie._verify, ['--path', folder])
shutil.rmtree(folder)
assert origin in result.output, result.output
assert 'Error 1' in result.output, result.output
@unittest.skip('depreciated')
@mock.patch('elodie.constants.CONFIG_FILE', '%s/config.ini-cli-batch-plugin-googlephotos' % gettempdir())
def test_cli_batch_plugin_googlephotos():
auth_file = helper.get_file('plugins/googlephotos/auth_file.json')
secrets_file = helper.get_file('plugins/googlephotos/secrets_file.json')
config_string = """
[Plugins]
plugins=GooglePhotos
[PluginGooglePhotos]
auth_file={}
secrets_file={}
"""
config_string_fmt = config_string.format(
auth_file,
secrets_file
)
with open('%s/config.ini-cli-batch-plugin-googlephotos' % gettempdir(), 'w') as f:
f.write(config_string_fmt)
if hasattr(load_config, 'config'):
del load_config.config
final_file_path_1 = helper.get_file('plain.jpg')
final_file_path_2 = helper.get_file('no-exif.jpg')
sample_metadata_1 = Photo(final_file_path_1).get_metadata()
sample_metadata_2 = Photo(final_file_path_2).get_metadata()
gp = GooglePhotos()
gp.after('', '', final_file_path_1, sample_metadata_1)
gp.after('', '', final_file_path_2, sample_metadata_1)
runner = CliRunner()
result = runner.invoke(elodie._batch)
if hasattr(load_config, 'config'):
del load_config.config
assert "elodie/elodie/tests/files/plain.jpg uploaded successfully.\"}\n" in result.output, result.output
assert "elodie/elodie/tests/files/no-exif.jpg uploaded successfully.\"}\n" in result.output, result.output
@unittest.skip('to fix')
def test_cli_debug_import():
runner = CliRunner()
# import
result = runner.invoke(elodie._import, ['--destination', '/does/not/exist', '/does/not/exist'])
assert "Could not find /does/not/exist\n" not in result.output, result.output
result = runner.invoke(elodie._import, ['--destination', '/does/not/exist', '--debug', '/does/not/exist'])
assert "Could not find /does/not/exist\n" in result.output, result.output
@unittest.skip('to fix')
def test_cli_debug_update():
runner = CliRunner()
# update
result = runner.invoke(elodie._update, ['--location', 'foobar', '/does/not/exist'])
assert "Could not find /does/not/exist\n" not in result.output, result.output
result = runner.invoke(elodie._update, ['--location', 'foobar', '--debug', '/does/not/exist'])
assert "Could not find /does/not/exist\n" in result.output, result.output

File diff suppressed because it is too large Load Diff

View File

@ -1,237 +0,0 @@
from __future__ import absolute_import
from __future__ import division
from builtins import range
from past.utils import old_div
# Project imports
import mock
import os
import random
import re
import sys
from mock import patch
from tempfile import gettempdir
# sys.path.insert(0, os.path.abspath(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))))
from . import helper
from elodie import geolocation
from elodie.localstorage import Db
os.environ['TZ'] = 'GMT'
ELODIE_DIR = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
def test_decimal_to_dms():
for x in range(0, 1000):
target_decimal_value = random.uniform(0.0, 180.0)
if(x % 2 == 1):
target_decimal_value = target_decimal_value * -1
dms = geolocation.decimal_to_dms(target_decimal_value)
check_value = (dms[0] + dms[1] / 60 + dms[2] / 3600) * dms[3]
target_decimal_value = round(target_decimal_value, 8)
check_value = round(check_value, 8)
assert target_decimal_value == check_value, '%s does not match %s' % (check_value, target_decimal_value)
def test_dms_to_decimal_positive_sign():
decimal = geolocation.dms_to_decimal(10, 20, 100, 'NE')
assert helper.isclose(decimal, 10.3611111111)
decimal = geolocation.dms_to_decimal(10, 20, 100, 'ne')
assert helper.isclose(decimal, 10.3611111111)
def test_dms_to_decimal_negative_sign():
decimal = geolocation.dms_to_decimal(10, 20, 100, 'SW')
assert helper.isclose(decimal, -10.3611111111)
decimal = geolocation.dms_to_decimal(10, 20, 100, 'sw')
assert helper.isclose(decimal, -10.3611111111)
def test_dms_string_latitude():
for x in range(0, 5):
target_decimal_value = random.uniform(0.0, 180.0)
if(x % 2 == 1):
target_decimal_value = target_decimal_value * -1
dms = geolocation.decimal_to_dms(target_decimal_value)
dms_string = geolocation.dms_string(target_decimal_value, 'latitude')
check_value = 'N' if target_decimal_value >= 0 else 'S'
assert check_value in dms_string, '%s not in %s' % (check_value, dms_string)
assert str(dms[0]) in dms_string, '%s not in %s' % (dms[0], dms_string)
def test_dms_string_longitude():
for x in range(0, 5):
target_decimal_value = random.uniform(0.0, 180.0)
if(x % 2 == 1):
target_decimal_value = target_decimal_value * -1
dms = geolocation.decimal_to_dms(target_decimal_value)
dms_string = geolocation.dms_string(target_decimal_value, 'longitude')
check_value = 'E' if target_decimal_value >= 0 else 'W'
assert check_value in dms_string, '%s not in %s' % (check_value, dms_string)
assert str(dms[0]) in dms_string, '%s not in %s' % (dms[0], dms_string)
def test_reverse_lookup_with_valid_key():
res = geolocation.lookup_osm(lat=37.368, lon=-122.03)
assert res['address']['city'] == 'Sunnyvale', res
def test_reverse_lookup_with_invalid_lat_lon():
res = geolocation.lookup_osm(lat=999, lon=999)
assert res is None, res
@mock.patch('elodie.geolocation.__KEY__', 'invalid_key')
def test_reverse_lookup_with_invalid_key():
res = geolocation.lookup_mapquest(lat=37.368, lon=-122.03)
assert res is None, res
def test_lookup_with_valid_key():
res = geolocation.lookup_mapquest(location='Sunnyvale, CA')
latLng = res['results'][0]['locations'][0]['latLng']
assert latLng['lat'] == 37.36883, latLng
assert latLng['lng'] == -122.03635, latLng
def test_lookup_with_invalid_location():
res = geolocation.lookup_mapquest(location='foobar dne')
assert res is None, res
def test_lookup_with_invalid_location():
res = geolocation.lookup_mapquest(location='foobar dne')
assert res is None, res
def test_lookup_with_valid_key():
res = geolocation.lookup_mapquest(location='Sunnyvale, CA')
latLng = res['results'][0]['locations'][0]['latLng']
assert latLng['lat'] == 37.36883, latLng
assert latLng['lng'] == -122.03635, latLng
@mock.patch('elodie.geolocation.__PREFER_ENGLISH_NAMES__', True)
def test_lookup_with_prefer_english_names_true():
res = geolocation.lookup_osm(lat=55.66333, lon=37.61583)
assert res['address']['city'] == 'Moscow', res
@mock.patch('elodie.geolocation.__PREFER_ENGLISH_NAMES__', False)
def test_lookup_with_prefer_english_names_false():
res = geolocation.lookup_osm(lat=55.66333, lon=37.61583)
assert res['address']['city'] == 'Москва', res
@mock.patch('elodie.constants.location_db', '%s/location.json-cached' % gettempdir())
def test_place_name_deprecated_string_cached():
# See gh-160 for backwards compatability needed when a string is stored instead of a dict
with open('%s/location.json-cached' % gettempdir(), 'w') as f:
f.write("""
[{"lat": 37.3667027222222, "long": -122.033383611111, "name": "OLDVALUE"}]
"""
)
db = Db(ELODIE_DIR)
place_name = geolocation.place_name(37.3667027222222, -122.033383611111,
db)
assert place_name['city'] == 'Sunnyvale', place_name
@mock.patch('elodie.constants.location_db', '%s/location.json-cached' % gettempdir())
def test_place_name_cached():
with open('%s/location.json-cached' % gettempdir(), 'w') as f:
f.write("""
[{"lat": 37.3667027222222, "long": -122.033383611111, "name": {"city": "UNITTEST"}}]
"""
)
db = Db(ELODIE_DIR)
place_name = geolocation.place_name(37.3667027222222, -122.033383611111,
db)
assert place_name['city'] == 'UNITTEST', place_name
def test_place_name_no_default():
# See gh-160 for backwards compatability needed when a string is stored instead of a dict
db = Db(ELODIE_DIR)
place_name = geolocation.place_name(123456.000, 123456.000, db)
assert place_name['default'] == 'Unknown Location', place_name
@mock.patch('elodie.geolocation.__KEY__', 'invalid_key')
def test_lookup_with_invalid_key():
res = geolocation.lookup_mapquest(location='Sunnyvale, CA')
assert res is None, res
@mock.patch('elodie.geolocation.__KEY__', '')
def test_lookup_with_no_key():
res = geolocation.lookup_mapquest(location='Sunnyvale, CA')
assert res is None, res
def test_parse_result_with_error():
res = geolocation.parse_result({'error': 'foo'})
assert res is None, res
def test_parse_result_with_city():
# http://open.mapquestapi.com/nominatim/v1/reverse.php?lat=37.368&lon=-122.03&key=key_goes_here&format=json
results = {
"place_id": "60197412",
"osm_type": "way",
"osm_id": "30907961",
"lat": "37.36746105",
"lon": "-122.030237558742",
"display_name": "111, East El Camino Real, Sunnyvale, Santa Clara County, California, 94087, United States of America",
"address": {
"house_number": "111",
"road": "East El Camino Real",
"city": "Sunnyvale",
"county": "Santa Clara County",
"state": "California",
"postcode": "94087",
"country": "United States of America",
"country_code": "us"
}
}
res = geolocation.parse_result(results)
assert res == results, res
def test_parse_result_with_lat_lon():
# http://open.mapquestapi.com/geocoding/v1/address?location=abcdefghijklmnopqrstuvwxyz&key=key_goes_here&format=json
results = {
"results": [
{
"locations": [
{
"latLng": {
"lat": 123.00,
"lng": -142.99
}
}
]
}
]
}
res = geolocation.parse_result(results)
assert res == results, res
def test_parse_result_with_unknown_lat_lon():
# http://open.mapquestapi.com/geocoding/v1/address?location=abcdefghijklmnopqrstuvwxyz&key=key_goes_here&format=json
results = {
"results": [
{
"locations": [
{
"latLng": {
"lat": 39.78373,
"lng": -100.445882
}
}
]
}
]
}
res = geolocation.parse_result(results)
assert res is None, res

View File

@ -1,263 +0,0 @@
# Project imports
import os
import sys
# sys.path.insert(0, os.path.abspath(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))))
from . import helper
from elodie.localstorage import Db
from elodie import constants
os.environ['TZ'] = 'GMT'
PHOTO_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'files')
def test_init_writes_files():
db = Db(PHOTO_PATH)
assert os.path.isfile(helper.get_hash_db(PHOTO_PATH)) == True
assert os.path.isfile(helper.get_location_db(PHOTO_PATH)) == True
def test_add_hash_default_do_not_write():
db = Db(PHOTO_PATH)
random_key = helper.random_string(10)
random_value = helper.random_string(12)
# Test with default False value as 3rd param
db.add_hash(random_key, random_value)
assert db.check_hash(random_key) == True, 'Lookup for hash did not return True'
# Instnatiate new db class to confirm random_key does not exist
db2 = Db(PHOTO_PATH)
assert db2.check_hash(random_key) == False
def test_add_hash_explicit_do_not_write():
db = Db(PHOTO_PATH)
random_key = helper.random_string(10)
random_value = helper.random_string(12)
# Test with explicit False value as 3rd param
db.add_hash(random_key, random_value, False)
assert db.check_hash(random_key) == True, 'Lookup for hash did not return True'
# Instnatiate new db class to confirm random_key does not exist
db2 = Db(PHOTO_PATH)
assert db2.check_hash(random_key) == False
def test_add_hash_explicit_write():
db = Db(PHOTO_PATH)
random_key = helper.random_string(10)
random_value = helper.random_string(12)
# Test with explicit True value as 3rd param
db.add_hash(random_key, random_value, True)
assert db.check_hash(random_key) == True, 'Lookup for hash did not return True'
# Instnatiate new db class to confirm random_key exists
db2 = Db(PHOTO_PATH)
assert db2.check_hash(random_key) == True
def test_backup_hash_db():
db = Db(PHOTO_PATH)
backup_file_name = db.backup_hash_db()
file_exists = os.path.isfile(backup_file_name)
os.remove(backup_file_name)
assert file_exists, backup_file_name
def test_check_hash_exists():
db = Db(PHOTO_PATH)
random_key = helper.random_string(10)
random_value = helper.random_string(12)
# Test with explicit False value as 3rd param
db.add_hash(random_key, random_value, False)
assert db.check_hash(random_key) == True, 'Lookup for hash did not return True'
def test_check_hash_does_not_exist():
db = Db(PHOTO_PATH)
random_key = helper.random_string(10)
assert db.check_hash(random_key) == False, 'Lookup for hash that should not exist returned True'
def test_get_hash_exists():
db = Db(PHOTO_PATH)
random_key = helper.random_string(10)
random_value = helper.random_string(12)
# Test with explicit False value as 3rd param
db.add_hash(random_key, random_value, False)
assert db.get_hash(random_key) == random_value, 'Lookup for hash that exists did not return value'
def test_get_hash_does_not_exist():
db = Db(PHOTO_PATH)
random_key = helper.random_string(10)
assert db.get_hash(random_key) is None, 'Lookup for hash that should not exist did not return None'
def test_get_all():
db = Db(PHOTO_PATH)
db.reset_hash_db()
random_keys = []
random_values = []
for _ in range(10):
random_keys.append(helper.random_string(10))
random_values.append(helper.random_string(12))
db.add_hash(random_keys[-1:][0], random_values[-1:][0], False)
counter = 0
for key, value in db.all():
assert key in random_keys, key
assert value in random_values, value
counter += 1
assert counter == 10, counter
def test_get_all_empty():
db = Db(PHOTO_PATH)
db.reset_hash_db()
counter = 0
for key, value in db.all():
counter += 1
# there's a final iteration because of the generator
assert counter == 0, counter
def test_reset_hash_db():
db = Db(PHOTO_PATH)
random_key = helper.random_string(10)
random_value = helper.random_string(12)
# Test with explicit False value as 3rd param
db.add_hash(random_key, random_value, False)
assert random_key in db.hash_db, random_key
db.reset_hash_db()
assert random_key not in db.hash_db, random_key
def test_update_hash_db():
db = Db(PHOTO_PATH)
random_key = helper.random_string(10)
random_value = helper.random_string(12)
# Test with default False value as 3rd param
db.add_hash(random_key, random_value)
assert db.check_hash(random_key) == True, 'Lookup for hash did not return True'
# Instnatiate new db class to confirm random_key does not exist
db2 = Db(PHOTO_PATH)
assert db2.check_hash(random_key) == False
db.update_hash_db()
# Instnatiate new db class to confirm random_key exists
db3 = Db(PHOTO_PATH)
assert db3.check_hash(random_key) == True
def test_checksum():
db = Db(PHOTO_PATH)
src = helper.get_file('plain.jpg')
checksum = db.checksum(src)
assert checksum == 'd5eb755569ddbc8a664712d2d7d6e0fa1ddfcdb378475e4a6758dc38d5ea9a16', 'Checksum for plain.jpg did not match'
def test_add_location():
db = Db(PHOTO_PATH)
latitude, longitude, name = helper.get_test_location()
db.add_location(latitude, longitude, name)
retrieved_name = db.get_location_name(latitude, longitude, 5)
assert name == retrieved_name
def test_get_location_name():
db = Db(PHOTO_PATH)
latitude, longitude, name = helper.get_test_location()
db.add_location(latitude, longitude, name)
# 1 meter
retrieved_name = db.get_location_name(latitude, longitude, 1)
assert name == retrieved_name
def test_get_location_name_within_threshold():
db = Db(PHOTO_PATH)
latitude, longitude, name = helper.get_test_location()
db.add_location(latitude, longitude, name)
print(latitude)
new_latitude = helper.random_coordinate(latitude, 4)
new_longitude = helper.random_coordinate(longitude, 4)
print(new_latitude)
# 10 miles
retrieved_name = db.get_location_name(new_latitude, new_longitude, 1600*10)
assert name == retrieved_name, 'Name (%r) did not match retrieved name (%r)' % (name, retrieved_name)
def test_get_location_name_outside_threshold():
db = Db(PHOTO_PATH)
latitude, longitude, name = helper.get_test_location()
db.add_location(latitude, longitude, name)
new_latitude = helper.random_coordinate(latitude, 1)
new_longitude = helper.random_coordinate(longitude, 1)
# 800 meters
retrieved_name = db.get_location_name(new_latitude, new_longitude, 800)
assert retrieved_name is None
def test_get_location_coordinates_exists():
db = Db(PHOTO_PATH)
latitude, longitude, name = helper.get_test_location()
name = '%s-%s' % (name, helper.random_string(10))
latitude = helper.random_coordinate(latitude, 1)
longitude = helper.random_coordinate(longitude, 1)
db.add_location(latitude, longitude, name)
location = db.get_location_coordinates(name)
assert location is not None
assert location[0] == latitude
assert location[1] == longitude
def test_get_location_coordinates_does_not_exists():
db = Db(PHOTO_PATH)
latitude, longitude, name = helper.get_test_location()
name = '%s-%s' % (name, helper.random_string(10))
latitude = helper.random_coordinate(latitude, 1)
longitude = helper.random_coordinate(longitude, 1)
location = db.get_location_coordinates(name)
assert location is None

View File

@ -1,82 +0,0 @@
# Project imports
import os
import sys
import unittest
from json import dumps
from mock import patch
try:
from StringIO import StringIO
except ImportError:
from io import StringIO
sys.path.insert(0, os.path.abspath(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))))
from elodie import constants
from elodie import log
def call_log_and_assert(func, args, expected):
saved_stdout = sys.stdout
try:
out = StringIO()
sys.stdout = out
func(*args)
output = out.getvalue()
assert output == expected, (expected, func, output)
finally:
sys.stdout = saved_stdout
def with_new_line(string):
return "{}\n".format(string)
@patch('elodie.log')
@patch('elodie.constants.debug', True)
def test_calls_print_debug_true(fake_log):
expected = 'some string'
fake_log.info.return_value = expected
fake_log.warn.return_value = expected
fake_log.error.return_value = expected
for func in [log.info, log.warn, log.error]:
call_log_and_assert(func, [expected], with_new_line(expected))
expected_json = {'foo':'bar'}
fake_log.info.return_value = expected_json
fake_log.warn.return_value = expected_json
fake_log.error.return_value = expected_json
for func in [log.info_json, log.warn_json, log.error_json]:
call_log_and_assert(func, [expected_json], with_new_line(dumps(expected_json)))
@patch('elodie.log')
@patch('elodie.constants.debug', False)
def test_calls_print_debug_false(fake_log):
expected = 'some other string'
fake_log.info.return_value = expected
fake_log.warn.return_value = expected
fake_log.error.return_value = expected
for func in [log.info, log.warn, log.error]:
call_log_and_assert(func, [expected], '')
expected_json = {'foo':'bar'}
fake_log.info.return_value = expected_json
fake_log.warn.return_value = expected_json
fake_log.error.return_value = expected_json
for func in [log.info_json, log.warn_json, log.error_json]:
call_log_and_assert(func, [expected_json], '')
@patch('elodie.log')
def test_calls_print_progress_no_new_line(fake_log):
expected = 'some other string'
fake_log.info.return_value = expected
fake_log.warn.return_value = expected
fake_log.error.return_value = expected
call_log_and_assert(log.progress, [expected], expected)
@patch('elodie.log')
def test_calls_print_progress_with_new_line(fake_log):
expected = "some other string\n"
fake_log.info.return_value = expected
fake_log.warn.return_value = expected
fake_log.error.return_value = expected
call_log_and_assert(log.progress, [expected, True], with_new_line(expected))

View File

@ -1,254 +0,0 @@
# Project imports
import mock
import os
import sys
from tempfile import gettempdir
sys.path.insert(0, os.path.abspath(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))))
from . import helper
from elodie.config import load_config
from elodie.plugins.plugins import Plugins, PluginBase, PluginDb
@mock.patch('elodie.constants.CONFIG_FILE', '%s/config.ini-load-plugins-unset-backwards-compat' % gettempdir())
def test_load_plugins_unset_backwards_compat():
with open('%s/config.ini-load-plugins-unset-backwards-compat' % gettempdir(), 'w') as f:
f.write("""
""")
if hasattr(load_config, 'config'):
del load_config.config
plugins = Plugins()
plugins.load()
if hasattr(load_config, 'config'):
del load_config.config
assert plugins.plugins == [], plugins.plugins
@mock.patch('elodie.constants.CONFIG_FILE', '%s/config.ini-load-plugins-exists-not-set' % gettempdir())
def test_load_plugins_exists_not_set():
with open('%s/config.ini-load-plugins-exists-not-set' % gettempdir(), 'w') as f:
f.write("""
[Plugins]
""")
if hasattr(load_config, 'config'):
del load_config.config
plugins = Plugins()
plugins.load()
if hasattr(load_config, 'config'):
del load_config.config
assert plugins.plugins == [], plugins.plugins
@mock.patch('elodie.constants.CONFIG_FILE', '%s/config.ini-load-plugins-one' % gettempdir())
def test_load_plugins_one():
with open('%s/config.ini-load-plugins-one' % gettempdir(), 'w') as f:
f.write("""
[Plugins]
plugins=Dummy
""")
if hasattr(load_config, 'config'):
del load_config.config
plugins = Plugins()
plugins.load()
if hasattr(load_config, 'config'):
del load_config.config
assert plugins.plugins == ['Dummy'], plugins.plugins
assert len(plugins.classes) == 1, len(plugins.classes)
@mock.patch('elodie.constants.CONFIG_FILE', '%s/config.ini-load-plugins-one-with-invalid' % gettempdir())
def test_load_plugins_one_with_invalid():
with open('%s/config.ini-load-plugins-one' % gettempdir(), 'w') as f:
f.write("""
[Plugins]
plugins=DNE
""")
if hasattr(load_config, 'config'):
del load_config.config
plugins = Plugins()
plugins.load()
if hasattr(load_config, 'config'):
del load_config.config
assert plugins.plugins == [], plugins.plugins
assert len(plugins.classes) == 0, len(plugins.classes)
@mock.patch('elodie.constants.CONFIG_FILE', '%s/config.ini-load-plugins-many' % gettempdir())
def test_load_plugins_many():
with open('%s/config.ini-load-plugins-many' % gettempdir(), 'w') as f:
f.write("""
[Plugins]
plugins=ThrowError,Dummy
""")
if hasattr(load_config, 'config'):
del load_config.config
plugins = Plugins()
plugins.load()
if hasattr(load_config, 'config'):
del load_config.config
assert plugins.plugins == ['ThrowError','Dummy'], plugins.plugins
assert plugins.classes['ThrowError'].__name__ == 'ThrowError', plugins.classes['ThrowError'].__name__
assert plugins.classes['Dummy'].__name__ == 'Dummy', plugins.classes['Dummy'].__name__
assert len(plugins.classes) == 2, len(plugins.classes)
@mock.patch('elodie.constants.CONFIG_FILE', '%s/config.ini-load-plugins-many-with-invalid' % gettempdir())
def test_load_plugins_set_many_with_invalid():
with open('%s/config.ini-load-plugins-many-with-invalid' % gettempdir(), 'w') as f:
f.write("""
[Plugins]
plugins=ThrowError,Dummy,DNE
""")
if hasattr(load_config, 'config'):
del load_config.config
plugins = Plugins()
plugins.load()
if hasattr(load_config, 'config'):
del load_config.config
assert plugins.plugins == ['ThrowError','Dummy'], plugins.plugins
@mock.patch('elodie.constants.CONFIG_FILE', '%s/config.ini-run-before' % gettempdir())
def test_run_before():
with open('%s/config.ini-run-before' % gettempdir(), 'w') as f:
f.write("""
[Plugins]
plugins=Dummy
""")
if hasattr(load_config, 'config'):
del load_config.config
plugins = Plugins()
plugins.load()
before_ran_1 = plugins.classes['Dummy'].before_ran
plugins.run_all_before('', '')
before_ran_2 = plugins.classes['Dummy'].before_ran
if hasattr(load_config, 'config'):
del load_config.config
assert before_ran_1 == False, before_ran_1
assert before_ran_2 == True, before_ran_2
@mock.patch('elodie.constants.CONFIG_FILE', '%s/config.ini-throw-error' % gettempdir())
def test_throw_error():
with open('%s/config.ini-throw-error' % gettempdir(), 'w') as f:
f.write("""
[Plugins]
plugins=ThrowError
""")
if hasattr(load_config, 'config'):
del load_config.config
plugins = Plugins()
plugins.load()
status_after = plugins.run_all_after('', '', '', '')
status_batch = plugins.run_batch()
status_before = plugins.run_all_before('', '')
if hasattr(load_config, 'config'):
del load_config.config
assert status_after == False, status_after
assert status_batch == False, status_batch
assert status_before == False, status_before
@mock.patch('elodie.constants.CONFIG_FILE', '%s/config.ini-throw-error-one-of-many' % gettempdir())
def test_throw_error_one_of_many():
with open('%s/config.ini-throw-error-one-of-many' % gettempdir(), 'w') as f:
f.write("""
[Plugins]
plugins=Dummy,ThrowError
""")
if hasattr(load_config, 'config'):
del load_config.config
plugins = Plugins()
plugins.load()
status_after = plugins.run_all_after('', '', '', '')
status_batch = plugins.run_batch()
status_before = plugins.run_all_before('', '')
if hasattr(load_config, 'config'):
del load_config.config
assert status_after == False, status_after
assert status_batch == False, status_batch
assert status_before == False, status_before
@mock.patch('elodie.constants.CONFIG_FILE', '%s/config.ini-throw-runtime-error' % gettempdir())
def test_throw_error_runtime_error():
with open('%s/config.ini-throw-runtime-error' % gettempdir(), 'w') as f:
f.write("""
[Plugins]
plugins=RuntimeError
""")
if hasattr(load_config, 'config'):
del load_config.config
plugins = Plugins()
plugins.load()
status_after = plugins.run_all_after('', '', '', '')
status_batch = plugins.run_batch()
status_before = plugins.run_all_before('', '')
if hasattr(load_config, 'config'):
del load_config.config
assert status_after == True, status_after
assert status_batch == True, status_batch
assert status_before == True, status_before
def test_plugin_base_inherits_db():
plugin_base = PluginBase()
assert hasattr(plugin_base.db, 'get')
assert hasattr(plugin_base.db, 'set')
assert hasattr(plugin_base.db, 'get_all')
assert hasattr(plugin_base.db, 'delete')
def test_db_initialize_file():
db = PluginDb('foobar')
try:
os.remove(db.db_file)
except OSError:
pass
db = PluginDb('foobar')
def test_db_get_then_set_then_get_then_delete():
db = PluginDb('foobar')
foo = db.get('foo')
assert foo is None, foo
db.set('foo', 'bar')
foo = db.get('foo')
assert foo == 'bar', foo
db.delete('foo')
foo = db.get('foo')
assert foo is None, foo
def test_db_get_all():
# we initialize the db to get the file path to delete then reinitialize
db = PluginDb('foobar')
try:
os.remove(db.db_file)
except OSError:
pass
db = PluginDb('foobar')
db.set('a', '1')
db.set('b', '2')
db.set('c', '3')
db.set('d', '4')
all_rows = db.get_all()
assert all_rows == {'a': '1', 'b': '2', 'c': '3', 'd': '4'}, all_rows

View File

@ -1,74 +0,0 @@
# Project imports
import os
import sys
import unittest
from json import dumps
from mock import patch
try:
from StringIO import StringIO
except ImportError:
from io import StringIO
sys.path.insert(0, os.path.abspath(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))))
from elodie import constants
from elodie.result import Result
def call_result_and_assert(result, expected):
saved_stdout = sys.stdout
try:
out = StringIO()
sys.stdout = out
result.write()
output = out.getvalue().strip()
assert output == expected, output
finally:
sys.stdout = saved_stdout
def test_add_multiple_rows_with_success():
expected = """****** SUMMARY ******
Metric Count
-------- -------
Success 2
Error 0"""
result = Result()
result.append(('id1', '/some/path/1'))
result.append(('id2', '/some/path/2'))
call_result_and_assert(result, expected)
def test_add_multiple_rows_with_failure():
expected = """****** ERROR DETAILS ******
File
------
id1
id2
****** SUMMARY ******
Metric Count
-------- -------
Success 0
Error 2"""
result = Result()
result.append(('id1', False))
result.append(('id2', False))
call_result_and_assert(result, expected)
def test_add_multiple_rows_with_failure_and_success():
expected = """****** ERROR DETAILS ******
File
------
id1
****** SUMMARY ******
Metric Count
-------- -------
Success 1
Error 1"""
result = Result()
result.append(('id1', False))
result.append(('id2', '/some/path'))
call_result_and_assert(result, expected)

View File

View File

View File

@ -1 +0,0 @@
{"scopes": ["https://www.googleapis.com/auth/photoslibrary", "https://www.googleapis.com/auth/photoslibrary.appendonly", "https://www.googleapis.com/auth/photoslibrary.sharing"], "id_token": null, "token": "ya29.Gls1B3ymBdURb3tBLAUJgxQtfTzKry0eaUqplbkHxfIYJH9sWvkalLwXprfAW-Ku0Fz8aP3jz7NrncJ2h58idSEgrYXPQ14iVSkwgUGE2gnsxZM6w4TbHz8ny8Yf", "client_id": "1004259275591-ogsk179e96cs0h126qj590mofk86gdqo.apps.googleusercontent.com", "token_uri": "https://oauth2.googleapis.com/token", "client_secret": "p84GOD_i7_PwDGbAmpnbwKiH", "refresh_token": "1/iHiK9Vbq9i5ebXScyQPDZf9_GJrDOWMvu-2zG9wRsDA"}

View File

@ -1 +0,0 @@
{"installed":{"client_id":"1004259275591-ogsk179e96cs0h126qj590mofk86gdqo.apps.googleusercontent.com","project_id":"elodietestphotos-1561522235041","auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://oauth2.googleapis.com/token","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs","client_secret":"p84GOD_i7_PwDGbAmpnbwKiH","redirect_uris":["urn:ietf:wg:oauth:2.0:oob","http://localhost"]}}

View File

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

Before

Width:  |  Height:  |  Size: 222 B

After

Width:  |  Height:  |  Size: 222 B

View File

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

View File

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

Before

Width:  |  Height:  |  Size: 9.2 KiB

After

Width:  |  Height:  |  Size: 9.2 KiB

View File

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

@ -1,9 +1,15 @@
""" pytest test configuration """ """ pytest test configuration """
from configparser import RawConfigParser
import pytest import pytest
from pathlib import Path
import shutil
import tempfile
from dozo import config
from dozo.exiftool import _ExifToolProc from dozo.exiftool import _ExifToolProc
DOZO_PATH = Path(__file__).parent.parent
@pytest.fixture(autouse=True) @pytest.fixture(autouse=True)
def reset_singletons(): def reset_singletons():
@ -11,3 +17,33 @@ def reset_singletons():
_ExifToolProc.instance = None _ExifToolProc.instance = None
def copy_sample_files():
src_path = tempfile.mkdtemp(prefix='dozo-src')
paths = Path(DOZO_PATH, 'samples/test_exif').glob('*')
file_paths = [x for x in paths if x.is_file()]
for file_path in file_paths:
source_path = Path(src_path, file_path.name)
shutil.copyfile(file_path, source_path)
return src_path, file_paths
@pytest.fixture(scope="module")
def conf_path():
tmp_path = tempfile.mkdtemp(prefix='dozo-')
conf = RawConfigParser()
conf['Path'] = {
'day_begins': '4',
'dirs_path':'%u{%Y-%m}/{city}|{city}-{%Y}/{folders[:1]}/{folder}',
'name':'{%Y-%m-%b-%H-%M-%S}-{basename}.%l{ext}'
}
conf['Geolocation'] = {
'geocoder': 'Nominatium'
}
conf_path = Path(tmp_path, "dozo.conf")
config.write(conf_path, conf)
yield conf_path
shutil.rmtree(tmp_path)

View File

@ -1,4 +1,3 @@
from configparser import RawConfigParser
from pathlib import Path from pathlib import Path
import pytest import pytest
import shutil import shutil
@ -20,28 +19,11 @@ def write_random_file(file_path):
class TestConfig: class TestConfig:
@pytest.fixture(scope="module")
def conf_path(self):
tmp_path = tempfile.mkdtemp(prefix='dozo-')
yield Path(tmp_path, "dozo.conf")
shutil.rmtree(tmp_path)
@pytest.fixture(scope="module") @pytest.fixture(scope="module")
def conf(self, conf_path): def conf(self, conf_path):
return config.load_config(conf_path) return config.load_config(conf_path)
def test_write(self, conf_path): def test_write(self, conf_path):
conf = RawConfigParser()
conf['Path'] = {
'day_begins': '4',
'dirs_path':'%u{%Y-%m}/{city}|{city}-{%Y}/{folders[:1]}/{folder}',
'name':'{%Y-%m-%b-%H-%M-%S}-{basename}.%l{ext}'
}
conf['Geolocation'] = {
'geocoder': 'Nominatium'
}
config.write(conf_path, conf)
assert conf_path.is_file() assert conf_path.is_file()
def test_load_config(self, conf): def test_load_config(self, conf):

View File

@ -4,11 +4,10 @@ import os
import pytest import pytest
from pathlib import Path from pathlib import Path
import re import re
import shutil
from sys import platform from sys import platform
import tempfile
from time import sleep from time import sleep
from .conftest import copy_sample_files
from dozo import constants from dozo import constants
from dozo.database import Db from dozo.database import Db
from dozo.filesystem import FileSystem from dozo.filesystem import FileSystem
@ -16,37 +15,25 @@ from dozo.media.media import Media
from dozo.exiftool import ExifToolCaching, exiftool_is_running, terminate_exiftool from dozo.exiftool import ExifToolCaching, exiftool_is_running, terminate_exiftool
DOZO_PATH = Path(__file__).parent.parent
@pytest.mark.skip() @pytest.mark.skip()
class TestDb: class TestDb:
pass pass
class TestFilesystem: class TestFilesystem:
def setup_class(cls): def setup_class(cls):
cls.SRCPATH = tempfile.mkdtemp(prefix='dozo-src') cls.src_paths, cls.file_paths = copy_sample_files()
filenames = ['photo.png', 'plain.jpg', 'text.txt', 'withoutextension',
'no-exif.jpg']
cls.FILE_PATHS = set()
for filename in filenames:
source_path = Path(cls.SRCPATH, filename)
file_path = Path(DOZO_PATH, 'samples', filename)
shutil.copyfile(file_path, source_path)
cls.FILE_PATHS.add(source_path)
cls.path_format = constants.default_path + '/' + constants.default_name cls.path_format = constants.default_path + '/' + constants.default_name
def teardown_class(self): def teardown_class(self):
terminate_exiftool() terminate_exiftool()
assert not exiftool_is_running() assert not exiftool_is_running()
def test_get_part(self): def test_get_part(self, tmp_path):
""" """
Test all parts Test all parts
""" """
# Item to search for: # Item to search for:
filesystem = FileSystem() filesystem = FileSystem()
items = filesystem.get_items() items = filesystem.get_items()
masks = [ masks = [
'{album}', '{album}',
@ -85,59 +72,56 @@ class TestFilesystem:
subdirs = Path('a', 'b', 'c', 'd') subdirs = Path('a', 'b', 'c', 'd')
for file_path in self.FILE_PATHS: for file_path in self.file_paths:
media = Media(str(file_path)) media = Media(str(file_path))
exif_data = ExifToolCaching(str(file_path)).asdict() exif_data = ExifToolCaching(str(file_path)).asdict()
metadata = media.get_metadata() metadata = media.get_metadata()
for item, regex in items.items(): for item, regex in items.items():
for mask in masks: for mask in masks:
matched = re.search(regex, mask) matched = re.search(regex, mask)
if matched: if matched:
part = filesystem.get_part(item, mask[1:-1], metadata, part = filesystem.get_part(item, mask[1:-1],
{}, subdirs) metadata, Db(tmp_path), subdirs)
# check if part is correct # check if part is correct
assert isinstance(part, str) assert isinstance(part, str), file_path
expected_part = ''
if item == 'basename': if item == 'basename':
expected_part = file_path.stem assert part == file_path.stem, file_path
elif item == 'date': elif item == 'date':
assert datetime.strptime(part, mask[1:-1]) assert datetime.strptime(part, mask[1:-1])
expected_part = part
elif item == 'folder': elif item == 'folder':
expected_part = subdirs.name assert part == subdirs.name, file_path
elif item == 'folders': elif item == 'folders':
if platform == "win32": if platform == "win32":
assert '\\' in part assert '\\' in part, file_path
else: else:
assert '/' in part assert '/' in part, file_path
expected_part = part
elif item == 'ext': elif item == 'ext':
expected_part = file_path.suffix[1:] assert part == file_path.suffix[1:], file_path
if item == 'name': elif item == 'name':
expected_part = file_path.stem expected_part = file_path.stem
for i, rx in filesystem.match_date_from_string(expected_part): for i, rx in filesystem.match_date_from_string(expected_part):
expected_part = re.sub(rx, '', expected_part) part = re.sub(rx, '', expected_part)
assert part == expected_part, file_path
elif item == 'custom': elif item == 'custom':
expected_part = mask[2:-2] assert part == mask[2:-2], file_path
elif item in ('city', 'country', 'location', 'state'): elif item in ('city', 'country', 'location', 'state'):
expected_part = part pass
elif item in exif_tags.keys(): elif item in exif_tags.keys():
f = False f = False
for key in exif_tags[item]: for key in exif_tags[item]:
if key in exif_data: if key in exif_data:
f = True f = True
expected_part = exif_data[key] assert part == exif_data[key], file_path
break break
if f == False: if f == False:
expected_part = '' assert part == '', file_path
else:
assert part == expected_part assert part == '', file_path
def test_get_date_taken(self): def test_get_date_taken(self):
filesystem = FileSystem() filesystem = FileSystem()
for file_path in self.FILE_PATHS: for file_path in self.file_paths:
exif_data = ExifToolCaching(str(file_path)).asdict() exif_data = ExifToolCaching(str(file_path)).asdict()
media = Media(str(file_path)) media = Media(str(file_path))
metadata = media.get_metadata() metadata = media.get_metadata()
@ -167,7 +151,7 @@ class TestFilesystem:
db = Db(tmp_path) db = Db(tmp_path)
filesystem = FileSystem(path_format=self.path_format) filesystem = FileSystem(path_format=self.path_format)
summary, has_errors = filesystem.sort_files([self.SRCPATH], tmp_path, db) summary, has_errors = filesystem.sort_files([self.src_paths], tmp_path, db)
# Summary is created and there is no errors # Summary is created and there is no errors
assert summary, summary assert summary, summary
@ -181,7 +165,7 @@ class TestFilesystem:
for mode in 'copy', 'move': for mode in 'copy', 'move':
filesystem = FileSystem(path_format=self.path_format, mode=mode) filesystem = FileSystem(path_format=self.path_format, mode=mode)
# copy mode # copy mode
src_path = Path(self.SRCPATH, 'photo.png') src_path = Path(self.src_paths, 'photo.png')
dest_path = Path(tmp_path,'photo_copy.png') dest_path = Path(tmp_path,'photo_copy.png')
src_checksum = filesystem.checksum(src_path) src_checksum = filesystem.checksum(src_path)
result_copy = filesystem.sort_file(src_path, dest_path) result_copy = filesystem.sort_file(src_path, dest_path)

View File

@ -4,6 +4,7 @@ from pathlib import Path
import shutil import shutil
import tempfile import tempfile
from .conftest import copy_sample_files
from dozo import constants from dozo import constants
from dozo.media.media import Media from dozo.media.media import Media
from dozo.media.audio import Audio from dozo.media.audio import Audio
@ -16,15 +17,7 @@ DOZO_PATH = Path(__file__).parent.parent
class TestMetadata: class TestMetadata:
def setup_class(cls): def setup_class(cls):
cls.SRCPATH = tempfile.mkdtemp(prefix='dozo-src') cls.src_paths, cls.file_paths = copy_sample_files()
filenames = ['invalid.jpg', 'photo.png', 'plain.jpg', 'text.txt', 'withoutextension']
cls.file_paths = set()
for filename in filenames:
source_path = Path(cls.SRCPATH, filename)
file_path = Path(DOZO_PATH, 'samples', filename)
shutil.copyfile(file_path, source_path)
cls.file_paths.add(source_path)
cls.path_format = constants.default_path + '/' + constants.default_name
def test_get_exiftool_attribute(self, tmp_path): def test_get_exiftool_attribute(self, tmp_path):
for file_path in self.file_paths: for file_path in self.file_paths: