def destination(self) -> Path: """ The destination Path for the target based on its metadata and user preferences. """ if self.directory: dir_head = format(self.metadata, str(self.directory)) dir_head = filename_sanitize(dir_head) dir_head = Path(dir_head) else: dir_head = self.source.parent if self._formatting: file_path = format(self.metadata, self._formatting) if self._settings.replacements: file_path = filename_replace(file_path, self._settings.replacements) file_path = filename_sanitize(file_path) file_path = Path(file_path) else: file_path = self.source.name dir_tail, filename = path.split(file_path) directory = Path(dir_head, dir_tail) if self._settings.scene: filename = filename_scenify(filename) if self._settings.lower: filename = filename.lower() return Path(directory, filename).resolve()
def destination(self) -> Path: """ The destination Path for the target based on its metadata and user preferences. """ if self.directory: dir_head_ = format(self.metadata, str(self.directory)) dir_head_ = str_sanitize(dir_head_) dir_head = Path(dir_head_) else: dir_head = self.source.parent file_path = format(self.metadata, self._settings.formatting_for(self.metadata.media)) dir_tail, filename = path.split(Path(file_path)) filename = filename_replace(filename, self._settings.replace_after) if self._settings.scene: filename = str_scenify(filename) if self._settings.lower: filename = filename.lower() filename = str_sanitize(filename) directory = Path(dir_head, dir_tail) return Path(directory, filename)
def test_only_replaces_whole_words(self): filename = "_the the theater the" replacements = {"the": "_"} expected = "_the _ theater _" actual = filename_replace(filename, replacements) self.assertEqual(expected, actual)
def test_multiple_replacement(self): replacements = {"the": "a", "lazy": "misunderstood", "dog": "cat"} expected = "a quick brown fox jumps over a misunderstood cat" actual = filename_replace(self.filename, replacements) self.assertEqual(expected, actual)
def test_single_replacement(self): replacements = {"brown": "red"} expected = "The quick red fox jumps over the lazy dog" actual = filename_replace(self.filename, replacements) self.assertEqual(expected, actual)
def test_no_change(self): replacements = {} expected = self.filename actual = filename_replace(self.filename, replacements) self.assertEqual(expected, actual)
def process_files( targets, user_media=None, test_run=False, id_key=None, **config ): """ Processes targets, relocating them as needed """ notify = Notify() # Begin processing files detection_count = 0 success_count = 0 for file_path in dir_crawl( targets, config.get("recurse", False), config.get("extension_mask") ): notify.heading("Detected File") blacklist = config.get("blacklist", ()) if any(match(b, file_stem(file_path)) for b in blacklist): notify.info("%s (blacklisted)" % file_path) continue else: print(file_stem(file_path)) # Print metadata fields meta = meta_parse(file_path, user_media) if config["verbose"] is True: for field, value in meta.items(): notify.verbose("%s: %s" % (field, value), True) # Print search results detection_count += 1 notify.heading("Query Results") results = provider_search(meta, id_key, **config) i = 1 hits = [] while i < int(config.get("max_hits", 15)): try: hit = next(results) print(" [%s] %s" % (i, hit)) hits.append(hit) i += 1 except (StopIteration, MapiNotFoundException): break # Skip hit if no hits if not hits: notify.info("None found! Skipping.", True) continue # Select first if batch if config.get("batch") is True: meta.update(hits[0]) # Prompt user for input else: print(" [RETURN] for default, [s]kip, [q]uit") abort = skip = None while True: selection = notify.prompt("Your Choice") # Catch default selection if not selection: meta.update(hits[0]) break # Catch skip hit (just break w/o changes) elif selection in ["s", "S", "skip", "SKIP"]: skip = True break # Quit (abort and exit) elif selection in ["q", "Q", "quit", "QUIT"]: abort = True break # Catch result choice within presented range elif selection.isdigit() and 0 < int(selection) < len(hits) + 1: meta.update(hits[int(selection) - 1]) break # Re-prompt if user input is invalid wrt to presented options else: print("\nInvalid selection, please try again.") # User requested to skip file... if skip is True: notify.info("Skipping rename, as per user request.", True) continue # User requested to exit... elif abort is True: notify.info("\nAborting, as per user request.") return # Create file path notify.heading("Processing File") media = meta["media"] template = config.get("%s_template" % media) dest_path = meta.format(template) if config.get("%s_destination" % media): dest_dir = meta.format(config.get("%s_destination" % media, "")) dest_path = "%s/%s" % (dest_dir, dest_path) dest_path = filename_sanitize(dest_path) dest_path = filename_replace(dest_path, config.get("replacements")) if config.get("scene") is True: dest_path = filename_scenify(dest_path) dest_path = realpath(dest_path) # Attempt to process file try: if not test_run: # TODO: create parent paths shutil_move(str(file_path), str(dest_path)) notify.info("Relocating file to '%s'" % dest_path, True) except IOError as e: notify.error(" Failed!", True) if config.get("verbose") is True: notify.verbose(e) else: notify.success("Success!", True) success_count += 1 # Summarize session outcome if not detection_count: print("") notify.alert('No media files found. "mnamer --help" for usage.') return if success_count == 0: outcome_colour = "red" elif success_count < detection_count: outcome_colour = "yellow" else: outcome_colour = "green" cprint( "\nSuccessfully processed %s out of %s files" % (success_count, detection_count), outcome_colour, )