Fix tests and cleanup
|
@ -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
|
|
|
@ -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']
|
|
|
@ -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()
|
|
|
@ -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'])
|
|
|
@ -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']
|
|
|
@ -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
|
|
|
@ -1,4 +0,0 @@
|
||||||
-r ../../requirements.txt
|
|
||||||
flake8==2.6.2
|
|
||||||
mock==1.3.0
|
|
||||||
nose==1.3.7
|
|
|
@ -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
|
|
|
@ -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
|
|
|
@ -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
|
|
|
@ -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
|
|
|
@ -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
|
|
|
@ -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
|
|
|
@ -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))
|
|
|
@ -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
|
|
|
@ -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)
|
|
|
@ -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"}
|
|
|
@ -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"]}}
|
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
Before Width: | Height: | Size: 222 B After Width: | Height: | Size: 222 B |
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 4.0 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 9.2 KiB After Width: | Height: | Size: 9.2 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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:
|
||||||
|
|