<commit_before>import logging
import os
from uuid import uuid4
import hashlib

from django.conf import settings
from django.contrib import admin
from django.core.files.storage import FileSystemStorage
from django.db import IntegrityError, connections, models
from django.db.utils import ConnectionDoesNotExist
from mptt.models import MPTTModel, TreeForeignKey
from django.utils.translation import ugettext as _
from django.dispatch import receiver

from constants import content_kinds, extensions, presets

def hyphenless_uuid():
    return str(uuid4()).replace("-", "")

def file_on_disk_name(instance, filename):
    """
    Create a name spaced file path from the File obejct's checksum property.
    This path will be used to store the content copy

    :param instance: File (content File model)
    :param filename: str
    :return: str
    """
    h = instance.checksum
    basename, ext = os.path.splitext(filename)
    return os.path.join(settings.STORAGE_ROOT, h[0], h[1], h + ext.lower())

class FileOnDiskStorage(FileSystemStorage):
    """
    Overrider FileSystemStorage's default save method to ignore duplicated file.
    """
    def get_available_name(self, name):
        return name

    def _save(self, name, content):
        if self.exists(name):
            # if the file exists, do not call the superclasses _save method
            logging.warn('Content copy "%s" already exists!' % name)
            return name
        return super(ContentCopyStorage, self)._save(name, content)

class Channel(models.Model):
    """ Permissions come from association with organizations """
    channel_id = models.UUIDField(primary_key=True, default=hyphenless_uuid)
    name = models.CharField(max_length=200)
    description = models.CharField(max_length=400, blank=True)
    author = models.CharField(max_length=400, blank=True)
    version = models.CharField(max_length=15, default='v0.01')
    thumbnail = models.TextField(blank=True)
    editors = models.ManyToManyField(
        'auth.User',
        related_name='editable_channels',
        verbose_name=_("editors"),
        help_text=_("Users with edit rights"),
    )
    published = models.ForeignKey('TopicTree', null=True, blank=True, related_name='published')
    deleted =  models.ForeignKey('TopicTree', null=True, blank=True, related_name='deleted')
    clipboard =  models.ForeignKey('TopicTree', null=True, blank=True, related_name='clipboard')
    draft =  models.ForeignKey('TopicTree', null=True, blank=True, related_name='draft')
    bookmarked_by = models.ManyToManyField(
        'auth.User',
        related_name='bookmarked_channels',
        verbose_name=_("bookmarded by"),
    )

    def save(self, *args, **kwargs):
        super(Channel, self).save(*args, **kwargs)
        if not self.draft:
            self.draft = TopicTree.objects.create(channel=self, name=self.name + " draft")
            self.draft.save()
            self.clipboard = TopicTree.objects.create(channel=self, name=self.name + " clipboard")
            self.clipboard.save()
            self.deleted = TopicTree.objects.create(channel=self, name=self.name + " deleted")
            self.deleted.save()
            self.save()

    """
    def delete(self):
        logging.warning("Channel Delete")
        self.draft.delete()
        self.clipboard.delete()
        self.deleted.delete()
        super(Channel, self).delete()
    """
    class Meta:
        verbose_name = _("Channel")
        verbose_name_plural = _("Channels")

class TopicTree(models.Model):
    """Base model for all channels"""

    name = models.CharField(
        max_length=255,
        verbose_name=_("topic tree name"),
        help_text=_("Displayed to the user"),
        default = "tree"
    )

    channel = models.ForeignKey(
        'Channel',
        verbose_name=_("channel"),
        null=True,
        help_text=_("For different versions of the tree in the same channel (trash, edit, workspace)"),
    )
    root_node = models.ForeignKey(
        'ContentNode',
        verbose_name=_("root node"),
        null=True,
        help_text=_(
            "The starting point for the tree, the title of it is the "
            "title shown in the menu"
        ),
    )
    is_published = models.BooleanField(
        default=False,
        verbose_name=_("Published"),
        help_text=_("If published, students can access this channel"),
    )

    def save(self, *args, **kwargs):
        isNew = not self.pk
        super(TopicTree, self).save(*args, **kwargs)
        if isNew:
            self.root_node = ContentNode.objects.create(title=self.channel.name, kind=ContentKind.objects.get(kind = content_kinds.TOPIC), total_file_size = 0, license=License.objects.first())
            self.root_node.save()
            self.save()

    class Meta:
        verbose_name = _("Topic tree")
        verbose_name_plural = _("Topic trees")

class ContentTag(models.Model):
    tag_name = models.CharField(max_length=30)
    channel = models.ForeignKey('Channel', related_name='tags', blank=True, null=True)
    """
    def delete(self):
        # No other nodes except for node about to be deleted use tag
        if len(Node.objects.filter(tags__tag_name__contains = self.tag_name)) <= 1:
            super(ContentTag, self).delete()
    """

    def __str__(self):
        return self.tag_name

    class Meta:
        unique_together = ['tag_name', 'channel']

