Beispiel #1
0
    def validate_config(cls, service_config, target):
        if ('udd' in service_config and asbool(service_config.get('udd'))
                and 'email' not in service_config):
            die("[%s] has no 'bts.email' but UDD search was requested" %
                (target, ))

        if 'packages' not in service_config and 'email' not in service_config:
            die("[%s] has neither 'bts.email' or 'bts.packages'" % (target, ))

        if ('udd_ignore_sponsor' in service_config
                and (not asbool(service_config.get('udd')))):
            die("[%s] defines settings for UDD search without enabling"
                " UDD search" % (target, ))

        IssueService.validate_config(service_config, target)
Beispiel #2
0
    def __init__(self, main_config, main_section, target):
        self.config = ServiceConfig(self.CONFIG_PREFIX, main_config, target)
        self.main_section = main_section
        self.target = target

        self.desc_len = 35
        if main_config.has_option(self.main_section, 'description_length'):
            self.desc_len = main_config.getint(
                self.main_section, 'description_length')

        self.anno_len = 45
        if main_config.has_option(self.main_section, 'annotation_length'):
            self.anno_len = main_config.getint(
                self.main_section, 'annotation_length')

        self.inline_links = True
        if main_config.has_option(self.main_section, 'inline_links'):
            self.inline_links = asbool(main_config.get(
                self.main_section, 'inline_links'))

        self.annotation_links = not self.inline_links
        if main_config.has_option(self.main_section, 'annotation_links'):
            self.annotation_links = asbool(
                main_config.get(self.main_section, 'annotation_links')
            )

        self.annotation_comments = True
        if main_config.has_option(self.main_section, 'annotation_comments'):
            self.annotation_comments = asbool(
                main_config.get(self.main_section, 'annotation_comments')
            )

        self.shorten = False
        if main_config.has_option(self.main_section, 'shorten'):
            self.shorten = asbool(main_config.get(self.main_section, 'shorten'))

        self.add_tags = []
        if 'add_tags' in self.config:
            for raw_option in self.config.get('add_tags').split(','):
                option = raw_option.strip(' +;')
                if option:
                    self.add_tags.append(option)

        self.default_priority = 'M'
        if 'default_priority' in self.config:
            self.default_priority = self.config.get('default_priority')

        log.info("Working on [%s]", self.target)
Beispiel #3
0
    def validate_config(cls, service_config, target):
        if ('udd' in service_config and
                asbool(service_config.get('udd')) and
                'email' not in service_config):
            die("[%s] has no 'bts.email' but UDD search was requested" %
                (target,))

        if 'packages' not in service_config and 'email' not in service_config:
            die("[%s] has neither 'bts.email' or 'bts.packages'" % (target,))

        if ('udd_ignore_sponsor' in service_config and
            (not asbool(service_config.get('udd')))):
            die("[%s] defines settings for UDD search without enabling"
                " UDD search" % (target,))

        IssueService.validate_config(service_config, target)
Beispiel #4
0
    def __init__(self, *args, **kw):
        super(BugzillaService, self).__init__(*args, **kw)
        self.base_uri = self.config_get('base_uri')
        self.username = self.config_get('username')
        self.password = self.config_get('password')
        self.ignore_cc = self.config_get_default('ignore_cc',
                                                 default=False,
                                                 to_type=lambda x: x == "True")
        # So more modern bugzilla's require that we specify
        # query_format=advanced along with the xmlrpc request.
        # https://bugzilla.redhat.com/show_bug.cgi?id=825370
        # ...but older bugzilla's don't know anything about that argument.
        # Here we make it possible for the user to specify whether they want
        # to pass that argument or not.
        self.advanced = asbool(self.config_get_default('advanced', 'no'))

        if not self.password or self.password.startswith("@oracle:"):
            self.password = get_service_password(
                self.get_keyring_service(self.config, self.target),
                self.username,
                oracle=self.password,
                interactive=self.config.interactive)

        url = 'https://%s/xmlrpc.cgi' % self.base_uri
        self.bz = bugzilla.Bugzilla(url=url)
        self.bz.login(self.username, self.password)
