diff --git a/filesystem.py b/filesystem.py deleted file mode 100644 index b1c341e..0000000 --- a/filesystem.py +++ /dev/null @@ -1,295 +0,0 @@ -""" -General file system methods. - -.. moduleauthor:: Jaisen Mathai -""" -from __future__ import print_function -from builtins import object - -import os -import re -import shutil -import time - -from elodie import geolocation -from elodie import constants -from elodie.localstorage import Db -from elodie.media.media import Media -from elodie.media.text import Text -from elodie.media.audio import Audio -from elodie.media.photo import Photo -from elodie.media.video import Video - - -class FileSystem(object): - - """A class for interacting with the file system.""" - - def create_directory(self, directory_path): - """Create a directory if it does not already exist. - - :param str directory_name: A fully qualified path of the - to create. - :returns: bool - """ - try: - if os.path.exists(directory_path): - return True - else: - os.makedirs(directory_path) - return True - except OSError: - # OSError is thrown for cases like no permission - pass - - return False - - def delete_directory_if_empty(self, directory_path): - """Delete a directory only if it's empty. - - Instead of checking first using `len([name for name in - os.listdir(directory_path)]) == 0`, we catch the OSError exception. - - :param str directory_name: A fully qualified path of the directory - to delete. - """ - try: - os.rmdir(directory_path) - return True - except OSError: - pass - - return False - - def get_all_files(self, path, extensions=None): - """Recursively get all files which match a path and extension. - - :param str path string: Path to start recursive file listing - :param tuple(str) extensions: File extensions to include (whitelist) - """ - files = [] - for dirname, dirnames, filenames in os.walk(path): - # print path to all filenames. - for filename in filenames: - if( - extensions is None or - filename.lower().endswith(extensions) - ): - files.append(os.path.join(dirname, filename)) - return files - - def get_current_directory(self): - """Get the current working directory. - - :returns: str - """ - return os.getcwd() - - def get_file_name(self, media): - """Generate file name for a photo or video using its metadata. - - We use an ISO8601-like format for the file name prefix. Instead of - colons as the separator for hours, minutes and seconds we use a hyphen. - https://en.wikipedia.org/wiki/ISO_8601#General_principles - - :param media: A Photo or Video instance - :type media: :class:`~elodie.media.photo.Photo` or - :class:`~elodie.media.video.Video` - :returns: str or None for non-photo or non-videos - """ - if(not media.is_valid()): - return None - - metadata = media.get_metadata() - if(metadata is None): - return None - - # If the file has EXIF title we use that in the file name - # (i.e. my-favorite-photo-img_1234.jpg) - # We want to remove the date prefix we add to the name. - # This helps when re-running the program on file which were already - # processed. - base_name = re.sub( - '^\d{4}-\d{2}-\d{2}_\d{2}-\d{2}-\d{2}-', - '', - metadata['base_name'] - ) - if(len(base_name) == 0): - base_name = metadata['base_name'] - - if( - 'title' in metadata and - metadata['title'] is not None and - len(metadata['title']) > 0 - ): - title_sanitized = re.sub('\W+', '-', metadata['title'].strip()) - base_name = base_name.replace('-%s' % title_sanitized, '') - base_name = '%s-%s' % (base_name, title_sanitized) - - file_name = '%s-%s.%s' % ( - time.strftime( - '%Y-%m-%d_%H-%M-%S', - metadata['date_taken'] - ), - base_name, - metadata['extension']) - return file_name.lower() - - def get_folder_name_by_date(self, time_obj): - """Get date based folder name. - - :param time time_obj: Time object to be used to determine folder name. - :returns: str - """ - return time.strftime('%Y-%m-%b', time_obj) - - def get_folder_path(self, metadata): - """Get folder path by various parameters. - - :param time time_obj: Time object to be used to determine folder name. - :returns: str - """ - path = [] - if(metadata['date_taken'] is not None): - path.append(time.strftime('%Y-%m-%b', metadata['date_taken'])) - - if(metadata['album'] is not None): - path.append(metadata['album']) - elif( - metadata['latitude'] is not None and - metadata['longitude'] is not None - ): - place_name = geolocation.place_name( - metadata['latitude'], - metadata['longitude'] - ) - if(place_name is not None): - path.append(place_name) - - # if we don't have a 2nd level directory we use 'Unknown Location' - if(len(path) < 2): - path.append('Unknown Location') - - # return '/'.join(path[::-1]) - return os.path.join(*path) - - def process_file(self, _file, destination, media, **kwargs): - move = False - if('move' in kwargs): - move = kwargs['move'] - - allow_duplicate = False - if('allowDuplicate' in kwargs): - allow_duplicate = kwargs['allowDuplicate'] - - if(not media.is_valid()): - print('%s is not a valid media file. Skipping...' % _file) - return - - metadata = media.get_metadata() - - directory_name = self.get_folder_path(metadata) - - dest_directory = os.path.join(destination, directory_name) - file_name = self.get_file_name(media) - dest_path = os.path.join(dest_directory, file_name) - - db = Db() - checksum = db.checksum(_file) - if(checksum is None): - if(constants.debug is True): - print('Could not get checksum for %s. Skipping...' % _file) - return - - # If duplicates are not allowed and this hash exists in the db then we - # return - if(allow_duplicate is False and db.check_hash(checksum) is True): - if(constants.debug is True): - print('%s already exists at %s. Skipping...' % ( - _file, - db.get_hash(checksum) - )) - return - - self.create_directory(dest_directory) - - if(move is True): - stat = os.stat(_file) - shutil.move(_file, dest_path) - os.utime(dest_path, (stat.st_atime, stat.st_mtime)) - else: - shutil.copy(_file, dest_path) - self.set_date_from_filename(dest_path) - - db.add_hash(checksum, dest_path) - db.update_hash_db() - - return dest_path - - def set_date_from_filename(self, file): - """ Set the modification time on the file base on the file name. - """ - - date_taken = None - file_name = os.path.basename(file) - # Initialize date taken to what's returned from the metadata function. - # If the folder and file name follow a time format of - # YYYY-MM/DD-IMG_0001.JPG then we override the date_taken - (year, month, day) = [None] * 3 - year_month_day_match = re.search('(\d{4})-(\d{2})-(\d{2})', file_name) - if(year_month_day_match is not None): - (year, month, day) = year_month_day_match.groups() - - # check if the file system path indicated a date and if so we - # override the metadata value - if(year is not None and month is not None and day is not None): - date_taken = time.strptime( - '{}-{}-{}'.format(year, month, day), - '%Y-%m-%d' - ) - - os.utime(file, (time.time(), time.mktime(date_taken))) - - def set_date_from_path_video(self, video): - """Set the modification time on the file based on the file path. - - Noop if the path doesn't match the format YYYY-MM/DD-IMG_0001.JPG. - - :param elodie.media.video.Video video: An instance of Video. - """ - date_taken = None - - video_file_path = video.get_file_path() - - # Initialize date taken to what's returned from the metadata function. - # If the folder and file name follow a time format of - # YYYY-MM/DD-IMG_0001.JPG then we override the date_taken - (year, month, day) = [None] * 3 - directory = os.path.dirname(video_file_path) - # If the directory matches we get back a match with - # groups() = (year, month) - year_month_match = re.search('(\d{4})-(\d{2})', directory) - if(year_month_match is not None): - (year, month) = year_month_match.groups() - day_match = re.search( - '^(\d{2})', - os.path.basename(video.get_file_path()) - ) - if(day_match is not None): - day = day_match.group(1) - - # check if the file system path indicated a date and if so we - # override the metadata value - if(year is not None and month is not None): - if(day is not None): - date_taken = time.strptime( - '{}-{}-{}'.format(year, month, day), - '%Y-%m-%d' - ) - else: - date_taken = time.strptime( - '{}-{}'.format(year, month), - '%Y-%m' - ) - - os.utime(video_file_path, (time.time(), time.mktime(date_taken)))