<commit_before>from __future__ import unicode_literals, division, absolute_import
from builtins import *  # noqa pylint: disable=unused-import, redefined-builtin

import logging

from flexget import plugin
from flexget.config_schema import one_or_more
from flexget.event import event
from flexget.utils.template import RenderError

log = logging.getLogger('notify')

ENTRY_CONTAINERS = ['entries', 'accepted', 'rejected', 'failed', 'undecided']
DEFAULT_DICTS = {
    'task': {
        'message': 'Task returned {{ task.accepted|length }} accepted entries',
        'title': '{{ task_name }}'},
    'entries': {
        'message': '{% if series_name is defined %}'
                   '{{ tvdb_series_name|d(series_name) }} '
                   '{{series_id}} {{tvdb_ep_name|d('')}}'
                   '{% elif imdb_name is defined %}'
                   '{{imdb_name}} {{imdb_year}}'
                   '{% elif title is defined %}'
                   '{{ title }}',
        'url': '{% if imdb_url is defined %}'
               '{{imdb_url}}'
               '{% endif %}',
        'title': '{{ task_name }}'
    }
}


class Notify(object):
    schema = {
        'type': 'object',
        'properties': {
            'to': {'type': 'array', 'items':
                {'allOf': [
                    {'$ref': '/schema/plugins?group=notifiers'},
                    {'maxProperties': 1,
                     'error_maxProperties': 'Plugin options within notify plugin must be indented '
                                            '2 more spaces than the first letter of the plugin name.',
                     'minProperties': 1}]}},
            'scope': {'type': 'string', 'enum': ['task', 'entries']},
            'what': one_or_more({'type': 'string', 'enum': ENTRY_CONTAINERS})
        },
        'required': ['to'],
        'additionalProperties': True
    }

    @staticmethod
    def prepare_config(config):
        config.setdefault('what', ['accepted'])
        if not isinstance(config['what'], list):
            config['what'] = [config['what']]
        config.setdefault('scope', 'entries')
        return config

    @staticmethod
    def render_value(entity, template, attribute, default):
        """
        Tries to render a template, fallback to default template and just value if unsuccessful

        :param entity: The entity to operate on, either `Entry` or `Task`
        :param template: The text to be rendered
        :param attribute: Attribute name to be fetched from the defaults
        :param default: The default dict, depending on entity type
        :return: A rendered value or original value
        """
        result = template
        try:
            result = entity.render(template)
        except (RenderError, ValueError) as e:
            log.debug('failed to render: %s', e.args[0])
            try:
                result = entity.render(default[attribute])
            except RenderError as e:
                log.warning('failed to render: %s', e.args[0])
            except KeyError as e:
                log.debug('tried to render a non existing value `%s` from defaults, skipping', attribute)
        return result

    def send_notification(self, task, config):
        config = self.prepare_config(config)
        scope = config.pop('scope')
        what = config.pop('what')
        notifiers = config.pop('to')

        if scope == 'entries':
            iterate_on = [getattr(task, container) for container in what]
        else:
            iterate_on = [[task]]

        for item in notifiers:
            for plugin_name, plugin_config in item.items():
                notifier = plugin.get_plugin_by_name(plugin_name).instance

                for container in iterate_on:
                    for entity in container:
                        message_data = plugin_config
                        for attribute, value in message_data.items():
                            message_data[attribute] = self.render_value(entity, value, attribute, DEFAULT_DICTS[scope])<commit_msg>Needless assignment fix<commit_after>from __future__ import unicode_literals, division, absolute_import
from builtins import *  # noqa pylint: disable=unused-import, redefined-builtin

import logging

from flexget import plugin
from flexget.config_schema import one_or_more
from flexget.event import event
from flexget.utils.template import RenderError

log = logging.getLogger('notify')

ENTRY_CONTAINERS = ['entries', 'accepted', 'rejected', 'failed', 'undecided']
DEFAULT_DICTS = {
    'task': {
        'message': 'Task returned {{ task.accepted|length }} accepted entries',
        'title': '{{ task_name }}'},
    'entries': {
        'message': '{% if series_name is defined %}'
                   '{{ tvdb_series_name|d(series_name) }} '
                   '{{series_id}} {{tvdb_ep_name|d('')}}'
                   '{% elif imdb_name is defined %}'
                   '{{imdb_name}} {{imdb_year}}'
                   '{% elif title is defined %}'
                   '{{ title }}',
        'url': '{% if imdb_url is defined %}'
               '{{imdb_url}}'
               '{% endif %}',
        'title': '{{ task_name }}'
    }
}


class Notify(object):
    schema = {
        'type': 'object',
        'properties': {
            'to': {'type': 'array', 'items':
                {'allOf': [
                    {'$ref': '/schema/plugins?group=notifiers'},
                    {'maxProperties': 1,
                     'error_maxProperties': 'Plugin options within notify plugin must be indented '
                                            '2 more spaces than the first letter of the plugin name.',
                     'minProperties': 1}]}},
            'scope': {'type': 'string', 'enum': ['task', 'entries']},
            'what': one_or_more({'type': 'string', 'enum': ENTRY_CONTAINERS})
        },
        'required': ['to'],
        'additionalProperties': True
    }

    @staticmethod
    def prepare_config(config):
        config.setdefault('what', ['accepted'])
        if not isinstance(config['what'], list):
            config['what'] = [config['what']]
        config.setdefault('scope', 'entries')
        return config

    @staticmethod
    def render_value(entity, template, attribute, default):
        """
        Tries to render a template, fallback to default template and just value if unsuccessful

        :param entity: The entity to operate on, either `Entry` or `Task`
        :param template: The text to be rendered
        :param attribute: Attribute name to be fetched from the defaults
        :param default: The default dict, depending on entity type
        :return: A rendered value or original value
        """
        result = template
        try:
            result = entity.render(template)
        except (RenderError, ValueError) as e:
            log.debug('failed to render: %s', e.args[0])
            try:
                result = entity.render(default[attribute])
            except RenderError as e:
                log.warning('failed to render: %s', e.args[0])
            except KeyError as e:
                log.debug('tried to render a non existing value `%s` from defaults, skipping', attribute)
        return result

    def send_notification(self, task, config):
        config = self.prepare_config(config)
        scope = config.pop('scope')
        what = config.pop('what')
        notifiers = config.pop('to')

        if scope == 'entries':
            iterate_on = [getattr(task, container) for container in what]
        else:
            iterate_on = [[task]]

        for item in notifiers:
            for plugin_name, plugin_config in item.items():
                notifier = plugin.get_plugin_by_name(plugin_name).instance

                for container in iterate_on:
                    for entity in container:
                        message_data = {}
                        for attribute, value in plugin_config.items():
                            message_data[attribute] = self.render_value(entity, value, attribute, DEFAULT_DICTS[scope])
{'fraction_non_alphanumeric': 0.12006946167204167, 'fraction_numerical': 0.0012403870007442323, 'mean_word_length': 2.0599620493358635, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1762549', 'n_tokens_mistral': 2154, 'n_tokens_neox': 2069, 'n_words': 620}