Merge branch 'pr-82'

This commit is contained in:
Jaisen Mathai 2016-02-11 15:25:19 -08:00
commit 4a985a6c5d
17 changed files with 178 additions and 59 deletions

View File

@ -15,9 +15,10 @@
How can I help you? <em>-- Elodie</em><i></i> How can I help you? <em>-- Elodie</em><i></i>
</div> </div>
<form class="importPhotos" action="" method="post"> <form class="importPhotos" action="" method="post">
<div class="content"> <div id="content" class="content">
<p> <p>
Let me know where your photos are and where you'd like me to put them as I sort them. Let me know where your photos are and where you'd like me to put them as I sort them.
<small><em>(You can drop your photos here to update its information.)</em></small>
</p> </p>
<div> <div>
<label for="source"><i class="icon-folder-open"></i> What folder are your photos in now?</label> <label for="source"><i class="icon-folder-open"></i> What folder are your photos in now?</label>

View File

@ -6,6 +6,8 @@ var __process__ = {};
if(typeof(require) === 'function') { if(typeof(require) === 'function') {
var ipc = require('ipc'); var ipc = require('ipc');
var path = require('path');
var os = require('os');
ipc.on('files', function(files) { ipc.on('files', function(files) {
__process__.files = files; __process__.files = files;
}); });
@ -32,7 +34,11 @@ if(typeof(require) === 'function') {
} }
}); });
ipc.on('update-photos-success', function(args) { ipc.on('update-photos-success', function(args) {
var response = JSON.parse(args['stdout']); if(os.platform() == 'win32'){
var response = JSON.parse(args['stdout'].replace(/\\/g, '\\\\'));
}else{
var response = JSON.parse(args['stdout']);
}
handlers.setSuccessTitle(); handlers.setSuccessTitle();
handlers.removeProgressIcons(); handlers.removeProgressIcons();
handlers.updateStatus(response); handlers.updateStatus(response);
@ -43,7 +49,28 @@ if(typeof(require) === 'function') {
ipc.send(name, message); ipc.send(name, message);
}; };
} }
}
window.onload = function () {
var broadcast = new Broadcast();
window.ondragover = function (e){ e.preventDefault(); return false };
window.ondragover = function (e){ e.preventDefault(); return false };
var holder = document.getElementById('content');
if(holder != null){
holder.ondrop = function (e) {
e.preventDefault();
files = []
for (var i = 0; i < e.dataTransfer.files.length; ++i) {
console.log(e.dataTransfer.files[i].path);
files.push(e.dataTransfer.files[i].path);
}
broadcast.send('load-update-photos', files);
return false;
};
}
};
};
function Handlers() { function Handlers() {
var self = this; var self = this;
@ -161,7 +188,7 @@ function Handlers() {
html = '<label>You selected ' + (files.length > 1 ? 'these photos' : 'this photo') + '</label>'; html = '<label>You selected ' + (files.length > 1 ? 'these photos' : 'this photo') + '</label>';
for(var i=0; i<files.length && i<16; i++) { for(var i=0; i<files.length && i<16; i++) {
if(files[i].match(/(mov|mp4|3gp|avi)/i) === null) { if(files[i].match(/(mov|mp4|3gp|avi)/i) === null) {
html += '<div class="center-cropped" style="background-image:url(\'file://'+files[i]+'\');" title="'+files[i]+'"></div>'; html += '<div class="center-cropped" style="background-image:url(\'file://'+fileUrl(files[i])+'\');" title="'+files[i]+'"></div>';
} else { } else {
html += '<div class="center-cropped video"></div>'; html += '<div class="center-cropped video"></div>';
} }
@ -200,6 +227,22 @@ function Handlers() {
el.style.display = 'block'; el.style.display = 'block';
} }
}; };
function fileUrl(str) {
if (typeof str !== 'string') {
throw new Error('Expected a string');
}
var pathName = path.resolve(str).replace(/\\/g, '/');
// Windows drive letter must be prefixed with a slash
if (pathName[0] !== '/') {
pathName = '/' + pathName;
}
return encodeURI('file://' + pathName);
};
} }
var handlers = new Handlers(); var handlers = new Handlers();
window.addEventListener('click', handlers.dispatch); window.addEventListener('click', handlers.dispatch);

