<commit_before>import os
import random
import string

from django.conf import settings, global_settings
from django.contrib.auth.models import User
from django.db import models
from django.db.models.signals import post_save
from django.utils.translation import ugettext_lazy as _

from django_extensions.db.fields import AutoSlugField
from sorl.thumbnail import ImageField
from djchoices.choices import DjangoChoices, ChoiceItem

from apps.bluebottle_utils.models import Address


class Language(models.Model):
    """
    A Language that user can speak write. This is separate from the user
    interface language.
    """
    # TODO Pre-populate this model with the languages from global_settings.
    language = models.CharField(max_length=5, unique=True,
                                choices=global_settings.LANGUAGES)

    def __unicode__(self):
        return self.get_language_display()


""" TODO: Make this generic for all user file uploads. """
def generate_picture_filename(instance, filename):
    """
    Creates a random directory and file name for uploaded pictures.

    The random directory allows the uploaded images to be evenly spread over
    1296 directories. This allows us to host more files before hitting bad
    performance of the OS filesystem and/or utility programs which can occur
    when a directory has thousands of files.

    An example return value is of this method is:
        'profiles/tw/tws9ea4eqaj37xnu24svp2vwndsytzysa.jpg'
    """
    # Create the upload directory string.
    char_set = string.ascii_lowercase + string.digits
    random_string = ''.join(random.choice(char_set) for i in range(33))
    upload_directory = os.path.join('profiles', random_string[0:2])

    # Get the file extension from the original filename.
    original_filename = os.path.basename(filename)
    file_extension = os.path.splitext(original_filename)[1]

    # Create the normalized path.
    normalized_filename = random_string + file_extension
    return os.path.normpath(os.path.join(upload_directory, normalized_filename))


# The UserProfile class is setup as per the recommendations in the Django
# documentation:
# https://docs.djangoproject.com/en/1.4/topics/auth/#storing-additional-information-about-users
class UserProfile(models.Model):
    """
    Additional information about a user.
    """
    class Gender(DjangoChoices):
        male = ChoiceItem('male', label=_("Male"))
        female = ChoiceItem('female', label=_("Female"))
        other = ChoiceItem('other', label=_("Other"))

    # The Django User model
    user = models.OneToOneField(User)
    slug = AutoSlugField(max_length=30, unique=True,
                         populate_from=('get_username',), overwrite=True)

    # Settings
    interface_language = models.CharField(max_length=5, null=True, blank=True,
                                          choices=settings.LANGUAGES)
    newsletter = models.BooleanField(_("Send Newsletter"), default=False)

    # Basic profile information
    birthdate = models.DateField(null=True, blank=True)
    gender = models.CharField(_('gender'),
        max_length=6, blank=True,
        null=True, choices=Gender.choices
    )
    location = models.CharField(max_length=100, blank=True)
    website = models.URLField(blank=True, max_length=255)
    # TODO Use generate_picture_filename (or something) for upload_to
    picture = ImageField(upload_to='profiles', null=True, blank=True)
    languages = models.ManyToManyField(Language, blank=True)
    deleted = models.DateTimeField(null=True, blank=True)

    # In-depth profile information
    about = models.TextField(blank=True)
    why = models.TextField(blank=True)
    contribution = models.TextField(blank=True)
    availability = models.CharField(max_length=255, blank=True)
    working_location = models.CharField(max_length=255, blank=True)

    def __unicode__(self):
        return self.user.username

    @property
    def get_username(self):
        return self.user.username

    class Meta:
        verbose_name_plural = _("User Profiles")


# Ensures that UserProfile and User instances stay in sync.
def sync_user_profile(sender, instance, created, **kwargs):
    if created:
        # Create a UserProfile whenever a User is created
        UserProfile.objects.create(user=instance)
    else:
        # Save the UserProfile to update the AutoSlugField when a User is saved.
        user_profile = instance.get_profile()
        # TODO In Django 1.5 this can be changed to only save the 'slug' field:
        # https://docs.djangoproject.com/en/dev/ref/models/instances/#the-pk-property
        user_profile.save()

post_save.connect(sync_user_profile, sender=User)

<commit_msg>Make sure an error is never generated for occasional unicode() calls of profiles without users.<commit_after>import os
import random
import string

from django.conf import settings, global_settings
from django.contrib.auth.models import User
from django.db import models
from django.db.models.signals import post_save
from django.utils.translation import ugettext_lazy as _

