def test_television__multi(self): path = TELEVISION_FILENAME + "E02" expected = { "episode": "1", "media": "television", "season": "1", "series": TELEVISION_SERIES, } actual = dict(meta_parse(path)) self.assertDictEqual(expected, actual)
def test_movie__full_path(self): path = MOVIE_DIR + MOVIE_TITLE + MEDIA_EXTENSION expected = { "title": "Spaceballs", "date": "1987-01-01", "media": "movie", "extension": ".mkv", } actual = dict(meta_parse(path)) self.assertDictEqual(expected, actual)
def test_extension__omitted(self): path = MOVIE_TITLE actual = meta_parse(path).get("extension") self.assertIsNone(actual)
def test_release_group_omitted(self): path = MOVIE_TITLE + MEDIA_EXTENSION actual = meta_parse(path) self.assertNotIn("group", actual)
def test_quality__omitted(self): path = MOVIE_TITLE + MEDIA_EXTENSION actual = meta_parse(path).get("quality") self.assertIsNone(actual)
def test_quality__provided_single(self): path = MOVIE_TITLE + "4k" + MEDIA_EXTENSION expected = "2160p" actual = meta_parse(path).get("quality") self.assertEqual(expected, actual)
def test_television__series_with_date(self): path = "The Daily Show 2017.11.01" + MEDIA_EXTENSION expected = "The Daily Show" actual = meta_parse(path)["series"] self.assertEqual(expected, actual)
def test_television__series_with_year(self): path = "Deception (2008) 01x01" + MEDIA_EXTENSION expected = "Deception (2008)" actual = meta_parse(path).get("series") self.assertEqual(expected, actual)
def test_movie__media_overide(self): path = "Deception (2008) 01x01" + MEDIA_EXTENSION expected = "movie" actual = meta_parse(path, media="movie")["media"] self.assertEqual(expected, actual)
def test_television__media_override(self): path = "Lost (2004)" + MEDIA_EXTENSION expected = "television" actual = meta_parse(path, media="television")["media"] self.assertEqual(expected, actual)
def test_television__series_with_country_code_2(self): path = TELEVISION_FILENAME + " [us]" expected = TELEVISION_SERIES + " (US)" actual = meta_parse(path).get("series") self.assertEqual(expected, actual)
def test_quality__provided_multiple(self): path = MOVIE_TITLE + "1080P ac3" + MEDIA_EXTENSION actual = meta_parse(path).get("quality") self.assertIn("1080p", actual) self.assertIn("Dolby Digital", actual)
def test_release_group__provided(self): path = "%s%s [%s]" % (MOVIE_TITLE, MEDIA_EXTENSION, MEDIA_GROUP) expected = MEDIA_GROUP actual = meta_parse(path).get("group") self.assertEqual(actual, expected)
def test_extension__provided(self): path = MOVIE_TITLE + MEDIA_EXTENSION expected = MEDIA_EXTENSION actual = meta_parse(path).get("extension") self.assertEqual(expected, actual)
def test_unknown(self): path = "" with self.assertRaises(MnamerException): meta_parse(path)
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, )