<commit_before># This file is part of OpenHatch.
# Copyright (C) 2010, 2011 <NAME>
# Copyright (C) 2009, 2010 OpenHatch, Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

import datetime
import reversion

from django.db import models
from django.core.urlresolvers import reverse
from django.utils.encoding import smart_str
from model_utils.managers import InheritanceManager

class RecentMessageFromCIA(models.Model):
    '''This model logs all messages from CIA.vc.
    At some point, we should examine how and when we want to flush this.'''
    # See http://cia.vc/stats/project/moin/.xml
    committer_identifier = models.CharField(max_length=255) # author, to cia.vc
    project_name = models.CharField(max_length=255) # project, to cia.vc
    path = models.CharField(max_length=255) # files, to cia.vc
    version = models.CharField(max_length=255) # version, to cia.vc
    message = models.CharField(max_length=255) # log, to cia.vc
    module = models.CharField(max_length=255) # module, to cia.vc
    branch = models.CharField(max_length=255) # branch, to cia.vc
    time_received = models.DateTimeField(auto_now_add=True)

class WebResponse(models.Model):
    '''This model abuses the databases as a network log. We store here
    successful and unsuccessful web requests so that we can refer to
    them later.'''
    # FIXME: It'd be nice to get the request's headers, not just the
    # server's response (despite the name of this class).
    text = models.TextField()
    url = models.TextField()
    status = models.IntegerField()
    response_headers = models.TextField() # a long multi-line string

    @staticmethod
    def create_from_browser(b):
        ret = WebResponse()

        # Seek to 0, just in case someone else tried to read before us
        b.response().seek(0)
        ret.text = b.response().read()

        ret.url = b.geturl()

        ret.status = 200 # Presumably it worked.

        # Use ''.join() on the response headers so we get a big ol' string
        ret.response_headers = ''.join(b.response()._headers.headers)

        return ret

    @staticmethod
    def create_from_http_error(error):
        return None

class TrackerModel(models.Model):
    '''This is the base Model that tracker types subclass.'''
    max_connections = models.IntegerField(blank=True, default=8,
            help_text="This is the maximum number of simultaneous connections that our bug importer will make to the tracker server.")
    created_for_project = models.ForeignKey(
        'search.Project', null=True,
        help_text='The project (if any) whose edit page caused the creation of this bug tracker model')
    objects = InheritanceManager()

    def get_edit_url(self):
        '''This method returns the URL you can use to access this tracker's edit
        link.

        It is part of this superclass so that derived classes can use the
        functionality without implementing it themselves. It relies on
        the classes being manually added to
        mysite.customs.bugimporters.all_trackers.'''
        import mysite.customs.bugimporters
        my_short_name = None

        for short_name in mysite.customs.bugimporters.all_trackers:
            klass = mysite.customs.bugimporters.all_trackers[short_name]['model']
            if self.__class__ == klass:
                my_short_name = short_name
                break

        # Did we find a short name suitable for use in a URL? If not, let's
        # just crash.
        if my_short_name is None:
            raise ValueError, ("The tracker class seems to be misconfigured. "
                               "Read the comments around this message.")

        return reverse('mysite.customs.views.edit_tracker', kwargs={
                'tracker_type': my_short_name,
                'tracker_name': self.tracker_name})


    def get_base_url(self):
        # Implement this in a subclass
        raise NotImplementedError

class TrackerQueryModel(models.Model):
    '''This model just exists to provide a way to grab a QuerySet
    containing all tracker queries.'''
    last_polled = models.DateTimeField(default=datetime.datetime(1970, 1, 1))
    objects = InheritanceManager()

    def get_query_url(self):
        # Implement this in a subclass
        raise NotImplementedError

