Python 3 compartibility added
This commit is contained in:
		
							parent
							
								
									4f19c0c00d
								
							
						
					
					
						commit
						af36de091e
					
				@ -2,14 +2,15 @@ language: python
 | 
				
			|||||||
dist: trusty
 | 
					dist: trusty
 | 
				
			||||||
python:
 | 
					python:
 | 
				
			||||||
  - "2.7"
 | 
					  - "2.7"
 | 
				
			||||||
 | 
					  - "3.4"
 | 
				
			||||||
virtualenv:
 | 
					virtualenv:
 | 
				
			||||||
  system_site_packages: true
 | 
					  system_site_packages: true
 | 
				
			||||||
before_install:
 | 
					before_install:
 | 
				
			||||||
  - "sudo apt-get update -qq"
 | 
					  - "sudo apt-get update -qq"
 | 
				
			||||||
  - "sudo apt-get install python-dev python-pip libimage-exiftool-perl -y"
 | 
					  - "sudo apt-get install python-dev python-pip libimage-exiftool-perl -y"
 | 
				
			||||||
install:
 | 
					install:
 | 
				
			||||||
  - "sudo pip install -r elodie/tests/requirements.txt"
 | 
					  - "pip install -r elodie/tests/requirements.txt"
 | 
				
			||||||
  - "sudo pip install coveralls"
 | 
					  - "pip install coveralls"
 | 
				
			||||||
# command to run tests
 | 
					# command to run tests
 | 
				
			||||||
# test mapquest key
 | 
					# test mapquest key
 | 
				
			||||||
before_script:
 | 
					before_script:
 | 
				
			||||||
@ -25,5 +26,5 @@ before_script:
 | 
				
			|||||||
  - "cd ${ELODIE_DIR}"
 | 
					  - "cd ${ELODIE_DIR}"
 | 
				
			||||||
after_success:
 | 
					after_success:
 | 
				
			||||||
  - "coveralls"
 | 
					  - "coveralls"
 | 
				
			||||||
script: 
 | 
					script:
 | 
				
			||||||
  - "nosetests --with-coverage --cover-package=elodie -w elodie/tests"
 | 
					  - "nosetests --with-coverage --cover-package=elodie -w elodie/tests"
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										35
									
								
								elodie.py
									
									
									
									
									
								
							
							
						
						
									
										35
									
								
								elodie.py
									
									
									
									
									
								
							@ -1,5 +1,6 @@
 | 
				
			|||||||
#!/usr/bin/env python
 | 
					#!/usr/bin/env python
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from __future__ import print_function
 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
import re
 | 
					import re
 | 
				
			||||||
import sys
 | 
					import sys
 | 
				
			||||||
@ -35,16 +36,16 @@ def import_file(_file, destination, album_from_folder, trash):
 | 
				
			|||||||
    """
 | 
					    """
 | 
				
			||||||
    if not os.path.exists(_file):
 | 
					    if not os.path.exists(_file):
 | 
				
			||||||
        if constants.debug:
 | 
					        if constants.debug:
 | 
				
			||||||
            print 'Could not find %s' % _file
 | 
					            print('Could not find %s' % _file)
 | 
				
			||||||
        print '{"source":"%s", "error_msg":"Could not find %s"}' % \
 | 
					        print('{"source":"%s", "error_msg":"Could not find %s"}' % \
 | 
				
			||||||
            (_file, _file)
 | 
					            (_file, _file))
 | 
				
			||||||
        return
 | 
					        return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    media = Media.get_class_by_file(_file, [Text, Audio, Photo, Video])
 | 
					    media = Media.get_class_by_file(_file, [Text, Audio, Photo, Video])
 | 
				
			||||||
    if not media:
 | 
					    if not media:
 | 
				
			||||||
        if constants.debug:
 | 
					        if constants.debug:
 | 
				
			||||||
            print 'Not a supported file (%s)' % _file
 | 
					            print('Not a supported file (%s)' % _file)
 | 
				
			||||||
        print '{"source":"%s", "error_msg":"Not a supported file"}' % _file
 | 
					        print('{"source":"%s", "error_msg":"Not a supported file"}' % _file)
 | 
				
			||||||
        return
 | 
					        return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if media.__name__ == 'Video':
 | 
					    if media.__name__ == 'Video':
 | 
				
			||||||
