class Matcher(MatcherBase): def __init__(self): super(Matcher, self).__init__() self.caper = Caper() addEvent('matcher.parse', self.parse) addEvent('matcher.match', self.match) addEvent('matcher.flatten_info', self.flattenInfo) addEvent('matcher.construct_from_raw', self.constructFromRaw) addEvent('matcher.correct_title', self.correctTitle) addEvent('matcher.correct_quality', self.correctQuality) def parse(self, name, parser='scene'): return self.caper.parse(name, parser) def match(self, release, media, quality): match = fireEvent('matcher.parse', release['name'], single = True) if len(match.chains) < 1: log.info2('Wrong: %s, unable to parse release name (no chains)', release['name']) return False for chain in match.chains: if fireEvent('%s.matcher.correct' % media['type'], chain, release, media, quality, single = True): return chain return False def correctTitle(self, chain, media): root_library = media['library']['root_library'] if 'show_name' not in chain.info or not len(chain.info['show_name']): log.info('Wrong: missing show name in parsed result') return False # Get the lower-case parsed show name from the chain chain_words = [x.lower() for x in chain.info['show_name']] # Build a list of possible titles of the media we are searching for titles = root_library['info']['titles'] # Add year suffix titles (will result in ['<name_one>', '<name_one> <suffix_one>', '<name_two>', ...]) suffixes = [None, root_library['info']['year']] titles = [ title + ((' %s' % suffix) if suffix else '') for title in titles for suffix in suffixes ] # Check show titles match # TODO check xem names for title in titles: for valid_words in [x.split(' ') for x in possibleTitles(title)]: if valid_words == chain_words: return True return False def correctQuality(self, chain, quality, quality_map): if quality['identifier'] not in quality_map: log.info2('Wrong: unknown preferred quality %s', quality['identifier']) return False if 'video' not in chain.info: log.info2('Wrong: no video tags found') return False video_tags = quality_map[quality['identifier']] if not self.chainMatch(chain, 'video', video_tags): log.info2('Wrong: %s tags not in chain', video_tags) return False return True
class CaperTests(object): def __init__(self, debug): self.caper = Caper(debug=debug) self.name_col = None self.test_names = None def _read_header(self, reader): header = next(reader) for i, col in enumerate(header): if col == 'name': self.name_col = i if self.name_col is None: raise Exception() def load(self, filename, limit=100): if not os.path.isfile(filename): raise Exception() with open(filename) as fp: reader = csv.reader(fp, escapechar='|') self._read_header(reader) self.test_names = [] for i, row in enumerate(reader): if not len(row) or row[0].startswith('#'): continue self.test_names.append(row[self.name_col]) if len(self.test_names) >= limit: break print "loaded %s names for testing" % len(self.test_names) def run(self, parser_type, arguments): max_num_length = len(str(len(self.test_names))) row_format = '[%%0%dd] %%s' % max_num_length start = arguments['start'] or raw_input('Start position: ') if start.strip() != '': start = int(start) else: start = 0 for i, name in enumerate(self.test_names): if i < start - 1: continue print row_format % (i + 1, name) result = self.caper.parse(name, parser_type) if arguments['print'] and result and result.chains: print "------------------------------------------------------------------------" for chain in result.chains: print "Chain [%s]: %s" % (chain.weight, chain.info) print "------------------------------------------------------------------------" if arguments['pause']: print "Press ENTER to continue testing" try: raw_input() except EOFError: return
class Matcher(MatcherBase): def __init__(self): super(Matcher, self).__init__() self.caper = Caper() addEvent('matcher.parse', self.parse) addEvent('matcher.match', self.match) addEvent('matcher.flatten_info', self.flattenInfo) addEvent('matcher.construct_from_raw', self.constructFromRaw) addEvent('matcher.correct_title', self.correctTitle) addEvent('matcher.correct_quality', self.correctQuality) def parse(self, name, parser='scene'): return self.caper.parse(name, parser) def match(self, release, media, quality): match = fireEvent('matcher.parse', release['name'], single=True) if len(match.chains) < 1: log.info2('Wrong: %s, unable to parse release name (no chains)', release['name']) return False for chain in match.chains: if fireEvent('%s.matcher.correct' % media['type'], chain, release, media, quality, single=True): return chain return False def correctTitle(self, chain, media): root = fireEvent('library.root', media, single=True) if 'show_name' not in chain.info or not len(chain.info['show_name']): log.info('Wrong: missing show name in parsed result') return False # Get the lower-case parsed show name from the chain chain_words = [x.lower() for x in chain.info['show_name']] # Build a list of possible titles of the media we are searching for titles = root['info']['titles'] # Add year suffix titles (will result in ['<name_one>', '<name_one> <suffix_one>', '<name_two>', ...]) suffixes = [None, root['info']['year']] titles = [ title + ((' %s' % suffix) if suffix else '') for title in titles for suffix in suffixes ] # Check show titles match # TODO check xem names for title in titles: for valid_words in [x.split(' ') for x in possibleTitles(title)]: if valid_words == chain_words: return True return False def correctQuality(self, chain, quality, quality_map): if quality['identifier'] not in quality_map: log.info2('Wrong: unknown preferred quality %s', quality['identifier']) return False if 'video' not in chain.info: log.info2('Wrong: no video tags found') return False video_tags = quality_map[quality['identifier']] if not self.chainMatch(chain, 'video', video_tags): log.info2('Wrong: %s tags not in chain', video_tags) return False return True