Merge pull request #64 from noonat/friendly-dep-errors
Added friendly errors when dependencies are not installed
This commit is contained in:
commit
1d86856a07
|
@ -7,7 +7,7 @@ before_install:
|
||||||
- "sudo apt-get update -qq"
|
- "sudo apt-get update -qq"
|
||||||
- "sudo apt-get install python-dev python-pip python-pyexiv2 libimage-exiftool-perl -y"
|
- "sudo apt-get install python-dev python-pip python-pyexiv2 libimage-exiftool-perl -y"
|
||||||
install:
|
install:
|
||||||
- "sudo pip install docopt LatLon nose requests"
|
- "sudo pip install docopt LatLon mock nose requests"
|
||||||
# command to run tests
|
# command to run tests
|
||||||
# test mapquest key
|
# test mapquest key
|
||||||
before_script:
|
before_script:
|
||||||
|
|
|
@ -7,6 +7,12 @@ import sys
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from docopt import docopt
|
from docopt import docopt
|
||||||
|
|
||||||
|
# Verify that external dependencies are present first, so the user gets a
|
||||||
|
# more user-friendly error instead of an ImportError traceback.
|
||||||
|
from elodie.dependencies import verify_dependencies
|
||||||
|
if not verify_dependencies():
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
from elodie import constants
|
from elodie import constants
|
||||||
from elodie import geolocation
|
from elodie import geolocation
|
||||||
from elodie.media.media import Media
|
from elodie.media.media import Media
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
"""Helpers for checking external dependencies."""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
from distutils.spawn import find_executable
|
||||||
|
|
||||||
|
|
||||||
|
EXIFTOOL_ERROR = u"""
|
||||||
|
It looks like you don't have exiftool installed, which Elodie requires.
|
||||||
|
Please take a look at the installation steps in the readme:
|
||||||
|
|
||||||
|
https://github.com/jmathai/elodie#install-everything-you-need
|
||||||
|
""".lstrip()
|
||||||
|
|
||||||
|
PYEXIV2_ERROR = u"""
|
||||||
|
{error_class_name}: {error}
|
||||||
|
|
||||||
|
It looks like you don't have pyexiv2 installed, which Elodie requires for
|
||||||
|
geolocation. Please take a look at the installation steps in the readme:
|
||||||
|
|
||||||
|
https://github.com/jmathai/elodie#install-everything-you-need
|
||||||
|
""".lstrip()
|
||||||
|
|
||||||
|
|
||||||
|
def get_exiftool():
|
||||||
|
"""Get path to executable exiftool binary.
|
||||||
|
|
||||||
|
We wrap this since we call it in a few places and we do a fallback.
|
||||||
|
|
||||||
|
@returns, None or string
|
||||||
|
"""
|
||||||
|
path = find_executable('exiftool')
|
||||||
|
# If exiftool wasn't found we try to brute force the homebrew location
|
||||||
|
if path is None:
|
||||||
|
path = '/usr/local/bin/exiftool'
|
||||||
|
if not os.path.isfile(path) or not os.access(path, os.X_OK):
|
||||||
|
return None
|
||||||
|
return path
|
||||||
|
|
||||||
|
|
||||||
|
def verify_dependencies():
|
||||||
|
"""Verify that external dependencies are installed.
|
||||||
|
|
||||||
|
Prints a message to stderr and returns False if any dependencies are
|
||||||
|
missing.
|
||||||
|
|
||||||
|
@returns, bool
|
||||||
|
"""
|
||||||
|
exiftool = get_exiftool()
|
||||||
|
if exiftool is None:
|
||||||
|
print >>sys.stderr, EXIFTOOL_ERROR
|
||||||
|
return False
|
||||||
|
|
||||||
|
try:
|
||||||
|
import pyexiv2
|
||||||
|
except ImportError as e:
|
||||||
|
print >>sys.stderr, PYEXIV2_ERROR.format(
|
||||||
|
error_class_name=e.__class__.__name__, error=e)
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
|
@ -4,8 +4,8 @@ Media package that's a parent class for media objects
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# load modules
|
# load modules
|
||||||
from distutils.spawn import find_executable
|
|
||||||
from elodie import constants
|
from elodie import constants
|
||||||
|
from elodie.dependencies import get_exiftool
|
||||||
|
|
||||||
import mimetypes
|
import mimetypes
|
||||||
import os
|
import os
|
||||||
|
@ -48,22 +48,6 @@ class Media(object):
|
||||||
|
|
||||||
return exiftool_attributes['album']
|
return exiftool_attributes['album']
|
||||||
|
|
||||||
"""
|
|
||||||
Get path to executable exiftool binary.
|
|
||||||
We wrap this since we call it in a few places and we do a fallback.
|
|
||||||
|
|
||||||
@returns, None or string
|
|
||||||
"""
|
|
||||||
def get_exiftool(self):
|
|
||||||
exiftool = find_executable('exiftool')
|
|
||||||
# If exiftool wasn't found we try to brute force the homebrew location
|
|
||||||
if(exiftool is None):
|
|
||||||
exiftool = '/usr/local/bin/exiftool'
|
|
||||||
if(not os.path.isfile(exiftool) or not os.access(exiftool, os.X_OK)): # noqa
|
|
||||||
return None
|
|
||||||
|
|
||||||
return exiftool
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Get the full path to the video.
|
Get the full path to the video.
|
||||||
|
|
||||||
|
@ -103,7 +87,7 @@ class Media(object):
|
||||||
if(self.exiftool_attributes is not None):
|
if(self.exiftool_attributes is not None):
|
||||||
return self.exiftool_attributes
|
return self.exiftool_attributes
|
||||||
|
|
||||||
exiftool = self.get_exiftool()
|
exiftool = get_exiftool()
|
||||||
if(exiftool is None):
|
if(exiftool is None):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@ -222,7 +206,7 @@ class Media(object):
|
||||||
if(name is None):
|
if(name is None):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
exiftool = self.get_exiftool()
|
exiftool = get_exiftool()
|
||||||
if(exiftool is None):
|
if(exiftool is None):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@ import time
|
||||||
|
|
||||||
from elodie import constants
|
from elodie import constants
|
||||||
from elodie import plist_parser
|
from elodie import plist_parser
|
||||||
|
from elodie.dependencies import get_exiftool
|
||||||
from media import Media
|
from media import Media
|
||||||
|
|
||||||
|
|
||||||
|
@ -145,7 +146,7 @@ class Video(Media):
|
||||||
@returns, string or None if exiftool is not found
|
@returns, string or None if exiftool is not found
|
||||||
"""
|
"""
|
||||||
def get_exif(self):
|
def get_exif(self):
|
||||||
exiftool = self.get_exiftool()
|
exiftool = get_exiftool()
|
||||||
if(exiftool is None):
|
if(exiftool is None):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
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
|
|
@ -21,11 +21,6 @@ from elodie.media.video import Video
|
||||||
|
|
||||||
os.environ['TZ'] = 'GMT'
|
os.environ['TZ'] = 'GMT'
|
||||||
|
|
||||||
def test_exiftool():
|
|
||||||
media = Media()
|
|
||||||
exiftool = media.get_exiftool()
|
|
||||||
|
|
||||||
assert exiftool is not None, exiftool
|
|
||||||
|
|
||||||
def test_get_file_path():
|
def test_get_file_path():
|
||||||
media = Media(helper.get_file('plain.jpg'))
|
media = Media(helper.get_file('plain.jpg'))
|
||||||
|
|
Loading…
Reference in New Issue