Beispiel #5
0
    def __init__(self, *args, **kw):
        super(BugzillaService, self).__init__(*args, **kw)
        self.base_uri = self.config_get('base_uri')
        self.username = self.config_get('username')
        self.password = self.config_get('password')
        self.ignore_cc = self.config_get_default('ignore_cc', default=False,
                                                 to_type=lambda x: x == "True")
        self.query_url = self.config_get_default('query_url', default=None)
        self.include_needinfos = self.config_get_default(
            'include_needinfos', False, to_type=lambda x: x == "True")
        self.open_statuses = self.config_get_default(
            'open_statuses', _open_statuses, to_type=lambda x: x.split(','))
        log.name(self.target).debug(" filtering on statuses: {0}", self.open_statuses)

        # So more modern bugzilla's require that we specify
        # query_format=advanced along with the xmlrpc request.
        # https://bugzilla.redhat.com/show_bug.cgi?id=825370
        # ...but older bugzilla's don't know anything about that argument.
        # Here we make it possible for the user to specify whether they want
        # to pass that argument or not.
        self.advanced = asbool(self.config_get_default('advanced', 'no'))

        if not self.password or self.password.startswith("@oracle:"):
            self.password = get_service_password(
                self.get_keyring_service(self.config, self.target),
                self.username, oracle=self.password,
                interactive=self.config.interactive
            )

        url = 'https://%s/xmlrpc.cgi' % self.base_uri
        self.bz = bugzilla.Bugzilla(url=url)
        self.bz.login(self.username, self.password)
Beispiel #6
0
    def __init__(self, *args, **kw):
        super(BugzillaService, self).__init__(*args, **kw)
        base_uri = self.config.get(self.target, 'bugzilla.base_uri')
        username = self.config.get(self.target, 'bugzilla.username')
        password = self.config.get(self.target, 'bugzilla.password')

        # So more modern bugzilla's require that we specify
        # query_format=advanced along with the xmlrpc request.
        # https://bugzilla.redhat.com/show_bug.cgi?id=825370
        # ...but older bugzilla's don't know anything about that argument.
        # Here we make it possible for the user to specify whether they want
        # to pass that argument or not.
        self.advanced = True  # Default to True.
        if self.config.has_option(self.target, 'bugzilla.advanced'):
            self.advanced = asbool(self.config.get(
                self.target, 'bugzilla.advanced'))

        if not password or password.startswith("@oracle:"):
            service = "bugzilla://%s@%s" % (username, base_uri)
            password = get_service_password(service, username, oracle=password,
                                            interactive=self.config.interactive)

        url = 'https://%s/xmlrpc.cgi' % base_uri
        self.bz = bugzilla.Bugzilla(url=url)
        self.bz.login(username, password)
Beispiel #7
0
    def __init__(self, *args, **kw):
        super(BugzillaService, self).__init__(*args, **kw)
        self.base_uri = self.config_get('base_uri')
        self.username = self.config_get('username')
        self.ignore_cc = self.config_get_default('ignore_cc',
                                                 default=False,
                                                 to_type=lambda x: x == "True")
        self.query_url = self.config_get_default('query_url', default=None)
        self.include_needinfos = self.config_get_default(
            'include_needinfos', False, to_type=lambda x: x == "True")
        self.open_statuses = self.config_get_default(
            'open_statuses', _open_statuses, to_type=lambda x: x.split(','))
        log.name(self.target).debug(" filtering on statuses: {0}",
                                    self.open_statuses)

        # So more modern bugzilla's require that we specify
        # query_format=advanced along with the xmlrpc request.
        # https://bugzilla.redhat.com/show_bug.cgi?id=825370
        # ...but older bugzilla's don't know anything about that argument.
        # Here we make it possible for the user to specify whether they want
        # to pass that argument or not.
        self.advanced = asbool(self.config_get_default('advanced', 'no'))

        self.password = self.config_get_password('password', self.username)

        url = 'https://%s/xmlrpc.cgi' % self.base_uri
        self.bz = bugzilla.Bugzilla(url=url)
        self.bz.login(self.username, self.password)
