flexget.plugins.module_manipulate
Covered: 80 lines
Missed: 2 lines
Skipped 21 lines
Percent: 97 %
  1
import logging
  2
import re
  3
from flexget.plugin import priority, register_plugin
  5
log = logging.getLogger('manipulate')
  8
class Manipulate(object):
  9
    """
 10
        Usage:
 12
        manipulate:
 13
          - <destination field>:
 14
              [event]: <event>
 15
              [from]: <source field>
 16
              [extract]: <regexp>
 17
              [replace]:
 18
                regexp: <regexp>
 19
                format: <regexp>
 21
        Example:
 23
        manipulate:
 24
          - title:
 25
              extract: \[\d\d\d\d\](.*)
 26
    """
 28
    def validator(self):
 29
        from flexget import validator
 30
        root = validator.factory()
 31
        bundle = root.accept('list').accept('dict')
 33
        bundle.reject_keys(['from', 'extract', 'replace', 'event'],
 34
            'Option \'$key\' has invalid indentation level. It needs 2 more spaces.')
 35
        edit = bundle.accept_any_key('dict')
 36
        edit.accept('choice', key='event').accept_choices(['metainfo', 'filter'], ignore_case=True)
 37
        edit.accept('text', key='from')
 38
        edit.accept('regexp', key='extract')
 39
        replace = edit.accept('dict', key='replace')
 40
        replace.accept('regexp', key='regexp', required=True)
 41
        replace.accept('text', key='format', required=True)
 42
        return root
 44
    def on_feed_start(self, feed):
 45
        """Separates the config into a dict with a list of jobs per event."""
 46
        config = feed.config['manipulate']
 47
        self.event_jobs = {'filter': [], 'metainfo': []}
 48
        for item in config:
 49
            for item_config in item.itervalues():
 51
                event = item_config.get('event', 'metainfo')
 52
                self.event_jobs[event].append(item)
 54
    @priority(255)
 55
    def on_feed_metainfo(self, feed):
 56
        if not self.event_jobs['metainfo']:
 58
            return
 59
        for entry in feed.entries:
 60
            self.process(feed, entry, self.event_jobs['metainfo'])
 62
    @priority(255)
 63
    def on_feed_filter(self, feed):
 64
        if not self.event_jobs['filter']:
 66
            return
 67
        for entry in feed.entries + feed.rejected:
 68
            self.process(feed, entry, self.event_jobs['filter'])
 70
    def process(self, feed, entry, jobs):
 72
        for item in jobs:
 73
            for field, config in item.iteritems():
 74
                from_field = field
 75
                if 'from' in config:
 76
                    from_field = config['from']
 77
                field_value = entry.get(from_field)
 78
                log.debug('field: %s from_field: %s field_value: %s' % (field, from_field, field_value))
 80
                if 'extract' in config:
 81
                    if not field_value:
 82
                        log.warning('Cannot extract, field %s is not present' % from_field)
 83
                        continue
 84
                    match = re.search(config['extract'], field_value)
 85
                    if match:
 86
                        groups = [x for x in match.groups() if x is not None]
 87
                        log.debug('groups: %s' % groups)
 88
                        field_value = ''.join(groups)
 89
                        log.debug('field %s after extract: %s' % (field, field_value))
 91
                if 'replace' in config:
 92
                    if not field_value:
 93
                        log.warning('Cannot replace, field %s is not present' % from_field)
 94
                        continue
 95
                    replace_config = config['replace']
 96
                    field_value = re.sub(replace_config['regexp'], replace_config['format'], field_value)
 97
                    log.debug('field %s after replace: %s' % (field, field_value))
 99
                entry[field] = field_value
100
                feed.verbose_progress('Field %s is now %s' % (field, entry[field]), log)
102
register_plugin(Manipulate, 'manipulate')