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)
 | 
					        sys.exit(1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@click.command('generate-db')
 | 
					@click.command('generate-db')
 | 
				
			||||||
@click.option('--source', type=click.Path(file_okay=False),
 | 
					@click.option('--path', type=click.Path(file_okay=False),
 | 
				
			||||||
              required=True, help='Source of your photo library.')
 | 
					              required=True, help='Path of your photo library.')
 | 
				
			||||||
@click.option('--debug', default=False, is_flag=True,
 | 
					@click.option('--debug', default=False, is_flag=True,
 | 
				
			||||||
              help='Override the value in constants.py with True.')
 | 
					              help='Override the value in constants.py with True.')
 | 
				
			||||||
def _generate_db(path, debug):
 | 
					def _generate_db(path, debug):
 | 
				
			||||||
@ -164,29 +164,31 @@ def _generate_db(path, debug):
 | 
				
			|||||||
    """
 | 
					    """
 | 
				
			||||||
    constants.debug = debug
 | 
					    constants.debug = debug
 | 
				
			||||||
    result = Result()
 | 
					    result = Result()
 | 
				
			||||||
    source = os.path.abspath(os.path.expanduser(source))
 | 
					    path = os.path.abspath(os.path.expanduser(path))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if not os.path.isdir(source):
 | 
					    if not os.path.isdir(path):
 | 
				
			||||||
        log.error('Source is not a valid directory %s' % source)
 | 
					        log.error('path is not a valid directory %s' % path)
 | 
				
			||||||
        sys.exit(1)
 | 
					        sys.exit(1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    db = Db(path)
 | 
					    db = Db(path)
 | 
				
			||||||
    db.backup_hash_db()
 | 
					    db.backup_hash_db()
 | 
				
			||||||
    db.reset_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))
 | 
					        result.append((current_file, True))
 | 
				
			||||||
        db.add_hash(db.checksum(current_file), current_file)
 | 
					        db.add_hash(db.checksum(current_file), current_file)
 | 
				
			||||||
        log.progress()
 | 
					        log.progress()
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    db.update_hash_db()
 | 
					    db.update_hash_db()
 | 
				
			||||||
    log.progress('', True)
 | 
					    log.progress('', True)
 | 
				
			||||||
    result.write()
 | 
					    result.write()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@click.command('verify')
 | 
					@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,
 | 
					@click.option('--debug', default=False, is_flag=True,
 | 
				
			||||||
              help='Override the value in constants.py with True.')
 | 
					              help='Override the value in constants.py with True.')
 | 
				
			||||||