Beispiel #8
0
def aggregate_issues(conf):
    """ Return all issues from every target.

    Takes a config object and a callable which returns a shortened url.
    """
    log.name('bugwarrior').info("Starting to aggregate remote issues.")

    # Create and call service objects for every target in the config
    targets = [t.strip() for t in conf.get('general', 'targets').split(',')]

    # This multiprocessing stuff is kind of experimental.
    use_multiprocessing = conf.has_option('general', 'multiprocessing') and \
        asbool(conf.get('general', 'multiprocessing'))

    if use_multiprocessing:
        log.name('bugwarrior').info("Spawning %i workers." % len(targets))
        pool = multiprocessing.Pool(processes=len(targets))
        map_function = pool.map
    else:
        log.name('bugwarrior').info("Processing targets in serial.")
        map_function = map

    issues_by_target = map_function(_aggregate_issues,
                                    zip([conf] * len(targets), targets))
    log.name('bugwarrior').info("Done aggregating remote issues.")
    if WORKER_FAILURE in issues_by_target:
        log.name('bugwarrior').critical("A worker failed.  Aborting.")
        raise RuntimeError('Worker failure')
    return sum(issues_by_target, [])
Beispiel #9
0
    def __init__(self, *args, **kw):
        super(BugzillaService, self).__init__(*args, **kw)
        base_uri = self.config.get(self.target, 'bugzilla.base_uri')
        username = self.config.get(self.target, 'bugzilla.username')
        password = self.config.get(self.target, 'bugzilla.password')

        # So more modern bugzilla's require that we specify
        # query_format=advanced along with the xmlrpc request.
        # https://bugzilla.redhat.com/show_bug.cgi?id=825370
        # ...but older bugzilla's don't know anything about that argument.
        # Here we make it possible for the user to specify whether they want
        # to pass that argument or not.
        self.advanced = True  # Default to True.
        if self.config.has_option(self.target, 'bugzilla.advanced'):
            self.advanced = asbool(
                self.config.get(self.target, 'bugzilla.advanced'))

        if not password or password.startswith("@oracle:"):
            service = "bugzilla://%s@%s" % (username, base_uri)
            password = get_service_password(
                service,
                username,
                oracle=password,
                interactive=self.config.interactive)

        url = 'https://%s/xmlrpc.cgi' % base_uri
        self.bz = bugzilla.Bugzilla(url=url)
        self.bz.login(username, password)
Beispiel #10
0
def aggregate_issues(conf):
    """ Return all issues from every target.

    Takes a config object and a callable which returns a shortened url.
    """
    log.name('bugwarrior').info("Starting to aggregate remote issues.")

    # Create and call service objects for every target in the config
    targets = [t.strip() for t in conf.get('general', 'targets').split(',')]

    # This multiprocessing stuff is kind of experimental.
    use_multiprocessing = conf.has_option('general', 'multiprocessing') and \
        asbool(conf.get('general', 'multiprocessing'))

    if use_multiprocessing:
        log.name('bugwarrior').info("Spawning %i workers." % len(targets))
        pool = multiprocessing.Pool(processes=len(targets))
        map_function = pool.map
    else:
        log.name('bugwarrior').info("Processing targets in serial.")
        map_function = map

    issues_by_target = map_function(
        _aggregate_issues,
        zip([conf] * len(targets), targets)
    )
    log.name('bugwarrior').info("Done aggregating remote issues.")

    if WORKER_FAILURE in issues_by_target:
        log.name('bugwarrior').critical("A worker failed.  Aborting.")
        raise RuntimeError('Worker failure')

    return sum(issues_by_target, [])