@ -56,7 +57,7 @@ def import_file(_file, destination, album_from_folder, trash):
 | 
				
			|||||||
    dest_path = FILESYSTEM.process_file(_file, destination,
 | 
					    dest_path = FILESYSTEM.process_file(_file, destination,
 | 
				
			||||||
        media, allowDuplicate=False, move=False)
 | 
					        media, allowDuplicate=False, move=False)
 | 
				
			||||||
    if dest_path:
 | 
					    if dest_path:
 | 
				
			||||||
        print '%s -> %s' % (_file, dest_path)
 | 
					        print('%s -> %s' % (_file, dest_path))
 | 
				
			||||||
    if trash:
 | 
					    if trash:
 | 
				
			||||||
        send2trash(_file)
 | 
					        send2trash(_file)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -109,9 +110,9 @@ def update_location(media, file_path, location_name):
 | 
				
			|||||||
            'latitude'], location_coords['longitude'])
 | 
					            'latitude'], location_coords['longitude'])
 | 
				
			||||||
        if not location_status:
 | 
					        if not location_status:
 | 
				
			||||||
            if constants.debug:
 | 
					            if constants.debug:
 | 
				
			||||||
                print 'Failed to update location'
 | 
					                print('Failed to update location')
 | 
				
			||||||
            print ('{"source":"%s",' % file_path,
 | 
					            print(('{"source":"%s",' % file_path,
 | 
				
			||||||
                '"error_msg":"Failed to update location"}')
 | 
					                '"error_msg":"Failed to update location"}'))
 | 
				
			||||||
            sys.exit(1)
 | 
					            sys.exit(1)
 | 
				
			||||||
    return True
 | 
					    return True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -125,8 +126,8 @@ def update_time(media, file_path, time_string):
 | 
				
			|||||||
    elif re.match(r'^\d{4}-\d{2}-\d{2} \d{2}:\d{2}\d{2}$', time_string):
 | 
					    elif re.match(r'^\d{4}-\d{2}-\d{2} \d{2}:\d{2}\d{2}$', time_string):
 | 
				
			||||||
        msg = ('Invalid time format. Use YYYY-mm-dd hh:ii:ss or YYYY-mm-dd')
 | 
					        msg = ('Invalid time format. Use YYYY-mm-dd hh:ii:ss or YYYY-mm-dd')
 | 
				
			||||||
        if constants.debug:
 | 
					        if constants.debug:
 | 
				
			||||||
            print msg
 | 
					            print(msg)
 | 
				
			||||||
        print '{"source":"%s", "error_msg":"%s"}' % (file_path, msg)
 | 
					        print('{"source":"%s", "error_msg":"%s"}' % (file_path, msg))
 | 
				
			||||||
        sys.exit(1)
 | 
					        sys.exit(1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    time = datetime.strptime(time_string, time_format)
 | 
					    time = datetime.strptime(time_string, time_format)
 | 
				
			||||||
@ -150,9 +151,9 @@ def _update(album, location, time, title, files):
 | 
				
			|||||||
    for file_path in files:
 | 
					    for file_path in files:
 | 
				
			||||||
        if not os.path.exists(file_path):
 | 
					        if not os.path.exists(file_path):
 | 
				
			||||||
            if constants.debug:
 | 
					            if constants.debug:
 | 
				
			||||||
                print 'Could not find %s' % file_path
 | 
					                print('Could not find %s' % file_path)
 | 
				
			||||||
            print '{"source":"%s", "error_msg":"Could not find %s"}' % \
 | 
					            print('{"source":"%s", "error_msg":"Could not find %s"}' % \
 | 
				
			||||||
                (file_path, file_path)
 | 
					                (file_path, file_path))
 | 
				
			||||||
            continue
 | 
					            continue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        file_path = os.path.expanduser(file_path)
 | 
					        file_path = os.path.expanduser(file_path)
 | 
				
			||||||
@ -209,9 +210,9 @@ def _update(album, location, time, title, files):
 | 
				
			|||||||
            dest_path = FILESYSTEM.process_file(file_path, destination,
 | 
					            dest_path = FILESYSTEM.process_file(file_path, destination,
 | 
				
			||||||
                updated_media, move=True, allowDuplicate=True)
 | 
					                updated_media, move=True, allowDuplicate=True)
 | 
				
			||||||
            if constants.debug:
 | 
					            if constants.debug:
 | 
				
			||||||
                print u'%s -> %s' % (file_path, dest_path)
 | 
					                print(u'%s -> %s' % (file_path, dest_path))
 | 
				
			||||||
            print '{"source":"%s", "destination":"%s"}' % (file_path,
 | 
					            print('{"source":"%s", "destination":"%s"}' % (file_path,
 | 
				
			||||||
                dest_path)
 | 
					                dest_path))
 | 
				
			||||||
            # If the folder we moved the file out of or its parent are empty
 | 
					            # If the folder we moved the file out of or its parent are empty
 | 
				
			||||||
            # we delete it.
 | 
					            # we delete it.
 | 
				
			||||||
            FILESYSTEM.delete_directory_if_empty(os.path.dirname(file_path))
 | 
					            FILESYSTEM.delete_directory_if_empty(os.path.dirname(file_path))
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,7 @@
 | 
				
			|||||||
"""
 | 
					"""
 | 
				
			||||||
Command line argument parsing for helper scripts.
 | 
					Command line argument parsing for helper scripts.
 | 
				
			||||||
"""
 | 
					"""
 | 
				
			||||||
 | 
					from __future__ import print_function
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import getopt
 | 
					import getopt
 | 
				
			||||||
import sys
 | 
					import sys
 | 
				
			||||||
@ -20,13 +21,13 @@ def parse(argv, options, long_options, usage):
 | 
				
			|||||||
    try:
 | 
					    try:
 | 
				
			||||||
        opts, args = getopt.getopt(argv, options, long_options)
 | 
					        opts, args = getopt.getopt(argv, options, long_options)
 | 
				
			||||||
    except getopt.GetoptError:
 | 
					    except getopt.GetoptError:
 | 
				
			||||||
        print usage
 | 
					        print(usage)
 | 
				
			||||||
        sys.exit(2)
 | 
					        sys.exit(2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return_arguments = {}
 | 
					    return_arguments = {}
 | 
				
			||||||
    for opt, arg in opts:
 | 
					    for opt, arg in opts:
 | 
				
			||||||
        if opt == '-h':
 | 
					        if opt == '-h':
 | 
				
			||||||
            print usage
 | 
					            print(usage)
 | 
				
			||||||
            sys.exit()
 | 
					            sys.exit()
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            return_arguments[sub('^-+', '', opt)] = arg
 | 
					            return_arguments[sub('^-+', '', opt)] = arg
 | 
				
			||||||
 | 
				
			|||||||
@ -2,6 +2,7 @@
 | 
				
			|||||||
Helpers for checking for an interacting with external dependencies. These are
 | 
					Helpers for checking for an interacting with external dependencies. These are
 | 
				
			||||||
things that Elodie requires, but aren't installed automatically for the user.
 | 
					things that Elodie requires, but aren't installed automatically for the user.
 | 
				
			||||||
"""
 | 
					"""
 | 
				
			||||||
 | 
					from __future__ import print_function
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
import sys
 | 
					import sys
 | 
				
			||||||
@ -43,7 +44,7 @@ def verify_dependencies():
 | 
				
			|||||||
    """
 | 
					    """
 | 
				
			||||||
    exiftool = get_exiftool()
 | 
					    exiftool = get_exiftool()
 | 
				
			||||||
    if exiftool is None:
 | 
					    if exiftool is None:
 | 
				
			||||||
        print >>sys.stderr, EXIFTOOL_ERROR
 | 
					        print(EXIFTOOL_ERROR, file=sys.stderr)
 | 
				
			||||||
        return False
 | 
					        return False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return True
 | 
					    return True
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										7
									
								
								elodie/external/pyexiftool.py
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										7
									
								
								elodie/external/pyexiftool.py
									
									
									
									
										vendored
									
									
								
							@ -273,8 +273,7 @@ class ExifTool(object):
 | 
				
			|||||||
        """
 | 
					        """
 | 
				
			||||||
        if not self.running:
 | 
					        if not self.running:
 | 
				
			||||||
            raise ValueError("ExifTool instance not running.")
 | 
					            raise ValueError("ExifTool instance not running.")
 | 
				
			||||||
        cmd_txt = b"\n".join(params + (b"-execute\n",))
 | 
					        self._process.stdin.write(b"\n".join(params + (b"-execute\n",)))
 | 
				
			||||||
        self._process.stdin.write(cmd_txt.encode("utf-8"))
 | 
					 | 
				
			||||||
        self._process.stdin.flush()
 | 
					        self._process.stdin.flush()
 | 
				
			||||||
        output = b""
 | 
					        output = b""
 | 
				
			||||||
        fd = self._process.stdout.fileno()
 | 
					        fd = self._process.stdout.fileno()
 | 
				
			||||||
@ -403,11 +402,13 @@ class ExifTool(object):
 | 
				
			|||||||
                            "an iterable of strings")
 | 
					                            "an iterable of strings")
 | 
				
			||||||
                
 | 
					                
 | 
				
			||||||
        params = []
 | 
					        params = []
 | 
				
			||||||
 | 
					        params_b = []
 | 
				
			||||||
        for tag, value in tags.items():
 | 
					        for tag, value in tags.items():
 | 
				
			||||||
            params.append(u'-%s=%s' % (tag, value))
 | 
					            params.append(u'-%s=%s' % (tag, value))
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
        params.extend(filenames)
 | 
					        params.extend(filenames)
 | 
				
			||||||
        return self.execute(*params)
 | 
					        params_b = [x.encode('utf-8') for x in params]
 | 
				
			||||||
 | 
					        return self.execute(*params_b)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def set_tags(self, tags, filename):
 | 
					    def set_tags(self, tags, filename):
 | 
				
			||||||
        """Writes the values of the specified tags for the given file.
 | 
					        """Writes the values of the specified tags for the given file.
 | 
				
			||||||
 | 
				
			|||||||