View File

@ -18,7 +18,7 @@
<a href="index.html" class="right"><i class="icon-media-add"></i></a> <a href="index.html" class="right"><i class="icon-media-add"></i></a>
</div> </div>
<form class="updatePhotos" action="" method="post"> <form class="updatePhotos" action="" method="post">
<div class="content"> <div id="content" class="content">
<div class="location"> <div class="location">
<label for="location-field"><i class="icon-map"></i>Change geolocation</label> <label for="location-field"><i class="icon-map"></i>Change geolocation</label>
<input id="location-field" type="text" placeholder="i.e. Sunnyvale, CA"> <input id="location-field" type="text" placeholder="i.e. Sunnyvale, CA">

View File

@ -16,3 +16,4 @@ ipc.on('update-photos', broadcast.updatePhotos);
ipc.on('launch-finder', broadcast.launchFinder); ipc.on('launch-finder', broadcast.launchFinder);
ipc.on('launch-url', broadcast.launchUrl); ipc.on('launch-url', broadcast.launchUrl);
ipc.on('program-quit', broadcast.programQuit); ipc.on('program-quit', broadcast.programQuit);
ipc.on('load-update-photos', toolbarUi.onDropFiles);

View File

@ -1,5 +1,5 @@
var exports = module.exports = {}; var exports = module.exports = {};
var path = require('path');
var exec = require('child_process').exec, var exec = require('child_process').exec,
config = require('./config.js'); config = require('./config.js');
@ -24,7 +24,7 @@ exports.importPhotos = function(event, args) {
args['source'] = args['source'].normalize(); args['source'] = args['source'].normalize();
args['destination'] = args['destination'].normalize(); args['destination'] = args['destination'].normalize();
update_command = __dirname + '/../../dist/elodie/elodie import --source="' + args['source'] + '" --destination="' + args['destination'] + '"'; update_command = path.normalize(__dirname + '/../../dist/elodie/elodie') + ' import --source="' + args['source'] + '" --destination="' + args['destination'] + '"';
//update_command = __dirname + '/../../elodie.py import --source="' + args['source'] + '" --destination="' + args['destination'] + '"'; //update_command = __dirname + '/../../elodie.py import --source="' + args['source'] + '" --destination="' + args['destination'] + '"';
console.log(update_command); console.log(update_command);
@ -73,8 +73,8 @@ exports.updatePhotos = function(event, args) {
return files return files
} }
files = normalize(args['files']) files = normalize(args['files'])
elodie_path = path.normalize(__dirname + '/../../dist/elodie/elodie');
update_command = __dirname + '/../../dist/elodie/elodie update' update_command = elodie_path +' update'
//update_command = __dirname + '/../../elodie.py update' //update_command = __dirname + '/../../elodie.py update'
if(args['location'].length > 0) { if(args['location'].length > 0) {
update_command += ' --location="' + args['location'] + '"'; update_command += ' --location="' + args['location'] + '"';

View File

@ -1,13 +1,14 @@
var exports = module.exports = {}; var exports = module.exports = {};
var fs = require('fs'), var fs = require('fs'),
os = require('os'),
defaultConfigFile = (function() { defaultConfigFile = (function() {
var f = __dirname; var f = __dirname;
for(var i=0; i<2; i++) { for(var i=0; i<2; i++) {
f = f.substr(0, f.lastIndexOf('/')); f = f.substr(0, f.lastIndexOf(os.platform() == 'win32' ? '\\' : '/'));
} }
return f + '/config.ini-sample'; return f + (os.platform() == 'win32' ? '\\config.ini-sample': '/config.ini-sample');
})(), })(),
configFile = (process.env.HOME || process.env.USERPROFILE) + '/.elodie/config.ini', configFile = (process.env.HOME || process.env.USERPROFILE) + (os.platform() == 'win32' ? '\\.elodie\\config.ini' : '/.elodie/config.ini'),
hasConfig, hasConfig,
setConfig; setConfig;

View File

@ -5,11 +5,15 @@ var menubar = require('menubar'),
tray = require('tray'), tray = require('tray'),
config = require('./config.js'), config = require('./config.js'),
loadUrl = null; loadUrl = null;
var os = require('os')
var s_dir = __dirname.substr(0,__dirname.lastIndexOf(os.platform() == 'win32' ? '\\' : '/')) +
(os.platform() == 'win32' ? '\\html' : '/html');
exports.app = app = menubar( exports.app = app = menubar(
{ {
preloadWindow: true, preloadWindow: true,
dir: __dirname.substr(0, __dirname.lastIndexOf('/')) + '/html', dir: s_dir,
index: 'index.html', index: 'index.html',
pages: { pages: {
'blank': 'blank.html', 'blank': 'blank.html',
@ -18,7 +22,9 @@ exports.app = app = menubar(
}, },
width: 400, width: 400,
height: 500, height: 500,
'window-position': 'trayCenter' 'window-position': 'trayCenter',
'frame': os.platform() == 'win32' ? true : false,
'always-on-top': os.platform() == 'win32' ? true : false
} }
); );
@ -59,6 +65,18 @@ exports.ready = function() {
}); });
}; };
exports.onDropFiles = function(event, args) {
var files = args;
loadUrl = app.getOption('pages')['location'];
app.showWindow();
app.window.webContents.on('did-finish-load', function() {
app.window.webContents.send('files', files);
app.window.webContents.send('preview', files);
});
};
exports.createWindow = function() { exports.createWindow = function() {
console.log('create-window') console.log('create-window')
}; };