class ContentNode(MPTTModel, models.Model):
    """
    By default, all nodes have a title and can be used as a topic.
    """
    content_id = models.UUIDField(primary_key=False, default=hyphenless_uuid, editable=False)
    title = models.CharField(max_length=200)
    description = models.CharField(max_length=400, blank=True)
    kind = models.ForeignKey('ContentKind', related_name='content_metadatas', blank=True, null=True)
    slug = models.CharField(max_length=100)
    total_file_size = models.IntegerField()
    license = models.ForeignKey('License')
    prerequisite = models.ManyToManyField('self', related_name='is_prerequisite_of', through='PrerequisiteContentRelationship', symmetrical=False, blank=True)
    is_related = models.ManyToManyField('self', related_name='relate_to', through='RelatedContentRelationship', symmetrical=False, blank=True)
    parent = TreeForeignKey('self', null=True, blank=True, related_name='children', db_index=True)
    tags = models.ManyToManyField(ContentTag, symmetrical=False, related_name='tagged_content', blank=True)
    sort_order = models.FloatField(max_length=50, default=0, verbose_name=_("sort order"), help_text=_("Ascending, lowest number shown first"))
    license_owner = models.CharField(max_length=200, blank=True, help_text=_("Organization of person who holds the essential rights"))
    cloned_source = TreeForeignKey('self', null=True, blank=True, models.SET_NULL, related_name='clones')

    created = models.DateTimeField(auto_now_add=True, verbose_name=_("created"))
    modified = models.DateTimeField(auto_now=True, verbose_name=_("modified"))

    published = models.BooleanField(
        default=False,
        verbose_name=_("Published"),
        help_text=_("If published, students can access this item"),
    )

    @property
    def has_draft(self):
        return self.draft_set.all().exists()

    @property
    def get_draft(self):
        """
        NB! By contract, only one draft should always exist per node, this is
        enforced by the OneToOneField relation.
        :raises: Draft.DoesNotExist and Draft.MultipleObjectsReturned
        """
        return Draft.objects.get(publish_in=self)
    """
    # If deleting all children
    def delete(self):
        logging.warning(self)<commit_msg>add original_node field that points to the very original node we copied from; set to self when creating a new node; set foreign key cascade behaviour to SET_NULL<commit_after>import logging
import os
from uuid import uuid4
import hashlib

from django.conf import settings
from django.contrib import admin
from django.core.files.storage import FileSystemStorage
from django.db import IntegrityError, connections, models
from django.db.utils import ConnectionDoesNotExist
from mptt.models import MPTTModel, TreeForeignKey
from django.utils.translation import ugettext as _
from django.dispatch import receiver

from constants import content_kinds, extensions, presets

def hyphenless_uuid():
    return str(uuid4()).replace("-", "")

def file_on_disk_name(instance, filename):
    """
    Create a name spaced file path from the File obejct's checksum property.
    This path will be used to store the content copy

    :param instance: File (content File model)
    :param filename: str
    :return: str
    """
    h = instance.checksum
    basename, ext = os.path.splitext(filename)
    return os.path.join(settings.STORAGE_ROOT, h[0], h[1], h + ext.lower())

class FileOnDiskStorage(FileSystemStorage):
    """
    Overrider FileSystemStorage's default save method to ignore duplicated file.
    """
    def get_available_name(self, name):
        return name

    def _save(self, name, content):
        if self.exists(name):
            # if the file exists, do not call the superclasses _save method
            logging.warn('Content copy "%s" already exists!' % name)
            return name
        return super(ContentCopyStorage, self)._save(name, content)

class Channel(models.Model):
    """ Permissions come from association with organizations """
    channel_id = models.UUIDField(primary_key=True, default=hyphenless_uuid)
    name = models.CharField(max_length=200)
    description = models.CharField(max_length=400, blank=True)
    author = models.CharField(max_length=400, blank=True)
    version = models.CharField(max_length=15, default='v0.01')
    thumbnail = models.TextField(blank=True)
    editors = models.ManyToManyField(
        'auth.User',
        related_name='editable_channels',
        verbose_name=_("editors"),
        help_text=_("Users with edit rights"),
    )
    published = models.ForeignKey('TopicTree', null=True, blank=True, related_name='published')
    deleted =  models.ForeignKey('TopicTree', null=True, blank=True, related_name='deleted')
    clipboard =  models.ForeignKey('TopicTree', null=True, blank=True, related_name='clipboard')
    draft =  models.ForeignKey('TopicTree', null=True, blank=True, related_name='draft')
    bookmarked_by = models.ManyToManyField(
        'auth.User',
        related_name='bookmarked_channels',
        verbose_name=_("bookmarded by"),
    )

    def save(self, *args, **kwargs):
        super(Channel, self).save(*args, **kwargs)
        if not self.draft:
            self.draft = TopicTree.objects.create(channel=self, name=self.name + " draft")
            self.draft.save()
            self.clipboard = TopicTree.objects.create(channel=self, name=self.name + " clipboard")
            self.clipboard.save()
            self.deleted = TopicTree.objects.create(channel=self, name=self.name + " deleted")
            self.deleted.save()
            self.save()

    """
    def delete(self):
        logging.warning("Channel Delete")
        self.draft.delete()
        self.clipboard.delete()
        self.deleted.delete()
        super(Channel, self).delete()
    """
    class Meta:
        verbose_name = _("Channel")
        verbose_name_plural = _("Channels")

class TopicTree(models.Model):
    """Base model for all channels"""

    name = models.CharField(
        max_length=255,
        verbose_name=_("topic tree name"),
        help_text=_("Displayed to the user"),
        default = "tree"
    )

    channel = models.ForeignKey(
        'Channel',
        verbose_name=_("channel"),
        null=True,
        help_text=_("For different versions of the tree in the same channel (trash, edit, workspace)"),
    )
    root_node = models.ForeignKey(
        'ContentNode',
        verbose_name=_("root node"),
        null=True,
        help_text=_(
            "The starting point for the tree, the title of it is the "
            "title shown in the menu"
        ),
    )
    is_published = models.BooleanField(
        default=False,
        verbose_name=_("Published"),
        help_text=_("If published, students can access this channel"),
    )

    def save(self, *args, **kwargs):
        isNew = not self.pk
        super(TopicTree, self).save(*args, **kwargs)
        if isNew:
            self.root_node = ContentNode.objects.create(title=self.channel.name, kind=ContentKind.objects.get(kind = content_kinds.TOPIC), total_file_size = 0, license=License.objects.first())
            self.root_node.save()
            self.save()

    class Meta:
        verbose_name = _("Topic tree")
        verbose_name_plural = _("Topic trees")

class ContentTag(models.Model):
    tag_name = models.CharField(max_length=30)
    channel = models.ForeignKey('Channel', related_name='tags', blank=True, null=True)
    """
    def delete(self):
        # No other nodes except for node about to be deleted use tag
        if len(Node.objects.filter(tags__tag_name__contains = self.tag_name)) <= 1:
            super(ContentTag, self).delete()
    """

    def __str__(self):
        return self.tag_name

    class Meta:
        unique_together = ['tag_name', 'channel']

class ContentNode(MPTTModel, models.Model):
    """
    By default, all nodes have a title and can be used as a topic.
    """
    content_id = models.UUIDField(primary_key=False, default=hyphenless_uuid, editable=False)
    title = models.CharField(max_length=200)
    description = models.CharField(max_length=400, blank=True)
    kind = models.ForeignKey('ContentKind', related_name='content_metadatas', blank=True, null=True)
    slug = models.CharField(max_length=100)
    total_file_size = models.IntegerField()
    license = models.ForeignKey('License')
    prerequisite = models.ManyToManyField('self', related_name='is_prerequisite_of', through='PrerequisiteContentRelationship', symmetrical=False, blank=True)
    is_related = models.ManyToManyField('self', related_name='relate_to', through='RelatedContentRelationship', symmetrical=False, blank=True)
    parent = TreeForeignKey('self', null=True, blank=True, related_name='children', db_index=True)
    tags = models.ManyToManyField(ContentTag, symmetrical=False, related_name='tagged_content', blank=True)
    sort_order = models.FloatField(max_length=50, default=0, verbose_name=_("sort order"), help_text=_("Ascending, lowest number shown first"))
    license_owner = models.CharField(max_length=200, blank=True, help_text=_("Organization of person who holds the essential rights"))
    cloned_source = TreeForeignKey('self', null=True, blank=True, models.SET_NULL, related_name='clones')
    original_ndoe = TreeForeignKey('self', null=True, blank=True, models.SET_NULL, related_name='descendants')

    created = models.DateTimeField(auto_now_add=True, verbose_name=_("created"))
    modified = models.DateTimeField(auto_now=True, verbose_name=_("modified"))

    published = models.BooleanField(
        default=False,
        verbose_name=_("Published"),
        help_text=_("If published, students can access this item"),
    )

    @property
    def has_draft(self):
        return self.draft_set.all().exists()

    @property
    def get_draft(self):
        """
        NB! By contract, only one draft should always exist per node, this is
        enforced by the OneToOneField relation.
        :raises: Draft.DoesNotExist and Draft.MultipleObjectsReturned
        """
        return Draft.objects.get(publish_in=self)
    """
    # If deleting all children
    def delete(self):
        logging.warning(self)
{'fraction_non_alphanumeric': 0.1127723468149, 'fraction_numerical': 0.005111494473196601, 'mean_word_length': 3.472, 'pattern_counts': {'":': 0, '<': 5, '<?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': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1071228', 'n_tokens_mistral': 4599, 'n_tokens_neox': 4494, 'n_words': 1092}