<commit_before># Copyright (c) 2010, <NAME> <<EMAIL>>
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

import datetime
import os
from django.core.urlresolvers import reverse
from django.db import models
from django.contrib.auth.models import User
from lib import feedparser, dateutil
from settings import SCREENSHOT_URL
from util import time_ago

# an event is currently either a blog post or a commit
class Event(models.Model):
  # title of the event
  title = models.CharField("Title", max_length = 128)
  
  # when the event occured
  date = models.DateTimeField()
  
  # the description is the main content for the event
  description = models.TextField()
  
  # the author of the event, if he/she is in dashboard
  author = models.ForeignKey(User, blank = True, null = True)

  # the author's name, if he/she isn't in dashboard
  author_name = models.CharField(max_length = 64, blank = True, null = True)
  
  # whether or not the description should be autoescaped
  def autoescape(self):
    return True
  
  # the tags that should wrap the description when displayed
  def wrap_tags(self):
    return None
  
  # the name of the event type, by default this is just the class name
  def type_name(self):
    return self.__class__.__name__
  
  # how old the event is (relative to now by default)
  def age(self, time = datetime.datetime.now()):
    return time_ago(self.date, time)
  
  # a link to more details on the event
  def link(self):
    return None

# a set of events (a blog or repository)
class EventSet(models.Model):
  # most recent time to add new events for
  most_recent_date = models.DateTimeField(default = datetime.datetime(1, 1, 1))
  
  # how recent was the last update?
  def age_ago(self, time = datetime.datetime.now()):
    return time_ago(self.most_recent_date, time)
  
  # when was this eventset last updated?
  def when_updated(self):
    if self.most_recent_date != datetime.datetime(1, 1, 1):
      return "{0} updated {1}".format(self.__class__.__name__, self.age_ago())
    else:
      return "{0} never updated".format(self.__class__.__name__,
                                        self.age_ago())
  
  class Meta:
    abstract = True

# a blog for a project
class Blog(EventSet):
  # link to the blog, if it isn't hosted on dashboard
  url = models.URLField("Blog Web Address", max_length = 64)
  rss = models.URLField("Blog Feed", max_length = 64)
  
  # external (from an rss feed)? or hosted by dashboard?
  external = models.BooleanField()
  
  # how recent was the last post?
  def age_ago(self, time = datetime.datetime.now()):
    return time_ago(self.most_recent_date, time)
  
  # fetches the posts from the rss feed
  def fetch(self):
    # don't fetch internally hosted blogs
    if not self.external: return
    
    # make sure we can add blogposts to the blog
    self.save()
    
    # parse and iterate the feed
    max_date = self.most_recent_date
    for post in feedparser.parse(self.rss).entries:
      # time manipation is fun
      date = dateutil.parser.parse(post.date)
      date = (date - date.utcoffset()).replace(tzinfo=None)
      
      # find the new most recently updated date
      if max_date < date:
        max_date = date
      
      # don't re-add old posts
      if self.most_recent_date >= date:
        continue
      
      # can we find an author for this blog post?
      author_name = post.author_detail['name']
      try:
        author_firstlast = author_name.split(' ')
        authors = User.objects.filter(first_name = author_firstlast[0],
                                      last_name = author_firstlast[1])
        if len(authors) is 1:
          author = authors[0]
        else:
          author = None
      except:
        author = None
      
      post = BlogPost(author_name = author_name,
                      title = post.title,
                      description = post.description,
                      summary = post.description,
                      date = date,
                      external = True)
      post.blog = self
      if author is not None:
        post.author = author
      post.save()
      
      # print out results
      print "Post by {0} in {1} at {2}".format(author_name,
                                               self.project.title,
                                               date)
    self.most_recent_date = max_date
    self.save()
  
# a post in a blog
class BlogPost(Event):<commit_msg>Fix problem if there is no author name in RSS<commit_after># Copyright (c) 2010, <NAME> <<EMAIL>>
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