View File

@ -5,7 +5,7 @@ Settings used by Elodie.
from os import path from os import path
#: If True, debug messages will be printed. #: If True, debug messages will be printed.
debug = True debug = False
#: Directory in which to store Elodie settings. #: Directory in which to store Elodie settings.
application_directory = '{}/.elodie'.format(path.expanduser('~')) application_directory = '{}/.elodie'.format(path.expanduser('~'))
@ -20,4 +20,7 @@ location_db = '{}/location.json'.format(application_directory)
script_directory = path.dirname(path.dirname(path.abspath(__file__))) script_directory = path.dirname(path.dirname(path.abspath(__file__)))
#: Path to Elodie's ExifTool config file. #: Path to Elodie's ExifTool config file.
exiftool_config = '%s/configs/ExifTool_config' % script_directory exiftool_config = path.join(script_directory, 'configs', 'ExifTool_config')
#: Accepted language in responses from MapQuest
accepted_language = 'en'

View File

@ -68,7 +68,7 @@ class FileSystem(object):
extensions is None or extensions is None or
filename.lower().endswith(extensions) filename.lower().endswith(extensions)
): ):
files.append('%s/%s' % (dirname, filename)) files.append(os.path.join(dirname, filename))
return files return files
def get_current_directory(self): def get_current_directory(self):
@ -164,7 +164,7 @@ class FileSystem(object):
path.append('Unknown Location') path.append('Unknown Location')
# return '/'.join(path[::-1]) # return '/'.join(path[::-1])
return '/'.join(path) return os.path.join(*path)
def process_file(self, _file, destination, media, **kwargs): def process_file(self, _file, destination, media, **kwargs):
move = False move = False
@ -179,9 +179,9 @@ class FileSystem(object):
directory_name = self.get_folder_path(metadata) directory_name = self.get_folder_path(metadata)
dest_directory = '%s/%s' % (destination, directory_name) dest_directory = os.path.join(destination, directory_name)
file_name = self.get_file_name(media) file_name = self.get_file_name(media)
dest_path = '%s/%s' % (dest_directory, file_name) dest_path = os.path.join(dest_directory, file_name)
db = Db() db = Db()
checksum = db.checksum(_file) checksum = db.checksum(_file)

View File

@ -161,9 +161,10 @@ def reverse_lookup(lat, lon):
try: try:
params = {'format': 'json', 'key': key, 'lat': lat, 'lon': lon} params = {'format': 'json', 'key': key, 'lat': lat, 'lon': lon}
headers = {"Accept-Language": constants.accepted_language}
r = requests.get( r = requests.get(
'http://open.mapquestapi.com/nominatim/v1/reverse.php?%s' % 'http://open.mapquestapi.com/nominatim/v1/reverse.php?%s' %
urllib.urlencode(params) urllib.urlencode(params), headers=headers
) )
return r.json() return r.json()
except requests.exceptions.RequestException as e: except requests.exceptions.RequestException as e:

