<commit_before>from datetime import datetime
from django.db.models.signals import post_save, post_delete
from django.db import models
from django.contrib.auth.models import User, Permission
from django.conf import settings
from django.db.models import Q
from django.core.exceptions import ValidationError
from deliverystore import load_deliverystore_backend
from django.utils.translation import ugettext as _



class BaseNode(models.Model):
    short_name = models.SlugField(max_length=20,
            help_text=u"Only numbers, letters, '_' and '-'.")
    long_name = models.CharField(max_length=100)

    class Meta:
        abstract = True

    def get_path(self):
        return unicode(self)

    def admins_unicode(self):
        return u', '.join(u.username for u in self.admins.all())

    def is_admin(self, user_obj):
        if self.admins.filter(pk=user_obj.pk):
            return True
        elif self.parentnode:
            return self.parentnode.is_admin(user_obj)
        else:
            return False

    @classmethod
    def where_is_admin(cls, user_obj):
        """ Get all nodes where `user_obj` is admin. """
        raise NotImplementedError()


class Node(BaseNode):
    parentnode = models.ForeignKey('self', blank=True, null=True)
    admins = models.ManyToManyField(User, blank=True)

    def __unicode__(self):
        if self.parentnode:
            return unicode(self.parentnode) + "." + self.short_name
        else:
            return self.short_name


    def iter_childnodes(self):
        for node in self.node_set.all():
            yield node
            for c in node.iter_childnodes():
                yield c

    def clean(self, *args, **kwargs):
        if self.parentnode == None:
            q = Node.objects.filter(parentnode=None)
            if q.count() == 0:
                raise ValidationError('At least one node *must* be root.')
            else:
                if q.all()[0] != self:
                    raise ValidationError('Only one node can be the root node.')

        if self.parentnode == self:
            raise ValidationError('A node can not be it\'s own parent.')

        for node in self.iter_childnodes():
            if node == self.parentnode:
                raise ValidationError('A node can not be the child of one of it\'s own children.')


        super(Node, self).clean(*args, **kwargs)

    @classmethod
    def _get_nodepks_where_isadmin(cls, user_obj):
        """ Get a list with the primary key of all nodes where the given
        `user_obj` is admin. """
        admnodes = Node.objects.filter(admins=user_obj)
        l = []
        def add_admnodes(admnodes):
            for a in admnodes.all():
                l.append(a.pk)
                add_admnodes(a.node_set)
        add_admnodes(admnodes)
        return l

    @classmethod
    def where_is_admin(cls, user_obj):
        return Node.objects.filter(pk__in=cls._get_nodepks_where_isadmin(user_obj))

    @classmethod
    def _get_pathlist_kw(cls, pathlist):
        """ Used by get_by_pathlist() to create the required kwargs for
        Node.objects.get(). Might be a starting point for more sophisticated
        queries including paths. """
        kw = {}
        key = 'short_name'
        for short_name in reversed(pathlist):
            kw[key] = short_name
            key = 'parentnode__' + key
        return kw

    @classmethod
    def get_by_pathlist(cls, pathlist):
        """ Get node by path just like get_by_path(), the parameter
        is a list of node-names instead of a single string. Example:
            >>> uio = Node(short_name='uio', long_name='UiO')
            >>> uio.save()
            >>> ifi = Node(short_name='ifi', long_name='Ifi', parentnode=uio)
            >>> ifi.save()
            >>> ifi
            <Node: uio.ifi>
            >>> Node.get_by_pathlist(['uio', 'ifi'])
            <Node: uio.ifi>
        """
        return Node.objects.get(**cls._get_pathlist_kw(pathlist))

    @classmethod
    def get_by_path(cls, path):
        """ Get a node by path. Just like `get_by_pathlist`, but the path is a
        string where the node-names are separated with '.'. """
        return cls.get_by_pathlist(path.split('.'))


    @classmethod
    def create_by_pathlist(cls, pathlist):
        """ Create a new node from the path given in `nodelist`, creating all
        missing parents. """
        parent = None
        n = None
        for i, short_name in enumerate(pathlist):
            try:
                n = Node.get_by_pathlist(pathlist[:i+1])
            except Node.DoesNotExist, e:
                n = Node(short_name=short_name, long_name=short_name, parentnode=parent)
                n.save()
            parent = n
        return n

    @classmethod
    def create_by_path(cls, path):
        """ Just like `get_by_pathlist`, but the path is a string where each `short_name`
        is separated by '.', instead of a list. """
        return cls.get_by_pathlist(path.split('.'))


class Subject(BaseNode):
    parentnode = models.ForeignKey(Node)
    admins = models.ManyToManyField(User, blank=True)

    @classmethod
    def where_is_admin(cls, user_obj):
        return Subject.objects.filter(
                Q(admins__pk=user_obj.pk)
                | Q(parentnode__pk__in=Node._get_nodepks_where_isadmin(user_obj))).distinct()

    def __unicode__(self):
        return self.short_name



