django-triager-bot / djangotriager / trac /

Full commit
from djangotriager.trac.server import get_proxy
from djangotriager.trac.patches import Patch
from djangotriager.wc.subversion import Subversion
from djangotriager.tests import TestRunner
from djangotriager.reporter import Reporter

class Ticket(object):
    Class representing a SCM ticket.
    def __init__(self, ticket_id):
        self._ticket_id = int(ticket_id)
        self.__patches = []
        self._reporter = Reporter("Ticket #%d" % self._ticket_id)

    def get_report(self):
        """Print the report generated so far.

        You can use this to retrieve the report instead of sending to the
        ticket's page at the SCM instance.
        return self._reporter.get_buffer()

    def get_by_query(cls, config, query):
        Retrieve all tickets that matches the query string given.
        proxy = get_proxy(config.get("trac"))
        return [cls(ticket_id) for ticket_id in proxy.ticket.query(query)]

    def get_patches(self, config):
        Return all patches available for the ticket.
        if not self.__patches:
            proxy = get_proxy(config.get("trac"))
            attachments = proxy.ticket.listAttachments(self._ticket_id)
            self.__patches = [Patch(config, self._ticket_id, file[0]) 
                                  for file in attachments 
                                      if Patch.validate(file[0])]
            self._reporter.warn("Patches retrieved: %r" % self.__patches)
        return self.__patches

    def try_patch(self, config, patch):
        """Check if the given patch is valid.

        The patch is applied in the working copy and validate through the test
        suite, after this the changes in the working copy is reverted.
        working_copy = Subversion(dir=config.get("working_copy"))
        self._reporter.warn("Cleaning working copy")
        self._reporter.warn("Trying patch %r" % patch)
        self._reporter.warn("Applying patch")
        is_valid = False
        if not patch.apply(working_copy.dir, logger=self._reporter):
            self._reporter.warn("Patch %r could not be applied..." % patch)
            self._reporter.warn("Running tests")
            is_valid = TestRunner(working_copy).run(logger=self._reporter)
        self._reporter.warn("Restoring working copy")
        return is_valid

    def try_patches(self, config, limit=None):
        patches = self.get_patches(config)
        if not patches:
            self._reporter.warn("No patch to process")
            for idx, patch in enumerate(reversed(patches)):
                self.try_patch(config, patch)
                if limit and idx == limit - 1:
                    self._reporter.warn("Limit of patches (%d) reached, "
                                        "finishing" % limit)