Source

django-triager-bot / djangotriager / main.py

Full commit
"""Main "entry point" module for package"""
import os
import sys

from argparse import ArgumentParser

from djangotriager.config import Configuration
from djangotriager.trac.tickets import Ticket
from djangotriager.exceptions import InvalidOptions
from djangotriager.wc.subversion import Subversion

__all__ = ('main', )

def get_parser():
    """
    Construct command-line argument parser with all allowed options.
    """
    parser = ArgumentParser(description='Trac Triager')
    parser.add_argument("--config", type=unicode,
                        help=(u"Configuration file you'd like to use "
                               "(will overwrite options given through "
                              "CLI)"))
    parser.add_argument("--ticket", type=int,
                        help=u"Ticket number you want to operate on")
    parser.add_argument("--send_report", type=bool,
                        help=(u"If the processing result must be sent "
                              "to the ticket's page on Trac"))
    parser.add_argument("--query", type=unicode,
                        help=(u"Trac query string to use when searching "
                              "for tickets"))
    parser.add_argument("--n_patches", type=int,
                        help=(u"Limit the number of the patches to "
                              "check, most recent first."))
    parser.add_argument("--trac", type=unicode,
                        help=(u"URL of the trac instance to use for "
                              "retrieving tickets"))
    parser.add_argument("command", type=unicode, choices=ACTIONS_MAP,
                        help=(u"Operation to perform with the ticket(s) "
                              "retrieved"))
    parser.add_argument('--working_copy', type=unicode,
                        help=(u"The SVN working copy directory to "
                              "use when trying tickets"))
    return parser

def main(argv=None, config=None, do_exit=True):
    """
    Main entry point for console script
    """
    parser = get_parser()
    namespace = parser.parse_args(argv or sys.argv[1:])

    config = config or Configuration()
    config.command = namespace.command

    if namespace.config:
        if (os.path.exists(namespace.config) 
            and os.path.isfile(namespace.config)):
            config.read_config(namespace.config)
        else:
            parser.error("The configuration file specified "
                         "doesn't exists or isn't a file.")
    config.merge_with_cmd(namespace)
    try:
        code = ACTIONS_MAP[config.command](config=config)
    except InvalidOptions, error:
        parser.error(error.message)

    if do_exit:
        sys.exit(code or 0)
    else:
        return code

def _process_tickets(config, func):
    config.ensure_one("ticket", "query")
    config.ensure_all("working_copy")
    if config.get("ticket"):
        tickets = [Ticket(config.get("ticket")), ]
    else:
        tickets = Ticket.get_by_query(config, config.get("query"))

    patches_limit = config.get("n_patches")
    patches_limit = patches_limit and int(patches_limit) or None
    wc = Subversion(dir=config.get("working_copy"))
    wc.revert_changes()
    wc.update()

    for ticket in tickets:
        func(ticket, wc, patches_limit)
        if not config.get("send_report"):
            print ticket.get_report()
        else:
            ticket.send_report(config)

def try_ticket(config):
    func = lambda ticket, wc, limit: \
        ticket.try_patches(config, wc, limit=limit)
    _process_tickets(config, func)

def apply_ticket(config):
    func = lambda ticket, wc, limit: \
        ticket.apply_patches(config, wc, limit=limit)
    _process_tickets(config, func)

ACTIONS_MAP = {
    'try': try_ticket,
    'apply': apply_ticket,
}