Example #1
0
    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)
Example #2
0
 def _construct_caper():
     # Caper (optional import)
     try:
         from caper import Caper
         return Caper()
     except ImportError as ex:
         log.info('Caper not available - "%s"', ex)
         return None
    def get_parser(cls):
        """
        :rtype: Caper
        """
        if cls.current is None:
            log.info('Initializing caper parsing library')
            cls.current = Caper()

        return cls.current
Example #4
0
    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)
Example #5
0
    def __init__(self, debug):
        self.caper = Caper(debug=debug)

        self.name_col = None
        self.test_names = None
Example #6
0
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
Example #7
0
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
Example #8
0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from helpers import setup_path
setup_path()

import logging
from logr import Logr
Logr.configure(logging.DEBUG)

from caper import Caper
from matchers import has_info
from hamcrest import *

caper = Caper()


def test_resolution():
    assert_that(caper.parse('Show Name.S01E05.720p-GROUP'),
                has_info('video', {'resolution': '720p'}))

    assert_that(caper.parse('Show Name.S01E05.1080p'),
                has_info('video', {'resolution': '1080p'}))

    assert_that(caper.parse('Show Name.S01E05.480p.HDTV-GROUP'),
                has_info('video', {'resolution': '480p'}))
Example #9
0
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