def _verify(debug):
 | 
					def _verify(path, debug):
 | 
				
			||||||
    constants.debug = debug
 | 
					    constants.debug = debug
 | 
				
			||||||
    result = Result()
 | 
					    result = Result()
 | 
				
			||||||
    db = Db(path)
 | 
					    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 \
 | 
					    if location_coords and 'latitude' in location_coords and \
 | 
				
			||||||
            'longitude' in location_coords:
 | 
					            'longitude' in location_coords:
 | 
				
			||||||
        location_status = media.set_location(location_coords[
 | 
					        location_status = media.set_location(location_coords[
 | 
				
			||||||
            'latitude'], location_coords['longitude'])
 | 
					            'latitude'], location_coords['longitude'], file_path)
 | 
				
			||||||
        if not location_status:
 | 
					        if not location_status:
 | 
				
			||||||
            log.error('Failed to update location')
 | 
					            log.error('Failed to update location')
 | 
				
			||||||
            log.all(('{"source":"%s",' % file_path,
 | 
					            log.all(('{"source":"%s",' % file_path,
 | 
				
			||||||
@ -307,7 +309,7 @@ def _update(album, location, time, title, paths, debug):
 | 
				
			|||||||
            update_time(media, current_file, time)
 | 
					            update_time(media, current_file, time)
 | 
				
			||||||
            updated = True
 | 
					            updated = True
 | 
				
			||||||
        if album:
 | 
					        if album:
 | 
				
			||||||
            media.set_album(album)
 | 
					            media.set_album(album, current_file)
 | 
				
			||||||
            updated = True
 | 
					            updated = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        import ipdb; ipdb.set_trace()
 | 
					        import ipdb; ipdb.set_trace()
 | 
				
			||||||
 | 
				
			|||||||
@ -17,7 +17,7 @@ from elodie.config import load_config
 | 
				
			|||||||
from elodie import constants
 | 
					from elodie import constants
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from elodie.localstorage import Db
 | 
					from elodie.localstorage import Db
 | 
				
			||||||
from elodie.media import base
 | 
					from elodie.media import media
 | 
				
			||||||
from elodie.plugins.plugins import Plugins
 | 
					from elodie.plugins.plugins import Plugins
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class FileSystem(object):
 | 
					class FileSystem(object):
 | 
				
			||||||
@ -94,7 +94,7 @@ class FileSystem(object):
 | 
				
			|||||||
        # If extensions is None then we get all supported extensions
 | 
					        # If extensions is None then we get all supported extensions
 | 
				
			||||||
        if not extensions:
 | 
					        if not extensions:
 | 
				
			||||||
            extensions = set()
 | 
					            extensions = set()
 | 
				
			||||||
            subclasses = base.get_all_subclasses()
 | 
					            subclasses = media.get_all_subclasses()
 | 
				
			||||||
            for cls in subclasses:
 | 
					            for cls in subclasses:
 | 
				
			||||||
                extensions.update(cls.extensions)
 | 
					                extensions.update(cls.extensions)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -679,7 +679,9 @@ class FileSystem(object):
 | 
				
			|||||||
            if album_from_folder:
 | 
					            if album_from_folder:
 | 
				
			||||||
                media.set_album_from_folder(dest_path)
 | 
					                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()
 | 
					        db.update_hash_db()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # Run `after()` for every loaded plugin and if any of them raise an exception
 | 
					        # 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 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.
 | 
					class.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. moduleauthor:: Jaisen Mathai <jaisen@jmathai.com>
 | 
					.. moduleauthor:: Jaisen Mathai <jaisen@jmathai.com>
 | 
				
			||||||
"""
 | 
					"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from .video import Video
 | 
					from .media import Media
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Audio(Video):
 | 
					class Audio(Media):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    """An audio object.
 | 
					    """An audio object.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -22,4 +22,7 @@ class Audio(Video):
 | 
				
			|||||||
    extensions = ('m4a',)
 | 
					    extensions = ('m4a',)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self, source=None):
 | 
					    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
 | 
					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
 | 
					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
 | 
					by all the media types. Its sub-classes (:class:`~elodie.media.Audio`,
 | 
				
			||||||
sub-classes (:class:`~elodie.media.audio.Audio`,
 | 
					:class:`~elodie.media.Photo`, and :class:`~elodie.media.Video`)
 | 
				
			||||||
:class:`~elodie.media.photo.Photo`, and :class:`~elodie.media.video.Video`)
 | 
					 | 
				
			||||||
are used to represent the actual files.
 | 
					are used to represent the actual files.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. moduleauthor:: Jaisen Mathai <jaisen@jmathai.com>
 | 
					.. moduleauthor:: Jaisen Mathai <jaisen@jmathai.com>
 | 
				
			||||||
"""
 | 
					"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import mimetypes
 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
import six
 | 
					import six
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -17,11 +17,17 @@ from elodie import log
 | 
				
			|||||||
from dateutil.parser import parse
 | 
					from dateutil.parser import parse
 | 
				
			||||||
import re
 | 
					import re
 | 
				
			||||||
from elodie.external.pyexiftool import ExifTool
 | 
					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.
 | 
					    :param str source: The fully qualified path to the video file.
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
@ -33,23 +39,221 @@ class Media(Base):
 | 
				
			|||||||
        'longitude': 'longitude_ref'
 | 
					        'longitude': 'longitude_ref'
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self, source=None):
 | 
					    PHOTO = ('arw', 'cr2', 'dng', 'gif', 'heic', 'jpeg', 'jpg', 'nef', 'png', 'rw2')
 | 
				
			||||||
        super(Media, self).__init__(source)
 | 
					    AUDIO = ('m4a',)
 | 
				
			||||||
        self.date_original = ['EXIF:DateTimeOriginal']
 | 
					    VIDEO = ('avi', 'm4v', 'mov', 'mp4', 'mpg', 'mpeg', '3gp', 'mts')
 | 
				
			||||||
        self.date_created = ['EXIF:CreateDate', 'QuickTime:CreateDate']
 | 
					
 | 
				
			||||||
 | 
					    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.date_modified = ['File:FileModifyDate', 'QuickTime:ModifyDate']
 | 
				
			||||||
        self.camera_make_keys = ['EXIF:Make', 'QuickTime:Make']
 | 
					        self.camera_make_keys = ['EXIF:Make', 'QuickTime:Make']
 | 
				
			||||||
        self.camera_model_keys = ['EXIF:Model', 'QuickTime:Model']
 | 
					        self.camera_model_keys = ['EXIF:Model', 'QuickTime:Model']
 | 
				
			||||||
        self.album_keys = ['XMP-xmpDM:Album', 'XMP:Album']
 | 
					        self.album_keys = ['XMP-xmpDM:Album', 'XMP:Album']
 | 
				
			||||||
        self.title_key = 'XMP:Title'
 | 
					        self.title_keys = ['XMP:Title', 'XMP:DisplayName']
 | 
				
			||||||
        self.latitude_keys = ['EXIF:GPSLatitude']
 | 
					        self.latitude_keys = [
 | 
				
			||||||
        self.longitude_keys = ['EXIF:GPSLongitude']
 | 
					            '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.latitude_ref_key = 'EXIF:GPSLatitudeRef'
 | 
				
			||||||
        self.longitude_ref_key = 'EXIF:GPSLongitudeRef'
 | 
					        self.longitude_ref_key = 'EXIF:GPSLongitudeRef'
 | 
				
			||||||
        self.original_name_key = 'XMP:OriginalFileName'
 | 
					        self.original_name_key = 'XMP:OriginalFileName'
 | 
				
			||||||
        self.set_gps_ref = True
 | 
					        self.set_gps_ref = True
 | 
				
			||||||
 | 
					        self.metadata = None
 | 
				
			||||||
        self.exif_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):
 | 
					    def get_album(self):
 | 
				
			||||||
        """Get album from EXIF
 | 
					        """Get album from EXIF
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -68,6 +272,7 @@ class Media(Base):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        return None
 | 
					        return None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_coordinate(self, type='latitude'):
 | 
					    def get_coordinate(self, type='latitude'):
 | 
				
			||||||
        """Get latitude or longitude of media from EXIF
 | 
					        """Get latitude or longitude of media from EXIF
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -114,6 +319,7 @@ class Media(Base):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        return None
 | 
					        return None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_exiftool_attributes(self):
 | 
					    def get_exiftool_attributes(self):
 | 
				
			||||||
        """Get attributes for the media object from exiftool.
 | 
					        """Get attributes for the media object from exiftool.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -185,6 +391,7 @@ class Media(Base):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        return None
 | 
					        return None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_camera_model(self):
 | 
					    def get_camera_model(self):
 | 
				
			||||||
        """Get the camera make stored in EXIF.
 | 
					        """Get the camera make stored in EXIF.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -204,6 +411,7 @@ class Media(Base):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        return None
 | 
					        return None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_original_name(self):
 | 
					    def get_original_name(self):
 | 
				
			||||||
        """Get the original name stored in EXIF.
 | 
					        """Get the original name stored in EXIF.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -222,6 +430,7 @@ class Media(Base):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        return exiftool_attributes[self.original_name_key]
 | 
					        return exiftool_attributes[self.original_name_key]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_title(self):
 | 
					    def get_title(self):
 | 
				
			||||||
        """Get the title for a photo of video
 | 
					        """Get the title for a photo of video
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -235,17 +444,19 @@ class Media(Base):
 | 
				
			|||||||
        if exiftool_attributes is None:
 | 
					        if exiftool_attributes is None:
 | 
				
			||||||
            return None
 | 
					            return None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if(self.title_key not in exiftool_attributes):
 | 
					        for title_key in self.title_keys:
 | 
				
			||||||
            return None
 | 
					            if title_key in exiftool_attributes:
 | 
				
			||||||
 | 
					                return exiftool_attributes[title_key]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return exiftool_attributes[self.title_key]
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def reset_cache(self):
 | 
					    def reset_cache(self):
 | 
				
			||||||
        """Resets any internal cache
 | 
					        """Resets any internal cache
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        self.exiftool_attributes = None
 | 
					        self.exiftool_attributes = None
 | 
				
			||||||
        self.exif_metadata = None
 | 
					        self.exif_metadata = None
 | 
				
			||||||
        super(Media, self).reset_cache()
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def set_album(self, name, path):
 | 
					    def set_album(self, name, path):
 | 
				
			||||||
        """Set album EXIF tag if not already set.
 | 
					        """Set album EXIF tag if not already set.
 | 
				
			||||||
@ -255,12 +466,16 @@ class Media(Base):
 | 
				
			|||||||
        if self.get_album() is not None:
 | 
					        if self.get_album() is not None:
 | 
				
			||||||
            return None
 | 
					            return None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        tags = {self.album_keys[0]: name}
 | 
					        tags = {}
 | 
				
			||||||
        status = ExifTool().set_tags(tags, path)
 | 
					        for key in self.album_keys:
 | 
				
			||||||
 | 
					            tags[key] = name
 | 
				
			||||||
 | 
					        status = self.__set_tags(tags, path)
 | 
				
			||||||
        self.reset_cache()
 | 
					        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.
 | 
					        """Set the date/time a photo was taken.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        :param datetime time: datetime object of when the 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:
 | 
					        for key in self.date_original:
 | 
				
			||||||
            tags[key] = formatted_time
 | 
					            tags[key] = formatted_time
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        status = self.__set_tags(tags)
 | 
					        status = self.__set_tags(tags, path)
 | 
				
			||||||
        if status == False:
 | 
					        if status == False:
 | 
				
			||||||
            # exif attribute date_original d'ont exist
 | 
					            # exif attribute date_original d'ont exist
 | 
				
			||||||
            for key in self.date_created:
 | 
					            for key in self.date_created:
 | 
				
			||||||
                tags[key] = formatted_time
 | 
					                tags[key] = formatted_time
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            status = self.__set_tags(tags)
 | 
					            status = self.__set_tags(tags, path)
 | 
				
			||||||
        self.reset_cache()
 | 
					        self.reset_cache()
 | 
				
			||||||
        return status
 | 
					        return status
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def set_location(self, latitude, longitude):
 | 
					
 | 
				
			||||||
 | 
					    def set_location(self, latitude, longitude, path):
 | 
				
			||||||
        if(not self.is_valid()):
 | 
					        if(not self.is_valid()):
 | 
				
			||||||
            return None
 | 
					            return None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # The lat/lon _keys array has an order of precedence.
 | 
					        # The lat/lon _keys array has an order of precedence.
 | 
				
			||||||
        # The first key is writable and we will give the writable
 | 
					        # The first key is writable and we will give the writable
 | 
				
			||||||
        #   key precence when reading.
 | 
					        #   key precence when reading.
 | 
				
			||||||
        tags = {
 | 
					        # TODO check
 | 
				
			||||||
            self.latitude_keys[0]: latitude,
 | 
					        # tags = {
 | 
				
			||||||
            self.longitude_keys[0]: longitude,
 | 
					        #     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
 | 
					        # If self.set_gps_ref == True then it means we are writing an EXIF
 | 
				
			||||||
        #   GPS tag which requires us to set the reference key.
 | 
					        #   GPS tag which requires us to set the reference key.
 | 
				
			||||||
        # That's because the lat/lon are absolute values.
 | 
					        # That's because the lat/lon are absolute values.
 | 
				
			||||||
 | 
					        # TODO set_gps_ref = False for Video ?
 | 
				
			||||||
        if self.set_gps_ref:
 | 
					        if self.set_gps_ref:
 | 
				
			||||||
            if latitude < 0:
 | 
					            if latitude < 0:
 | 
				
			||||||
                tags[self.latitude_ref_key] = 'S'
 | 
					                tags[self.latitude_ref_key] = 'S'
 | 
				
			||||||
@ -306,12 +529,13 @@ class Media(Base):
 | 
				
			|||||||
            if longitude < 0:
 | 
					            if longitude < 0:
 | 
				
			||||||
                tags[self.longitude_ref_key] = 'W'
 | 
					                tags[self.longitude_ref_key] = 'W'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        status = self.__set_tags(tags)
 | 
					        status = self.__set_tags(tags, path)
 | 
				
			||||||
        self.reset_cache()
 | 
					        self.reset_cache()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return status
 | 
					        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.
 | 
					        """Sets the original name EXIF tag if not already set.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        :returns: True, False, None
 | 
					        :returns: True, False, None
 | 
				
			||||||
@ -320,14 +544,17 @@ class Media(Base):
 | 
				
			|||||||
        if self.get_original_name() is not None:
 | 
					        if self.get_original_name() is not None:
 | 
				
			||||||
            return None
 | 
					            return None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        name = os.path.basename(path)
 | 
					        if name == None:
 | 
				
			||||||
 | 
					            name = os.path.basename(self.source)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        tags = {self.original_name_key: name}
 | 
					        tags = {self.original_name_key: name}
 | 
				
			||||||
        status = ExifTool().set_tags(tags, path)
 | 
					        status = self.__set_tags(tags, path)
 | 
				
			||||||
        self.reset_cache()
 | 
					        self.reset_cache()
 | 
				
			||||||
        return status != ''
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def set_title(self, title):
 | 
					        return status
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def set_title(self, title, path):
 | 
				
			||||||
        """Set title for a photo.
 | 
					        """Set title for a photo.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        :param str title: Title of the photo.
 | 
					        :param str title: Title of the photo.
 | 
				
			||||||
@ -339,23 +566,43 @@ class Media(Base):
 | 
				
			|||||||
        if(title is None):
 | 
					        if(title is None):
 | 
				
			||||||
            return None
 | 
					            return None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        tags = {self.title_key: title}
 | 
					        tags = {}
 | 
				
			||||||
        status = self.__set_tags(tags)
 | 
					        for key in self.title_keys:
 | 
				
			||||||
 | 
					            tags[key] = title
 | 
				
			||||||
 | 
					        status = self.__set_tags(tags, path)
 | 
				
			||||||
        self.reset_cache()
 | 
					        self.reset_cache()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return status
 | 
					        return status
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __set_tags(self, tags):
 | 
					
 | 
				
			||||||
 | 
					    def __set_tags(self, tags, path):
 | 
				
			||||||
        if(not self.is_valid()):
 | 
					        if(not self.is_valid()):
 | 
				
			||||||
            return None
 | 
					            return None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        source = self.source
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        status = ''
 | 
					        status = ''
 | 
				
			||||||
        status = ExifTool().set_tags(tags,source)
 | 
					        status = ExifTool().set_tags(tags, path)
 | 
				
			||||||
        if status.decode().find('unchanged') != -1 or status == '':
 | 
					        if status.decode().find('unchanged') != -1 or status == '':
 | 
				
			||||||
            return False
 | 
					            return False
 | 
				
			||||||
        if status.decode().find('error') != -1:
 | 
					        if status.decode().find('error') != -1:
 | 
				
			||||||
            return False
 | 
					            return False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return True
 | 
					        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')
 | 
					    extensions = ('arw', 'cr2', 'dng', 'gif', 'heic', 'jpeg', 'jpg', 'nef', 'png', 'rw2')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self, source=None):
 | 
					    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
 | 
					        # We only want to parse EXIF once so we store it here
 | 
				
			||||||
        self.exif = None
 | 
					        self.exif = None
 | 
				
			||||||
@ -79,5 +79,5 @@ class Photo(Media):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                    if(im.format is None):
 | 
					                    if(im.format is None):
 | 
				
			||||||
                        return False
 | 
					                        return False
 | 
				
			||||||
        
 | 
					
 | 
				
			||||||
        return extension in self.extensions
 | 
					        return extension in self.extensions
 | 
				
			||||||
 | 
				
			|||||||
@ -28,31 +28,9 @@ class Video(Media):
 | 
				
			|||||||
    extensions = ('avi', 'm4v', 'mov', 'mp4', 'mpg', 'mpeg', '3gp', 'mts')
 | 
					    extensions = ('avi', 'm4v', 'mov', 'mp4', 'mpg', 'mpeg', '3gp', 'mts')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self, source=None):
 | 
					    def __init__(self, source=None):
 | 
				
			||||||
        super(Video, self).__init__(source)
 | 
					        super().__init__(source)
 | 
				
			||||||
        self.date_original = [
 | 
					        # self.set_gps_ref = False
 | 
				
			||||||
            'EXIF:DateTimeOriginal',
 | 
					
 | 
				
			||||||
            'H264:DateTimeOriginal',
 | 
					
 | 
				
			||||||
            'QuickTime:ContentCreateDate'
 | 
					    def is_valid(self):
 | 
				
			||||||
        ]
 | 
					        return super().is_valid()
 | 
				
			||||||
        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
 | 
					 | 
				
			||||||
 | 
				
			|||||||
@ -9,8 +9,7 @@ from elodie import log
 | 
				
			|||||||
from elodie.compatability import _decode
 | 
					from elodie.compatability import _decode
 | 
				
			||||||
from elodie.filesystem import FileSystem
 | 
					from elodie.filesystem import FileSystem
 | 
				
			||||||
from elodie.localstorage import Db
 | 
					from elodie.localstorage import Db
 | 
				
			||||||
from elodie.media.base import Base, get_all_subclasses
 | 
					from elodie.media.media import Media, get_all_subclasses
 | 
				
			||||||
from elodie.media.media import Media
 | 
					 | 
				
			||||||
from elodie.media.audio import Audio
 | 
					from elodie.media.audio import Audio
 | 
				
			||||||
from elodie.media.photo import Photo
 | 
					from elodie.media.photo import Photo
 | 
				
			||||||
from elodie.media.video import Video
 | 
					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
 | 
					import time
 | 
				
			||||||
from datetime import datetime
 | 
					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__)))))
 | 
					sys.path.insert(0, os.path.abspath(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import helper
 | 
					import helper
 | 
				
			||||||
@ -100,16 +99,16 @@ def test_set_date_original():
 | 
				
			|||||||
    origin = '%s/audio.m4a' % folder
 | 
					    origin = '%s/audio.m4a' % folder
 | 
				
			||||||
    shutil.copyfile(helper.get_file('audio.m4a'), origin)
 | 
					    shutil.copyfile(helper.get_file('audio.m4a'), origin)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    media = Media(origin)
 | 
					    audio = Audio(origin)
 | 
				
			||||||
    date = datetime(2013, 9, 30, 7, 6, 5)
 | 
					    date = datetime(2013, 9, 30, 7, 6, 5)
 | 
				
			||||||
    status = media.set_date_original(date)
 | 
					    status = audio.set_date_original(date)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    assert status == True, status
 | 
					    assert status == True, status
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    audio_new = Audio(origin)
 | 
					    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)
 | 
					    shutil.rmtree(folder)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -134,7 +133,7 @@ def test_set_location():
 | 
				
			|||||||
    assert status == True, status
 | 
					    assert status == True, status
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    audio_new = Audio(origin)
 | 
					    audio_new = Audio(origin)
 | 
				
			||||||
    metadata = audio_new.get_metadata()
 | 
					    metadata = audio_new.get_metadata(update_cache=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    shutil.rmtree(folder)
 | 
					    shutil.rmtree(folder)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -160,7 +159,7 @@ def test_set_location_minus():
 | 
				
			|||||||
    assert status == True, status
 | 
					    assert status == True, status
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    audio_new = Audio(origin)
 | 
					    audio_new = Audio(origin)
 | 
				
			||||||
    metadata = audio_new.get_metadata()
 | 
					    metadata = audio_new.get_metadata(update_cache=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    shutil.rmtree(folder)
 | 
					    shutil.rmtree(folder)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -202,7 +201,7 @@ def test_set_title_non_ascii():
 | 
				
			|||||||
    assert status == True, status
 | 
					    assert status == True, status
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    audio_new = Audio(origin)
 | 
					    audio_new = Audio(origin)
 | 
				
			||||||
    metadata = audio_new.get_metadata()
 | 
					    metadata = audio_new.get_metadata(update_cache=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    shutil.rmtree(folder)
 | 
					    shutil.rmtree(folder)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -9,13 +9,13 @@ import shutil
 | 
				
			|||||||
import string
 | 
					import string
 | 
				
			||||||
import tempfile
 | 
					import tempfile
 | 
				
			||||||
import time
 | 
					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__)))))
 | 
					sys.path.insert(0, os.path.abspath(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import helper
 | 
					import helper
 | 
				
			||||||
 | 
					from elodie.media.media import Media, get_all_subclasses
 | 
				
			||||||
from elodie.media.audio import Audio
 | 
					from elodie.media.audio import Audio
 | 
				
			||||||
from elodie.media.media import Media
 | 
					 | 
				
			||||||
from elodie.media.photo import Photo
 | 
					from elodie.media.photo import Photo
 | 
				
			||||||
from elodie.media.video import Video
 | 
					from elodie.media.video import Video
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -24,6 +24,119 @@ os.environ['TZ'] = 'GMT'
 | 
				
			|||||||
setup_module = helper.setup_module
 | 
					setup_module = helper.setup_module
 | 
				
			||||||
teardown_module = helper.teardown_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():
 | 
					def test_get_file_path():
 | 
				
			||||||
    media = Media(helper.get_file('plain.jpg'))
 | 
					    media = Media(helper.get_file('plain.jpg'))
 | 
				
			||||||
    path = media.get_file_path()
 | 
					    path = media.get_file_path()
 | 
				
			||||||
@ -63,42 +176,16 @@ def test_get_class_by_file_invalid_type():
 | 
				
			|||||||
                                    [Photo, Video, Audio])
 | 
					                                    [Photo, Video, Audio])
 | 
				
			||||||
    assert media is None
 | 
					    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():
 | 
					def test_set_original_name_when_exists():
 | 
				
			||||||
    temporary_folder, folder = helper.create_working_folder()
 | 
					    temporary_folder, folder = helper.create_working_folder()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    origin = '%s/%s' % (folder, 'with-original-name.jpg')
 | 
					    origin = '%s/%s' % (folder, 'with-original-name.jpg')
 | 
				
			||||||
    file = helper.get_file('with-original-name.jpg')
 | 
					    file = helper.get_file('with-original-name.jpg')
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    shutil.copyfile(file, origin)
 | 
					    shutil.copyfile(file, origin)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    media = Media.get_class_by_file(origin, [Photo])
 | 
					    media = Media.get_class_by_file(origin, [Photo])
 | 
				
			||||||
    result = media.set_original_name()
 | 
					    result = media.set_original_name(origin)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    assert result is None, result
 | 
					    assert result is None, result
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -107,13 +194,13 @@ def test_set_original_name_when_does_not_exist():
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    origin = '%s/%s' % (folder, 'plain.jpg')
 | 
					    origin = '%s/%s' % (folder, 'plain.jpg')
 | 
				
			||||||
    file = helper.get_file('plain.jpg')
 | 
					    file = helper.get_file('plain.jpg')
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    shutil.copyfile(file, origin)
 | 
					    shutil.copyfile(file, origin)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    media = Media.get_class_by_file(origin, [Photo])
 | 
					    media = Media.get_class_by_file(origin, [Photo])
 | 
				
			||||||
    metadata_before = media.get_metadata()
 | 
					    metadata_before = media.get_metadata()
 | 
				
			||||||
    result = media.set_original_name()
 | 
					    result = media.set_original_name(origin)
 | 
				
			||||||
    metadata_after = media.get_metadata()
 | 
					    metadata_after = media.get_metadata(update_cache=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    assert metadata_before['original_name'] is None, metadata_before
 | 
					    assert metadata_before['original_name'] is None, metadata_before
 | 
				
			||||||
    assert metadata_after['original_name'] == 'plain.jpg', metadata_after
 | 
					    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')
 | 
					    origin = '%s/%s' % (folder, 'plain.jpg')
 | 
				
			||||||
    file = helper.get_file('plain.jpg')
 | 
					    file = helper.get_file('plain.jpg')
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    shutil.copyfile(file, origin)
 | 
					    shutil.copyfile(file, origin)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    new_name = helper.random_string(15)
 | 
					    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])
 | 
					    media = Media.get_class_by_file(origin, [Photo])
 | 
				
			||||||
    metadata_before = media.get_metadata()
 | 
					    metadata_before = media.get_metadata()
 | 
				
			||||||
    result = media.set_original_name(new_name)
 | 
					    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_before['original_name'] is None, metadata_before
 | 
				
			||||||
    assert metadata_after['original_name'] == new_name, metadata_after
 | 
					    assert metadata_after['original_name'] == new_name, metadata_after
 | 
				
			||||||
