<commit_before>import json
import random

from django.db import models
from django.contrib.auth.models import User
from django.utils.functional import cached_property

from markupfield.fields import MarkupField

from hvad.models import TranslatableModel, TranslatedFields
from hvad.manager import TranslationManager

from ..utils import HashedUploadTo


experiment_thumbnail_upload_to = HashedUploadTo('thumbnail')
experimentdetail_image_upload_to = HashedUploadTo('image')


class ExperimentManager(TranslationManager):

    def get_by_natural_key(self, slug):
        return self.get(slug=slug)


class Experiment(TranslatableModel):
    objects = ExperimentManager()

    class Meta:
        ordering = ['order']

    translations = TranslatedFields(
        title=models.CharField(max_length=128),
        short_title=models.CharField(max_length=60, blank=True, default=''),
        description=models.TextField(),
        measurements=MarkupField(blank=True, default='',
                                 default_markup_type='plain'),
    )

    slug = models.SlugField(max_length=128, unique=True, db_index=True)
    thumbnail = models.ImageField(upload_to=experiment_thumbnail_upload_to)
    xpi_url = models.URLField()
    version = models.CharField(blank=True, max_length=128)
    order = models.IntegerField(default=0)
    changelog_url = models.URLField(blank=True)
    contribute_url = models.URLField(blank=True)
    privacy_notice_url = models.URLField(blank=True)
    addon_id = models.CharField(max_length=500, blank=False,)

    users = models.ManyToManyField(User, through='UserInstallation')
    contributors = models.ManyToManyField(User, related_name='contributor')

    created = models.DateTimeField(auto_now_add=True)
    modified = models.DateTimeField(auto_now=True)

    @cached_property
    def installation_count(self):
        return UserInstallation.objects.distinct('user').filter(
            experiment=self).count()

    def __str__(self):
        return self.title

    def natural_key(self):
        return (self.slug,)


class ExperimentDetail(TranslatableModel):
    experiment = models.ForeignKey('Experiment', related_name='details',
                                   db_index=True)

    order = models.IntegerField(default=0)

    translations = TranslatedFields(
        headline=models.CharField(max_length=256),
        copy=models.TextField()
    )

    image = models.ImageField(upload_to=experimentdetail_image_upload_to)

    created = models.DateTimeField(auto_now_add=True)
    modified = models.DateTimeField(auto_now=True)

    class Meta:
        ordering = ('experiment', 'order', 'modified',)


class UserInstallation(models.Model):

    experiment = models.ForeignKey(Experiment)
    user = models.ForeignKey(User)
    client_id = models.CharField(blank=True, max_length=128)

    created = models.DateTimeField(auto_now_add=True)
    modified = models.DateTimeField(auto_now=True)

    class Meta:
        unique_together = ('experiment', 'user', 'client_id',)

    @cached_property
    def features(self):
        return FeatureState.objects.get_for_installation(self)


class UserFeedback(models.Model):

    experiment = models.ForeignKey('Experiment', related_name='feedbacks',
                                   db_index=True)

    # User should be optional for if/when we have UX to submit anonymous
    # feedback, or we anonymize a user's feedback post-submission
    user = models.ForeignKey(User, blank=True, null=True)

    question = models.CharField(max_length=256)
    answer = models.CharField(max_length=256, blank=True)
    extra = models.TextField(blank=True)

    created = models.DateTimeField(auto_now_add=True)
    modified = models.DateTimeField(auto_now=True)


class Feature(models.Model):
    experiment = models.ForeignKey(Experiment, related_name='features',
                                   db_index=True)
    slug = models.SlugField(max_length=128, unique=True, db_index=True)
    title = models.CharField(max_length=128)
    default_active = models.BooleanField(default=False)

    created = models.DateTimeField(auto_now_add=True)
    modified = models.DateTimeField(auto_now=True)


class FeatureConditionManager(models.Manager):

    operator_registry = {}

    def register_operator(self, name, description=''):
        """Decorator to register a condition operator function"""
        def decorator(func):
            self.operator_registry[name] = dict(
                func=func, description=description)
            return func
        return decorator

    def get_operator_choices(self):
        """Assemble list of operator choices for form fields"""
        return [
            (name, '%s: %s' % (name, operator['description']))
            for name, operator in self.operator_registry.items()
        ]

    def apply_conditions_for_installation(self, installation):
        conditions = FeatureCondition.objects.filter(
            experiment=installation.experiment)
        for condition in conditions:
            operator = self.operator_registry.get(condition.operator, None)
            if operator is not None:
                # TODO: Report some error on an unknown operator?
                operator['func'](condition, installation)


class FeatureCondition(models.Model):
    objects = FeatureConditionManager()

    experiment = models.ForeignKey(Experiment, related_name='conditions',
                                   db_index=True)
    operator = models.CharField(max_length=256, choices=[('', 'None'), ])
    argument = models.TextField()
    comment = models.TextField()
<commit_msg>Make comment field optional on experiment feature conditions<commit_after>import json
import random

from django.db import models
from django.contrib.auth.models import User
from django.utils.functional import cached_property