class BugzillaTrackerModel(TrackerModel):
    '''This model stores the data for individual Bugzilla trackers.'''
    tracker_name = models.CharField(max_length=200, unique=True,
                                    blank=False, null=False)
    base_url = models.URLField(max_length=200, unique=True,
                               blank=False, null=False, verify_exists=False,
            help_text="This is the URL to the homepage of the Bugzilla tracker instance. Remove any homepage filenames such as 'index.cgi' from this.")
    bug_project_name_format = models.CharField(max_length=200, blank=False,
            help_text="Any string here will be used verbatim as the project name for each bug aside from the keys '{tracker_name}', '{component}' and '{product}', which are replaced with the tracker's name from above and the relevant data from each individual bug respectively.")
    QUERY_URL_TYPES = (
            ('xml', 'Bug XML query'),
            ('tracker', 'Tracker bug URL'),
            )
    query_url_type = models.CharField(max_length=20, choices=QUERY_URL_TYPES, blank=False, default='xml',
            help_text="This field is deprecated, and will be removed once all Bugzilla trackers are in the asynchronous framework.")
    BITESIZED_TYPES = (
            ('key', 'Keyword'),
            ('wboard', 'Whiteboard tag'),
            )
    bitesized_type = models.CharField(max_length=10, choices=BITESIZED_TYPES, blank=True)
    bitesized_text = models.CharField(max_length=200, blank=True, default='',
            help_text="This is the text that the field type selected above will contain that indicates a bite-sized bug. Separate multiple values with single commas (,) only.")
    DOCUMENTATION_TYPES = (
            ('key', 'Keyword'),
            ('comp', 'Component'),
            ('prod', 'Product'),
            )
    documentation_type = models.CharField(max_length=10, choices=DOCUMENTATION_TYPES, blank=True)
    documentation_text = models.CharField(max_length=200, blank=True, default='',
            help_text="This is the text that the field type selected above will contain that indicates a documentation bug. Separate multiple values with single commas (,) only.")
    as_appears_in_distribution = models.CharField(max_length=200, blank=True, default='')

    all_trackers = models.Manager()

    def __str__(self):
        return smart_str('%s' % (self.tracker_name))

    def get_base_url(self):
        return self.base_url

    def create_class_that_can_actually_crawl_bugs(self):
        # FIXME: This is totally busted.
        # If you run the tests, you'll see that the project_name isn't somehow
        # flowing through, and I don't know why. :-(
        import mysite.customs.bugtrackers.bugzilla
        factory = mysite.customs.bugtrackers.bugzilla.bugzilla_tracker_factory(self)
        instance = factory()
        return instance

class BugzillaQueryModel(TrackerQueryModel):
    '''This model stores query or tracker URLs for BugzillaTracker objects.'''
    url = models.URLField(max_length=400,
                          blank=False, null=False)
    QUERY_TYPES = (
            ('xml', 'Bug XML query'),
            ('tracker', 'Tracker bug URL'),
            )
    query_type = models.CharField(max_length=20, choices=QUERY_TYPES, blank=False, default='xml',
            help_text="We support two types of bug importing from Bugzilla - search queries that return an XML dump of all the bugs, and tracking bugs that depend on all the bugs to be imported here.")
    description = models.CharField(max_length=200, blank=True, default='')
    tracker = models.ForeignKey(BugzillaTrackerModel)

    def get_query_url(self):
        return self.url

reversion.register(BugzillaTrackerModel, follow=["bugzillaquerymodel_set"])
reversion.register(BugzillaQueryModel)
<commit_msg>Remove unused method in Bugzilla model<commit_after># This file is part of OpenHatch.
# Copyright (C) 2010, 2011 <NAME>
# Copyright (C) 2009, 2010 OpenHatch, Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

import datetime
import reversion

from django.db import models
from django.core.urlresolvers import reverse
from django.utils.encoding import smart_str
from model_utils.managers import InheritanceManager

class RecentMessageFromCIA(models.Model):
    '''This model logs all messages from CIA.vc.
    At some point, we should examine how and when we want to flush this.'''
    # See http://cia.vc/stats/project/moin/.xml
    committer_identifier = models.CharField(max_length=255) # author, to cia.vc
    project_name = models.CharField(max_length=255) # project, to cia.vc
    path = models.CharField(max_length=255) # files, to cia.vc
    version = models.CharField(max_length=255) # version, to cia.vc
    message = models.CharField(max_length=255) # log, to cia.vc
    module = models.CharField(max_length=255) # module, to cia.vc
    branch = models.CharField(max_length=255) # branch, to cia.vc
    time_received = models.DateTimeField(auto_now_add=True)

class WebResponse(models.Model):
    '''This model abuses the databases as a network log. We store here
    successful and unsuccessful web requests so that we can refer to
    them later.'''
    # FIXME: It'd be nice to get the request's headers, not just the
    # server's response (despite the name of this class).
    text = models.TextField()
    url = models.TextField()
    status = models.IntegerField()
    response_headers = models.TextField() # a long multi-line string

    @staticmethod
    def create_from_browser(b):
        ret = WebResponse()

        # Seek to 0, just in case someone else tried to read before us
        b.response().seek(0)
        ret.text = b.response().read()

        ret.url = b.geturl()

        ret.status = 200 # Presumably it worked.

        # Use ''.join() on the response headers so we get a big ol' string
        ret.response_headers = ''.join(b.response()._headers.headers)

        return ret

    @staticmethod
    def create_from_http_error(error):
        return None