View File

@ -98,7 +98,7 @@ class Db(object):
:returns: str or None :returns: str or None
""" """
hasher = hashlib.sha256() hasher = hashlib.sha256()
with open(file_path, 'r') as f: with open(file_path, 'rb') as f:
buf = f.read(blocksize) buf = f.read(blocksize)
while len(buf) > 0: while len(buf) > 0:

View File

@ -106,9 +106,10 @@ class Media(object):
source = self.source source = self.source
process_output = subprocess.Popen( process_output = subprocess.Popen(
['%s "%s"' % (exiftool, source)], '%s "%s"' % (exiftool, source),
stdout=subprocess.PIPE, stdout=subprocess.PIPE,
shell=True shell=True,
universal_newlines=True
) )
output = process_output.stdout.read() output = process_output.stdout.read()
@ -224,8 +225,8 @@ class Media(object):
if(constants.debug is True): if(constants.debug is True):
print '%s -config "%s" -xmp-elodie:Album="%s" "%s"' % (exiftool, exiftool_config, name, source) # noqa print '%s -config "%s" -xmp-elodie:Album="%s" "%s"' % (exiftool, exiftool_config, name, source) # noqa
process_output = subprocess.Popen( process_output = subprocess.Popen(
['%s -config "%s" -xmp-elodie:Album="%s" "%s"' % '%s -config "%s" -xmp-elodie:Album="%s" "%s"' %
(exiftool, exiftool_config, name, source)], (exiftool, exiftool_config, name, source),
stdout=subprocess.PIPE, stdout=subprocess.PIPE,
shell=True shell=True
) )

View File

@ -156,9 +156,10 @@ class Video(Media):
source = self.source source = self.source
process_output = subprocess.Popen( process_output = subprocess.Popen(
['%s "%s"' % (exiftool, source)], '%s "%s"' % (exiftool, source),
stdout=subprocess.PIPE, stdout=subprocess.PIPE,
shell=True shell=True,
universal_newlines=True
) )
return process_output.stdout.read() return process_output.stdout.read()

View File