import datetime
import os
from django.core.urlresolvers import reverse
from django.db import models
from django.contrib.auth.models import User
from lib import feedparser, dateutil
from settings import SCREENSHOT_URL
from util import time_ago

# an event is currently either a blog post or a commit
class Event(models.Model):
  # title of the event
  title = models.CharField("Title", max_length = 128)
  
  # when the event occured
  date = models.DateTimeField()
  
  # the description is the main content for the event
  description = models.TextField()
  
  # the author of the event, if he/she is in dashboard
  author = models.ForeignKey(User, blank = True, null = True)

  # the author's name, if he/she isn't in dashboard
  author_name = models.CharField(max_length = 64, blank = True, null = True)
  
  # whether or not the description should be autoescaped
  def autoescape(self):
    return True
  
  # the tags that should wrap the description when displayed
  def wrap_tags(self):
    return None
  
  # the name of the event type, by default this is just the class name
  def type_name(self):
    return self.__class__.__name__
  
  # how old the event is (relative to now by default)
  def age(self, time = datetime.datetime.now()):
    return time_ago(self.date, time)
  
  # a link to more details on the event
  def link(self):
    return None

# a set of events (a blog or repository)
class EventSet(models.Model):
  # most recent time to add new events for
  most_recent_date = models.DateTimeField(default = datetime.datetime(1, 1, 1))
  
  # how recent was the last update?
  def age_ago(self, time = datetime.datetime.now()):
    return time_ago(self.most_recent_date, time)
  
  # when was this eventset last updated?
  def when_updated(self):
    if self.most_recent_date != datetime.datetime(1, 1, 1):
      return "{0} updated {1}".format(self.__class__.__name__, self.age_ago())
    else:
      return "{0} never updated".format(self.__class__.__name__,
                                        self.age_ago())
  
  class Meta:
    abstract = True

# a blog for a project
class Blog(EventSet):
  # link to the blog, if it isn't hosted on dashboard
  url = models.URLField("Blog Web Address", max_length = 64)
  rss = models.URLField("Blog Feed", max_length = 64)
  
  # external (from an rss feed)? or hosted by dashboard?
  external = models.BooleanField()
  
  # how recent was the last post?
  def age_ago(self, time = datetime.datetime.now()):
    return time_ago(self.most_recent_date, time)
  
  # fetches the posts from the rss feed
  def fetch(self):
    # don't fetch internally hosted blogs
    if not self.external: return
    
    # make sure we can add blogposts to the blog
    self.save()
    
    # parse and iterate the feed
    max_date = self.most_recent_date
    for post in feedparser.parse(self.rss).entries:
      # time manipation is fun
      date = dateutil.parser.parse(post.date)
      date = (date - date.utcoffset()).replace(tzinfo=None)
      
      # find the new most recently updated date
      if max_date < date:
        max_date = date
      
      # don't re-add old posts
      if self.most_recent_date >= date:
        continue
      
      # can we find an author for this blog post?
      try:
        author_name = post.author_details['name']
        author_firstlast = author_name.split(' ')
        authors = User.objects.filter(first_name = author_firstlast[0],
                                      last_name = author_firstlast[1])
        if len(authors) is 1:
          author = authors[0]
        else:
          author = None
      except:
        author_name = None
        author = None
      
      post = BlogPost(author_name = author_name,
                      title = post.title,
                      description = post.description,
                      summary = post.description,
                      date = date,
                      external = True)
      post.blog = self
      if author is not None:
        post.author = author
      post.save()
      
      # print out results
      print "Post by {0} in {1} at {2}".format(author_name,
                                               self.project.title,
                                               date)
    self.most_recent_date = max_date
    self.save()
  
# a post in a blog
class BlogPost(Event):
{'fraction_non_alphanumeric': 0.0769455252918288, 'fraction_numerical': 0.005642023346303502, 'mean_word_length': 2.5562089242476653, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 12, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4017076', 'n_tokens_mistral': 2978, 'n_tokens_neox': 2836, 'n_words': 1106}