from markupfield.fields import MarkupField

from hvad.models import TranslatableModel, TranslatedFields
from hvad.manager import TranslationManager

from ..utils import HashedUploadTo


experiment_thumbnail_upload_to = HashedUploadTo('thumbnail')
experimentdetail_image_upload_to = HashedUploadTo('image')


class ExperimentManager(TranslationManager):

    def get_by_natural_key(self, slug):
        return self.get(slug=slug)


class Experiment(TranslatableModel):
    objects = ExperimentManager()

    class Meta:
        ordering = ['order']

    translations = TranslatedFields(
        title=models.CharField(max_length=128),
        short_title=models.CharField(max_length=60, blank=True, default=''),
        description=models.TextField(),
        measurements=MarkupField(blank=True, default='',
                                 default_markup_type='plain'),
    )

    slug = models.SlugField(max_length=128, unique=True, db_index=True)
    thumbnail = models.ImageField(upload_to=experiment_thumbnail_upload_to)
    xpi_url = models.URLField()
    version = models.CharField(blank=True, max_length=128)
    order = models.IntegerField(default=0)
    changelog_url = models.URLField(blank=True)
    contribute_url = models.URLField(blank=True)
    privacy_notice_url = models.URLField(blank=True)
    addon_id = models.CharField(max_length=500, blank=False,)

    users = models.ManyToManyField(User, through='UserInstallation')
    contributors = models.ManyToManyField(User, related_name='contributor')

    created = models.DateTimeField(auto_now_add=True)
    modified = models.DateTimeField(auto_now=True)

    @cached_property
    def installation_count(self):
        return UserInstallation.objects.distinct('user').filter(
            experiment=self).count()

    def __str__(self):
        return self.title

    def natural_key(self):
        return (self.slug,)


class ExperimentDetail(TranslatableModel):
    experiment = models.ForeignKey('Experiment', related_name='details',
                                   db_index=True)

    order = models.IntegerField(default=0)

    translations = TranslatedFields(
        headline=models.CharField(max_length=256),
        copy=models.TextField()
    )

    image = models.ImageField(upload_to=experimentdetail_image_upload_to)

    created = models.DateTimeField(auto_now_add=True)
    modified = models.DateTimeField(auto_now=True)

    class Meta:
        ordering = ('experiment', 'order', 'modified',)


class UserInstallation(models.Model):

    experiment = models.ForeignKey(Experiment)
    user = models.ForeignKey(User)
    client_id = models.CharField(blank=True, max_length=128)

    created = models.DateTimeField(auto_now_add=True)
    modified = models.DateTimeField(auto_now=True)

    class Meta:
        unique_together = ('experiment', 'user', 'client_id',)

    @cached_property
    def features(self):
        return FeatureState.objects.get_for_installation(self)


class UserFeedback(models.Model):

    experiment = models.ForeignKey('Experiment', related_name='feedbacks',
                                   db_index=True)

    # User should be optional for if/when we have UX to submit anonymous
    # feedback, or we anonymize a user's feedback post-submission
    user = models.ForeignKey(User, blank=True, null=True)

    question = models.CharField(max_length=256)
    answer = models.CharField(max_length=256, blank=True)
    extra = models.TextField(blank=True)

    created = models.DateTimeField(auto_now_add=True)
    modified = models.DateTimeField(auto_now=True)


class Feature(models.Model):
    experiment = models.ForeignKey(Experiment, related_name='features',
                                   db_index=True)
    slug = models.SlugField(max_length=128, unique=True, db_index=True)
    title = models.CharField(max_length=128)
    default_active = models.BooleanField(default=False)

    created = models.DateTimeField(auto_now_add=True)
    modified = models.DateTimeField(auto_now=True)


class FeatureConditionManager(models.Manager):

    operator_registry = {}

    def register_operator(self, name, description=''):
        """Decorator to register a condition operator function"""
        def decorator(func):
            self.operator_registry[name] = dict(
                func=func, description=description)
            return func
        return decorator

    def get_operator_choices(self):
        """Assemble list of operator choices for form fields"""
        return [
            (name, '%s: %s' % (name, operator['description']))
            for name, operator in self.operator_registry.items()
        ]

    def apply_conditions_for_installation(self, installation):
        conditions = FeatureCondition.objects.filter(
            experiment=installation.experiment)
        for condition in conditions:
            operator = self.operator_registry.get(condition.operator, None)
            if operator is not None:
                # TODO: Report some error on an unknown operator?
                operator['func'](condition, installation)


class FeatureCondition(models.Model):
    objects = FeatureConditionManager()

    experiment = models.ForeignKey(Experiment, related_name='conditions',
                                   db_index=True)
    operator = models.CharField(max_length=256, choices=[('', 'None'), ])
    argument = models.TextField()
    comment = models.TextField(blank=True)

{'fraction_non_alphanumeric': 0.09628183512290354, 'fraction_numerical': 0.0065666873724376604, 'mean_word_length': 3.5333869670152858, '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': 10, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7198181', 'n_tokens_mistral': 3212, 'n_tokens_neox': 3065, 'n_words': 615}