from django_extensions.db.fields import AutoSlugField
from sorl.thumbnail import ImageField
from djchoices.choices import DjangoChoices, ChoiceItem

from apps.bluebottle_utils.models import Address


class Language(models.Model):
    """
    A Language that user can speak write. This is separate from the user
    interface language.
    """
    # TODO Pre-populate this model with the languages from global_settings.
    language = models.CharField(max_length=5, unique=True,
                                choices=global_settings.LANGUAGES)

    def __unicode__(self):
        return self.get_language_display()


""" TODO: Make this generic for all user file uploads. """
def generate_picture_filename(instance, filename):
    """
    Creates a random directory and file name for uploaded pictures.

    The random directory allows the uploaded images to be evenly spread over
    1296 directories. This allows us to host more files before hitting bad
    performance of the OS filesystem and/or utility programs which can occur
    when a directory has thousands of files.

    An example return value is of this method is:
        'profiles/tw/tws9ea4eqaj37xnu24svp2vwndsytzysa.jpg'
    """
    # Create the upload directory string.
    char_set = string.ascii_lowercase + string.digits
    random_string = ''.join(random.choice(char_set) for i in range(33))
    upload_directory = os.path.join('profiles', random_string[0:2])

    # Get the file extension from the original filename.
    original_filename = os.path.basename(filename)
    file_extension = os.path.splitext(original_filename)[1]

    # Create the normalized path.
    normalized_filename = random_string + file_extension
    return os.path.normpath(os.path.join(upload_directory, normalized_filename))


# The UserProfile class is setup as per the recommendations in the Django
# documentation:
# https://docs.djangoproject.com/en/1.4/topics/auth/#storing-additional-information-about-users
class UserProfile(models.Model):
    """
    Additional information about a user.
    """
    class Gender(DjangoChoices):
        male = ChoiceItem('male', label=_("Male"))
        female = ChoiceItem('female', label=_("Female"))
        other = ChoiceItem('other', label=_("Other"))

    # The Django User model
    user = models.OneToOneField(User)
    slug = AutoSlugField(max_length=30, unique=True,
                         populate_from=('get_username',), overwrite=True)

    # Settings
    interface_language = models.CharField(max_length=5, null=True, blank=True,
                                          choices=settings.LANGUAGES)
    newsletter = models.BooleanField(_("Send Newsletter"), default=False)

    # Basic profile information
    birthdate = models.DateField(null=True, blank=True)
    gender = models.CharField(_('gender'),
        max_length=6, blank=True,
        null=True, choices=Gender.choices
    )
    location = models.CharField(max_length=100, blank=True)
    website = models.URLField(blank=True, max_length=255)
    # TODO Use generate_picture_filename (or something) for upload_to
    picture = ImageField(upload_to='profiles', null=True, blank=True)
    languages = models.ManyToManyField(Language, blank=True)
    deleted = models.DateTimeField(null=True, blank=True)

    # In-depth profile information
    about = models.TextField(blank=True)
    why = models.TextField(blank=True)
    contribution = models.TextField(blank=True)
    availability = models.CharField(max_length=255, blank=True)
    working_location = models.CharField(max_length=255, blank=True)

    def __unicode__(self):
        try:
            return self.user.username
        except User.DoesNotExist:
            return str(self.pk)

    @property
    def get_username(self):
        return self.user.username

    class Meta:
        verbose_name_plural = _("User Profiles")


# Ensures that UserProfile and User instances stay in sync.
def sync_user_profile(sender, instance, created, **kwargs):
    if created:
        # Create a UserProfile whenever a User is created
        UserProfile.objects.create(user=instance)
    else:
        # Save the UserProfile to update the AutoSlugField when a User is saved.
        user_profile = instance.get_profile()
        # TODO In Django 1.5 this can be changed to only save the 'slug' field:
        # https://docs.djangoproject.com/en/dev/ref/models/instances/#the-pk-property
        user_profile.save()

post_save.connect(sync_user_profile, sender=User)


{'fraction_non_alphanumeric': 0.08672455277748718, 'fraction_numerical': 0.007741395543466889, 'mean_word_length': 3.571975131516021, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 4, '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': '735007', 'n_tokens_mistral': 2740, 'n_tokens_neox': 2627, 'n_words': 753}