diff options
author | Antoine Beaupré <anarcat@debian.org> | 2018-03-14 12:24:17 -0400 |
---|---|---|
committer | Antoine Beaupré <anarcat@debian.org> | 2018-03-14 12:24:17 -0400 |
commit | 0a297829eaf3912c939e1b43a3ef6ddeb7607b38 (patch) | |
tree | 51733e0d6ffb00f0f7dfe01dccd48b2a598e5153 /raphodo/renameandmovefile.py | |
parent | 88c8bd4cd2ee4707f8a43be4d89c4e040dcced2f (diff) |
New upstream version 0.9.9upstream/0.9.9
Diffstat (limited to 'raphodo/renameandmovefile.py')
-rwxr-xr-x | raphodo/renameandmovefile.py | 163 |
1 files changed, 110 insertions, 53 deletions
diff --git a/raphodo/renameandmovefile.py b/raphodo/renameandmovefile.py index 1405cc5..3dd59b1 100755 --- a/raphodo/renameandmovefile.py +++ b/raphodo/renameandmovefile.py @@ -44,7 +44,6 @@ from gettext import gettext as _ import raphodo.exiftool as exiftool import raphodo.generatename as gn -import raphodo.problemnotification as pn from raphodo.preferences import DownloadsTodayTracker, Preferences from raphodo.constants import (ConflictResolution, FileType, DownloadStatus, RenameAndMoveStatus) from raphodo.interprocess import (RenameAndMoveFileData, RenameAndMoveFileResults, DaemonProcess) @@ -126,14 +125,19 @@ class SyncRawJpeg: Returns SyncRawJpegStatus.no_match and a sequence number of None if no match """ + if name in self.photos: if datetime_roughly_equal(self.photos[name].date_time, date_time, 30): if extension in self.photos[name].extension: - return SyncRawJpegMatch(SyncRawJpegStatus.error_already_downloaded, - self.photos[name].sequence_number_used) + return SyncRawJpegMatch( + SyncRawJpegStatus.error_already_downloaded, + self.photos[name].sequence_number_used + ) else: - return SyncRawJpegMatch(SyncRawJpegStatus.matching_pair, - self.photos[name].sequence_number_used) + return SyncRawJpegMatch( + SyncRawJpegStatus.matching_pair, + self.photos[name].sequence_number_used + ) else: return SyncRawJpegMatch(SyncRawJpegStatus.error_datetime_mismatch, None) return SyncRawJpegMatch(SyncRawJpegStatus.no_match, None) @@ -153,10 +157,9 @@ def load_metadata(rpd_file: Union[Photo, Video], """ Loads the metadata for the file. + :param rpd_file: photo or video :param et_process: the daemon ExifTool process - :param temp_file: If true, the the metadata from the temporary file - rather than the original source file is used. This is important, - because the metadata can be modified by the filemodify process + :param problems: problems encountered renaming the file :return True if operation succeeded, false otherwise """ if rpd_file.metadata is None: @@ -171,8 +174,8 @@ def load_metadata(rpd_file: Union[Photo, Video], return True -def _generate_name(generator: Union[gn.PhotoName, gn.PhotoSubfolder, gn.VideoName, - gn.VideoSubfolder], +def _generate_name(generator: Union[gn.PhotoName, gn.PhotoSubfolder, gn.VideoName, + gn.VideoSubfolder], rpd_file: Union[Photo, Video], et_process: exiftool.ExifTool, problems: RenamingProblems) -> str: @@ -205,6 +208,7 @@ def generate_subfolder(rpd_file: Union[Photo, Video], :param rpd_file: file to work on :param et_process: the daemon ExifTool process + :param problems: problems encountered renaming the file """ if rpd_file.file_type == FileType.photo: @@ -223,12 +227,13 @@ def generate_name(rpd_file: Union[Photo, Video], :param rpd_file: file to work on :param et_process: the daemon ExifTool process + :param problems: problems encountered renaming the file """ if rpd_file.file_type == FileType.photo: - generator = gn.PhotoName(rpd_file.name_pref_list, problems=problems) + generator = gn.PhotoName(pref_list=rpd_file.name_pref_list, problems=problems) else: - generator = gn.VideoName(rpd_file.name_pref_list, problems=problems) + generator = gn.VideoName(pref_list=rpd_file.name_pref_list, problems=problems) rpd_file.download_name = _generate_name(generator, rpd_file, et_process, problems) @@ -268,9 +273,11 @@ class RenameMoveFileWorker(DaemonProcess): dt = datetime.fromtimestamp(modification_time) date = dt.strftime("%x") time = dt.strftime("%X") - except: - logging.error("Could not determine the file modification time of %s", - rpd_file.download_full_file_name) + except Exception: + logging.error( + "Could not determine the file modification time of %s", + rpd_file.download_full_file_name + ) date = time = '' source = rpd_file.get_souce_href() @@ -312,7 +319,7 @@ class RenameMoveFileWorker(DaemonProcess): """ Handle cases where file failed to download """ - uri=get_uri( + uri = get_uri( full_file_name=rpd_file.full_file_name, camera_details=rpd_file.camera_details ) device = make_href(name=rpd_file.device_display_name, uri=rpd_file.device_uri) @@ -365,7 +372,7 @@ class RenameMoveFileWorker(DaemonProcess): assert isinstance(i1_date_time, datetime) i1_date = i1_date_time.strftime("%x") i1_time = i1_date_time.strftime("%X") - assert isinstance(image2_date_time,datetime) + assert isinstance(image2_date_time, datetime) image2_date = image2_date_time.strftime("%x") image2_time = image2_date_time.strftime("%X") @@ -383,7 +390,7 @@ class RenameMoveFileWorker(DaemonProcess): def _move_associate_file(self, extension: str, full_base_name: str, - temp_associate_file: str) -> str: + temp_associate_file: str) -> str: """ Move (rename) the associate file using the pre-generated name. @@ -617,7 +624,8 @@ class RenameMoveFileWorker(DaemonProcess): else: matching_pair = self.sync_raw_jpeg.matching_pair( name=photo_name, extension=photo_ext, - date_time=date_time) # type: SyncRawJpegMatch + date_time=date_time + ) # type: SyncRawJpegMatch sequence_to_use = matching_pair.sequence_number if matching_pair.status == SyncRawJpegStatus.error_already_downloaded: # this exact file has already been @@ -628,16 +636,19 @@ class RenameMoveFileWorker(DaemonProcess): DuplicateFileWhenSyncingProblem( name=rpd_file.name, uri=rpd_file.get_uri(), - file_type = rpd_file.title, + file_type=rpd_file.title, ) ) rpd_file.status = DownloadStatus.download_failed failed = True else: - self.sequences.set_matched_sequence_value(matching_pair.sequence_number) + self.sequences.matched_sequences = matching_pair.sequence_number + self.sequences.use_matched_sequences = self.sequences.matched_sequences is \ + not None if matching_pair.status == SyncRawJpegStatus.error_datetime_mismatch: self.same_name_different_exif(photo_name, rpd_file) + return SyncRawJpegResult(sequence_to_use, failed, photo_name, photo_ext) def prepare_rpd_file(self, rpd_file: Union[Photo, Video]) -> None: @@ -661,7 +672,7 @@ class RenameMoveFileWorker(DaemonProcess): except OSError: logging.error("Failed to delete temporary file %s", rpd_file.temp_full_file_name) - def generate_names(self, rpd_file: Union[Photo, Video]) -> bool: + def generate_names(self, rpd_file: Union[Photo, Video], synchronize_raw_jpg: bool) -> bool: rpd_file.strip_characters = self.prefs.strip_characters @@ -672,18 +683,24 @@ class RenameMoveFileWorker(DaemonProcess): rpd_file.download_subfolder, rpd_file.name) self.sequences.stored_sequence_no = self.prefs.stored_sequence_no + if self.must_synchronize_raw_jpg and rpd_file.file_type == FileType.video: + self.sequences.use_matched_sequences = False + rpd_file.sequences = self.sequences # generate the file name generate_name(rpd_file, self.exiftool_process, self.problems) if rpd_file.name_generation_problem: - logging.warning("Encountered a problem generating file name for file %s", - rpd_file.name) + logging.warning( + "Encountered a problem generating file name for file %s", + rpd_file.name + ) rpd_file.status = DownloadStatus.downloaded_with_warning else: - logging.debug("Generated file name %s for file %s", rpd_file.download_name, - rpd_file.name) + logging.debug( + "Generated file name %s for file %s", rpd_file.download_name, rpd_file.name + ) else: logging.error("Failed to generate subfolder name for file: %s", rpd_file.name) @@ -700,8 +717,9 @@ class RenameMoveFileWorker(DaemonProcess): move_succeeded = False rpd_file.download_path = os.path.join(rpd_file.download_folder, rpd_file.download_subfolder) - rpd_file.download_full_file_name = os.path.join(rpd_file.download_path, - rpd_file.download_name) + rpd_file.download_full_file_name = os.path.join( + rpd_file.download_path, rpd_file.download_name + ) rpd_file.download_full_base_name = os.path.splitext(rpd_file.download_full_file_name)[0] if not os.path.isdir(rpd_file.download_path): @@ -727,8 +745,10 @@ class RenameMoveFileWorker(DaemonProcess): try: if os.path.exists(rpd_file.download_full_file_name): raise OSError(errno.EEXIST, "File exists: %s" % rpd_file.download_full_file_name) - logging.debug("Renaming %s to %s .....", - rpd_file.temp_full_file_name, rpd_file.download_full_file_name) + logging.debug( + "Renaming %s to %s .....", + rpd_file.temp_full_file_name, rpd_file.download_full_file_name + ) os.rename(rpd_file.temp_full_file_name, rpd_file.download_full_file_name) logging.debug("....successfully renamed file") move_succeeded = True @@ -749,19 +769,26 @@ class RenameMoveFileWorker(DaemonProcess): return move_succeeded def process_file(self, rpd_file: Union[Photo, Video], download_count: int) -> bool: + """ + Generate file & subfolder name, and move (rename) photo / video + :param rpd_file: photo or video + :param download_count: used to track the file being downloaded via a counter + :return: success or otherwise of operation + """ + move_succeeded = False self.prepare_rpd_file(rpd_file) - synchronize_raw_jpg = (self.prefs.must_synchronize_raw_jpg() and - rpd_file.file_type == FileType.photo) + synchronize_raw_jpg = self.must_synchronize_raw_jpg and rpd_file.file_type == FileType.photo + if synchronize_raw_jpg: sync_result = self.sync_raw_jpg(rpd_file) if sync_result.failed: return False - generation_succeeded = self.generate_names(rpd_file) + generation_succeeded = self.generate_names(rpd_file, synchronize_raw_jpg) if generation_succeeded: move_succeeded = self.move_file(rpd_file) @@ -782,11 +809,12 @@ class RenameMoveFileWorker(DaemonProcess): if not synchronize_raw_jpg or (synchronize_raw_jpg and sync_result.sequence_to_use is None): - uses_sequence_session_no = self.prefs.any_pref_uses_session_sequence_no() - uses_sequence_letter = self.prefs.any_pref_uses_sequence_letter_value() - if uses_sequence_session_no or uses_sequence_letter: - self.sequences.increment(uses_sequence_session_no, uses_sequence_letter) - if self.prefs.any_pref_uses_stored_sequence_no(): + + if self.uses_sequence_session_no or self.uses_sequence_letter: + self.sequences.increment( + self.uses_sequence_session_no, self.uses_sequence_letter + ) + if self.uses_stored_sequence_no: if self.prefs.stored_sequence_no == self.platform_c_maxint: # wrap value if it exceeds the maximum size value that Qt can display # in its spinbox @@ -809,6 +837,32 @@ class RenameMoveFileWorker(DaemonProcess): return move_succeeded + def initialise_downloads_today_stored_number(self) -> None: + """ + Initialize (or reinitialize) Downloads Today and Stored No + sequence values from the program preferences. + """ + + # Synchronize QSettings instance in preferences class + self.prefs.sync() + + # Track downloads today, using a class whose purpose is to + # take the value in the user prefs, increment, and then + # finally used to update the prefs + self.downloads_today_tracker = DownloadsTodayTracker( + day_start=self.prefs.day_start, + downloads_today=self.prefs.downloads_today + ) + + def initialise_sequence_number_usage(self) -> None: + """ + Determine what type of sequence numbers are being used in file name generation + """ + + self.uses_sequence_session_no = self.prefs.any_pref_uses_session_sequence_no() + self.uses_sequence_letter = self.prefs.any_pref_uses_sequence_letter_value() + self.uses_stored_sequence_no = self.prefs.any_pref_uses_stored_sequence_no() + def run(self) -> None: """ Generate subfolder and filename, and attempt to move the file @@ -826,6 +880,12 @@ class RenameMoveFileWorker(DaemonProcess): # suffixes to duplicate files self.duplicate_files = {} + self.initialise_downloads_today_stored_number() + + self.sequences = gn.Sequences( + self.downloads_today_tracker, self.prefs.stored_sequence_no + ) + with stdchannel_redirected(sys.stderr, os.devnull): with exiftool.ExifTool() as self.exiftool_process: while True: @@ -839,29 +899,26 @@ class RenameMoveFileWorker(DaemonProcess): data = pickle.loads(content) # type: RenameAndMoveFileData if data.message == RenameAndMoveStatus.download_started: - # Synchronize QSettings instance in preferences class - self.prefs.sync() - - # Track downloads today, using a class whose purpose is to - # take the value in the user prefs, increment, and then - # finally used to update the prefs - self.downloads_today_tracker = DownloadsTodayTracker( - day_start=self.prefs.day_start, - downloads_today=self.prefs.downloads_today) - - self.sequences = gn.Sequences(self.downloads_today_tracker, - self.prefs.stored_sequence_no) + + # reinitialize downloads today and stored sequence number + # in case the user has updated them via the user interface + self.initialise_downloads_today_stored_number() + self.sequences.downloads_today_tracker = self.downloads_today_tracker + self.sequences.stored_sequence_no = self.prefs.stored_sequence_no + dl_today = self.downloads_today_tracker.get_or_reset_downloads_today() logging.debug("Completed downloads today: %s", dl_today) + self.initialise_sequence_number_usage() + + self.must_synchronize_raw_jpg = self.prefs.must_synchronize_raw_jpg() + self.problems = RenamingProblems() elif data.message == RenameAndMoveStatus.download_completed: if len(self.problems): self.content = pickle.dumps( - RenameAndMoveFileResults( - problems=self.problems - ), + RenameAndMoveFileResults(problems=self.problems), pickle.HIGHEST_PROTOCOL ) self.send_message_to_sink() |