Beispiel #11
0
    def __init__(self, *args, **kw):
        super(BugzillaService, self).__init__(*args, **kw)
        self.base_uri = self.config.get('base_uri')
        self.username = self.config.get('username')
        self.ignore_cc = self.config.get('ignore_cc', default=False,
                                                 to_type=lambda x: x == "True")
        self.query_url = self.config.get('query_url', default=None)
        self.include_needinfos = self.config.get(
            'include_needinfos', False, to_type=lambda x: x == "True")
        self.open_statuses = self.config.get('open_statuses', _open_statuses, to_type=aslist)
        log.debug(" filtering on statuses: %r", self.open_statuses)

        # So more modern bugzilla's require that we specify
        # query_format=advanced along with the xmlrpc request.
        # https://bugzilla.redhat.com/show_bug.cgi?id=825370
        # ...but older bugzilla's don't know anything about that argument.
        # Here we make it possible for the user to specify whether they want
        # to pass that argument or not.
        self.advanced = asbool(self.config.get('advanced', 'no'))

        url = 'https://%s/xmlrpc.cgi' % self.base_uri
        api_key = self.config.get('api_key', default=None)
        if api_key:
            try:
                self.bz = bugzilla.Bugzilla(url=url, api_key=api_key)
            except TypeError:
                raise Exception("Bugzilla API keys require python-bugzilla>=2.1.0")
        else:
            password = self.get_password('password', self.username)
            self.bz = bugzilla.Bugzilla(url=url)
            self.bz.login(self.username, password)
Beispiel #12
0
    def __init__(self, config, main_section, target):
        self.config = config
        self.main_section = main_section
        self.target = target

        self.desc_len = 35
        if config.has_option(self.main_section, 'description_length'):
            self.desc_len = self.config.getint(self.main_section,
                                               'description_length')

        self.anno_len = 45
        if config.has_option(self.main_section, 'annotation_length'):
            self.anno_len = self.config.getint(self.main_section,
                                               'annotation_length')

        self.inline_links = True
        if config.has_option(self.main_section, 'inline_links'):
            self.inline_links = asbool(
                config.get(self.main_section, 'inline_links'))

        self.annotation_links = not self.inline_links
        if config.has_option(self.main_section, 'annotation_links'):
            self.annotation_links = asbool(
                config.get(self.main_section, 'annotation_links'))

        self.annotation_comments = True
        if config.has_option(self.main_section, 'annotation_comments'):
            self.annotation_comments = asbool(
                config.get(self.main_section, 'annotation_comments'))

        self.shorten = False
        if config.has_option(self.main_section, 'shorten'):
            self.shorten = asbool(config.get(self.main_section, 'shorten'))

        self.add_tags = []
        if config.has_option(self.target, 'add_tags'):
            for raw_option in self.config.get(self.target,
                                              'add_tags').split(','):
                option = raw_option.strip(' +;')
                if option:
                    self.add_tags.append(option)

        self.default_priority = 'M'
        if config.has_option(self.target, 'default_priority'):
            self.default_priority = config.get(self.target, 'default_priority')

        log.name(target).info("Working on [{0}]", self.target)
Beispiel #13
0
    def __init__(self, config, main_section, target):
        self.config = config
        self.main_section = main_section
        self.target = target

        self.desc_len = 35
        if config.has_option(self.main_section, 'description_length'):
            self.desc_len = self.config.getint(self.main_section, 'description_length')

        self.anno_len = 45
        if config.has_option(self.main_section, 'annotation_length'):
            self.anno_len = self.config.getint(self.main_section, 'annotation_length')

        self.inline_links = True
        if config.has_option(self.main_section, 'inline_links'):
            self.inline_links = asbool(config.get(self.main_section, 'inline_links'))

        self.annotation_links = not self.inline_links
        if config.has_option(self.main_section, 'annotation_links'):
            self.annotation_links = asbool(
                config.get(self.main_section, 'annotation_links')
            )

        self.annotation_comments = True
        if config.has_option(self.main_section, 'annotation_comments'):
            self.annotation_comments = asbool(
                config.get(self.main_section, 'annotation_comments')
            )

        self.shorten = False
        if config.has_option(self.main_section, 'shorten'):
            self.shorten = asbool(config.get(self.main_section, 'shorten'))

        self.add_tags = []
        if config.has_option(self.target, 'add_tags'):
            for raw_option in self.config.get(
                self.target, 'add_tags'
            ).split(','):
                option = raw_option.strip(' +;')
                if option:
                    self.add_tags.append(option)

        self.default_priority = 'M'
        if config.has_option(self.target, 'default_priority'):
            self.default_priority = config.get(self.target, 'default_priority')

        log.name(target).info("Working on [{0}]", self.target)