@ -3,6 +3,8 @@ General file system methods.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
.. moduleauthor:: Jaisen Mathai <jaisen@jmathai.com>
 | 
					.. moduleauthor:: Jaisen Mathai <jaisen@jmathai.com>
 | 
				
			||||||
"""
 | 
					"""
 | 
				
			||||||
 | 
					from __future__ import print_function
 | 
				
			||||||
 | 
					from builtins import object
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
import re
 | 
					import re
 | 
				
			||||||
@ -176,7 +178,7 @@ class FileSystem(object):
 | 
				
			|||||||
            allow_duplicate = kwargs['allowDuplicate']
 | 
					            allow_duplicate = kwargs['allowDuplicate']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if(not media.is_valid()):
 | 
					        if(not media.is_valid()):
 | 
				
			||||||
            print '%s is not a valid media file. Skipping...' % _file
 | 
					            print('%s is not a valid media file. Skipping...' % _file)
 | 
				
			||||||
            return
 | 
					            return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        metadata = media.get_metadata()
 | 
					        metadata = media.get_metadata()
 | 
				
			||||||
@ -191,17 +193,17 @@ class FileSystem(object):
 | 
				
			|||||||
        checksum = db.checksum(_file)
 | 
					        checksum = db.checksum(_file)
 | 
				
			||||||
        if(checksum is None):
 | 
					        if(checksum is None):
 | 
				
			||||||
            if(constants.debug is True):
 | 
					            if(constants.debug is True):
 | 
				
			||||||
                print 'Could not get checksum for %s. Skipping...' % _file
 | 
					                print('Could not get checksum for %s. Skipping...' % _file)
 | 
				
			||||||
            return
 | 
					            return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # If duplicates are not allowed and this hash exists in the db then we
 | 
					        # If duplicates are not allowed and this hash exists in the db then we
 | 
				
			||||||
        #   return
 | 
					        #   return
 | 
				
			||||||
        if(allow_duplicate is False and db.check_hash(checksum) is True):
 | 
					        if(allow_duplicate is False and db.check_hash(checksum) is True):
 | 
				
			||||||
            if(constants.debug is True):
 | 
					            if(constants.debug is True):
 | 
				
			||||||
                print '%s already exists at %s. Skipping...' % (
 | 
					                print('%s already exists at %s. Skipping...' % (
 | 
				
			||||||
                    _file,
 | 
					                    _file,
 | 
				
			||||||
                    db.get_hash(checksum)
 | 
					                    db.get_hash(checksum)
 | 
				
			||||||
                )
 | 
					                ))
 | 
				
			||||||
            return
 | 
					            return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.create_directory(dest_directory)
 | 
					        self.create_directory(dest_directory)
 | 
				
			||||||
 | 
				
			|||||||