class Period(BaseNode):
    parentnode = models.ForeignKey(Subject)
    start_time = models.DateTimeField()
    end_time = models.DateTimeField()
    admins = models.ManyToManyField(User, blank=True)


    @classmethod
    def where_is_admin(cls, user_obj):
        return Period.objects.filter(
                Q(admins=user_obj) |
                Q(parentnode__admins=user_obj) |
                Q(parentnode__parentnode__pk__in=Node._get_nodepks_where_isadmin(user_obj))
        ).distinct()

    def __unicode__(self):
        return unicode(self.parentnode) + " - " + self.short_name


class Assignment(BaseNode):
    parentnode = models.ForeignKey(Period)
    deadline = models.DateTimeField()
    publishing_time = models.DateTimeField()
    admins = models.ManyToManyField(User, blank=True)

    @classmethod
    def where_is_admin(cls, user_obj):
        return Assignment.objects.filter(
                Q(admins=user_obj) |
                Q(parentnode__admins=user_obj) |
                Q(parentnode__parentnode__admins=user_obj) |
                Q(parentnode__parentnode__parentnode__pk__in=Node._get_nodepks_where_isadmin(user_obj))
        ).distinct()

    def __unicode__(self):
        return unicode(self.parentnode) + " - " + self.short_name

    @classmethod
    def where_is_examiner(cls, user_obj):
        return Assignment.objects.filter(
            assignmentgroup_set__examiners=user_obj
            ).distinct()

    def assignment_groups_where_is_examiner(self, user_obj):
        return self.assignmentgroup_set.filter(examiners=user_obj)
 


class AssignmentGroup(models.Model):
    parentnode = models.ForeignKey(Assignment)
    students = models.ManyToManyField(User, blank=True, related_name="students")
    examiners = models.ManyToManyField(User, blank=True, related_name="examiners")
    is_open = models.BooleanField(blank=True, default=True,
            help_text = _('If this is checked, the group can add deliveries.'))

    @classmethod
    def where_is_admin(cls, user_obj):
        return AssignmentGroup.objects.filter(
                Q(parentnode__admins=user_obj) |
                Q(parentnode__parentnode__admins=user_obj) |
                Q(parentnode__parentnode__parentnode__admins=user_obj) |
                Q(parentnode__parentnode__parentnode__parentnode__pk__in=Node._get_nodepks_where_isadmin(user_obj))
        ).distinct()

    @classmethod
    def where_is_student(cls, user_obj):<commit_msg>added newline to fix som doc-stuff<commit_after>from datetime import datetime
from django.db.models.signals import post_save, post_delete
from django.db import models
from django.contrib.auth.models import User, Permission
from django.conf import settings
from django.db.models import Q
from django.core.exceptions import ValidationError
from deliverystore import load_deliverystore_backend
from django.utils.translation import ugettext as _



class BaseNode(models.Model):
    short_name = models.SlugField(max_length=20,
            help_text=u"Only numbers, letters, '_' and '-'.")
    long_name = models.CharField(max_length=100)

    class Meta:
        abstract = True

    def get_path(self):
        return unicode(self)

    def admins_unicode(self):
        return u', '.join(u.username for u in self.admins.all())

    def is_admin(self, user_obj):
        if self.admins.filter(pk=user_obj.pk):
            return True
        elif self.parentnode:
            return self.parentnode.is_admin(user_obj)
        else:
            return False

    @classmethod
    def where_is_admin(cls, user_obj):
        """ Get all nodes where `user_obj` is admin. """
        raise NotImplementedError()