@ -4,6 +4,9 @@ import sys
import re import re
import shutil import shutil
from datetime import datetime
from datetime import timedelta
import time
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.dirname(os.path.realpath(__file__))))))
@ -12,13 +15,14 @@ from elodie.filesystem import FileSystem
from elodie.media.media import Media from elodie.media.media import Media
from elodie.media.photo import Photo from elodie.media.photo import Photo
from elodie.media.video import Video from elodie.media.video import Video
from nose.plugins.skip import SkipTest
os.environ['TZ'] = 'GMT' os.environ['TZ'] = 'GMT'
def test_create_directory_success(): def test_create_directory_success():
filesystem = FileSystem() filesystem = FileSystem()
folder = '%s/%s' % (helper.temp_dir(), helper.random_string(10)) folder = os.path.join(helper.temp_dir(), helper.random_string(10))
status = filesystem.create_directory(folder) status = filesystem.create_directory(folder)
# Needs to be a subdirectory # Needs to be a subdirectory
@ -34,7 +38,7 @@ def test_create_directory_success():
def test_create_directory_recursive_success(): def test_create_directory_recursive_success():
filesystem = FileSystem() filesystem = FileSystem()
folder = '%s/%s/%s' % (helper.temp_dir(), helper.random_string(10), helper.random_string(10)) folder = os.path.join(helper.temp_dir(), helper.random_string(10), helper.random_string(10))
status = filesystem.create_directory(folder) status = filesystem.create_directory(folder)
# Needs to be a subdirectory # Needs to be a subdirectory
@ -47,6 +51,8 @@ def test_create_directory_recursive_success():
shutil.rmtree(folder) shutil.rmtree(folder)
def test_create_directory_invalid_permissions(): def test_create_directory_invalid_permissions():
if os.name == 'nt':
raise SkipTest("It isn't implemented on Windows")
filesystem = FileSystem() filesystem = FileSystem()
status = filesystem.create_directory('/apathwhichdoesnotexist/afolderwhichdoesnotexist') status = filesystem.create_directory('/apathwhichdoesnotexist/afolderwhichdoesnotexist')
@ -54,7 +60,7 @@ def test_create_directory_invalid_permissions():
def test_delete_directory_if_empty(): def test_delete_directory_if_empty():
filesystem = FileSystem() filesystem = FileSystem()
folder = '%s/%s' % (helper.temp_dir(), helper.random_string(10)) folder = os.path.join(helper.temp_dir(), helper.random_string(10))
os.makedirs(folder) os.makedirs(folder)
assert os.path.isdir(folder) == True assert os.path.isdir(folder) == True
@ -67,7 +73,7 @@ def test_delete_directory_if_empty():
def test_delete_directory_if_empty_when_not_empty(): def test_delete_directory_if_empty_when_not_empty():
filesystem = FileSystem() filesystem = FileSystem()
folder = '%s/%s/%s' % (helper.temp_dir(), helper.random_string(10), helper.random_string(10)) folder = os.path.join(helper.temp_dir(), helper.random_string(10), helper.random_string(10))
os.makedirs(folder) os.makedirs(folder)
parent_folder = os.path.dirname(folder) parent_folder = os.path.dirname(folder)
@ -126,14 +132,14 @@ def test_get_file_name_plain():
media = Photo(helper.get_file('plain.jpg')) media = Photo(helper.get_file('plain.jpg'))
file_name = filesystem.get_file_name(media) file_name = filesystem.get_file_name(media)
assert file_name == '2015-12-05_00-59-26-plain.jpg', file_name assert file_name == helper.path_tz_fix('2015-12-05_00-59-26-plain.jpg'), file_name
def test_get_file_name_with_title(): def test_get_file_name_with_title():
filesystem = FileSystem() filesystem = FileSystem()
media = Photo(helper.get_file('with-title.jpg')) media = Photo(helper.get_file('with-title.jpg'))
file_name = filesystem.get_file_name(media) file_name = filesystem.get_file_name(media)
assert file_name == '2015-12-05_00-59-26-with-title-some-title.jpg', file_name assert file_name == helper.path_tz_fix('2015-12-05_00-59-26-with-title-some-title.jpg'), file_name
def test_get_folder_name_by_date(): def test_get_folder_name_by_date():
filesystem = FileSystem() filesystem = FileSystem()
@ -152,34 +158,34 @@ def test_get_folder_path_plain():
media = Photo(helper.get_file('plain.jpg')) media = Photo(helper.get_file('plain.jpg'))
path = filesystem.get_folder_path(media.get_metadata()) path = filesystem.get_folder_path(media.get_metadata())
assert path == '2015-12-Dec/Unknown Location', path assert path == os.path.join('2015-12-Dec','Unknown Location'), path
def test_get_folder_path_with_title(): def test_get_folder_path_with_title():
filesystem = FileSystem() filesystem = FileSystem()
media = Photo(helper.get_file('with-title.jpg')) media = Photo(helper.get_file('with-title.jpg'))
path = filesystem.get_folder_path(media.get_metadata()) path = filesystem.get_folder_path(media.get_metadata())
assert path == '2015-12-Dec/Unknown Location', path assert path == os.path.join('2015-12-Dec','Unknown Location'), path
def test_get_folder_path_with_location(): def test_get_folder_path_with_location():
filesystem = FileSystem() filesystem = FileSystem()
media = Photo(helper.get_file('with-location.jpg')) media = Photo(helper.get_file('with-location.jpg'))
path = filesystem.get_folder_path(media.get_metadata()) path = filesystem.get_folder_path(media.get_metadata())
assert path == '2015-12-Dec/Sunnyvale', path assert path == os.path.join('2015-12-Dec','Sunnyvale'), path
def test_get_folder_path_with_location_and_title(): def test_get_folder_path_with_location_and_title():
filesystem = FileSystem() filesystem = FileSystem()
media = Photo(helper.get_file('with-location-and-title.jpg')) media = Photo(helper.get_file('with-location-and-title.jpg'))
path = filesystem.get_folder_path(media.get_metadata()) path = filesystem.get_folder_path(media.get_metadata())
assert path == '2015-12-Dec/Sunnyvale', path assert path == os.path.join('2015-12-Dec','Sunnyvale'), path
def test_process_file_plain(): def test_process_file_plain():
filesystem = FileSystem() filesystem = FileSystem()
temporary_folder, folder = helper.create_working_folder() temporary_folder, folder = helper.create_working_folder()
origin = '%s/photo.jpg' % folder origin = os.path.join(folder,'photo.jpg')
shutil.copyfile(helper.get_file('plain.jpg'), origin) shutil.copyfile(helper.get_file('plain.jpg'), origin)
media = Photo(origin) media = Photo(origin)
@ -193,7 +199,7 @@ def test_process_file_plain():
assert origin_checksum is not None, origin_checksum assert origin_checksum is not None, origin_checksum
assert origin_checksum == destination_checksum, destination_checksum assert origin_checksum == destination_checksum, destination_checksum
assert '2015-12-Dec/Unknown Location/2015-12-05_00-59-26-photo.jpg' in destination, destination assert helper.path_tz_fix(os.path.join('2015-12-Dec','Unknown Location','2015-12-05_00-59-26-photo.jpg')) in destination, destination
def test_process_file_with_title(): def test_process_file_with_title():
filesystem = FileSystem() filesystem = FileSystem()
@ -213,13 +219,13 @@ def test_process_file_with_title():
assert origin_checksum is not None, origin_checksum assert origin_checksum is not None, origin_checksum
assert origin_checksum == destination_checksum, destination_checksum assert origin_checksum == destination_checksum, destination_checksum
assert '2015-12-Dec/Unknown Location/2015-12-05_00-59-26-photo-some-title.jpg' in destination, destination assert helper.path_tz_fix(os.path.join('2015-12-Dec','Unknown Location','2015-12-05_00-59-26-photo-some-title.jpg')) in destination, destination
def test_process_file_with_location(): def test_process_file_with_location():
filesystem = FileSystem() filesystem = FileSystem()
temporary_folder, folder = helper.create_working_folder() temporary_folder, folder = helper.create_working_folder()
origin = '%s/photo.jpg' % folder origin = os.path.join(folder,'photo.jpg')
shutil.copyfile(helper.get_file('with-location.jpg'), origin) shutil.copyfile(helper.get_file('with-location.jpg'), origin)
media = Photo(origin) media = Photo(origin)
@ -233,13 +239,13 @@ def test_process_file_with_location():
assert origin_checksum is not None, origin_checksum assert origin_checksum is not None, origin_checksum
assert origin_checksum == destination_checksum, destination_checksum assert origin_checksum == destination_checksum, destination_checksum
assert '2015-12-Dec/Sunnyvale/2015-12-05_00-59-26-photo.jpg' in destination, destination assert helper.path_tz_fix(os.path.join('2015-12-Dec','Sunnyvale','2015-12-05_00-59-26-photo.jpg')) in destination, destination
def test_process_file_with_location_and_title(): def test_process_file_with_location_and_title():
filesystem = FileSystem() filesystem = FileSystem()
temporary_folder, folder = helper.create_working_folder() temporary_folder, folder = helper.create_working_folder()
origin = '%s/photo.jpg' % folder origin = os.path.join(folder,'photo.jpg')
shutil.copyfile(helper.get_file('with-location-and-title.jpg'), origin) shutil.copyfile(helper.get_file('with-location-and-title.jpg'), origin)
media = Photo(origin) media = Photo(origin)
@ -253,13 +259,13 @@ def test_process_file_with_location_and_title():
assert origin_checksum is not None, origin_checksum assert origin_checksum is not None, origin_checksum
assert origin_checksum == destination_checksum, destination_checksum assert origin_checksum == destination_checksum, destination_checksum
assert '2015-12-Dec/Sunnyvale/2015-12-05_00-59-26-photo-some-title.jpg' in destination, destination assert helper.path_tz_fix(os.path.join('2015-12-Dec','Sunnyvale','2015-12-05_00-59-26-photo-some-title.jpg')) in destination, destination
def test_process_file_with_album(): def test_process_file_with_album():
filesystem = FileSystem() filesystem = FileSystem()
temporary_folder, folder = helper.create_working_folder() temporary_folder, folder = helper.create_working_folder()
origin = '%s/photo.jpg' % folder origin = os.path.join(folder,'photo.jpg')
shutil.copyfile(helper.get_file('with-album.jpg'), origin) shutil.copyfile(helper.get_file('with-album.jpg'), origin)
media = Photo(origin) media = Photo(origin)
@ -273,13 +279,13 @@ def test_process_file_with_album():
assert origin_checksum is not None, origin_checksum assert origin_checksum is not None, origin_checksum
assert origin_checksum == destination_checksum, destination_checksum assert origin_checksum == destination_checksum, destination_checksum
assert '2015-12-Dec/Test Album/2015-12-05_00-59-26-photo.jpg' in destination, destination assert helper.path_tz_fix(os.path.join('2015-12-Dec','Test Album','2015-12-05_00-59-26-photo.jpg')) in destination, destination
def test_process_file_with_album_and_title(): def test_process_file_with_album_and_title():
filesystem = FileSystem() filesystem = FileSystem()
temporary_folder, folder = helper.create_working_folder() temporary_folder, folder = helper.create_working_folder()
origin = '%s/photo.jpg' % folder origin = os.path.join(folder,'photo.jpg')
shutil.copyfile(helper.get_file('with-album-and-title.jpg'), origin) shutil.copyfile(helper.get_file('with-album-and-title.jpg'), origin)
media = Photo(origin) media = Photo(origin)
@ -293,13 +299,13 @@ def test_process_file_with_album_and_title():
assert origin_checksum is not None, origin_checksum assert origin_checksum is not None, origin_checksum
assert origin_checksum == destination_checksum, destination_checksum assert origin_checksum == destination_checksum, destination_checksum
assert '2015-12-Dec/Test Album/2015-12-05_00-59-26-photo-some-title.jpg' in destination, destination assert helper.path_tz_fix(os.path.join('2015-12-Dec','Test Album','2015-12-05_00-59-26-photo-some-title.jpg')) in destination, destination
def test_process_file_with_album_and_title_and_location(): def test_process_file_with_album_and_title_and_location():
filesystem = FileSystem() filesystem = FileSystem()
temporary_folder, folder = helper.create_working_folder() temporary_folder, folder = helper.create_working_folder()
origin = '%s/photo.jpg' % folder origin = os.path.join(folder,'photo.jpg')
shutil.copyfile(helper.get_file('with-album-and-title-and-location.jpg'), origin) shutil.copyfile(helper.get_file('with-album-and-title-and-location.jpg'), origin)
media = Photo(origin) media = Photo(origin)
@ -313,4 +319,4 @@ def test_process_file_with_album_and_title_and_location():
assert origin_checksum is not None, origin_checksum assert origin_checksum is not None, origin_checksum
assert origin_checksum == destination_checksum, destination_checksum assert origin_checksum == destination_checksum, destination_checksum
assert '2015-12-Dec/Test Album/2015-12-05_00-59-26-photo-some-title.jpg' in destination, destination assert helper.path_tz_fix(os.path.join('2015-12-Dec','Test Album','2015-12-05_00-59-26-photo-some-title.jpg')) in destination, destination