@ -1,32 +1,21 @@
 | 
				
			|||||||
"""Look up geolocation information for media objects."""
 | 
					"""Look up geolocation information for media objects."""
 | 
				
			||||||
 | 
					from __future__ import print_function
 | 
				
			||||||
 | 
					from __future__ import division
 | 
				
			||||||
 | 
					from future import standard_library
 | 
				
			||||||
 | 
					standard_library.install_aliases()
 | 
				
			||||||
 | 
					from past.utils import old_div
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from os import path
 | 
					from os import path
 | 
				
			||||||
from ConfigParser import ConfigParser
 | 
					from configparser import ConfigParser
 | 
				
			||||||
import fractions
 | 
					import fractions
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import requests
 | 
					import requests
 | 
				
			||||||
import urllib
 | 
					import urllib.request, urllib.parse, urllib.error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from elodie import constants
 | 
					from elodie import constants
 | 
				
			||||||
from elodie.localstorage import Db
 | 
					from elodie.localstorage import Db
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Fraction(fractions.Fraction):
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    """Only create Fractions from floats.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    Should be compatible with Python 2.6, though untested.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    >>> Fraction(0.3)
 | 
					 | 
				
			||||||
    Fraction(3, 10)
 | 
					 | 
				
			||||||
    >>> Fraction(1.1)
 | 
					 | 
				
			||||||
    Fraction(11, 10)
 | 
					 | 
				
			||||||
    """
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def __new__(cls, value, ignore=None):
 | 
					 | 
				
			||||||
        return fractions.Fraction.from_float(value).limit_denominator(99999)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def coordinates_by_name(name):
 | 
					def coordinates_by_name(name):
 | 
				
			||||||
    # Try to get cached location first
 | 
					    # Try to get cached location first
 | 
				
			||||||
    db = Db()
 | 
					    db = Db()
 | 
				
			||||||