@ -154,10 +241,10 @@ def test_set_original_name():
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        shutil.copyfile(file_path, origin)
 | 
					        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()
 | 
					        metadata = media.get_metadata()
 | 
				
			||||||
        media.set_original_name()
 | 
					        media.set_original_name(origin)
 | 
				
			||||||
        metadata_updated = media.get_metadata()
 | 
					        metadata_updated = media.get_metadata(update_cache=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        shutil.rmtree(folder)
 | 
					        shutil.rmtree(folder)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -10,7 +10,6 @@ import time
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
from nose.plugins.skip import SkipTest
 | 
					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__)))))
 | 
					sys.path.insert(0, os.path.abspath(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import helper
 | 
					import helper
 | 
				
			||||||
@ -122,8 +121,8 @@ def test_get_coordinates_with_null_coordinate():
 | 
				
			|||||||
    assert longitude is None, longitude
 | 
					    assert longitude is None, longitude
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_get_date_original():
 | 
					def test_get_date_original():
 | 
				
			||||||
    media = Media(helper.get_file('plain.jpg'))
 | 
					    photo = Photo(helper.get_file('plain.jpg'))
 | 
				
			||||||
    date_original = media.get_date_attribute(['EXIF:DateTimeOriginal'])
 | 
					    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 == (2015, 12, 5, 0, 59, 26, 5, 339, 0), date_original
 | 
				
			||||||
    assert date_original == datetime(2015, 12, 5, 0, 59, 26), 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']
 | 
					    assert metadata['album'] is None, metadata['album']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    status = photo.set_album('Test Album')
 | 
					    status = photo.set_album('Test Album', origin)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    assert status == True, status
 | 
					    assert status == True, status
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    photo_new = Photo(origin)
 | 
					    photo_new = Photo(origin)
 | 
				
			||||||
    metadata_new = photo_new.get_metadata()
 | 
					    metadata_new = photo_new.get_metadata(update_cache=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    shutil.rmtree(folder)
 | 
					    shutil.rmtree(folder)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -193,14 +192,14 @@ def test_set_date_original_with_missing_datetimeoriginal():
 | 
				
			|||||||
    origin = '%s/photo.jpg' % folder
 | 
					    origin = '%s/photo.jpg' % folder
 | 
				
			||||||
    shutil.copyfile(helper.get_file('no-exif.jpg'), origin)
 | 
					    shutil.copyfile(helper.get_file('no-exif.jpg'), origin)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    media = Media(origin)
 | 
					    photo = Photo(origin)
 | 
				
			||||||
    time = datetime(2013, 9, 30, 7, 6, 5)
 | 
					    time = datetime(2013, 9, 30, 7, 6, 5)
 | 
				
			||||||
    status = media.set_date_original(time)
 | 
					    status = photo.set_date_original(time)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    assert status == True, status
 | 
					    assert status == True, status
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    photo_new = Photo(origin)
 | 
					    photo_new = Photo(origin)
 | 
				
			||||||
    metadata = photo_new.get_metadata()
 | 
					    metadata = photo_new.get_metadata(update_cache=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    date_original = metadata['date_original']
 | 
					    date_original = metadata['date_original']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -216,13 +215,13 @@ def test_set_date_original():
 | 
				
			|||||||
    origin = '%s/photo.jpg' % folder
 | 
					    origin = '%s/photo.jpg' % folder
 | 
				
			||||||
    shutil.copyfile(helper.get_file('plain.jpg'), origin)
 | 
					    shutil.copyfile(helper.get_file('plain.jpg'), origin)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    media = Media(origin)
 | 
					    photo = Photo(origin)
 | 
				
			||||||
    status = media.set_date_original(datetime(2013, 9, 30, 7, 6, 5))
 | 
					    status = photo.set_date_original(datetime(2013, 9, 30, 7, 6, 5))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    assert status == True, status
 | 
					    assert status == True, status
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    media_new = Media(origin)
 | 
					    photo_new = Photo(origin)
 | 
				
			||||||
    metadata = media_new.get_metadata()
 | 
					    metadata = photo_new.get_metadata(update_cache=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    date_original = metadata['date_original']
 | 
					    date_original = metadata['date_original']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -250,7 +249,7 @@ def test_set_location():
 | 
				
			|||||||
    assert status == True, status
 | 
					    assert status == True, status
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    photo_new = Photo(origin)
 | 
					    photo_new = Photo(origin)
 | 
				
			||||||
    metadata = photo_new.get_metadata()
 | 
					    metadata = photo_new.get_metadata(update_cache=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    shutil.rmtree(folder)
 | 
					    shutil.rmtree(folder)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -276,7 +275,7 @@ def test_set_location_minus():
 | 
				
			|||||||
    assert status == True, status
 | 
					    assert status == True, status
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    photo_new = Photo(origin)
 | 
					    photo_new = Photo(origin)
 | 
				
			||||||
    metadata = photo_new.get_metadata()
 | 
					    metadata = photo_new.get_metadata(update_cache=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    shutil.rmtree(folder)
 | 
					    shutil.rmtree(folder)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -297,7 +296,7 @@ def test_set_title():
 | 
				
			|||||||
    assert status == True, status
 | 
					    assert status == True, status
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    photo_new = Photo(origin)
 | 
					    photo_new = Photo(origin)
 | 
				
			||||||
    metadata = photo_new.get_metadata()
 | 
					    metadata = photo_new.get_metadata(update_cache=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    shutil.rmtree(folder)
 | 
					    shutil.rmtree(folder)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -318,7 +317,7 @@ def test_set_title_non_ascii():
 | 
				
			|||||||
    assert status == True, status
 | 
					    assert status == True, status
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    photo_new = Photo(origin)
 | 
					    photo_new = Photo(origin)
 | 
				
			||||||
    metadata = photo_new.get_metadata()
 | 
					    metadata = photo_new.get_metadata(update_cache=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    shutil.rmtree(folder)
 | 
					    shutil.rmtree(folder)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -395,7 +394,7 @@ def _test_photo_type_set(type, date):
 | 
				
			|||||||
    assert status == True, status
 | 
					    assert status == True, status
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    photo_new = Photo(origin)
 | 
					    photo_new = Photo(origin)
 | 
				
			||||||
    metadata = photo_new.get_metadata()
 | 
					    metadata = photo_new.get_metadata(update_cache=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    shutil.rmtree(folder)
 | 
					    shutil.rmtree(folder)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -9,7 +9,6 @@ import time
 | 
				
			|||||||
from datetime import datetime
 | 
					from datetime import datetime
 | 
				
			||||||
from dateutil.parser import parse
 | 
					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__)))))
 | 
					sys.path.insert(0, os.path.abspath(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import helper
 | 
					import helper
 | 
				
			||||||
@ -102,7 +101,7 @@ def test_set_album():
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    assert metadata['album'] is None, metadata['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
 | 
					    assert status == True, status
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user