Beispiel #14
0
def aggregate_issues(conf, main_section):
    """ Return all issues from every target. """
    log.name('bugwarrior').info("Starting to aggregate remote issues.")

    # Create and call service objects for every target in the config
    targets = [t.strip() for t in conf.get(main_section, 'targets').split(',')]

    queue = multiprocessing.Queue()

    log.name('bugwarrior').info("Spawning %i workers." % len(targets))
    processes = []

    if (
        conf.has_option(main_section, 'development')
        and asbool(conf.get(main_section, 'development'))
    ):
        for target in targets:
            _aggregate_issues(
                conf,
                main_section,
                target,
                queue,
                conf.get(target, 'service')
            )
    else:
        for target in targets:
            proc = multiprocessing.Process(
                target=_aggregate_issues,
                args=(conf, main_section, target, queue, conf.get(target, 'service'))
            )
            proc.start()
            processes.append(proc)

            # Sleep for 1 second here to try and avoid a race condition where
            # all N workers start up and ask the gpg-agent process for
            # information at the same time.  This causes gpg-agent to fumble
            # and tell some of our workers some incomplete things.
            time.sleep(1)

    currently_running = len(targets)
    while currently_running > 0:
        issue = queue.get(True)
        if isinstance(issue, tuple):
            completion_type, args = issue
            if completion_type == SERVICE_FINISHED_ERROR:
                target, e = args
                log.name('bugwarrior').info("Terminating workers")
                for process in processes:
                    process.terminate()
                raise RuntimeError(
                    "critical error in target '{}'".format(target))
            currently_running -= 1
            continue
        yield issue

    log.name('bugwarrior').info("Done aggregating remote issues.")
Beispiel #15
0
def aggregate_issues(conf, main_section):
    """ Return all issues from every target. """
    log.name('bugwarrior').info("Starting to aggregate remote issues.")

    # Create and call service objects for every target in the config
    targets = [t.strip() for t in conf.get(main_section, 'targets').split(',')]

    queue = multiprocessing.Queue()

    log.name('bugwarrior').info("Spawning %i workers." % len(targets))
    processes = []

    if (conf.has_option(main_section, 'development')
            and asbool(conf.get(main_section, 'development'))):
        for target in targets:
            _aggregate_issues(conf, main_section, target, queue,
                              conf.get(target, 'service'))
    else:
        for target in targets:
            proc = multiprocessing.Process(target=_aggregate_issues,
                                           args=(conf, main_section, target,
                                                 queue,
                                                 conf.get(target, 'service')))
            proc.start()
            processes.append(proc)

            # Sleep for 1 second here to try and avoid a race condition where
            # all N workers start up and ask the gpg-agent process for
            # information at the same time.  This causes gpg-agent to fumble
            # and tell some of our workers some incomplete things.
            time.sleep(1)

    currently_running = len(targets)
    while currently_running > 0:
        issue = queue.get(True)
        if isinstance(issue, tuple):
            completion_type, args = issue
            if completion_type == SERVICE_FINISHED_ERROR:
                target, e = args
                for process in processes:
                    process.terminate()
                yield ABORT_PROCESSING, e
            currently_running -= 1
            continue
        yield issue

    log.name('bugwarrior').info("Done aggregating remote issues.")