@ -88,7 +77,7 @@ def dms_to_decimal(degrees, minutes, seconds, direction=' '):
 | 
				
			|||||||
    if(direction[0] in 'WSws'):
 | 
					    if(direction[0] in 'WSws'):
 | 
				
			||||||
        sign = -1
 | 
					        sign = -1
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
        float(degrees) + float(minutes) / 60 + float(seconds) / 3600
 | 
					        float(degrees) + old_div(float(minutes), 60) + old_div(float(seconds), 3600)
 | 
				
			||||||
    ) * sign
 | 
					    ) * sign
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -159,17 +148,17 @@ def reverse_lookup(lat, lon):
 | 
				
			|||||||
        headers = {"Accept-Language": constants.accepted_language}
 | 
					        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), headers=headers
 | 
					            urllib.parse.urlencode(params),headers=headers
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
        return r.json()
 | 
					        return r.json()
 | 
				
			||||||
    except requests.exceptions.RequestException as e:
 | 
					    except requests.exceptions.RequestException as e:
 | 
				
			||||||
        if(constants.debug is True):
 | 
					        if(constants.debug is True):
 | 
				
			||||||
            print e
 | 
					            print(e)
 | 
				
			||||||
        return None
 | 
					        return None
 | 
				
			||||||
    except ValueError as e:
 | 
					    except ValueError as e:
 | 
				
			||||||
        if(constants.debug is True):
 | 
					        if(constants.debug is True):
 | 
				
			||||||
            print r.text
 | 
					            print(r.text)
 | 
				
			||||||
            print e
 | 
					            print(e)
 | 
				
			||||||
        return None
 | 
					        return None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -182,18 +171,18 @@ def lookup(name):
 | 
				
			|||||||
    try:
 | 
					    try:
 | 
				
			||||||
        params = {'format': 'json', 'key': key, 'location': name}
 | 
					        params = {'format': 'json', 'key': key, 'location': name}
 | 
				
			||||||
        if(constants.debug is True):
 | 
					        if(constants.debug is True):
 | 
				
			||||||
            print 'http://open.mapquestapi.com/geocoding/v1/address?%s' % urllib.urlencode(params)  # noqa
 | 
					            print('http://open.mapquestapi.com/geocoding/v1/address?%s' % urllib.parse.urlencode(params))  # noqa
 | 
				
			||||||
        r = requests.get(
 | 
					        r = requests.get(
 | 
				
			||||||
            'http://open.mapquestapi.com/geocoding/v1/address?%s' %
 | 
					            'http://open.mapquestapi.com/geocoding/v1/address?%s' %
 | 
				
			||||||
            urllib.urlencode(params)
 | 
					            urllib.parse.urlencode(params)
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
        return r.json()
 | 
					        return r.json()
 | 
				
			||||||
    except requests.exceptions.RequestException as e:
 | 
					    except requests.exceptions.RequestException as e:
 | 
				
			||||||
        if(constants.debug is True):
 | 
					        if(constants.debug is True):
 | 
				
			||||||
            print e
 | 
					            print(e)
 | 
				
			||||||
        return None
 | 
					        return None
 | 
				
			||||||
    except ValueError as e:
 | 
					    except ValueError as e:
 | 
				
			||||||
        if(constants.debug is True):
 | 
					        if(constants.debug is True):
 | 
				
			||||||
            print r.text
 | 
					            print(r.text)
 | 
				
			||||||
            print e
 | 
					            print(e)
 | 
				
			||||||
        return None
 | 
					        return None
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,8 @@
 | 
				
			|||||||
"""
 | 
					"""
 | 
				
			||||||
Methods for interacting with information Elodie caches about stored media.
 | 
					Methods for interacting with information Elodie caches about stored media.
 | 
				
			||||||
"""
 | 
					"""
 | 
				
			||||||
 | 
					from builtins import map
 | 
				
			||||||
 | 
					from builtins import object
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import hashlib
 | 
					import hashlib
 | 
				
			||||||
import json
 | 
					import json
 | 
				
			||||||
@ -141,17 +143,17 @@ class Db(object):
 | 
				
			|||||||
            the given latitude and longitude.
 | 
					            the given latitude and longitude.
 | 
				
			||||||
        :returns: str, or None if a matching location couldn't be found.
 | 
					        :returns: str, or None if a matching location couldn't be found.
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        last_d = sys.maxint
 | 
					        last_d = sys.maxsize
 | 
				
			||||||
        name = None
 | 
					        name = None
 | 
				
			||||||
        for data in self.location_db:
 | 
					        for data in self.location_db:
 | 
				
			||||||
            # As threshold is quite small use simple math
 | 
					            # As threshold is quite small use simple math
 | 
				
			||||||
            # From http://stackoverflow.com/questions/15736995/how-can-i-quickly-estimate-the-distance-between-two-latitude-longitude-points  # noqa
 | 
					            # From http://stackoverflow.com/questions/15736995/how-can-i-quickly-estimate-the-distance-between-two-latitude-longitude-points  # noqa
 | 
				
			||||||
            # convert decimal degrees to radians
 | 
					            # convert decimal degrees to radians
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            lon1, lat1, lon2, lat2 = map(
 | 
					            lon1, lat1, lon2, lat2 = list(map(
 | 
				
			||||||
                radians,
 | 
					                radians,
 | 
				
			||||||
                [longitude, latitude, data['long'], data['lat']]
 | 
					                [longitude, latitude, data['long'], data['lat']]
 | 
				
			||||||
            )
 | 
					            ))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            r = 6371000  # radius of the earth in m
 | 
					            r = 6371000  # radius of the earth in m
 | 
				
			||||||
            x = (lon2 - lon1) * cos(0.5 * (lat2 + lat1))
 | 
					            x = (lon2 - lon1) * cos(0.5 * (lat2 + lat1))
 | 
				
			||||||
 | 
				
			|||||||
@ -5,8 +5,9 @@ class.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
.. moduleauthor:: Jaisen Mathai <jaisen@jmathai.com>
 | 
					.. moduleauthor:: Jaisen Mathai <jaisen@jmathai.com>
 | 
				
			||||||
"""
 | 
					"""
 | 
				
			||||||
 | 
					from __future__ import absolute_import
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from video import Video
 | 
					from .video import Video
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Audio(Video):
 | 
					class Audio(Video):
 | 
				
			||||||
 | 
				
			|||||||
@ -13,6 +13,10 @@ are used to represent the actual files.
 | 
				
			|||||||
import mimetypes
 | 
					import mimetypes
 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					try:
 | 
				
			||||||
 | 
					      basestring
 | 
				
			||||||
 | 
					except NameError:
 | 
				
			||||||
 | 
					      basestring = str
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Base(object):
 | 
					class Base(object):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -8,6 +8,8 @@ are used to represent the actual files.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
.. moduleauthor:: Jaisen Mathai <jaisen@jmathai.com>
 | 
					.. moduleauthor:: Jaisen Mathai <jaisen@jmathai.com>
 | 
				
			||||||
"""
 | 
					"""
 | 
				
			||||||
 | 
					from __future__ import print_function
 | 
				
			||||||
 | 
					from builtins import object
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# load modules
 | 
					# load modules
 | 
				
			||||||
from elodie import constants
 | 
					from elodie import constants
 | 
				
			||||||
 | 
				
			|||||||
@ -4,6 +4,9 @@ image objects (JPG, DNG, etc.).
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
.. moduleauthor:: Jaisen Mathai <jaisen@jmathai.com>
 | 
					.. moduleauthor:: Jaisen Mathai <jaisen@jmathai.com>
 | 
				
			||||||
"""
 | 
					"""
 | 
				
			||||||
 | 
					from __future__ import print_function
 | 
				
			||||||
 | 
					from __future__ import absolute_import
 | 
				
			||||||
 | 
					from builtins import str
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import imghdr
 | 
					import imghdr
 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
@ -15,7 +18,7 @@ from re import compile
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from elodie import constants
 | 
					from elodie import constants
 | 
				
			||||||
from media import Media
 | 
					from .media import Media
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Photo(Media):
 | 
					class Photo(Media):
 | 
				
			||||||
@ -95,7 +98,7 @@ class Photo(Media):
 | 
				
			|||||||
                        break
 | 
					                        break
 | 
				
			||||||
            except BaseException as e:
 | 
					            except BaseException as e:
 | 
				
			||||||
                if(constants.debug is True):
 | 
					                if(constants.debug is True):
 | 
				
			||||||
                    print e
 | 
					                    print(e)
 | 
				
			||||||
                pass
 | 
					                pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if(seconds_since_epoch == 0):
 | 
					        if(seconds_since_epoch == 0):
 | 
				
			||||||
 | 
				
			|||||||
@ -123,7 +123,7 @@ class Text(Base):
 | 
				
			|||||||
                self.metadata_line = parsed_json
 | 
					                self.metadata_line = parsed_json
 | 
				
			||||||
        except ValueError:
 | 
					        except ValueError:
 | 
				
			||||||
            if(constants.debug is True):
 | 
					            if(constants.debug is True):
 | 
				
			||||||
                print 'Could not parse JSON from first line: %s' % first_line
 | 
					                print('Could not parse JSON from first line: %s' % first_line)
 | 
				
			||||||
            pass
 | 
					            pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def write_metadata(self, **kwargs):
 | 
					    def write_metadata(self, **kwargs):
 | 
				
			||||||
 | 
				
			|||||||
@ -4,6 +4,12 @@ objects (AVI, MOV, etc.).
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
.. moduleauthor:: Jaisen Mathai <jaisen@jmathai.com>
 | 
					.. moduleauthor:: Jaisen Mathai <jaisen@jmathai.com>
 | 
				
			||||||
"""
 | 
					"""
 | 
				
			||||||
 | 
					from __future__ import print_function
 | 
				
			||||||
 | 
					from __future__ import absolute_import
 | 
				
			||||||
 | 
					from __future__ import division
 | 
				
			||||||
 | 
					from builtins import str
 | 
				
			||||||
 | 
					from builtins import object
 | 
				
			||||||
 | 
					from past.utils import old_div
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# load modules
 | 
					# load modules
 | 
				
			||||||
from distutils.spawn import find_executable
 | 
					from distutils.spawn import find_executable
 | 
				
			||||||
@ -13,7 +19,7 @@ import os
 | 
				
			|||||||
import re
 | 
					import re
 | 
				
			||||||
import time
 | 
					import time
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from media import Media
 | 
					from .media import Media
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Video(Media):
 | 
					class Video(Media):
 | 
				
			||||||
 | 
				
			|||||||
@ -1,3 +1,4 @@
 | 
				
			|||||||
 | 
					from __future__ import absolute_import
 | 
				
			||||||
# Project imports
 | 
					# Project imports
 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
import re
 | 
					import re
 | 
				
			||||||
@ -11,7 +12,7 @@ import mock
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
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__))))))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import helper
 | 
					from . import helper
 | 
				
			||||||
