def print_renamed_files(files): """ Present the files that need to be renamed to the user. """ if not files: print("Failed to find any files to rename") sys.exit(1) print("PATH = {}".format(Settings.path)) print("-------" + '-' * len(Settings.path)) same = 0 for tuple_ in files: if not tuple_: same += 1 continue else: old, new = tuple_ old = os.path.split(old)[1].encode(Settings.encoding, 'ignore') new = os.path.split(new)[1].encode(Settings.encoding, 'ignore') print("OLD: {0}".format(utils.encode(old))) print("NEW: {0}".format(utils.encode(new))) print() if same > 0: if same == 1: num = "1 file doesn't" else: num = "{} files don't".format(same) print("{} need to be renamed".format(num))
def print_renamed_files(files): """ Present the files that need to be renamed to the user. """ if not files: print ("Failed to find any files to rename") sys.exit(1) print ("PATH = {}".format(Settings.path)) print ("-------" + '-' * len(Settings.path)) same = 0 for tuple_ in files: if not tuple_: same += 1 continue else: old, new = tuple_ old = os.path.split(old)[1].encode(Settings.encoding, 'ignore') new = os.path.split(new)[1].encode(Settings.encoding, 'ignore') print ("OLD: {0}".format(utils.encode(old))) print ("NEW: {0}".format(utils.encode(new))) print() if same > 0: if same == 1: num = "1 file doesn't" else: num = "{} files don't".format(same) print("{} need to be renamed".format(num))
def __init__(self, files, parent=None): super(RenameDialog, self).__init__(parent) self.setGeometry(100, 100, 750, 500) self.setWindowTitle("Rename Files Utility") self.files = files self.buttonBox = QtGui.QDialogButtonBox(QtCore.Qt.Vertical) self.buttonBox = QtGui.QDialogButtonBox(QtGui.QDialogButtonBox.Cancel | QtGui.QDialogButtonBox.Ok) self.buttonBox.rejected.connect(self.close) self.model = QtGui.QStandardItemModel() self.view = QtGui.QListView() self.view.setModel(self.model) layout = QtGui.QVBoxLayout() layout.addWidget(self.view) layout.addWidget(self.buttonBox) self.setLayout(layout) if not self.files: self.model.appendRow( QtGui.QStandardItem("No files need to be renamed")) self.buttonBox.accepted.connect(self.close) self.buttonBox.accepted.connect(self.close) else: self.files, self.same_count = self.prepare_renamed_files( self.files) if not self.files: self.print_renamed_files() for old, new in self.files: item = QtGui.QStandardItem() old_name = utils.encode(os.path.split(old)[1]) new_name = utils.encode(os.path.split(new)[1]) string = utils.encode("OLD: {}\nNEW: {}\n".format( old_name, new_name)) item.setText(string) item.setCheckState(QtCore.Qt.Checked) item.setCheckable(True) item.rename_info = (old, new) if item.text(): self.model.appendRow(item) self.buttonBox.accepted.connect(self.rename) self.view.show() self.show()
def __init__(self, files, parent=None): super(RenameDialog, self).__init__(parent) self.setGeometry(100, 100, 750, 500) self.setWindowTitle("Rename Files Utility") self.files = files self.buttonBox = QtGui.QDialogButtonBox(QtCore.Qt.Vertical) self.buttonBox = QtGui.QDialogButtonBox(QtGui.QDialogButtonBox.Cancel | QtGui.QDialogButtonBox.Ok) self.buttonBox.rejected.connect(self.close) self.model = QtGui.QStandardItemModel() self.view = QtGui.QListView() self.view.setModel(self.model) layout = QtGui.QVBoxLayout() layout.addWidget(self.view) layout.addWidget(self.buttonBox) self.setLayout(layout) if not self.files: self.model.appendRow(QtGui.QStandardItem("No files need to be renamed")) self.buttonBox.accepted.connect(self.close) self.buttonBox.accepted.connect(self.close) else: self.files, self.same_count = self.prepare_renamed_files(self.files) if not self.files: self.print_renamed_files() for old, new in self.files: item = QtGui.QStandardItem() old_name = utils.encode(os.path.split(old)[1]) new_name = utils.encode(os.path.split(new)[1]) string = utils.encode("OLD: {}\nNEW: {}\n".format(old_name, new_name)) item.setText(string) item.setCheckState(QtCore.Qt.Checked) item.setCheckable(True) item.rename_info = (old, new) if item.text(): self.model.appendRow(item) self.buttonBox.accepted.connect(self.rename) self.view.show() self.show()
def _parse_local(title): """ Try to find the anime ID (aid) in the dump file provided by AniDB """ if not utils.file_exists_in_resources('animetitles.dat'): logging.warning("AniDB database file not found, unable to poll AniDB at this time") logging.warning("Try using the --update-db option to download an copy of it") return -1 logging.info("Searching the AniDB database file") title = title.lower() regex = re.compile(r'(?P<aid>\d+)\|(?P<type>\d)\|(?P<lang>.+)\|(?P<title>.*)') sequence = difflib.SequenceMatcher(lambda x: x in punct, title.lower()) guesses = [] with utils.open_file_in_resources('animetitles.dat') as f: for line in f: res = regex.search(line) if not res: continue original_title = utils.encode(res.group('title').lower()) clean_title = utils.prepare_title(utils.encode(res.group('title'))).lower() if utils.prepare_title(title) in (original_title, clean_title): return int(res.group('aid')) sequence.set_seq2(clean_title.lower()) ratio = sequence.quick_ratio() if ratio > .80: d = dict(ratio=ratio, aid=res.group('aid'), title=original_title) guesses.append(d) if guesses: logging.info("{} possibilities".format(len(guesses))) guesses = sorted(guesses, key=lambda x: x['ratio']) aid = guesses[0]['aid'] name = guesses[0]['title'] logging.error("Closest show to '{}' on AniDB is '{}'' with id {}".format(title, name, aid)) for guess in guesses[1:]: logging.info("Similar show {} [{}] also found".format(guess['title'], guess['aid'])) return -1
def get_episodes(self, showTitle, expiration=None): """Returns the episodes associated with the show id""" if not showTitle: raise ValueError("get_episodes expects a string") title = (showTitle, ) query = """ SELECT e.title, e.season, e.number, e.count, e.type, s.sid, s.time FROM episodes AS e INNER JOIN shows AS s ON s.sid=e.sid AND s.title=? """ with self.connection as conn: curs = conn.execute(query, title) result = curs.fetchall() eps = [] if not result: return eps diffDays = (datetime.datetime.now() - result[0][-1]) logging.info("{} days old".format(diffDays.days)) if not expiration: expiration = Settings.db_update if diffDays.days >= expiration: #If the show is older than a week remove it then return not found logging.warning("Show is older than a week, updating...") sid = result[0][-2] self.remove_show(sid) return eps for episode in result: title = utils.encode(episode[0]) season = episode[1] number = episode[2] count = episode[3] type_ = utils.encode(episode[4]) eps.append( Episode(title=title, number=number, season=season, count=count, type=type_)) return eps
def show_title(self, val): """ Sets the shows title to the value passed as well as prepares it for use """ logging.debug("Setting show title to: {}".format(val)) self.title = utils.encode(val.capitalize()) self.proper_title = utils.prepare_title(val)
def __init__(self, show, fmt=None): """ Allows printing of custom formatted episode information """ self.show = show self._format_string = utils.encode(fmt) if fmt else Settings.format ## Use a negative lookahead assertion to ensure that the ## tag had not been escaped regex = r'(?<!\\)(?P<tag>\{start}.*?\{end})' regex = regex.format(start=Settings.tag_start, end=Settings.tag_end) self.tag_regex = re.compile(regex, re.I) self.tokens = self.tag_regex.split(self._format_string) self.strip_whitespace_regex = re.compile(r'[\s]+') self.episode_number_tags = Settings.tags['episode_number_tags'] self.type_tags = Settings.tags['type_tags'] self.season_number_tags = Settings.tags['season_number_tags'] self.episode_count_tags = Settings.tags['episode_count_tags'] self.episode_name_tags = Settings.tags['episode_name_tags'] self.hash_tags = Settings.tags['hash_tags'] self.series_name_tags = Settings.tags['series_name_tags'] self.check_for_duplicate_tokens()
def poll(title): cleanTitle = utils.prepare_title(title) episodes = [] url = "http://www.epguides.com/{0}".format(cleanTitle) fd = utils.get_url_descriptor(url) if fd is None: return utils.show_not_found count = 1 for line in fd.iter_lines(): info = epguides_regex.match(utils.encode(line)) if info is not None: name = info.group('name') episode = info.group('episode') season = int(info.group('season')) name = re.sub('<.*?>', '', name).strip() if '[Trailer]' in name: name = name.replace('[Trailer]', '') if name == "TBA": continue episodes.append( Episode(title=name, number=episode, season=season, count=count)) count += 1 return episodes
def poll(title): cleanTitle = utils.prepare_title(title) episodes = [] url = "http://www.epguides.com/{0}".format(cleanTitle) fd = utils.get_url_descriptor(url) if fd is None: return utils.show_not_found count = 1 for line in fd.iter_lines(): info = epguides_regex.match(utils.encode(line)) if info is not None: name = info.group('name') episode = info.group('episode') season = int(info.group('season')) name = re.sub('<.*?>', '', name).strip() if '[Trailer]' in name: name = name.replace('[Trailer]', '') if name == "TBA": continue episodes.append(Episode(title=name, number=episode, season=season, count=count)) count += 1 return episodes
def display_specials(show, header=False): if header: print ("\nSpecials") print ("---------") for eps in show.specials: line = show.formatter.display(eps).encode(Settings.encoding, 'ignore') print(utils.encode(line))
def display_specials(show, header=False): if header: print("\nSpecials") print("---------") for eps in show.specials: line = show.formatter.display(eps).encode(Settings.encoding, 'ignore') print(utils.encode(line))
def get_episodes(self, showTitle, expiration=None): """Returns the episodes associated with the show id""" if not showTitle: raise ValueError("get_episodes expects a string") title = (showTitle, ) query = """ SELECT e.title, e.season, e.number, e.count, e.type, s.sid, s.time FROM episodes AS e INNER JOIN shows AS s ON s.sid=e.sid AND s.title=? """ with self.connection as conn: curs = conn.execute(query, title) result = curs.fetchall() eps = [] if not result: return eps diffDays = (datetime.datetime.now() - result[0][-1]) logging.info("{} days old".format(diffDays.days)) if not expiration: expiration = Settings.db_update if diffDays.days >= expiration: #If the show is older than a week remove it then return not found logging.warning("Show is older than a week, updating...") sid = result[0][-2] self.remove_show(sid) return eps for episode in result: title = utils.encode(episode[0]) season = episode[1] number = episode[2] count = episode[3] type_ = utils.encode(episode[4]) eps.append(Episode(title=title, number=number, season=season, count=count, type=type_)) return eps
def format_string(self, fmt=None): """ Set the format string for the formatter """ if fmt: self._format_string = utils.encode(fmt) self.tokens = self.tag_regex.split(fmt) else: raise AttributeError("Empty format string set")
def __init__(self, seriesTitle, episodes=None): self.title = utils.encode(string.capwords(seriesTitle)) self.proper_title = utils.prepare_title(seriesTitle.lower()) self.episodes = [] self.specials = [] self._episodes_by_season = defaultdict(list) self.formatter = None if episodes: self.add_episodes(episodes)
def __init__(self, **kwargs): """ A container for an episode's information collected from the web """ #title, number, season=1, count=-1, super(Episode, self).__init__(kwargs) self.title = utils.encode(kwargs['title']) self.season = int(kwargs.get('season', 1)) self.number = int(kwargs['number']) self.count = int(kwargs.get('count', '-1')) self.type = kwargs.get('type', 'Episode') self.file = kwargs.get('file', None) self.is_special = (self.type.lower() != "episode")
def display(self, episode): """ Displays the episode according to the users format """ args = [] escaped_token = "\{}".format(Settings.tag_start) for token in self.tokens: if escaped_token in token: args.append(token.replace(escaped_token, Settings.tag_start)) elif self.tag_regex.match(token): #If it's a tag try to resolve it token = self.strip_whitespace_regex.sub("", token) args.append(self._parse(episode, token[1:-1])) else: args.append(token) return utils.encode(''.join(args)).strip()
def display_episodes(show, episodes, header=False): if header: print ("\nShow: {0}".format(show.title)) print ("Number of episodes: {0}".format(len(show.episodes))) print ("Number of specials: {0}".format(len(show.specials))) print ("Number of seasons: {0}".format(show.episodes[-1].season)) print ("-" * 30) curr_season = episodes[0].season for eps in episodes: if curr_season != eps.season and header: print ("\nSeason {0}".format(eps.season)) print ("----------") line = show.formatter.display(eps).encode(Settings.encoding, 'ignore') print(utils.encode(line)) curr_season = eps.season
def display_episodes(show, episodes, header=False): if header: print("\nShow: {0}".format(show.title)) print("Number of episodes: {0}".format(len(show.episodes))) print("Number of specials: {0}".format(len(show.specials))) print("Number of seasons: {0}".format(show.episodes[-1].season)) print("-" * 30) curr_season = episodes[0].season for eps in episodes: if curr_season != eps.season and header: print("\nSeason {0}".format(eps.season)) print("----------") line = show.formatter.display(eps).encode(Settings.encoding, 'ignore') print(utils.encode(line)) curr_season = eps.season
def __init__(self, dbName=""): """Establish a connection to the show database""" if not dbName: raise ValueError("Empty database name passed to cache") if dbName != ':memory:': dbName = os.path.join(resource_path, dbName) try: self.connection = connect(dbName, detect_types=PARSE_DECLTYPES) logging.debug("Creating database: {}".format(dbName)) self.connection.executescript(create_database) except OperationalError as reason: logging.error("Error connecting to database: {}".format(reason)) raise reason else: #Make sure everything is utf-8 self.connection.text_factory = lambda x: utils.encode(x)