def test_get_class_by_file_invalid_type(): media = Media.get_class_by_file(None, [Photo, Video, Audio]) assert media is None media = Media.get_class_by_file(False, [Photo, Video, Audio]) assert media is None media = Media.get_class_by_file(True, [Photo, Video, Audio]) assert media is None
def import_file(_file, destination, album_from_folder, trash, allow_duplicates): """Set file metadata and move it to destination. """ if not os.path.exists(_file): log.warn('Could not find %s' % _file) print('{"source":"%s", "error_msg":"Could not find %s"}' % \ (_file, _file)) return # Check if the source, _file, is a child folder within destination elif destination.startswith(os.path.dirname(_file)): print('{"source": "%s", "destination": "%s", "error_msg": "Source cannot be in destination"}' % (_file, destination)) return media = Media.get_class_by_file(_file, [Text, Audio, Photo, Video]) if not media: log.warn('Not a supported file (%s)' % _file) print('{"source":"%s", "error_msg":"Not a supported file"}' % _file) return if album_from_folder: media.set_album_from_folder() dest_path = FILESYSTEM.process_file(_file, destination, media, allowDuplicate=allow_duplicates, move=False) if dest_path: print('%s -> %s' % (_file, dest_path)) if trash: send2trash(_file) return dest_path or None
def test_set_original_name(): files = ['plain.jpg', 'audio.m4a', 'photo.nef', 'video.mov'] for file in files: ext = os.path.splitext(file)[1] temporary_folder, folder = helper.create_working_folder() random_file_name = '%s%s' % (helper.random_string(10), ext) origin = '%s/%s' % (folder, random_file_name) file_path = helper.get_file(file) if file_path is False: file_path = helper.download_file(file, folder) shutil.copyfile(file_path, origin) media = Media.get_class_by_file(origin, [Audio, Media, Photo, Video]) metadata = media.get_metadata() media.set_original_name() metadata_updated = media.get_metadata() shutil.rmtree(folder) assert metadata['original_name'] is None, metadata['original_name'] assert metadata_updated['original_name'] == random_file_name, metadata_updated['original_name']
def import_file(_file, destination, album_from_folder, trash): """Set file metadata and move it to destination. """ if not os.path.exists(_file): if constants.debug: print 'Could not find %s' % _file print '{"source":"%s", "error_msg":"Could not find %s"}' % \ (_file, _file) return media = Media.get_class_by_file(_file, [Text, Audio, Photo, Video]) if not media: if constants.debug: print 'Not a supported file (%s)' % _file print '{"source":"%s", "error_msg":"Not a supported file"}' % _file return if media.__name__ == 'Video': FILESYSTEM.set_date_from_path_video(media) if album_from_folder: media.set_album_from_folder() dest_path = FILESYSTEM.process_file(_file, destination, media, allowDuplicate=False, move=False) if dest_path: print '%s -> %s' % (_file, dest_path) if trash: send2trash(_file)
def import_file(_file, destination, album_from_folder, trash): """Set file metadata and move it to destination. """ if not os.path.exists(_file): if constants.debug: print 'Could not find %s' % _file print '{"source":"%s", "error_msg":"Could not find %s"}' % \ (_file, _file) return media = Media.get_class_by_file(_file, [Audio, Photo, Video]) if not media: if constants.debug: print 'Not a supported file (%s)' % _file print '{"source":"%s", "error_msg":"Not a supported file"}' % _file return if media.__name__ == 'Video': FILESYSTEM.set_date_from_path_video(media) if album_from_folder: media.set_album_from_folder() dest_path = FILESYSTEM.process_file(_file, destination, media, allowDuplicate=False, move=False) if dest_path: print '%s -> %s' % (_file, dest_path) if trash: send2trash(_file)
def import_file(file_path, config, manifest, metadata_dict, move=False, allow_duplicates=False, dryrun=False): """Set file metadata and move it to destination. """ if not os.path.exists(file_path): log.warn('Import_file: Could not find %s' % file_path) return target = config["targets"][0] target_base_path = target["base_path"] # Check if the source, _file, is a child folder within destination # .... this is not the right time to be checking for that. Lots of unnecessary checks # elif destination.startswith(os.path.abspath(os.path.dirname(_file))+os.sep): # print('{"source": "%s", "destination": "%s", "error_msg": "Source cannot be in destination"}' % (_file, destination)) # return # Creates an object of the right type, using the file extension ie .jpg -> photo media = Media.get_class_by_file(file_path, get_all_subclasses()) if not media: log.warn('Not a supported file (%s)' % file_path) return # if album_from_folder: # media.set_album_from_folder() checksum = manifest.checksum(file_path) is_duplicate = (checksum in manifest.entries) # Merge it into the manifest regardless of duplicate entries, to record all sources for a given file manifest_entry = FILESYSTEM.generate_manifest(file_path, target, metadata_dict, media) manifest.merge({checksum: manifest_entry}) if (not allow_duplicates) and is_duplicate: log.debug( "[ ] File {} already present in manifest; allow_duplicates is false; skipping" .format(file_path)) return True if dryrun: log.info("Generated manifest: {}".format(file_path)) return manifest_entry is not None else: result = FILESYSTEM.execute_manifest(file_path, manifest_entry, target_base_path, move_not_copy=move) # if dest_path: # print('%s -> %s' % (_file, dest_path)) # if trash: # send2trash(_file) return result
def test_get_original_name(): temporary_folder, folder = helper.create_working_folder() origin = '%s/%s' % (folder, 'with-original-name.jpg') file = helper.get_file('with-original-name.jpg') shutil.copyfile(file, origin) media = Media.get_class_by_file(origin, [Photo]) original_name = media.get_original_name() assert original_name == 'originalfilename.jpg', original_name
def test_get_original_name_invalid_file(): temporary_folder, folder = helper.create_working_folder() origin = '%s/%s' % (folder, 'invalid.jpg') file = helper.get_file('invalid.jpg') shutil.copyfile(file, origin) media = Media.get_class_by_file(origin, [Photo]) original_name = media.get_original_name() assert original_name is None, original_name
def test_set_original_name_when_exists(): temporary_folder, folder = helper.create_working_folder() origin = '%s/%s' % (folder, 'with-original-name.jpg') file = helper.get_file('with-original-name.jpg') shutil.copyfile(file, origin) media = Media.get_class_by_file(origin, [Photo]) result = media.set_original_name() assert result is None, result
def add_original_name(source, subclasses): media = Media.get_class_by_file(source, subclasses) if media is None: print('{} is not a valid media object'.format(source)) return metadata = media.get_metadata() if metadata['original_name'] is not None: print('{} already has OriginalFileName...Skipping'.format(source)) return original_name = parse_original_name_from_media(metadata) return media.set_original_name(original_name)
def test_set_original_name_when_does_not_exist(): temporary_folder, folder = helper.create_working_folder() origin = '%s/%s' % (folder, 'plain.jpg') file = helper.get_file('plain.jpg') shutil.copyfile(file, origin) media = Media.get_class_by_file(origin, [Photo]) metadata_before = media.get_metadata() result = media.set_original_name() metadata_after = media.get_metadata() assert metadata_before['original_name'] is None, metadata_before assert metadata_after['original_name'] == 'plain.jpg', metadata_after assert result is True, result
def test_set_original_name_with_arg(): temporary_folder, folder = helper.create_working_folder() origin = '%s/%s' % (folder, 'plain.jpg') file = helper.get_file('plain.jpg') shutil.copyfile(file, origin) new_name = helper.random_string(15) media = Media.get_class_by_file(origin, [Photo]) metadata_before = media.get_metadata() result = media.set_original_name(new_name) metadata_after = media.get_metadata() assert metadata_before['original_name'] is None, metadata_before assert metadata_after['original_name'] == new_name, metadata_after assert result is True, result
def import_file(_file, destination, album_from_folder, trash, allow_duplicates): _file = _decode(_file) destination = _decode(destination) """Set file metadata and move it to destination. """ if not os.path.exists(_file): log.warn('Could not find %s' % _file) log.all('{"source":"%s", "error_msg":"Could not find %s"}' % (_file, _file)) return # Check if the source, _file, is a child folder within destination elif destination.startswith( os.path.abspath(os.path.dirname(_file)) + os.sep): log.all( '{"source": "%s", "destination": "%s", "error_msg": "Source cannot be in destination"}' % (_file, destination)) return media = Media.get_class_by_file(_file, get_all_subclasses()) if not media: log.warn('Not a supported file (%s)' % _file) log.all('{"source":"%s", "error_msg":"Not a supported file"}' % _file) return if album_from_folder: media.set_album_from_folder() dest_path = FILESYSTEM.process_file(_file, destination, media, allowDuplicate=allow_duplicates, move=False) if dest_path: log.all('%s -> %s' % (_file, dest_path)) if trash: send2trash(_file) return dest_path or None
def test_get_class_by_file_video(): media = Media.get_class_by_file(helper.get_file('video.mov'), [Photo, Video]) assert media.__name__ == 'Video'
def test_get_class_by_file_photo(): media = Media.get_class_by_file(helper.get_file('plain.jpg'), [Photo, Video]) assert media.__name__ == 'Photo'
def test_get_file_path(): media = Media(helper.get_file('plain.jpg')) path = media.get_file_path() assert 'plain.jpg' in path, path
def test_exiftool(): media = Media() exiftool = media.get_exiftool() assert exiftool is not None, exiftool
def _update(album, location, time, title, files): """Update files. """ for file_path in files: if not os.path.exists(file_path): if constants.debug: print 'Could not find %s' % file_path print '{"source":"%s", "error_msg":"Could not find %s"}' % \ (file_path, file_path) continue file_path = os.path.expanduser(file_path) destination = os.path.expanduser( os.path.dirname(os.path.dirname(os.path.dirname(file_path)))) media = Media.get_class_by_file(file_path, [Text, Audio, Photo, Video]) if not media: continue updated = False if location: update_location(media, file_path, location) updated = True if time: update_time(media, file_path, time) updated = True if album: media.set_album(album) updated = True # Updating a title can be problematic when doing it 2+ times on a file. # You would end up with img_001.jpg -> img_001-first-title.jpg -> # img_001-first-title-second-title.jpg. # To resolve that we have to track the prior title (if there was one. # Then we massage the updated_media's metadata['base_name'] to remove # the old title. # Since FileSystem.get_file_name() relies on base_name it will properly # rename the file by updating the title instead of appending it. remove_old_title_from_name = False if title: # We call get_metadata() to cache it before making any changes metadata = media.get_metadata() title_update_status = media.set_title(title) original_title = metadata['title'] if title_update_status and original_title: # @TODO: We should move this to a shared method since # FileSystem.get_file_name() does it too. original_title = re.sub(r'\W+', '-', original_title.lower()) original_base_name = metadata['base_name'] remove_old_title_from_name = True updated = True if updated: updated_media = Media.get_class_by_file( file_path, [Text, Audio, Photo, Video]) # See comments above on why we have to do this when titles # get updated. if remove_old_title_from_name and len(original_title) > 0: updated_media.get_metadata() updated_media.set_metadata_basename( original_base_name.replace('-%s' % original_title, '')) dest_path = FILESYSTEM.process_file(file_path, destination, updated_media, move=True, allowDuplicate=True) if constants.debug: print u'%s -> %s' % (file_path, dest_path) print '{"source":"%s", "destination":"%s"}' % (file_path, dest_path) # If the folder we moved the file out of or its parent are empty # we delete it. FILESYSTEM.delete_directory_if_empty(os.path.dirname(file_path)) FILESYSTEM.delete_directory_if_empty( os.path.dirname(os.path.dirname(file_path)))
def _update(params): """Update files. """ for file_path in params['INPUT']: if not os.path.exists(file_path): if constants.debug: print 'Could not find %s' % file_path print '{"source":"%s", "error_msg":"Could not find %s"}' % \ (file_path, file_path) continue file_path = os.path.expanduser(file_path) destination = os.path.expanduser(os.path.dirname(os.path.dirname( os.path.dirname(file_path)))) media = Media.get_class_by_file(file_path, [Audio, Photo, Video]) if not media: continue updated = False if params['--location']: updated = update_location(media, file_path, params['--location']) if params['--time']: updated = update_time(media, file_path, params['--time']) if params['--album']: media.set_album(params['--album']) updated = True # Updating a title can be problematic when doing it 2+ times on a file. # You would end up with img_001.jpg -> img_001-first-title.jpg -> # img_001-first-title-second-title.jpg. # To resolve that we have to track the prior title (if there was one. # Then we massage the updated_media's metadata['base_name'] to remove # the old title. # Since FileSystem.get_file_name() relies on base_name it will properly # rename the file by updating the title instead of appending it. remove_old_title_from_name = False if params['--title']: # We call get_metadata() to cache it before making any changes metadata = media.get_metadata() title_update_status = media.set_title(params['--title']) original_title = metadata['title'] if title_update_status and original_title: # @TODO: We should move this to a shared method since # FileSystem.get_file_name() does it too. original_title = re.sub(r'\W+', '-', original_title.lower()) original_base_name = metadata['base_name'] remove_old_title_from_name = True updated = True if updated: updated_media = Media.get_class_by_file(file_path, [Audio, Photo, Video]) # See comments above on why we have to do this when titles # get updated. if remove_old_title_from_name and len(original_title) > 0: updated_media.get_metadata() updated_media.set_metadata_basename( original_base_name.replace('-%s' % original_title, '')) dest_path = FILESYSTEM.process_file(file_path, destination, updated_media, move=True, allowDuplicate=True) if constants.debug: print u'%s -> %s' % (file_path, dest_path) print '{"source":"%s", "destination":"%s"}' % (file_path, dest_path) # If the folder we moved the file out of or its parent are empty # we delete it. FILESYSTEM.delete_directory_if_empty(os.path.dirname(file_path)) FILESYSTEM.delete_directory_if_empty( os.path.dirname(os.path.dirname(file_path)))
def test_get_class_by_file_unsupported(): media = Media.get_class_by_file(helper.get_file('text.txt'), [Photo, Video]) assert media is None
def test_get_class_by_file_empty(): media = Media.get_class_by_file(helper.get_file('.DS_Store'), [Photo, Video, Audio]) assert media is None
def is_valid(): media = Media() assert not media.is_valid()
def _update(album, location, time, title, paths, debug): """Update a file's EXIF. Automatically modifies the file's location and file name accordingly. """ constants.debug = debug has_errors = False result = Result() files = set() for path in paths: path = os.path.expanduser(path) if os.path.isdir(path): files.update(FILESYSTEM.get_all_files(path, None)) else: files.add(path) for current_file in files: if not os.path.exists(current_file): has_errors = True result.append((current_file, False)) log.warn('Could not find %s' % current_file) log.all('{"source":"%s", "error_msg":"Could not find %s"}' % (current_file, current_file)) continue current_file = os.path.expanduser(current_file) # The destination folder structure could contain any number of levels # So we calculate that and traverse up the tree. # '/path/to/file/photo.jpg' -> '/path/to/file' -> # ['path','to','file'] -> ['path','to'] -> '/path/to' current_directory = os.path.dirname(current_file) destination_depth = -1 * len(FILESYSTEM.get_folder_path_definition()) destination = os.sep.join( os.path.normpath( current_directory ).split(os.sep)[:destination_depth] ) media = Media.get_class_by_file(current_file, get_all_subclasses()) if not media: continue updated = False if location: update_location(media, current_file, location) updated = True if time: update_time(media, current_file, time) updated = True if album: media.set_album(album) updated = True # Updating a title can be problematic when doing it 2+ times on a file. # You would end up with img_001.jpg -> img_001-first-title.jpg -> # img_001-first-title-second-title.jpg. # To resolve that we have to track the prior title (if there was one. # Then we massage the updated_media's metadata['base_name'] to remove # the old title. # Since FileSystem.get_file_name() relies on base_name it will properly # rename the file by updating the title instead of appending it. remove_old_title_from_name = False if title: # We call get_metadata() to cache it before making any changes metadata = media.get_metadata() title_update_status = media.set_title(title) original_title = metadata['title'] if title_update_status and original_title: # @TODO: We should move this to a shared method since # FileSystem.get_file_name() does it too. original_title = re.sub(r'\W+', '-', original_title.lower()) original_base_name = metadata['base_name'] remove_old_title_from_name = True updated = True if updated: updated_media = Media.get_class_by_file(current_file, get_all_subclasses()) # See comments above on why we have to do this when titles # get updated. if remove_old_title_from_name and len(original_title) > 0: updated_media.get_metadata() updated_media.set_metadata_basename( original_base_name.replace('-%s' % original_title, '')) dest_path = FILESYSTEM.process_file(current_file, destination, updated_media, move=True, allowDuplicate=True) log.info(u'%s -> %s' % (current_file, dest_path)) log.all('{"source":"%s", "destination":"%s"}' % (current_file, dest_path)) # If the folder we moved the file out of or its parent are empty # we delete it. FILESYSTEM.delete_directory_if_empty(os.path.dirname(current_file)) FILESYSTEM.delete_directory_if_empty( os.path.dirname(os.path.dirname(current_file))) result.append((current_file, dest_path)) # Trip has_errors to False if it's already False or dest_path is. has_errors = has_errors is True or not dest_path else: has_errors = False result.append((current_file, False)) result.write() if has_errors: sys.exit(1)
def _update(album, location, time, title, files): """Update a file's EXIF. Automatically modifies the file's location and file name accordingly. """ result = Result() for current_file in files: if not os.path.exists(current_file): if constants.debug: print('Could not find %s' % current_file) print('{"source":"%s", "error_msg":"Could not find %s"}' % \ (current_file, current_file)) continue current_file = os.path.expanduser(current_file) destination = os.path.expanduser(os.path.dirname(os.path.dirname( os.path.dirname(current_file)))) media = Media.get_class_by_file(current_file, [Text, Audio, Photo, Video]) if not media: continue updated = False if location: update_location(media, current_file, location) updated = True if time: update_time(media, current_file, time) updated = True if album: media.set_album(album) updated = True # Updating a title can be problematic when doing it 2+ times on a file. # You would end up with img_001.jpg -> img_001-first-title.jpg -> # img_001-first-title-second-title.jpg. # To resolve that we have to track the prior title (if there was one. # Then we massage the updated_media's metadata['base_name'] to remove # the old title. # Since FileSystem.get_file_name() relies on base_name it will properly # rename the file by updating the title instead of appending it. remove_old_title_from_name = False if title: # We call get_metadata() to cache it before making any changes metadata = media.get_metadata() title_update_status = media.set_title(title) original_title = metadata['title'] if title_update_status and original_title: # @TODO: We should move this to a shared method since # FileSystem.get_file_name() does it too. original_title = re.sub(r'\W+', '-', original_title.lower()) original_base_name = metadata['base_name'] remove_old_title_from_name = True updated = True if updated: updated_media = Media.get_class_by_file(current_file, [Text, Audio, Photo, Video]) # See comments above on why we have to do this when titles # get updated. if remove_old_title_from_name and len(original_title) > 0: updated_media.get_metadata() updated_media.set_metadata_basename( original_base_name.replace('-%s' % original_title, '')) dest_path = FILESYSTEM.process_file(current_file, destination, updated_media, move=True, allowDuplicate=True) log.info(u'%s -> %s' % (current_file, dest_path)) print('{"source":"%s", "destination":"%s"}' % (current_file, dest_path)) # If the folder we moved the file out of or its parent are empty # we delete it. FILESYSTEM.delete_directory_if_empty(os.path.dirname(current_file)) FILESYSTEM.delete_directory_if_empty( os.path.dirname(os.path.dirname(current_file))) result.append((current_file, dest_path)) else: result.append((current_file, False)) result.write()