from elodie.filesystem import FileSystem
 | 
					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
 | 
				
			||||||
 | 
				
			|||||||
@ -1,3 +1,7 @@
 | 
				
			|||||||
 | 
					from __future__ import absolute_import
 | 
				
			||||||
 | 
					from __future__ import division
 | 
				
			||||||
 | 
					from builtins import range
 | 
				
			||||||
 | 
					from past.utils import old_div
 | 
				
			||||||
# Project imports
 | 
					# Project imports
 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
import random
 | 
					import random
 | 
				
			||||||
@ -6,7 +10,7 @@ import sys
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
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__))))))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import helper
 | 
					from . import helper
 | 
				
			||||||
from elodie import geolocation
 | 
					from elodie import geolocation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
os.environ['TZ'] = 'GMT'
 | 
					os.environ['TZ'] = 'GMT'
 | 
				
			||||||
@ -18,7 +22,7 @@ def test_decimal_to_dms():
 | 
				
			|||||||
        target_decimal_value = random.uniform(0.0, 180.0)
 | 
					        target_decimal_value = random.uniform(0.0, 180.0)
 | 
				
			||||||
        if(x % 2 == 1):
 | 
					        if(x % 2 == 1):
 | 
				
			||||||
            target_decimal_value = target_decimal_value * -1
 | 
					            target_decimal_value = target_decimal_value * -1
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
        dms = geolocation.decimal_to_dms(target_decimal_value)
 | 
					        dms = geolocation.decimal_to_dms(target_decimal_value)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        check_value = (dms[0] + dms[1] / 60 + dms[2] / 3600) * dms[3]
 | 
					        check_value = (dms[0] + dms[1] / 60 + dms[2] / 3600) * dms[3]
 | 
				
			||||||