Beispiel #16
0
    def __init__(self, *args, **kw):
        super(BugzillaService, self).__init__(*args, **kw)
        self.base_uri = self.config.get('base_uri')
        self.username = self.config.get('username')
        self.ignore_cc = self.config.get('ignore_cc',
                                         default=False,
                                         to_type=lambda x: x == "True")
        self.query_url = self.config.get('query_url', default=None)
        self.include_needinfos = self.config.get('include_needinfos',
                                                 False,
                                                 to_type=lambda x: x == "True")
        self.open_statuses = self.config.get('open_statuses',
                                             _open_statuses,
                                             to_type=aslist)
        log.debug(" filtering on statuses: %r", self.open_statuses)

        # So more modern bugzilla's require that we specify
        # query_format=advanced along with the xmlrpc request.
        # https://bugzilla.redhat.com/show_bug.cgi?id=825370
        # ...but older bugzilla's don't know anything about that argument.
        # Here we make it possible for the user to specify whether they want
        # to pass that argument or not.
        self.advanced = asbool(self.config.get('advanced', 'no'))

        url = 'https://%s/xmlrpc.cgi' % self.base_uri
        api_key = self.config.get('api_key', default=None)
        if api_key:
            try:
                self.bz = bugzilla.Bugzilla(url=url, api_key=api_key)
            except TypeError:
                raise Exception(
                    "Bugzilla API keys require python-bugzilla>=2.1.0")
        else:
            password = self.get_password('password', self.username)
            self.bz = bugzilla.Bugzilla(url=url)
            self.bz.login(self.username, password)
Beispiel #17
0
def send_notification(issue, op, conf):
    notify_backend = conf.get('notifications', 'backend')

    # Notifications for growlnotify on Mac OS X
    if notify_backend == 'growlnotify':
        import gntp.notifier
        growl = gntp.notifier.GrowlNotifier(
            applicationName="Bugwarrior",
            notifications=["New Updates", "New Messages"],
            defaultNotifications=["New Messages"],
        )
        growl.register()
        if op == 'bw_finished':
            growl.notify(
                noteType="New Messages",
                title="Bugwarrior",
                description="Finished querying for new issues.\n%s" %
                issue['description'],
                sticky=asbool(conf.get(
                    'notifications', 'finished_querying_sticky', 'True')),
                icon="https://upload.wikimedia.org/wikipedia/"
                "en/5/59/Taskwarrior_logo.png",
                priority=1,
            )
            return
        message = "%s task: %s" % (op, issue['description'].encode("utf-8"))
        metadata = _get_metadata(issue)
        if metadata is not None:
            message += metadata
        growl.notify(
            noteType="New Messages",
            title="Bugwarrior",
            description=message,
            sticky=asbool(conf.get(
                'notifications', 'task_crud_sticky', 'True')),
            icon="https://upload.wikimedia.org/wikipedia/"
            "en/5/59/Taskwarrior_logo.png",
            priority=1,
        )
        return
    elif notify_backend == 'pynotify':
        _cache_logo()

        import pynotify
        pynotify.init("bugwarrior")

        if op == 'bw finished':
            message = "Finished querying for new issues.\n%s" %\
                issue['description']
        else:
            message = "%s task: %s" % (
                op, issue['description'].encode("utf-8"))
            metadata = _get_metadata(issue)
            if metadata is not None:
                message += metadata

        pynotify.Notification("Bugwarrior", message, logo_path).show()
    elif notify_backend == 'gobject':
        _cache_logo()

        from gi.repository import Notify
        Notify.init("bugwarrior")

        if op == 'bw finished':
            message = "Finished querying for new issues.\n%s" %\
                issue['description']
        else:
            message = "%s task: %s" % (
                op, issue['description'].encode("utf-8"))
            metadata = _get_metadata(issue)
            if metadata is not None:
                message += metadata

        Notify.Notification.new("Bugwarrior", message, logo_path).show()
