Refactoring media class
This commit is contained in:
parent
6b2d2b31c3
commit
cb8a4cd24e
22
elodie.py
22
elodie.py
|
@ -155,8 +155,8 @@ def _import(destination, source, file, album_from_folder, trash,
|
|||
sys.exit(1)
|
||||
|
||||
@click.command('generate-db')
|
||||
@click.option('--source', type=click.Path(file_okay=False),
|
||||
required=True, help='Source of your photo library.')
|
||||
@click.option('--path', type=click.Path(file_okay=False),
|
||||
required=True, help='Path of your photo library.')
|
||||
@click.option('--debug', default=False, is_flag=True,
|
||||
help='Override the value in constants.py with True.')
|
||||
def _generate_db(path, debug):
|
||||
|
@ -164,29 +164,31 @@ def _generate_db(path, debug):
|
|||
"""
|
||||
constants.debug = debug
|
||||
result = Result()
|
||||
source = os.path.abspath(os.path.expanduser(source))
|
||||
path = os.path.abspath(os.path.expanduser(path))
|
||||
|
||||
if not os.path.isdir(source):
|
||||
log.error('Source is not a valid directory %s' % source)
|
||||
if not os.path.isdir(path):
|
||||
log.error('path is not a valid directory %s' % path)
|
||||
sys.exit(1)
|
||||
|
||||
db = Db(path)
|
||||
db.backup_hash_db()
|
||||
db.reset_hash_db()
|
||||
|
||||
for current_file in FILESYSTEM.get_all_files(source):
|
||||
for current_file in FILESYSTEM.get_all_files(path):
|
||||
result.append((current_file, True))
|
||||
db.add_hash(db.checksum(current_file), current_file)
|
||||
log.progress()
|
||||
|
||||
|
||||
db.update_hash_db()
|
||||
log.progress('', True)
|
||||
result.write()
|
||||
|
||||
@click.command('verify')
|
||||
@click.option('--path', type=click.Path(file_okay=False),
|
||||
required=True, help='Path of your photo library.')
|
||||
@click.option('--debug', default=False, is_flag=True,
|
||||
help='Override the value in constants.py with True.')
|
||||
def _verify(debug):
|
||||
def _verify(path, debug):
|
||||
constants.debug = debug
|
||||
result = Result()
|
||||
db = Db(path)
|
||||
|
@ -216,7 +218,7 @@ def update_location(media, file_path, location_name, db):
|
|||
if location_coords and 'latitude' in location_coords and \
|
||||
'longitude' in location_coords:
|
||||
location_status = media.set_location(location_coords[
|
||||
'latitude'], location_coords['longitude'])
|
||||
'latitude'], location_coords['longitude'], file_path)
|
||||
if not location_status:
|
||||
log.error('Failed to update location')
|
||||
log.all(('{"source":"%s",' % file_path,
|
||||
|
@ -307,7 +309,7 @@ def _update(album, location, time, title, paths, debug):
|
|||
update_time(media, current_file, time)
|
||||
updated = True
|
||||
if album:
|
||||
media.set_album(album)
|
||||
media.set_album(album, current_file)
|
||||
updated = True
|
||||
|
||||
import ipdb; ipdb.set_trace()
|
||||
|
|
|
@ -17,7 +17,7 @@ from elodie.config import load_config
|
|||
from elodie import constants
|
||||
|
||||
from elodie.localstorage import Db
|
||||
from elodie.media import base
|
||||
from elodie.media import media
|
||||
from elodie.plugins.plugins import Plugins
|
||||
|
||||
class FileSystem(object):
|
||||
|
@ -94,7 +94,7 @@ class FileSystem(object):
|
|||
# If extensions is None then we get all supported extensions
|
||||
if not extensions:
|
||||
extensions = set()
|
||||
subclasses = base.get_all_subclasses()
|
||||
subclasses = media.get_all_subclasses()
|
||||
for cls in subclasses:
|
||||
extensions.update(cls.extensions)
|
||||
|
||||
|
@ -679,7 +679,9 @@ class FileSystem(object):
|
|||
if album_from_folder:
|
||||
media.set_album_from_folder(dest_path)
|
||||
|
||||
db.add_hash(checksum, dest_path)
|
||||
# get checksum of dest file
|
||||
dest_checksum = db.checksum(dest_path)
|
||||
db.add_hash(dest_checksum, dest_path)
|
||||
db.update_hash_db()
|
||||
|
||||
# Run `after()` for every loaded plugin and if any of them raise an exception
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
"""
|
||||
The audio module contains classes specifically for dealing with audio files.
|
||||
The :class:`Audio` class inherits from the :class:`~elodie.media.video.Video`
|
||||
The :class:`Audio` class inherits from the :class:`~elodie.media.Media`
|
||||
class.
|
||||
|
||||
.. moduleauthor:: Jaisen Mathai <jaisen@jmathai.com>
|
||||
"""
|
||||
|
||||
from .video import Video
|
||||
from .media import Media
|
||||
|
||||
|
||||
class Audio(Video):
|
||||
class Audio(Media):
|
||||
|
||||
"""An audio object.
|
||||
|
||||
|
@ -22,4 +22,7 @@ class Audio(Video):
|
|||
extensions = ('m4a',)
|
||||
|
||||
def __init__(self, source=None):
|
||||
super(Audio, self).__init__(source)
|
||||
super().__init__(source)
|
||||
|
||||
def is_valid(self):
|
||||
return super().is_valid()
|
||||
|
|
|
@ -1,264 +0,0 @@
|
|||
"""
|
||||
The base module provides a base :class:`Base` class for all objects that
|
||||
are tracked by Elodie. The Base class provides some base functionality used
|
||||
by all the media types, but isn't itself used to represent anything. Its
|
||||
sub-classes (:class:`~elodie.media.audio.Audio`,
|
||||
:class:`~elodie.media.photo.Photo`, :class:`~elodie.media.video.Video`)
|
||||
are used to represent the actual files.
|
||||
|
||||
.. moduleauthor:: Jaisen Mathai <jaisen@jmathai.com>
|
||||
"""
|
||||
|
||||
import mimetypes
|
||||
import os
|
||||
|
||||
try: # Py3k compatibility
|
||||
basestring
|
||||
except NameError:
|
||||
basestring = (bytes, str)
|
||||
|
||||
|
||||
class Base(object):
|
||||
|
||||
"""The base class for all media objects.
|
||||
|
||||
:param str source: The fully qualified path to the video file.
|
||||
"""
|
||||
|
||||
__name__ = 'Base'
|
||||
|
||||
PHOTO = ('arw', 'cr2', 'dng', 'gif', 'heic', 'jpeg', 'jpg', 'nef', 'png', 'rw2')
|
||||
AUDIO = ('m4a',)
|
||||
VIDEO = ('avi', 'm4v', 'mov', 'mp4', 'mpg', 'mpeg', '3gp', 'mts')
|
||||
|
||||
extensions = PHOTO + AUDIO + VIDEO
|
||||
|
||||
def __init__(self, source=None):
|
||||
self.source = source
|
||||
self.reset_cache()
|
||||
|
||||
def format_metadata(self, **kwargs):
|
||||
"""Method to consistently return a populated metadata dictionary.
|
||||
|
||||
:returns: dict
|
||||
"""
|
||||
|
||||
def get_album(self):
|
||||
"""Base method for getting an album
|
||||
|
||||
:returns: None
|
||||
"""
|
||||
return None
|
||||
|
||||
def get_file_path(self):
|
||||
"""Get the full path to the video.
|
||||
|
||||
:returns: string
|
||||
"""
|
||||
return self.source
|
||||
|
||||
def get_coordinate(self, type):
|
||||
return None
|
||||
|
||||
def get_extension(self):
|
||||
"""Get the file extension as a lowercased string.
|
||||
|
||||
:returns: string or None for a non-video
|
||||
"""
|
||||
if(not self.is_valid()):
|
||||
return None
|
||||
|
||||
source = self.source
|
||||
return os.path.splitext(source)[1][1:].lower()
|
||||
|
||||
def get_camera_make(self):
|
||||
return None
|
||||
|
||||
def get_camera_model(self):
|
||||
return None
|
||||
|
||||
def get_metadata(self, update_cache=False):
|
||||
"""Get a dictionary of metadata for any file.
|
||||
|
||||
All keys will be present and have a value of None if not obtained.
|
||||
|
||||
:returns: dict or None for non-text files
|
||||
"""
|
||||
if(not self.is_valid()):
|
||||
return None
|
||||
|
||||
if(isinstance(self.metadata, dict) and update_cache is False):
|
||||
return self.metadata
|
||||
|
||||
source = self.source
|
||||
folder = os.path.basename(os.path.dirname(source))
|
||||
album = self.get_album()
|
||||
album_from_folder = True
|
||||
if album_from_folder and (album is None or album == ''):
|
||||
album = folder
|
||||
|
||||
self.metadata = {
|
||||
'date_original': self.get_date_attribute(self.date_original),
|
||||
'date_created': self.get_date_attribute(self.date_created),
|
||||
'date_modified': self.get_date_attribute(self.date_modified),
|
||||
'camera_make': self.get_camera_make(),
|
||||
'camera_model': self.get_camera_model(),
|
||||
'latitude': self.get_coordinate('latitude'),
|
||||
'longitude': self.get_coordinate('longitude'),
|
||||
'album': album,
|
||||
'title': self.get_title(),
|
||||
'mime_type': self.get_mimetype(),
|
||||
'original_name': self.get_original_name(),
|
||||
'base_name': folder,
|
||||
'extension': self.get_extension(),
|
||||
'directory_path': os.path.dirname(source)
|
||||
}
|
||||
|
||||
return self.metadata
|
||||
|
||||
def get_mimetype(self):
|
||||
"""Get the mimetype of the file.
|
||||
|
||||
:returns: str or None for unsupported files.
|
||||
"""
|
||||
if(not self.is_valid()):
|
||||
return None
|
||||
|
||||
source = self.source
|
||||
mimetype = mimetypes.guess_type(source)
|
||||
if(mimetype is None):
|
||||
return None
|
||||
|
||||
return mimetype[0]
|
||||
|
||||
def get_original_name(self):
|
||||
"""Get the original name of the file from before it was imported.
|
||||
Does not include the extension.
|
||||
Overridden by Media class for files with EXIF.
|
||||
|
||||
:returns: str or None for unsupported files.
|
||||
"""
|
||||
return None
|
||||
|
||||
def get_title(self):
|
||||
"""Base method for getting the title of a file
|
||||
|
||||
:returns: None
|
||||
"""
|
||||
return None
|
||||
|
||||
def is_valid(self):
|
||||
"""Check the file extension against valid file extensions.
|
||||
|
||||
The list of valid file extensions come from self.extensions.
|
||||
|
||||
:returns: bool
|
||||
"""
|
||||
source = self.source
|
||||
return os.path.splitext(source)[1][1:].lower() in self.extensions
|
||||
|
||||
def reset_cache(self):
|
||||
"""Resets any internal cache
|
||||
"""
|
||||
self.metadata = None
|
||||
|
||||
def set_album(self, name):
|
||||
"""Base method for setting the album of a file
|
||||
|
||||
:returns: None
|
||||
"""
|
||||
return None
|
||||
|
||||
def set_album_from_folder(self, path):
|
||||
"""Set the album attribute based on the leaf folder name
|
||||
|
||||
:returns: bool
|
||||
"""
|
||||
metadata = self.get_metadata()
|
||||
|
||||
# If this file has an album already set we do not overwrite EXIF
|
||||
if(not isinstance(metadata, dict) or metadata['album'] is not None):
|
||||
return False
|
||||
|
||||
folder = os.path.basename(metadata['directory_path'])
|
||||
# If folder is empty we skip
|
||||
if(len(folder) == 0):
|
||||
return False
|
||||
|
||||
self.set_album(folder)
|
||||
if status == False:
|
||||
return False
|
||||
return True
|
||||
|
||||
def set_metadata_basename(self, new_basename):
|
||||
"""Update the basename attribute in the metadata dict for this instance.
|
||||
|
||||
This is used for when we update the EXIF title of a media file. Since
|
||||
that determines the name of a file if we update the title of a file
|
||||
more than once it appends to the file name.
|
||||
|
||||
i.e. 2015-12-31_00-00-00-my-first-title-my-second-title.jpg
|
||||
|
||||
:param str new_basename: New basename of file (with the old title
|
||||
removed).
|
||||
"""
|
||||
self.get_metadata()
|
||||
self.metadata['base_name'] = new_basename
|
||||
|
||||
def set_metadata(self, **kwargs):
|
||||
"""Method to manually update attributes in metadata.
|
||||
|
||||
:params dict kwargs: Named parameters to update.
|
||||
"""
|
||||
metadata = self.get_metadata()
|
||||
for key in kwargs:
|
||||
if(key in metadata):
|
||||
self.metadata[key] = kwargs[key]
|
||||
|
||||
def set_original_name(self):
|
||||
"""Stores the original file name into EXIF/metadata.
|
||||
:returns: bool
|
||||
"""
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
def get_class_by_file(cls, _file, classes):
|
||||
"""Static method to get a media object by file.
|
||||
"""
|
||||
if not isinstance(_file, basestring) or not os.path.isfile(_file):
|
||||
return None
|
||||
|
||||
extension = os.path.splitext(_file)[1][1:].lower()
|
||||
|
||||
if len(extension) > 0:
|
||||
for i in classes:
|
||||
if(extension in i.extensions):
|
||||
return i(_file)
|
||||
|
||||
return None
|
||||
|
||||
@classmethod
|
||||
def get_valid_extensions(cls):
|
||||
"""Static method to access static extensions variable.
|
||||
|
||||
:returns: tuple(str)
|
||||
"""
|
||||
return cls.extensions
|
||||
|
||||
|
||||
def get_all_subclasses(cls=None):
|
||||
"""Module method to get all subclasses of Base.
|
||||
"""
|
||||
subclasses = set()
|
||||
|
||||
this_class = Base
|
||||
if cls is not None:
|
||||
this_class = cls
|
||||
|
||||
subclasses.add(this_class)
|
||||
|
||||
this_class_subclasses = this_class.__subclasses__()
|
||||
for child_class in this_class_subclasses:
|
||||
subclasses.update(get_all_subclasses(child_class))
|
||||
|
||||
return subclasses
|
|
@ -1,14 +1,14 @@
|
|||
"""
|
||||
The media module provides a base :class:`Media` class for media objects that
|
||||
are tracked by Elodie. The Media class provides some base functionality used
|
||||
by all the media types, but isn't itself used to represent anything. Its
|
||||
sub-classes (:class:`~elodie.media.audio.Audio`,
|
||||
:class:`~elodie.media.photo.Photo`, and :class:`~elodie.media.video.Video`)
|
||||
by all the media types. Its sub-classes (:class:`~elodie.media.Audio`,
|
||||
:class:`~elodie.media.Photo`, and :class:`~elodie.media.Video`)
|
||||
are used to represent the actual files.
|
||||
|
||||
.. moduleauthor:: Jaisen Mathai <jaisen@jmathai.com>
|
||||
"""
|
||||
|
||||
import mimetypes
|
||||
import os
|
||||
import six
|
||||
|
||||
|
@ -17,11 +17,17 @@ from elodie import log
|
|||
from dateutil.parser import parse
|
||||
import re
|
||||
from elodie.external.pyexiftool import ExifTool
|
||||
from elodie.media.base import Base
|
||||
|
||||
class Media(Base):
|
||||
# TODO remove
|
||||
# try: # Py3k compatibility
|
||||
# basestring
|
||||
# except NameError:
|
||||
# basestring = (bytes, str)
|
||||
|
||||
"""The base class for all media objects.
|
||||
|
||||
class Media():
|
||||
|
||||
"""The media class for all media objects.
|
||||
|
||||
:param str source: The fully qualified path to the video file.
|
||||
"""
|
||||
|
@ -33,23 +39,221 @@ class Media(Base):
|
|||
'longitude': 'longitude_ref'
|
||||
}
|
||||
|
||||
def __init__(self, source=None):
|
||||
super(Media, self).__init__(source)
|
||||
self.date_original = ['EXIF:DateTimeOriginal']
|
||||
self.date_created = ['EXIF:CreateDate', 'QuickTime:CreateDate']
|
||||
PHOTO = ('arw', 'cr2', 'dng', 'gif', 'heic', 'jpeg', 'jpg', 'nef', 'png', 'rw2')
|
||||
AUDIO = ('m4a',)
|
||||
VIDEO = ('avi', 'm4v', 'mov', 'mp4', 'mpg', 'mpeg', '3gp', 'mts')
|
||||
|
||||
extensions = PHOTO + AUDIO + VIDEO
|
||||
|
||||
|
||||
def __init__(self, sources=None):
|
||||
self.source = sources
|
||||
self.reset_cache()
|
||||
self.date_original = [
|
||||
'EXIF:DateTimeOriginal',
|
||||
'H264:DateTimeOriginal',
|
||||
'QuickTime:ContentCreateDate'
|
||||
]
|
||||
self.date_created = [
|
||||
'EXIF:CreateDate',
|
||||
'QuickTime:CreationDate',
|
||||
'QuickTime:CreateDate',
|
||||
'QuickTime:CreationDate-und-US',
|
||||
'QuickTime:MediaCreateDate'
|
||||
]
|
||||
self.date_modified = ['File:FileModifyDate', 'QuickTime:ModifyDate']
|
||||
self.camera_make_keys = ['EXIF:Make', 'QuickTime:Make']
|
||||
self.camera_model_keys = ['EXIF:Model', 'QuickTime:Model']
|
||||
self.album_keys = ['XMP-xmpDM:Album', 'XMP:Album']
|
||||
self.title_key = 'XMP:Title'
|
||||
self.latitude_keys = ['EXIF:GPSLatitude']
|
||||
self.longitude_keys = ['EXIF:GPSLongitude']
|
||||
self.title_keys = ['XMP:Title', 'XMP:DisplayName']
|
||||
self.latitude_keys = [
|
||||
'EXIF:GPSLatitude',
|
||||
'XMP:GPSLatitude',
|
||||
# 'QuickTime:GPSLatitude',
|
||||
'Composite:GPSLatitude'
|
||||
]
|
||||
self.longitude_keys = [
|
||||
'EXIF:GPSLongitude',
|
||||
'XMP:GPSLongitude',
|
||||
# 'QuickTime:GPSLongitude',
|
||||
'Composite:GPSLongitude'
|
||||
]
|
||||
self.latitude_ref_key = 'EXIF:GPSLatitudeRef'
|
||||
self.longitude_ref_key = 'EXIF:GPSLongitudeRef'
|
||||
self.original_name_key = 'XMP:OriginalFileName'
|
||||
self.set_gps_ref = True
|
||||
self.metadata = None
|
||||
self.exif_metadata = None
|
||||
|
||||
|
||||
def format_metadata(self, **kwargs):
|
||||
"""Method to consistently return a populated metadata dictionary.
|
||||
|
||||
:returns: dict
|
||||
"""
|
||||
|
||||
def get_file_path(self):
|
||||
"""Get the full path to the video.
|
||||
|
||||
:returns: string
|
||||
"""
|
||||
return self.source
|
||||
|
||||
|
||||
def get_extension(self):
|
||||
"""Get the file extension as a lowercased string.
|
||||
|
||||
:returns: string or None for a non-video
|
||||
"""
|
||||
if(not self.is_valid()):
|
||||
return None
|
||||
|
||||
source = self.source
|
||||
return os.path.splitext(source)[1][1:].lower()
|
||||
|
||||
|
||||
def get_metadata(self, update_cache=False, album_from_folder=False):
|
||||
"""Get a dictionary of metadata for any file.
|
||||
|
||||
All keys will be present and have a value of None if not obtained.
|
||||
|
||||
:returns: dict or None for non-text files
|
||||
"""
|
||||
if(not self.is_valid()):
|
||||
return None
|
||||
|
||||
if(isinstance(self.metadata, dict) and update_cache is False):
|
||||
return self.metadata
|
||||
|
||||
source = self.source
|
||||
folder = os.path.basename(os.path.dirname(source))
|
||||
album = self.get_album()
|
||||
if album_from_folder and (album is None or album == ''):
|
||||
album = folder
|
||||
|
||||
self.metadata = {
|
||||
'date_original': self.get_date_attribute(self.date_original),
|
||||
'date_created': self.get_date_attribute(self.date_created),
|
||||
'date_modified': self.get_date_attribute(self.date_modified),
|
||||
'camera_make': self.get_camera_make(),
|
||||
'camera_model': self.get_camera_model(),
|
||||
'latitude': self.get_coordinate('latitude'),
|
||||
'longitude': self.get_coordinate('longitude'),
|
||||
'album': album,
|
||||
'title': self.get_title(),
|
||||
'mime_type': self.get_mimetype(),
|
||||
'original_name': self.get_original_name(),
|
||||
'base_name': os.path.basename(os.path.splitext(source)[0]),
|
||||
'extension': self.get_extension(),
|
||||
'directory_path': os.path.dirname(source)
|
||||
}
|
||||
|
||||
return self.metadata
|
||||
|
||||
|
||||
def get_mimetype(self):
|
||||
"""Get the mimetype of the file.
|
||||
|
||||
:returns: str or None for unsupported files.
|
||||
"""
|
||||
if(not self.is_valid()):
|
||||
return None
|
||||
|
||||
source = self.source
|
||||
mimetype = mimetypes.guess_type(source)
|
||||
if(mimetype is None):
|
||||
return None
|
||||
|
||||
return mimetype[0]
|
||||
|
||||
|
||||
def is_valid(self):
|
||||
"""Check the file extension against valid file extensions.
|
||||
|
||||
The list of valid file extensions come from self.extensions.
|
||||
|
||||
:returns: bool
|
||||
"""
|
||||
source = self.source
|
||||
return os.path.splitext(source)[1][1:].lower() in self.extensions
|
||||
|
||||
|
||||
def set_album_from_folder(self, path):
|
||||
"""Set the album attribute based on the leaf folder name
|
||||
|
||||
:returns: bool
|
||||
"""
|
||||
metadata = self.get_metadata()
|
||||
|
||||
# If this file has an album already set we do not overwrite EXIF
|
||||
if(not isinstance(metadata, dict) or metadata['album'] is not None):
|
||||
return False
|
||||
|
||||
folder = os.path.basename(metadata['directory_path'])
|
||||
# If folder is empty we skip
|
||||
if(len(folder) == 0):
|
||||
return False
|
||||
|
||||
status = self.set_album(folder, path)
|
||||
if status == False:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def set_metadata_basename(self, new_basename):
|
||||
"""Update the basename attribute in the metadata dict for this instance.
|
||||
|
||||
This is used for when we update the EXIF title of a media file. Since
|
||||
that determines the name of a file if we update the title of a file
|
||||
more than once it appends to the file name.
|
||||
|
||||
i.e. 2015-12-31_00-00-00-my-first-title-my-second-title.jpg
|
||||
|
||||
:param str new_basename: New basename of file (with the old title
|
||||
removed).
|
||||
"""
|
||||
self.get_metadata()
|
||||
self.metadata['base_name'] = new_basename
|
||||
|
||||
|
||||
def set_metadata(self, **kwargs):
|
||||
"""Method to manually update attributes in metadata.
|
||||
|
||||
:params dict kwargs: Named parameters to update.
|
||||
"""
|
||||
metadata = self.get_metadata()
|
||||
for key in kwargs:
|
||||
if(key in metadata):
|
||||
self.metadata[key] = kwargs[key]
|
||||
|
||||
|
||||
@classmethod
|
||||
def get_class_by_file(cls, _file, classes):
|
||||
"""Static method to get a media object by file.
|
||||
"""
|
||||
basestring = (bytes, str)
|
||||
if not isinstance(_file, basestring) or not os.path.isfile(_file):
|
||||
return None
|
||||
|
||||
extension = os.path.splitext(_file)[1][1:].lower()
|
||||
|
||||
if len(extension) > 0:
|
||||
for i in classes:
|
||||
if(extension in i.extensions):
|
||||
return i(_file)
|
||||
|
||||
return None
|
||||
|
||||
|
||||
@classmethod
|
||||
def get_valid_extensions(cls):
|
||||
"""Static method to access static extensions variable.
|
||||
|
||||
:returns: tuple(str)
|
||||
"""
|
||||
return cls.extensions
|
||||
|
||||
|
||||
def get_album(self):
|
||||
"""Get album from EXIF
|
||||
|
||||
|
@ -68,6 +272,7 @@ class Media(Base):
|
|||
|
||||
return None
|
||||
|
||||
|
||||
def get_coordinate(self, type='latitude'):
|
||||
"""Get latitude or longitude of media from EXIF
|
||||
|
||||
|
@ -114,6 +319,7 @@ class Media(Base):
|
|||
|
||||
return None
|
||||
|
||||
|
||||
def get_exiftool_attributes(self):
|
||||
"""Get attributes for the media object from exiftool.
|
||||
|
||||
|
@ -185,6 +391,7 @@ class Media(Base):
|
|||
|
||||
return None
|
||||
|
||||
|
||||
def get_camera_model(self):
|
||||
"""Get the camera make stored in EXIF.
|
||||
|
||||
|
@ -204,6 +411,7 @@ class Media(Base):
|
|||
|
||||
return None
|
||||
|
||||
|
||||
def get_original_name(self):
|
||||
"""Get the original name stored in EXIF.
|
||||
|
||||
|
@ -222,6 +430,7 @@ class Media(Base):
|
|||
|
||||
return exiftool_attributes[self.original_name_key]
|
||||
|
||||
|
||||
def get_title(self):
|
||||
"""Get the title for a photo of video
|
||||
|
||||
|
@ -235,17 +444,19 @@ class Media(Base):
|
|||
if exiftool_attributes is None:
|
||||
return None
|
||||
|
||||
if(self.title_key not in exiftool_attributes):
|
||||
return None
|
||||
for title_key in self.title_keys:
|
||||
if title_key in exiftool_attributes:
|
||||
return exiftool_attributes[title_key]
|
||||
|
||||
return None
|
||||
|
||||
return exiftool_attributes[self.title_key]
|
||||
|
||||
def reset_cache(self):
|
||||
"""Resets any internal cache
|
||||
"""
|
||||
self.exiftool_attributes = None
|
||||
self.exif_metadata = None
|
||||
super(Media, self).reset_cache()
|
||||
|
||||
|
||||
def set_album(self, name, path):
|
||||
"""Set album EXIF tag if not already set.
|
||||
|
@ -255,12 +466,16 @@ class Media(Base):
|
|||
if self.get_album() is not None:
|
||||
return None
|
||||
|
||||
tags = {self.album_keys[0]: name}
|
||||
status = ExifTool().set_tags(tags, path)
|
||||
tags = {}
|
||||
for key in self.album_keys:
|
||||
tags[key] = name
|
||||
status = self.__set_tags(tags, path)
|
||||
self.reset_cache()
|
||||
return status != ''
|
||||
|
||||
def set_date_original(self, time):
|
||||
return status
|
||||
|
||||
|
||||
def set_date_original(self, time, path):
|
||||
"""Set the date/time a photo was taken.
|
||||
|
||||
:param datetime time: datetime object of when the photo was taken
|
||||
|
@ -274,31 +489,39 @@ class Media(Base):
|
|||
for key in self.date_original:
|
||||
tags[key] = formatted_time
|
||||
|
||||
status = self.__set_tags(tags)
|
||||
status = self.__set_tags(tags, path)
|
||||
if status == False:
|
||||
# exif attribute date_original d'ont exist
|
||||
for key in self.date_created:
|
||||
tags[key] = formatted_time
|
||||
|
||||
status = self.__set_tags(tags)
|
||||
status = self.__set_tags(tags, path)
|
||||
self.reset_cache()
|
||||
return status
|
||||
|
||||
def set_location(self, latitude, longitude):
|
||||
|
||||
def set_location(self, latitude, longitude, path):
|
||||
if(not self.is_valid()):
|
||||
return None
|
||||
|
||||
# The lat/lon _keys array has an order of precedence.
|
||||
# The first key is writable and we will give the writable
|
||||
# key precence when reading.
|
||||
tags = {
|
||||
self.latitude_keys[0]: latitude,
|
||||
self.longitude_keys[0]: longitude,
|
||||
}
|
||||
# TODO check
|
||||
# tags = {
|
||||
# self.latitude_keys[0]: latitude,
|
||||
# self.longitude_keys[0]: longitude,
|
||||
# }
|
||||
tags = {}
|
||||
for key in self.latitude_keys:
|
||||
tags[key] = latitude
|
||||
for key in self.longitude_keys:
|
||||
tags[key] = longitude
|
||||
|
||||
# If self.set_gps_ref == True then it means we are writing an EXIF
|
||||
# GPS tag which requires us to set the reference key.
|
||||
# That's because the lat/lon are absolute values.
|
||||
# TODO set_gps_ref = False for Video ?
|
||||
if self.set_gps_ref:
|
||||
if latitude < 0:
|
||||
tags[self.latitude_ref_key] = 'S'
|
||||
|
@ -306,12 +529,13 @@ class Media(Base):
|
|||
if longitude < 0:
|
||||
tags[self.longitude_ref_key] = 'W'
|
||||
|
||||
status = self.__set_tags(tags)
|
||||
status = self.__set_tags(tags, path)
|
||||
self.reset_cache()
|
||||
|
||||
return status
|
||||
|
||||
def set_original_name(self, path):
|
||||
|
||||
def set_original_name(self, path, name=None):
|
||||
"""Sets the original name EXIF tag if not already set.
|
||||
|
||||
:returns: True, False, None
|
||||
|
@ -320,14 +544,17 @@ class Media(Base):
|
|||
if self.get_original_name() is not None:
|
||||
return None
|
||||
|
||||
name = os.path.basename(path)
|
||||
if name == None:
|
||||
name = os.path.basename(self.source)
|
||||
|
||||
tags = {self.original_name_key: name}
|
||||
status = ExifTool().set_tags(tags, path)
|
||||
status = self.__set_tags(tags, path)
|
||||
self.reset_cache()
|
||||
return status != ''
|
||||
|
||||
def set_title(self, title):
|
||||
return status
|
||||
|
||||
|
||||
def set_title(self, title, path):
|
||||
"""Set title for a photo.
|
||||
|
||||
:param str title: Title of the photo.
|
||||
|
@ -339,23 +566,43 @@ class Media(Base):
|
|||
if(title is None):
|
||||
return None
|
||||
|
||||
tags = {self.title_key: title}
|
||||
status = self.__set_tags(tags)
|
||||
tags = {}
|
||||
for key in self.title_keys:
|
||||
tags[key] = title
|
||||
status = self.__set_tags(tags, path)
|
||||
self.reset_cache()
|
||||
|
||||
return status
|
||||
|
||||
def __set_tags(self, tags):
|
||||
|
||||
def __set_tags(self, tags, path):
|
||||
if(not self.is_valid()):
|
||||
return None
|
||||
|
||||
source = self.source
|
||||
|
||||
status = ''
|
||||
status = ExifTool().set_tags(tags,source)
|
||||
status = ExifTool().set_tags(tags, path)
|
||||
if status.decode().find('unchanged') != -1 or status == '':
|
||||
return False
|
||||
if status.decode().find('error') != -1:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def get_all_subclasses(cls=None):
|
||||
"""Module method to get all subclasses of Media.
|
||||
"""
|
||||
subclasses = set()
|
||||
|
||||
this_class = Media
|
||||
if cls is not None:
|
||||
this_class = cls
|
||||
|
||||
subclasses.add(this_class)
|
||||
|
||||
this_class_subclasses = this_class.__subclasses__()
|
||||
for child_class in this_class_subclasses:
|
||||
subclasses.update(get_all_subclasses(child_class))
|
||||
|
||||
return subclasses
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ class Photo(Media):
|
|||
extensions = ('arw', 'cr2', 'dng', 'gif', 'heic', 'jpeg', 'jpg', 'nef', 'png', 'rw2')
|
||||
|
||||
def __init__(self, source=None):
|
||||
super(Photo, self).__init__(source)
|
||||
super().__init__(source)
|
||||
|
||||
# We only want to parse EXIF once so we store it here
|
||||
self.exif = None
|
||||
|
@ -79,5 +79,5 @@ class Photo(Media):
|
|||
|
||||
if(im.format is None):
|
||||
return False
|
||||
|
||||
|
||||
return extension in self.extensions
|
||||
|
|
|
@ -28,31 +28,9 @@ class Video(Media):
|
|||
extensions = ('avi', 'm4v', 'mov', 'mp4', 'mpg', 'mpeg', '3gp', 'mts')
|
||||
|
||||
def __init__(self, source=None):
|
||||
super(Video, self).__init__(source)
|
||||
self.date_original = [
|
||||
'EXIF:DateTimeOriginal',
|
||||
'H264:DateTimeOriginal',
|
||||
'QuickTime:ContentCreateDate'
|
||||
]
|
||||
self.date_created = [
|
||||
'EXIF:CreateDate',
|
||||
'QuickTime:CreationDate',
|
||||
'QuickTime:CreateDate',
|
||||
'QuickTime:CreationDate-und-US',
|
||||
'QuickTime:MediaCreateDate'
|
||||
]
|
||||
self.date_modified = ['File:FileModifyDate']
|
||||
self.title_key = 'XMP:DisplayName'
|
||||
self.latitude_keys = [
|
||||
'XMP:GPSLatitude',
|
||||
# 'QuickTime:GPSLatitude',
|
||||
'Composite:GPSLatitude'
|
||||
]
|
||||
self.longitude_keys = [
|
||||
'XMP:GPSLongitude',
|
||||
# 'QuickTime:GPSLongitude',
|
||||
'Composite:GPSLongitude'
|
||||
]
|
||||
self.latitude_ref_key = 'EXIF:GPSLatitudeRef'
|
||||
self.longitude_ref_key = 'EXIF:GPSLongitudeRef'
|
||||
self.set_gps_ref = False
|
||||
super().__init__(source)
|
||||
# self.set_gps_ref = False
|
||||
|
||||
|
||||
def is_valid(self):
|
||||
return super().is_valid()
|
||||
|
|
|
@ -9,8 +9,7 @@ from elodie import log
|
|||
from elodie.compatability import _decode
|
||||
from elodie.filesystem import FileSystem
|
||||
from elodie.localstorage import Db
|
||||
from elodie.media.base import Base, get_all_subclasses
|
||||
from elodie.media.media import Media
|
||||
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
|
||||
|
|
|
@ -1,138 +0,0 @@
|
|||
# Project imports
|
||||
import os
|
||||
import sys
|
||||
|
||||
import hashlib
|
||||
import random
|
||||
import re
|
||||
import shutil
|
||||
import string
|
||||
import tempfile
|
||||
import time
|
||||
|
||||
sys.path.insert(0, os.path.abspath(os.path.dirname(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.media.base import Base, get_all_subclasses
|
||||
from elodie.media.media import Media
|
||||
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(Base)
|
||||
expected = {Media, Base, Photo, Video, Audio}
|
||||
assert subclasses == expected, subclasses
|
||||
|
||||
def test_get_class_by_file_without_extension():
|
||||
base_file = helper.get_file('withoutextension')
|
||||
|
||||
cls = Base.get_class_by_file(base_file, [Audio, Photo, Video])
|
||||
|
||||
assert cls is None, cls
|
||||
|
||||
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()
|
||||
|
||||
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)
|
||||
|
||||
photo = Photo(origin)
|
||||
metadata = photo.get_metadata()
|
||||
|
||||
assert metadata['album'] is None, metadata['album']
|
||||
|
||||
new_album_name = os.path.split(folder)[1]
|
||||
status = photo.set_album_from_folder()
|
||||
|
||||
assert status == True, status
|
||||
|
||||
photo_new = Photo(origin)
|
||||
metadata_new = photo_new.get_metadata()
|
||||
|
||||
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)
|
||||
|
||||
photo = Photo(origin)
|
||||
|
||||
metadata = photo.get_metadata()
|
||||
|
||||
assert metadata['title'] == None, metadata['title']
|
||||
|
||||
new_title = 'Some Title'
|
||||
photo.set_metadata(title = new_title)
|
||||
|
||||
new_metadata = photo.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)
|
||||
|
||||
photo = Photo(origin)
|
||||
|
||||
metadata = photo.get_metadata()
|
||||
|
||||
assert metadata['base_name'] == 'photo', metadata['base_name']
|
||||
|
||||
new_basename = 'Some Base Name'
|
||||
photo.set_metadata_basename(new_basename)
|
||||
|
||||
new_metadata = photo.get_metadata()
|
||||
|
||||
assert new_metadata['base_name'] == new_basename, new_metadata['base_name']
|
|
@ -8,7 +8,6 @@ import tempfile
|
|||
import time
|
||||
from datetime import datetime
|
||||
|
||||
sys.path.insert(0, os.path.abspath(os.path.dirname(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
|
||||
|
@ -100,16 +99,16 @@ def test_set_date_original():
|
|||
origin = '%s/audio.m4a' % folder
|
||||
shutil.copyfile(helper.get_file('audio.m4a'), origin)
|
||||
|
||||
media = Media(origin)
|
||||
audio = Audio(origin)
|
||||
date = datetime(2013, 9, 30, 7, 6, 5)
|
||||
status = media.set_date_original(date)
|
||||
status = audio.set_date_original(date)
|
||||
|
||||
assert status == True, status
|
||||
|
||||
audio_new = Audio(origin)
|
||||
metadata = audio_new.get_metadata()
|
||||
metadata = audio_new.get_metadata(update_cache=True)
|
||||
|
||||
date_original = metadata['date_created']
|
||||
date_original = metadata['date_original']
|
||||
|
||||
shutil.rmtree(folder)
|
||||
|
||||
|
@ -134,7 +133,7 @@ def test_set_location():
|
|||
assert status == True, status
|
||||
|
||||
audio_new = Audio(origin)
|
||||
metadata = audio_new.get_metadata()
|
||||
metadata = audio_new.get_metadata(update_cache=True)
|
||||
|
||||
shutil.rmtree(folder)
|
||||
|
||||
|
@ -160,7 +159,7 @@ def test_set_location_minus():
|
|||
assert status == True, status
|
||||
|
||||
audio_new = Audio(origin)
|
||||
metadata = audio_new.get_metadata()
|
||||
metadata = audio_new.get_metadata(update_cache=True)
|
||||
|
||||
shutil.rmtree(folder)
|
||||
|
||||
|
@ -202,7 +201,7 @@ def test_set_title_non_ascii():
|
|||
assert status == True, status
|
||||
|
||||
audio_new = Audio(origin)
|
||||
metadata = audio_new.get_metadata()
|
||||
metadata = audio_new.get_metadata(update_cache=True)
|
||||
|
||||
shutil.rmtree(folder)
|
||||
|
|
@ -9,13 +9,13 @@ 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.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.media.media import Media, get_all_subclasses
|
||||
from elodie.media.audio import Audio
|
||||
from elodie.media.media import Media
|
||||
from elodie.media.photo import Photo
|
||||
from elodie.media.video import Video
|
||||
|
||||
|
@ -24,6 +24,119 @@ 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_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 None, cls
|
||||
|
||||
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()
|
||||
|
@ -63,42 +176,16 @@ def test_get_class_by_file_invalid_type():
|
|||
[Photo, Video, Audio])
|
||||
assert media is None
|
||||
|
||||
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_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()
|
||||
result = media.set_original_name(origin)
|
||||
|
||||
assert result is None, result
|
||||
|
||||
|
@ -107,13 +194,13 @@ def test_set_original_name_when_does_not_exist():
|
|||
|
||||
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()
|
||||
metadata_after = 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
|
||||
|
@ -124,7 +211,7 @@ def test_set_original_name_with_arg():
|
|||
|
||||
origin = '%s/%s' % (folder, 'plain.jpg')
|
||||
file = helper.get_file('plain.jpg')
|
||||
|
||||
|
||||
shutil.copyfile(file, origin)
|
||||
|
||||
new_name = helper.random_string(15)
|
||||
|
@ -132,7 +219,7 @@ def test_set_original_name_with_arg():
|
|||
media = Media.get_class_by_file(origin, [Photo])
|
||||
metadata_before = media.get_metadata()
|
||||
result = media.set_original_name(new_name)
|
||||
metadata_after = media.get_metadata()
|
||||
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
|
||||
|
@ -154,10 +241,10 @@ def test_set_original_name():
|
|||
|
||||
shutil.copyfile(file_path, origin)
|
||||
|
||||
media = Media.get_class_by_file(origin, [Audio, Media, Photo, Video])
|
||||
media = Media.get_class_by_file(origin, [Audio, Photo, Video])
|
||||
metadata = media.get_metadata()
|
||||
media.set_original_name()
|
||||
metadata_updated = media.get_metadata()
|
||||
media.set_original_name(origin)
|
||||
metadata_updated = media.get_metadata(update_cache=True)
|
||||
|
||||
shutil.rmtree(folder)
|
||||
|
|
@ -10,7 +10,6 @@ import time
|
|||
|
||||
from nose.plugins.skip import SkipTest
|
||||
|
||||
sys.path.insert(0, os.path.abspath(os.path.dirname(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
|
||||
|
@ -122,8 +121,8 @@ def test_get_coordinates_with_null_coordinate():
|
|||
assert longitude is None, longitude
|
||||
|
||||
def test_get_date_original():
|
||||
media = Media(helper.get_file('plain.jpg'))
|
||||
date_original = media.get_date_attribute(['EXIF:DateTimeOriginal'])
|
||||
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
|
||||
|
@ -174,12 +173,12 @@ def test_set_album():
|
|||
|
||||
assert metadata['album'] is None, metadata['album']
|
||||
|
||||
status = photo.set_album('Test Album')
|
||||
status = photo.set_album('Test Album', origin)
|
||||
|
||||
assert status == True, status
|
||||
|
||||
photo_new = Photo(origin)
|
||||
metadata_new = photo_new.get_metadata()
|
||||
metadata_new = photo_new.get_metadata(update_cache=True)
|
||||
|
||||
shutil.rmtree(folder)
|
||||
|
||||
|
@ -193,14 +192,14 @@ def test_set_date_original_with_missing_datetimeoriginal():
|
|||
origin = '%s/photo.jpg' % folder
|
||||
shutil.copyfile(helper.get_file('no-exif.jpg'), origin)
|
||||
|
||||
media = Media(origin)
|
||||
photo = Photo(origin)
|
||||
time = datetime(2013, 9, 30, 7, 6, 5)
|
||||
status = media.set_date_original(time)
|
||||
status = photo.set_date_original(time)
|
||||
|
||||
assert status == True, status
|
||||
|
||||
photo_new = Photo(origin)
|
||||
metadata = photo_new.get_metadata()
|
||||
metadata = photo_new.get_metadata(update_cache=True)
|
||||
|
||||
date_original = metadata['date_original']
|
||||
|
||||
|
@ -216,13 +215,13 @@ def test_set_date_original():
|
|||
origin = '%s/photo.jpg' % folder
|
||||
shutil.copyfile(helper.get_file('plain.jpg'), origin)
|
||||
|
||||
media = Media(origin)
|
||||
status = media.set_date_original(datetime(2013, 9, 30, 7, 6, 5))
|
||||
photo = Photo(origin)
|
||||
status = photo.set_date_original(datetime(2013, 9, 30, 7, 6, 5))
|
||||
|
||||
assert status == True, status
|
||||
|
||||
media_new = Media(origin)
|
||||
metadata = media_new.get_metadata()
|
||||
photo_new = Photo(origin)
|
||||
metadata = photo_new.get_metadata(update_cache=True)
|
||||
|
||||
date_original = metadata['date_original']
|
||||
|
||||
|
@ -250,7 +249,7 @@ def test_set_location():
|
|||
assert status == True, status
|
||||
|
||||
photo_new = Photo(origin)
|
||||
metadata = photo_new.get_metadata()
|
||||
metadata = photo_new.get_metadata(update_cache=True)
|
||||
|
||||
shutil.rmtree(folder)
|
||||
|
||||
|
@ -276,7 +275,7 @@ def test_set_location_minus():
|
|||
assert status == True, status
|
||||
|
||||
photo_new = Photo(origin)
|
||||
metadata = photo_new.get_metadata()
|
||||
metadata = photo_new.get_metadata(update_cache=True)
|
||||
|
||||
shutil.rmtree(folder)
|
||||
|
||||
|
@ -297,7 +296,7 @@ def test_set_title():
|
|||
assert status == True, status
|
||||
|
||||
photo_new = Photo(origin)
|
||||
metadata = photo_new.get_metadata()
|
||||
metadata = photo_new.get_metadata(update_cache=True)
|
||||
|
||||
shutil.rmtree(folder)
|
||||
|
||||
|
@ -318,7 +317,7 @@ def test_set_title_non_ascii():
|
|||
assert status == True, status
|
||||
|
||||
photo_new = Photo(origin)
|
||||
metadata = photo_new.get_metadata()
|
||||
metadata = photo_new.get_metadata(update_cache=True)
|
||||
|
||||
shutil.rmtree(folder)
|
||||
|
||||
|
@ -395,7 +394,7 @@ def _test_photo_type_set(type, date):
|
|||
assert status == True, status
|
||||
|
||||
photo_new = Photo(origin)
|
||||
metadata = photo_new.get_metadata()
|
||||
metadata = photo_new.get_metadata(update_cache=True)
|
||||
|
||||
shutil.rmtree(folder)
|
||||
|
|
@ -9,7 +9,6 @@ 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.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
|
||||
|
@ -102,7 +101,7 @@ def test_set_album():
|
|||
|
||||
assert metadata['album'] is None, metadata['album']
|
||||
|
||||
status = video.set_album('Test Album')
|
||||
status = video.set_album('Test Album', origin)
|
||||
|
||||
assert status == True, status
|
||||
|
Loading…
Reference in New Issue