@ -34,7 +38,7 @@ def test_dms_string_latitude():
 | 
				
			|||||||
        target_decimal_value = random.uniform(0.0, 180.0)
 | 
					        target_decimal_value = random.uniform(0.0, 180.0)
 | 
				
			||||||
        if(x % 2 == 1):
 | 
					        if(x % 2 == 1):
 | 
				
			||||||
            target_decimal_value = target_decimal_value * -1
 | 
					            target_decimal_value = target_decimal_value * -1
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
        dms = geolocation.decimal_to_dms(target_decimal_value)
 | 
					        dms = geolocation.decimal_to_dms(target_decimal_value)
 | 
				
			||||||
        dms_string = geolocation.dms_string(target_decimal_value, 'latitude')
 | 
					        dms_string = geolocation.dms_string(target_decimal_value, 'latitude')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -49,7 +53,7 @@ def test_dms_string_longitude():
 | 
				
			|||||||
        target_decimal_value = random.uniform(0.0, 180.0)
 | 
					        target_decimal_value = random.uniform(0.0, 180.0)
 | 
				
			||||||
        if(x % 2 == 1):
 | 
					        if(x % 2 == 1):
 | 
				
			||||||
            target_decimal_value = target_decimal_value * -1
 | 
					            target_decimal_value = target_decimal_value * -1
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
        dms = geolocation.decimal_to_dms(target_decimal_value)
 | 
					        dms = geolocation.decimal_to_dms(target_decimal_value)
 | 
				
			||||||
        dms_string = geolocation.dms_string(target_decimal_value, 'longitude')
 | 
					        dms_string = geolocation.dms_string(target_decimal_value, 'longitude')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,3 +1,7 @@
 | 
				
			|||||||
 | 
					from __future__ import division
 | 
				
			||||||
 | 
					from __future__ import unicode_literals
 | 
				
			||||||
 | 
					from builtins import range
 | 
				
			||||||
 | 
					from past.utils import old_div
 | 
				
			||||||
import hashlib
 | 
					import hashlib
 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
import random
 | 
					import random
 | 
				
			||||||
@ -12,7 +16,7 @@ from datetime import timedelta
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
def checksum(file_path, blocksize=65536):
 | 
					def checksum(file_path, blocksize=65536):
 | 
				
			||||||
    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:
 | 
				
			||||||