View File

@ -3,6 +3,11 @@ import os
import random import random
import string import string
import tempfile import tempfile
import re
import time
from datetime import datetime
from datetime import timedelta
def checksum(file_path, blocksize=65536): def checksum(file_path, blocksize=65536):
hasher = hashlib.sha256() hasher = hashlib.sha256()
@ -17,14 +22,14 @@ def checksum(file_path, blocksize=65536):
def create_working_folder(): def create_working_folder():
temporary_folder = tempfile.gettempdir() temporary_folder = tempfile.gettempdir()
folder = '%s/%s/%s' % (temporary_folder, random_string(10), random_string(10)) folder = os.path.join(temporary_folder, random_string(10), random_string(10))
os.makedirs(folder) os.makedirs(folder)
return (temporary_folder, folder) return (temporary_folder, folder)
def get_file(name): def get_file(name):
current_folder = os.path.dirname(os.path.realpath(__file__)) current_folder = os.path.dirname(os.path.realpath(__file__))
return '%s/files/%s' % (current_folder, name) return os.path.join(current_folder, 'files', name)
def get_test_location(): def get_test_location():
return (61.013710, 99.196656, 'Siberia') return (61.013710, 99.196656, 'Siberia')
@ -53,3 +58,37 @@ def random_coordinate(coordinate, precision):
def temp_dir(): def temp_dir():
return tempfile.gettempdir() 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 = (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

View File

@ -3,7 +3,7 @@
import os import os
import sys import sys
import datetime from datetime import datetime
import shutil import shutil
import tempfile import tempfile
import time import time
@ -95,7 +95,8 @@ def test_get_date_taken():
photo = Photo(helper.get_file('plain.jpg')) photo = Photo(helper.get_file('plain.jpg'))
date_taken = photo.get_date_taken() date_taken = photo.get_date_taken()
assert date_taken == (2015, 12, 5, 0, 59, 26, 5, 339, 0), date_taken # assert date_taken == (2015, 12, 5, 0, 59, 26, 5, 339, 0), date_taken
assert date_taken == helper.time_convert((2015, 12, 5, 0, 59, 26, 5, 339, 0)), date_taken
def test_get_date_taken_without_exif(): def test_get_date_taken_without_exif():
source = helper.get_file('no-exif.jpg') source = helper.get_file('no-exif.jpg')
@ -125,7 +126,7 @@ def test_set_date_taken_with_missing_datetimeoriginal():
shutil.copyfile(helper.get_file('no-exif.jpg'), origin) shutil.copyfile(helper.get_file('no-exif.jpg'), origin)
photo = Photo(origin) photo = Photo(origin)
status = photo.set_date_taken(datetime.datetime(2013, 9, 30, 7, 6, 5)) status = photo.set_date_taken(datetime(2013, 9, 30, 7, 6, 5))
assert status == True, status assert status == True, status
@ -136,7 +137,8 @@ def test_set_date_taken_with_missing_datetimeoriginal():
shutil.rmtree(folder) shutil.rmtree(folder)
assert date_taken == (2013, 9, 30, 7, 6, 5, 0, 273, 0), metadata['date_taken'] #assert date_taken == (2013, 9, 30, 7, 6, 5, 0, 273, 0), metadata['date_taken']
assert date_taken == helper.time_convert((2013, 9, 30, 7, 6, 5, 0, 273, 0)), metadata['date_taken']
def test_set_date_taken(): def test_set_date_taken():
temporary_folder, folder = helper.create_working_folder() temporary_folder, folder = helper.create_working_folder()
@ -145,7 +147,7 @@ def test_set_date_taken():
shutil.copyfile(helper.get_file('plain.jpg'), origin) shutil.copyfile(helper.get_file('plain.jpg'), origin)
photo = Photo(origin) photo = Photo(origin)
status = photo.set_date_taken(datetime.datetime(2013, 9, 30, 7, 6, 5)) status = photo.set_date_taken(datetime(2013, 9, 30, 7, 6, 5))
assert status == True, status assert status == True, status
@ -156,7 +158,8 @@ def test_set_date_taken():
shutil.rmtree(folder) shutil.rmtree(folder)
assert date_taken == (2013, 9, 30, 7, 6, 5, 0, 273, 0), metadata['date_taken'] #assert date_taken == (2013, 9, 30, 7, 6, 5, 0, 273, 0), metadata['date_taken']
assert date_taken == helper.time_convert((2013, 9, 30, 7, 6, 5, 0, 273, 0)), metadata['date_taken']
def test_set_location(): def test_set_location():
raise SkipTest('gh-31, precision is lost in conversion from decimal to dms') raise SkipTest('gh-31, precision is lost in conversion from decimal to dms')

View File

@ -2,3 +2,4 @@ click>=6.2,<7.0
LatLon>=1.0.2,<2.0 LatLon>=1.0.2,<2.0
requests>=2.9.1,<3.0 requests>=2.9.1,<3.0
send2trash>=1.3.0,<2.0 send2trash>=1.3.0,<2.0
mock>=1.3.0