<commit_before>from datetime import datetime
from alert.exceptions import AlertIDAlreadyInUse, AlertBackendIDAlreadyInUse,\
    InvalidApplicableUsers
import django
from django.template.loader import render_to_string, find_template
from django.contrib.sites.models import Site
from django.template import TemplateDoesNotExist
from django.contrib.auth.models import User
from django.db import models

ALERT_TYPES = {}
ALERT_BACKENDS = {}

ALERT_TYPE_CHOICES = [] 
ALERT_BACKEND_CHOICES = []



class AlertMeta(type):

    def __new__(cls, name, bases, attrs):
        new_alert = super(AlertMeta, cls).__new__(cls, name, bases, attrs)
        
        # If this isn't a subclass of BaseAlert, don't do anything special.
        parents = [b for b in bases if isinstance(b, AlertMeta)]
        if not parents: 
            return new_alert
        
        # allow subclasses to use the auto id feature
        id = getattr(new_alert, 'id', name)
        for parent in parents:
            if getattr(parent, 'id', None) == id:
                id = name
                break
        
        new_alert.id = id
        
        if new_alert.id in ALERT_TYPES.keys():
            raise AlertIDAlreadyInUse("The alert ID, \"%s\" was delared more than once" % new_alert.id)
        
        ALERT_TYPES[new_alert.id] = new_alert()
        ALERT_TYPE_CHOICES.append((new_alert.id, new_alert.title))
        
        return new_alert



class BaseAlert(object):
    __metaclass__ = AlertMeta
    
    default = False
    sender = None
    template_filetype = "txt"
    
    
    
    def __init__(self):
        kwargs = {}
        if self.sender:
            kwargs['sender'] = self.sender
        
        self.signal.connect(self.signal_handler, **kwargs)
    
    def __repr__(self):
        return "<Alert: %s>" % self.id
    
    def __str__(self):
        return str(self.id)
    
    def signal_handler(self, **kwargs):
    
        if self.before(**kwargs) is False: 
            return

        from alert.models import AlertPreference
        from alert.models import Alert
        
        users = self.get_applicable_users(**kwargs)
        if isinstance(users, models.Model):
            users = [users]
        
        if len(users) and not isinstance(users[0], User):
            raise InvalidApplicableUsers("%s.get_applicable_users() returned an invalid value. Acceptable values are a django.contrib.auth.models.User instance OR an iterable containing 0 or more User instances" % (self.id))
        
        site = Site.objects.get_current()
        
        def mk_alert(user, backend):
            context = self.get_template_context(BACKEND=backend, USER=user, SITE=site, ALERT=self, **kwargs)
            template_kwargs = {'backend': backend, 'context': context }
            return Alert(
                          user=user, 
                          backend=backend.id,
                          alert_type=self.id,
                          when=self.get_send_time(**kwargs),
                          title=self.get_title(**template_kwargs),
                          body=self.get_body(**template_kwargs)
                          )
        alerts = [mk_alert(user, backend) for (user, backend) in AlertPreference.objects.get_recipients_for_notice(self.id, users)]
        
        if django.VERSION >= (1, 5):
            Alert.objects.bulk_create(alerts, batch_size=1000)
        elif django.VERSION >= (1, 4):
            Alert.objects.bulk_create(alerts)
        else:
            for alert in alerts: alert.save()
    
    
    def before(self, **kwargs):
        pass
    
    
    def get_send_time(self, **kwargs):
        return datetime.now()
    
    
    def get_applicable_users(self, instance, **kwargs):
        return [instance.user]
    
    
    def get_template_context(self, **kwargs):
        return kwargs


    def _get_template(self, backend, part, filetype='txt'):
        template = "alerts/%s/%s/%s.%s" % (self.id, backend.id, part, filetype)
        try:
            find_template(template)
            return template
        except TemplateDoesNotExist:
            pass
        <commit_msg>bug fix for performance enhancement<commit_after>from datetime import datetime
from alert.exceptions import AlertIDAlreadyInUse, AlertBackendIDAlreadyInUse,\
    InvalidApplicableUsers
import django
from django.template.loader import render_to_string, find_template
from django.contrib.sites.models import Site
from django.template import TemplateDoesNotExist
from django.contrib.auth.models import User
from django.db import models
from itertools import islice