@ -73,7 +77,7 @@ def random_decimal():
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
def random_coordinate(coordinate, precision):
 | 
					def random_coordinate(coordinate, precision):
 | 
				
			||||||
    # Here we add to the decimal section of the coordinate by a given precision
 | 
					    # Here we add to the decimal section of the coordinate by a given precision
 | 
				
			||||||
    return coordinate + ((10.0 / (10.0**precision)) * random_decimal())
 | 
					    return coordinate + ((old_div(10.0, (10.0**precision))) * random_decimal())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def temp_dir():
 | 
					def temp_dir():
 | 
				
			||||||
    return tempfile.gettempdir()
 | 
					    return tempfile.gettempdir()
 | 
				
			||||||
@ -91,8 +95,8 @@ def is_windows():
 | 
				
			|||||||
def path_tz_fix(file_name):
 | 
					def path_tz_fix(file_name):
 | 
				
			||||||
  if is_windows():
 | 
					  if is_windows():
 | 
				
			||||||
      # Calculate the offset between UTC and local time
 | 
					      # Calculate the offset between UTC and local time
 | 
				
			||||||
      tz_shift = (datetime.fromtimestamp(0) -
 | 
					      tz_shift = old_div((datetime.fromtimestamp(0) -
 | 
				
			||||||
                  datetime.utcfromtimestamp(0)).seconds/3600
 | 
					                  datetime.utcfromtimestamp(0)).seconds,3600)
 | 
				
			||||||
      # replace timestamp in file_name
 | 
					      # replace timestamp in file_name
 | 
				
			||||||
      m = re.search('(\d{4}-\d{2}-\d{2}_\d{2}-\d{2}-\d{2})',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')))
 | 
					      t_date = datetime.fromtimestamp(time.mktime(time.strptime(m.group(0), '%Y-%m-%d_%H-%M-%S')))
 | 
				
			||||||
 | 
				
			|||||||
@ -1,10 +1,12 @@
 | 
				
			|||||||
 | 
					from __future__ import print_function
 | 
				
			||||||
 | 
					from __future__ import absolute_import
 | 
				
			||||||
# Project imports
 | 
					# Project imports
 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
import sys
 | 
					import sys
 | 
				
			||||||
 | 
					
 | 
				
			||||||
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__))))))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import helper
 | 
					from . import helper
 | 
				
			||||||
from elodie.localstorage import Db
 | 
					from elodie.localstorage import Db
 | 
				
			||||||
from elodie import constants
 | 
					from elodie import constants
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -154,10 +156,10 @@ def test_get_location_name_within_threshold():
 | 
				
			|||||||
    latitude, longitude, name = helper.get_test_location()
 | 
					    latitude, longitude, name = helper.get_test_location()
 | 
				
			||||||
    db.add_location(latitude, longitude, name)
 | 
					    db.add_location(latitude, longitude, name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    print latitude
 | 
					    print(latitude)
 | 
				
			||||||
    new_latitude = helper.random_coordinate(latitude, 4)
 | 
					    new_latitude = helper.random_coordinate(latitude, 4)
 | 
				
			||||||
    new_longitude = helper.random_coordinate(longitude, 4)
 | 
					    new_longitude = helper.random_coordinate(longitude, 4)
 | 
				
			||||||
    print new_latitude
 | 
					    print(new_latitude)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # 10 miles
 | 
					    # 10 miles
 | 
				
			||||||
    retrieved_name = db.get_location_name(new_latitude, new_longitude, 1600*10)
 | 
					    retrieved_name = db.get_location_name(new_latitude, new_longitude, 1600*10)
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +1,6 @@
 | 
				
			|||||||
# -*- coding: utf-8
 | 
					# -*- coding: utf-8
 | 
				
			||||||
# Project imports
 | 
					# Project imports
 | 
				
			||||||
 | 
					from __future__ import print_function
 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
import sys
 | 
					import sys
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -56,7 +57,7 @@ def test_get_date_taken():
 | 
				
			|||||||
    audio = Audio(helper.get_file('audio.m4a'))
 | 
					    audio = Audio(helper.get_file('audio.m4a'))
 | 
				
			||||||
    date_taken = audio.get_date_taken()
 | 
					    date_taken = audio.get_date_taken()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    print '%r' % date_taken
 | 
					    print('%r' % date_taken)
 | 
				
			||||||
    assert date_taken == (2016, 1, 4, 5, 24, 15, 0, 19, 0), date_taken
 | 
					    assert date_taken == (2016, 1, 4, 5, 24, 15, 0, 19, 0), date_taken
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_get_exiftool_attributes():
 | 
					def test_get_exiftool_attributes():
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +1,6 @@
 | 
				
			|||||||
# -*- coding: utf-8
 | 
					# -*- coding: utf-8
 | 
				
			||||||
# Project imports
 | 
					# Project imports
 | 
				
			||||||
 | 
					from __future__ import unicode_literals
 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
import sys
 | 
					import sys
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,3 +1,4 @@
 | 
				
			|||||||
click>=6.2,<7.0
 | 
					click>=6.2,<7.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
 | 
				
			||||||
 | 
					future
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user