<commit_before>
import datetime, pprint
import cPickle as pickle

import feedparser

from django.db import models
from django.template.defaultfilters import slugify

from basecampreporting.project import Project as BasecampProject


class InvalidBasecampUrl(Exception):
    pass

class MissingCredentials(Exception):
    pass

class RSSFeed(models.Model):
    """Represents an RSS feed."""
    url = models.URLField(verify_exists=True, unique=True, max_length=255)
    name = models.CharField(max_length=255)
    feed_info = models.TextField(blank=True, editable=False)
    feed_contents = models.TextField(blank=True, editable=False)
    parsed_at = models.DateTimeField(editable=False, null=True) 
    update_error = models.TextField(blank=True)

    feedparser = feedparser

    class Meta:
        verbose_name = "RSS Feed"


    def update_feed(self, save=True):
        parsed = self.feedparser.parse(self.url)
        self.feed_contents = pickle.dumps(parsed['entries'])

        info = {}
        for key, value in parsed.items():
            if key != 'entries':
                info[key] = value
        self.feed_info = pickle.dumps(info)
        self.parsed_at = datetime.datetime.now()
        if save:
            self.save()

    @property
    def contents(self):
        if not self.feed_contents:
            return {}
        return pickle.loads(str(self.feed_contents))

    @property
    def info(self):
        if not self.feed_contents:
            return {} 
        return pickle.loads(str(self.feed_info))

    def __unicode__(self):
        return self.name

    def save(self, force_insert=False, force_update=False):
        if self.info and self.contents:
            pass #We've been parsed at least once
        else:
            self.update_feed(save=False)

        if not self.name:
            self.name = self.info['feed']['title']
        super(RSSFeed, self).save(force_insert, force_update)

class Project(models.Model):
    """Represents a Basecamp-backed project"""
    slug = models.SlugField(unique=True, blank=True, help_text="This will be prefilled from the project's name if left blank.")
    basecamp_url = models.URLField(verify_exists=False, unique=True, help_text="Example: https://ajcprojects.updatelog.com/projects/2404439/project/log")
    basecamp_id = models.IntegerField(unique=True, blank=True)
    name = models.CharField(max_length=255, blank=True, help_text="This will be prefilled from the project if left blank.")
    created_at = models.DateTimeField(editable=False)
    updated_at = models.DateTimeField(editable=False)
     

    basecamp_updated_at = models.DateTimeField(editable=False, null=True)
    description = models.TextField(blank=True, help_text="A brief summary of the project and it's goals.")
    summary_data = models.TextField(blank=True, editable=False)
    readable_summary = models.TextField(blank=True)
    update_error = models.TextField(blank=True)

    feeds = models.ManyToManyField(RSSFeed, related_name="projects")

    BasecampProject = BasecampProject

    class Meta:
        ordering = ['name']<commit_msg>Allowing projects to _not_ have RSS feeds. Thanks to Maura for the bug report and patch<commit_after>
import datetime, pprint
import cPickle as pickle

import feedparser

from django.db import models
from django.template.defaultfilters import slugify

from basecampreporting.project import Project as BasecampProject


class InvalidBasecampUrl(Exception):
    pass

class MissingCredentials(Exception):
    pass

class RSSFeed(models.Model):
    """Represents an RSS feed."""
    url = models.URLField(verify_exists=True, unique=True, max_length=255)
    name = models.CharField(max_length=255)
    feed_info = models.TextField(blank=True, editable=False)
    feed_contents = models.TextField(blank=True, editable=False)
    parsed_at = models.DateTimeField(editable=False, null=True) 
    update_error = models.TextField(blank=True)

    feedparser = feedparser

    class Meta:
        verbose_name = "RSS Feed"


    def update_feed(self, save=True):
        parsed = self.feedparser.parse(self.url)
        self.feed_contents = pickle.dumps(parsed['entries'])

        info = {}
        for key, value in parsed.items():
            if key != 'entries':
                info[key] = value
        self.feed_info = pickle.dumps(info)
        self.parsed_at = datetime.datetime.now()
        if save:
            self.save()

    @property
    def contents(self):
        if not self.feed_contents:
            return {}
        return pickle.loads(str(self.feed_contents))

    @property
    def info(self):
        if not self.feed_contents:
            return {} 
        return pickle.loads(str(self.feed_info))

    def __unicode__(self):
        return self.name

    def save(self, force_insert=False, force_update=False):
        if self.info and self.contents:
            pass #We've been parsed at least once
        else:
            self.update_feed(save=False)

        if not self.name:
            self.name = self.info['feed']['title']
        super(RSSFeed, self).save(force_insert, force_update)

class Project(models.Model):
    """Represents a Basecamp-backed project"""
    slug = models.SlugField(unique=True, blank=True, help_text="This will be prefilled from the project's name if left blank.")
    basecamp_url = models.URLField(verify_exists=False, unique=True, help_text="Example: https://ajcprojects.updatelog.com/projects/2404439/project/log")
    basecamp_id = models.IntegerField(unique=True, blank=True)
    name = models.CharField(max_length=255, blank=True, help_text="This will be prefilled from the project if left blank.")
    created_at = models.DateTimeField(editable=False)
    updated_at = models.DateTimeField(editable=False)
     

    basecamp_updated_at = models.DateTimeField(editable=False, null=True)
    description = models.TextField(blank=True, help_text="A brief summary of the project and it's goals.")
    summary_data = models.TextField(blank=True, editable=False)
    readable_summary = models.TextField(blank=True)
    update_error = models.TextField(blank=True)

    feeds = models.ManyToManyField(RSSFeed, related_name="projects", blank=True)

    BasecampProject = BasecampProject

    class Meta:
        ordering = ['name']
{'fraction_non_alphanumeric': 0.1003498727735369, 'fraction_numerical': 0.005089058524173028, 'mean_word_length': 3.385634588563459, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 2, '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': '4857561', 'n_tokens_mistral': 1891, 'n_tokens_neox': 1818, 'n_words': 429}