ALERT_TYPES = {}
ALERT_BACKENDS = {}

ALERT_TYPE_CHOICES = [] 
ALERT_BACKEND_CHOICES = []

def grouper(n, iterable):
    iterable = iter(iterable)
    while True:
        chunk = tuple(islice(iterable, n))
        if not chunk: return
        yield chunk

class AlertMeta(type):

    def __new__(cls, name, bases, attrs):
        new_alert = super(AlertMeta, cls).__new__(cls, name, bases, attrs)
        
        # If this isn't a subclass of BaseAlert, don't do anything special.
        parents = [b for b in bases if isinstance(b, AlertMeta)]
        if not parents: 
            return new_alert
        
        # allow subclasses to use the auto id feature
        id = getattr(new_alert, 'id', name)
        for parent in parents:
            if getattr(parent, 'id', None) == id:
                id = name
                break
        
        new_alert.id = id
        
        if new_alert.id in ALERT_TYPES.keys():
            raise AlertIDAlreadyInUse("The alert ID, \"%s\" was delared more than once" % new_alert.id)
        
        ALERT_TYPES[new_alert.id] = new_alert()
        ALERT_TYPE_CHOICES.append((new_alert.id, new_alert.title))
        
        return new_alert



class BaseAlert(object):
    __metaclass__ = AlertMeta
    
    default = False
    sender = None
    template_filetype = "txt"
    
    
    
    def __init__(self):
        kwargs = {}
        if self.sender:
            kwargs['sender'] = self.sender
        
        self.signal.connect(self.signal_handler, **kwargs)
    
    def __repr__(self):
        return "<Alert: %s>" % self.id
    
    def __str__(self):
        return str(self.id)
    
    def signal_handler(self, **kwargs):
    
        if self.before(**kwargs) is False: 
            return

        from alert.models import AlertPreference
        from alert.models import Alert
        
        users = self.get_applicable_users(**kwargs)
        if isinstance(users, models.Model):
            users = [users]
        
        try:
            user_count = users.count()
        except:
            user_count = len(users)
            
        if user_count and not isinstance(users[0], User):
            raise InvalidApplicableUsers("%s.get_applicable_users() returned an invalid value. Acceptable values are a django.contrib.auth.models.User instance OR an iterable containing 0 or more User instances" % (self.id))
        
        site = Site.objects.get_current()
        
        def mk_alert(user, backend):
            context = self.get_template_context(BACKEND=backend, USER=user, SITE=site, ALERT=self, **kwargs)
            template_kwargs = {'backend': backend, 'context': context }
            return Alert(
                          user=user, 
                          backend=backend.id,
                          alert_type=self.id,
                          when=self.get_send_time(**kwargs),
                          title=self.get_title(**template_kwargs),
                          body=self.get_body(**template_kwargs)
                          )
        alerts = (mk_alert(user, backend) for (user, backend) in AlertPreference.objects.get_recipients_for_notice(self.id, users))
        
        # bulk create is much faster so use it when available
        if django.VERSION >= (1, 4):
            created = 0
            for alerts_group in grouper(100, alerts):
                # break bulk create into groups of 100 to avoid the dreaded
                # OperationalError: (2006, 'MySQL server has gone away')
                Alert.objects.bulk_create(alerts_group)
                created += 100
        else:
            for alert in alerts: alert.save()
    
    
    def before(self, **kwargs):
        pass
    
    
    def get_send_time(self, **kwargs):
        return datetime.now()
    
    
    def get_applicable_users(self, instance, **kwargs):
        return [instance.user]
    
    
    def get_template_context(self, **kwargs):
        return kwargs


    def _get_template(self, backend, part, filetype='txt'):
        template = "alerts/%s/%s/%s.%s" % (self.id, backend.id, part, filetype)
        try:
            find_template(template)
            return template
        except TemplateDoesNotExist:
            pass
        
{'fraction_non_alphanumeric': 0.08961464572268053, 'fraction_numerical': 0.003164199344558707, 'mean_word_length': 2.0061141304347827, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 8, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7506530', 'n_tokens_mistral': 2564, 'n_tokens_neox': 2459, 'n_words': 641}