class TrackerModel(models.Model):
    '''This is the base Model that tracker types subclass.'''
    max_connections = models.IntegerField(blank=True, default=8,
            help_text="This is the maximum number of simultaneous connections that our bug importer will make to the tracker server.")
    created_for_project = models.ForeignKey(
        'search.Project', null=True,
        help_text='The project (if any) whose edit page caused the creation of this bug tracker model')
    objects = InheritanceManager()

    def get_edit_url(self):
        '''This method returns the URL you can use to access this tracker's edit
        link.

        It is part of this superclass so that derived classes can use the
        functionality without implementing it themselves. It relies on
        the classes being manually added to
        mysite.customs.bugimporters.all_trackers.'''
        import mysite.customs.bugimporters
        my_short_name = None

        for short_name in mysite.customs.bugimporters.all_trackers:
            klass = mysite.customs.bugimporters.all_trackers[short_name]['model']
            if self.__class__ == klass:
                my_short_name = short_name
                break

        # Did we find a short name suitable for use in a URL? If not, let's
        # just crash.
        if my_short_name is None:
            raise ValueError, ("The tracker class seems to be misconfigured. "
                               "Read the comments around this message.")

        return reverse('mysite.customs.views.edit_tracker', kwargs={
                'tracker_type': my_short_name,
                'tracker_name': self.tracker_name})


    def get_base_url(self):
        # Implement this in a subclass
        raise NotImplementedError

class TrackerQueryModel(models.Model):
    '''This model just exists to provide a way to grab a QuerySet
    containing all tracker queries.'''
    last_polled = models.DateTimeField(default=datetime.datetime(1970, 1, 1))
    objects = InheritanceManager()

    def get_query_url(self):
        # Implement this in a subclass
        raise NotImplementedError

class BugzillaTrackerModel(TrackerModel):
    '''This model stores the data for individual Bugzilla trackers.'''
    tracker_name = models.CharField(max_length=200, unique=True,
                                    blank=False, null=False)
    base_url = models.URLField(max_length=200, unique=True,
                               blank=False, null=False, verify_exists=False,
            help_text="This is the URL to the homepage of the Bugzilla tracker instance. Remove any homepage filenames such as 'index.cgi' from this.")
    bug_project_name_format = models.CharField(max_length=200, blank=False,
            help_text="Any string here will be used verbatim as the project name for each bug aside from the keys '{tracker_name}', '{component}' and '{product}', which are replaced with the tracker's name from above and the relevant data from each individual bug respectively.")
    QUERY_URL_TYPES = (
            ('xml', 'Bug XML query'),
            ('tracker', 'Tracker bug URL'),
            )
    query_url_type = models.CharField(max_length=20, choices=QUERY_URL_TYPES, blank=False, default='xml',
            help_text="This field is deprecated, and will be removed once all Bugzilla trackers are in the asynchronous framework.")
    BITESIZED_TYPES = (
            ('key', 'Keyword'),
            ('wboard', 'Whiteboard tag'),
            )
    bitesized_type = models.CharField(max_length=10, choices=BITESIZED_TYPES, blank=True)
    bitesized_text = models.CharField(max_length=200, blank=True, default='',
            help_text="This is the text that the field type selected above will contain that indicates a bite-sized bug. Separate multiple values with single commas (,) only.")
    DOCUMENTATION_TYPES = (
            ('key', 'Keyword'),
            ('comp', 'Component'),
            ('prod', 'Product'),
            )
    documentation_type = models.CharField(max_length=10, choices=DOCUMENTATION_TYPES, blank=True)
    documentation_text = models.CharField(max_length=200, blank=True, default='',
            help_text="This is the text that the field type selected above will contain that indicates a documentation bug. Separate multiple values with single commas (,) only.")
    as_appears_in_distribution = models.CharField(max_length=200, blank=True, default='')

    all_trackers = models.Manager()

    def __str__(self):
        return smart_str('%s' % (self.tracker_name))

    def get_base_url(self):
        return self.base_url

class BugzillaQueryModel(TrackerQueryModel):
    '''This model stores query or tracker URLs for BugzillaTracker objects.'''
    url = models.URLField(max_length=400,
                          blank=False, null=False)
    QUERY_TYPES = (
            ('xml', 'Bug XML query'),
            ('tracker', 'Tracker bug URL'),
            )
    query_type = models.CharField(max_length=20, choices=QUERY_TYPES, blank=False, default='xml',
            help_text="We support two types of bug importing from Bugzilla - search queries that return an XML dump of all the bugs, and tracking bugs that depend on all the bugs to be imported here.")
    description = models.CharField(max_length=200, blank=True, default='')
    tracker = models.ForeignKey(BugzillaTrackerModel)

    def get_query_url(self):
        return self.url

reversion.register(BugzillaTrackerModel, follow=["bugzillaquerymodel_set"])
reversion.register(BugzillaQueryModel)

{'fraction_non_alphanumeric': 0.0858967598289096, 'fraction_numerical': 0.009609187320560146, 'mean_word_length': 3.141713176413492, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 10}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '323170', 'n_tokens_mistral': 4900, 'n_tokens_neox': 4625, 'n_words': 1627}