Beispiel #18
0
 def _bool_option(section, option, default):
     try:
         return section in conf.sections() and \
             asbool(conf.get(section, option, default))
     except NoOptionError:
         return default
Beispiel #19
0
 def _bool_option(section, option, default):
     try:
         return section in conf.sections() and \
             asbool(conf.get(section, option, default))
     except NoOptionError:
         return default
Beispiel #20
0
 def _bool_option(section, option, default):
     try:
         return asbool(conf.get(section, option))
     except (NoSectionError, NoOptionError):
         return default
Beispiel #21
0
 def _bool_option(section, option, default):
     try:
         return asbool(conf.get(section, option))
     except (NoSectionError, NoOptionError):
         return default
Beispiel #22
0
    def to_taskwarrior(self):
        author = self.record['author']
        milestone = self.record.get('milestone')
        created = self.record['created_at']
        updated = self.record.get('updated_at')
        state = self.record['state']
        upvotes = self.record.get('upvotes', 0)
        downvotes = self.record.get('downvotes', 0)
        work_in_progress = int(asbool(self.record.get('work_in_progress', 0)))
        assignee = self.record.get('assignee')
        duedate = self.record.get('due_date')
        weight = self.record.get('weight')
        number = (self.record['id']
                  if self.extra['type'] == 'todo' else self.record['iid'])
        priority = (self.origin['default_priority']
                    if self.extra['type'] == 'issue' else 'H')
        title = ('Todo from %s for %s' %
                 (author['name'], self.extra['project'])
                 if self.extra['type'] == 'todo' else self.record['title'])
        description = (self.record['body'] if self.extra['type'] == 'todo' else
                       self.record['description'])

        if milestone and (self.extra['type'] == 'issue' or
                          (self.extra['type'] == 'merge_request'
                           and duedate is None)):
            duedate = milestone['due_date']
        if milestone:
            milestone = milestone['title']
        if created:
            created = self.parse_date(created).replace(microsecond=0)
        if updated:
            updated = self.parse_date(updated).replace(microsecond=0)
        if duedate:
            duedate = self.parse_date(duedate)
        if author:
            author = author['username']
        if assignee:
            assignee = assignee['username']

        self.title = title

        return {
            'project': self.extra['project'],
            'priority': priority,
            'annotations': self.extra.get('annotations', []),
            'tags': self.get_tags(),
            'due': duedate,
            'entry': created,
            self.URL: self.extra['issue_url'],
            self.REPO: self.extra['project'],
            self.TYPE: self.extra['type'],
            self.TITLE: title,
            self.DESCRIPTION: description,
            self.MILESTONE: milestone,
            self.NUMBER: str(number),
            self.CREATED_AT: created,
            self.UPDATED_AT: updated,
            self.DUEDATE: duedate,
            self.STATE: state,
            self.UPVOTES: upvotes,
            self.DOWNVOTES: downvotes,
            self.WORK_IN_PROGRESS: work_in_progress,
            self.AUTHOR: author,
            self.ASSIGNEE: assignee,
            self.NAMESPACE: self.extra['namespace'],
            self.WEIGHT: weight,
        }