class Node(BaseNode):
    parentnode = models.ForeignKey('self', blank=True, null=True)
    admins = models.ManyToManyField(User, blank=True)

    def __unicode__(self):
        if self.parentnode:
            return unicode(self.parentnode) + "." + self.short_name
        else:
            return self.short_name


    def iter_childnodes(self):
        for node in self.node_set.all():
            yield node
            for c in node.iter_childnodes():
                yield c

    def clean(self, *args, **kwargs):
        if self.parentnode == None:
            q = Node.objects.filter(parentnode=None)
            if q.count() == 0:
                raise ValidationError('At least one node *must* be root.')
            else:
                if q.all()[0] != self:
                    raise ValidationError('Only one node can be the root node.')

        if self.parentnode == self:
            raise ValidationError('A node can not be it\'s own parent.')

        for node in self.iter_childnodes():
            if node == self.parentnode:
                raise ValidationError('A node can not be the child of one of it\'s own children.')


        super(Node, self).clean(*args, **kwargs)

    @classmethod
    def _get_nodepks_where_isadmin(cls, user_obj):
        """ Get a list with the primary key of all nodes where the given
        `user_obj` is admin. """
        admnodes = Node.objects.filter(admins=user_obj)
        l = []
        def add_admnodes(admnodes):
            for a in admnodes.all():
                l.append(a.pk)
                add_admnodes(a.node_set)
        add_admnodes(admnodes)
        return l

    @classmethod
    def where_is_admin(cls, user_obj):
        return Node.objects.filter(pk__in=cls._get_nodepks_where_isadmin(user_obj))

    @classmethod
    def _get_pathlist_kw(cls, pathlist):
        """ Used by get_by_pathlist() to create the required kwargs for
        Node.objects.get(). Might be a starting point for more sophisticated
        queries including paths. """
        kw = {}
        key = 'short_name'
        for short_name in reversed(pathlist):
            kw[key] = short_name
            key = 'parentnode__' + key
        return kw

    @classmethod
    def get_by_pathlist(cls, pathlist):
        """ Get node by path just like get_by_path(), the parameter
        is a list of node-names instead of a single string. Example:
        
            >>> uio = Node(short_name='uio', long_name='UiO')
            >>> uio.save()
            >>> ifi = Node(short_name='ifi', long_name='Ifi', parentnode=uio)
            >>> ifi.save()
            >>> ifi
            <Node: uio.ifi>
            >>> Node.get_by_pathlist(['uio', 'ifi'])
            <Node: uio.ifi>
        """
        return Node.objects.get(**cls._get_pathlist_kw(pathlist))

    @classmethod
    def get_by_path(cls, path):
        """ Get a node by path. Just like `get_by_pathlist`, but the path is a
        string where the node-names are separated with '.'. """
        return cls.get_by_pathlist(path.split('.'))


    @classmethod
    def create_by_pathlist(cls, pathlist):
        """ Create a new node from the path given in `nodelist`, creating all
        missing parents. """
        parent = None
        n = None
        for i, short_name in enumerate(pathlist):
            try:
                n = Node.get_by_pathlist(pathlist[:i+1])
            except Node.DoesNotExist, e:
                n = Node(short_name=short_name, long_name=short_name, parentnode=parent)
                n.save()
            parent = n
        return n

    @classmethod
    def create_by_path(cls, path):
        """ Just like `get_by_pathlist`, but the path is a string where each `short_name`
        is separated by '.', instead of a list. """
        return cls.get_by_pathlist(path.split('.'))


class Subject(BaseNode):
    parentnode = models.ForeignKey(Node)
    admins = models.ManyToManyField(User, blank=True)

    @classmethod
    def where_is_admin(cls, user_obj):
        return Subject.objects.filter(
                Q(admins__pk=user_obj.pk)
                | Q(parentnode__pk__in=Node._get_nodepks_where_isadmin(user_obj))).distinct()

    def __unicode__(self):
        return self.short_name



class Period(BaseNode):
    parentnode = models.ForeignKey(Subject)
    start_time = models.DateTimeField()
    end_time = models.DateTimeField()
    admins = models.ManyToManyField(User, blank=True)


    @classmethod
    def where_is_admin(cls, user_obj):
        return Period.objects.filter(
                Q(admins=user_obj) |
                Q(parentnode__admins=user_obj) |
                Q(parentnode__parentnode__pk__in=Node._get_nodepks_where_isadmin(user_obj))
        ).distinct()

    def __unicode__(self):
        return unicode(self.parentnode) + " - " + self.short_name


class Assignment(BaseNode):
    parentnode = models.ForeignKey(Period)
    deadline = models.DateTimeField()
    publishing_time = models.DateTimeField()
    admins = models.ManyToManyField(User, blank=True)

    @classmethod
    def where_is_admin(cls, user_obj):
        return Assignment.objects.filter(
                Q(admins=user_obj) |
                Q(parentnode__admins=user_obj) |
                Q(parentnode__parentnode__admins=user_obj) |
                Q(parentnode__parentnode__parentnode__pk__in=Node._get_nodepks_where_isadmin(user_obj))
        ).distinct()

    def __unicode__(self):
        return unicode(self.parentnode) + " - " + self.short_name

    @classmethod
    def where_is_examiner(cls, user_obj):
        return Assignment.objects.filter(
            assignmentgroup_set__examiners=user_obj
            ).distinct()

    def assignment_groups_where_is_examiner(self, user_obj):
        return self.assignmentgroup_set.filter(examiners=user_obj)
 


class AssignmentGroup(models.Model):
    parentnode = models.ForeignKey(Assignment)
    students = models.ManyToManyField(User, blank=True, related_name="students")
    examiners = models.ManyToManyField(User, blank=True, related_name="examiners")
    is_open = models.BooleanField(blank=True, default=True,
            help_text = _('If this is checked, the group can add deliveries.'))


    @classmethod
    def where_is_admin(cls, user_obj):
        return AssignmentGroup.objects.filter(
                Q(parentnode__admins=user_obj) |
                Q(parentnode__parentnode__admins=user_obj) |
                Q(parentnode__parentnode__parentnode__admins=user_obj) |
                Q(parentnode__parentnode__parentnode__parentnode__pk__in=Node._get_nodepks_where_isadmin(user_obj))
        ).distinct()

    @classmethod
    def where_is_student(cls, user_obj):
{'fraction_non_alphanumeric': 0.09789987944927352, 'fraction_numerical': 0.001015164012435759, 'mean_word_length': 2.51438127090301, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 43, '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': '3181379', 'n_tokens_mistral': 4831, 'n_tokens_neox': 4644, 'n_words': 1072}