Beispiel #23
0
    def to_taskwarrior(self):
        author = self.record['author']
        milestone = self.record.get('milestone')
        created = self.record['created_at']
        updated = self.record.get('updated_at')
        state = self.record['state']
        upvotes = self.record.get('upvotes', 0)
        downvotes = self.record.get('downvotes', 0)
        work_in_progress = int(asbool(self.record.get('work_in_progress', 0)))
        assignee = self.record.get('assignee')
        duedate = self.record.get('due_date')
        weight = self.record.get('weight')
        number = (
            self.record['id'] if self.extra['type'] == 'todo'
            else self.record['iid'])
        priority = (
            self.origin['default_priority'] if self.extra['type'] == 'issue'
            else 'H')
        title = (
            'Todo from %s for %s' % (author['name'], self.extra['project'])
            if self.extra['type'] == 'todo' else self.record['title'])
        description = (
            self.record['body'] if self.extra['type'] == 'todo'
            else self.record['description'])

        if milestone and (
                self.extra['type'] == 'issue' or
                (self.extra['type'] == 'merge_request' and duedate is None)):
            duedate = milestone['due_date']
        if milestone:
            milestone = milestone['title']
        if created:
            created = self.parse_date(created).replace(microsecond=0)
        if updated:
            updated = self.parse_date(updated).replace(microsecond=0)
        if duedate:
            duedate = self.parse_date(duedate)
        if author:
            author = author['username']
        if assignee:
            assignee = assignee['username']


        self.title = title

        return {
            'project': self.extra['project'],
            'priority': priority,
            'annotations': self.extra.get('annotations', []),
            'tags': self.get_tags(),
            'due': duedate,
            'entry': created,

            self.URL: self.extra['issue_url'],
            self.REPO: self.extra['project'],
            self.TYPE: self.extra['type'],
            self.TITLE: title,
            self.DESCRIPTION: description,
            self.MILESTONE: milestone,
            self.NUMBER: number,
            self.CREATED_AT: created,
            self.UPDATED_AT: updated,
            self.DUEDATE: duedate,
            self.STATE: state,
            self.UPVOTES: upvotes,
            self.DOWNVOTES: downvotes,
            self.WORK_IN_PROGRESS: work_in_progress,
            self.AUTHOR: author,
            self.ASSIGNEE: assignee,
            self.NAMESPACE: self.extra['namespace'],
            self.WEIGHT: weight,
        }
Beispiel #24
0
def send_notification(issue, op, conf):
    notify_backend = conf.get('notifications', 'backend')

    # Notifications for growlnotify on Mac OS X
    if notify_backend == 'growlnotify':
        import gntp.notifier
        growl = gntp.notifier.GrowlNotifier(
            applicationName="Bugwarrior",
            notifications=["New Updates", "New Messages"],
            defaultNotifications=["New Messages"],
        )
        growl.register()
        if op == 'bw_finished':
            growl.notify(
                noteType="New Messages",
                title="Bugwarrior",
                description="Finished querying for new issues.\n%s" %
                issue['description'],
                sticky=asbool(conf.get(
                    'notifications', 'finished_querying_sticky', 'True')),
                icon="https://upload.wikimedia.org/wikipedia/"
                "en/5/59/Taskwarrior_logo.png",
                priority=1,
            )
            return
        message = "%s task: %s" % (op, issue['description'].encode("utf-8"))
        metadata = _get_metadata(issue)
        if metadata is not None:
            message += metadata
        growl.notify(
            noteType="New Messages",
            title="Bugwarrior",
            description=message,
            sticky=asbool(conf.get(
                'notifications', 'task_crud_sticky', 'True')),
            icon="https://upload.wikimedia.org/wikipedia/"
            "en/5/59/Taskwarrior_logo.png",
            priority=1,
        )
        return
    elif notify_backend == 'pynotify':
        _cache_logo()

        import pynotify
        pynotify.init("bugwarrior")

        if op == 'bw finished':
            message = "Finished querying for new issues.\n%s" %\
                issue['description']
        else:
            message = "%s task: %s" % (
                op, issue['description'].encode("utf-8"))
            metadata = _get_metadata(issue)
            if metadata is not None:
                message += metadata

        pynotify.Notification("Bugwarrior", message, logo_path).show()
    elif notify_backend == 'gobject':
        _cache_logo()

        from gi.repository import Notify
        Notify.init("bugwarrior")

        if op == 'bw finished':
            message = "Finished querying for new issues.\n%s" %\
                issue['description']
        else:
            message = "%s task: %s" % (
                op, issue['description'].encode("utf-8"))
            metadata = _get_metadata(issue)
            if metadata is not None:
                message += metadata.encode("utf-8")

        Notify.Notification.new("Bugwarrior", message, logo_path).show()