Skip to content

Commit

Permalink
Merge pull request #94 from coddingtonbear/add_tags_option
Browse files Browse the repository at this point in the history
Add tags option
  • Loading branch information
ralphbean committed Mar 7, 2014
2 parents 8d0dd7a + 79b3220 commit 64e6b26
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 21 deletions.
26 changes: 25 additions & 1 deletion bugwarrior/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,21 @@ Create a ``~/.bugwarriorrc`` file with the following contents.
# Use "password = @oracle:eval:<command>" to use the output of <command> as the password.
# Note that using one of these strategies is in general more secure
# than storing a password in plain text.
#
# COMMON SERVICE PROPERTIES:
# Services all implement the following options:
#
# Space-separated list of tags to add to all created issues:
# > add_tags = tag1 tag2
# A priority to set incoming tasks to by default ('H', 'M', or 'L')
# > default_priority = M
# A template to use for generating the task description (see service details
# for more information about what fields are available)
# > description_template = {{githubtitle}}
# Only create tasks for issues found assigned to the specified username
# > only_if_assigned = myusername
# Above, but also create tasks for issues that are unassigned
# > also_unassigned = True

# General stuff.
[general]
Expand Down Expand Up @@ -96,6 +111,7 @@ Create a ``~/.bugwarriorrc`` file with the following contents.
service = github
github.username = ralphbean
default_priority = H
add_tags = open_source

# You can override how an issue's description is created by entering
# a one-line Jinja template like the below; in addition to the default
Expand Down Expand Up @@ -128,6 +144,7 @@ Create a ``~/.bugwarriorrc`` file with the following contents.
bitbucket.username = ralphbean
bitbucket.password = mypassword
default_priority = M
add_tags = open_source

# You can override how an issue's description is created by entering
# a one-line Jinja template like the below; in addition to the default
Expand All @@ -144,7 +161,7 @@ Create a ``~/.bugwarriorrc`` file with the following contents.
[paj_bitbucket]
service = bitbucket
bitbucket.username = paj
bitbucket.only_if_assigned = ralphbean
only_if_assigned = ralphbean
default_priority = L

# Here's an example of a trac target. Scrape every ticket and only include them
Expand All @@ -161,6 +178,7 @@ Create a ``~/.bugwarriorrc`` file with the following contents.
only_if_assigned = ralph
also_unassigned = True
default_priority = H
add_tags = work

# You can override how an issue's description is created by entering
# a one-line Jinja template like the below; in addition to the default
Expand All @@ -182,6 +200,7 @@ Create a ``~/.bugwarriorrc`` file with the following contents.
bugzilla.base_uri = bugzilla.redhat.com
bugzilla.username = [email protected]
bugzilla.password = OMG_LULZ
add_tags = mozilla

# You can override how an issue's description is created by entering
# a one-line Jinja template like the below; in addition to the default
Expand All @@ -201,6 +220,7 @@ Create a ``~/.bugwarriorrc`` file with the following contents.
megaplan.project_name = example

default_priority = H
add_tags = megaplan important

# You can override how an issue's description is created by entering
# a one-line Jinja template like the below; in addition to the default
Expand All @@ -227,6 +247,7 @@ Create a ``~/.bugwarriorrc`` file with the following contents.
# 4 and 5(the default). You can find your particular version in the footer at
# the dashboard.
jira.version = 5
add_tags = enterprisey work

# You can override how an issue's description is created by entering
# a one-line Jinja template like the below; in addition to the default
Expand All @@ -245,6 +266,7 @@ Create a ``~/.bugwarriorrc`` file with the following contents.
teamlab.login = alice
teamlab.password = secret
teamlab.project_name = example_teamlab
add_tags = whatever

# You can override how an issue's description is created by entering
# a one-line Jinja template like the below; in addition to the default
Expand All @@ -263,6 +285,7 @@ Create a ``~/.bugwarriorrc`` file with the following contents.
redmine.key = c0c4c014cafebabe
redmine.user_id = 7
redmine.project_name = redmine
add_tags = chiliproject

# You can override how an issue's description is created by entering
# a one-line Jinja template like the below; in addition to the default
Expand Down Expand Up @@ -293,6 +316,7 @@ Create a ``~/.bugwarriorrc`` file with the following contents.
activecollab3.url = https://ac.example.org/api.php
activecollab3.key = your-api-key
activecollab3.user_id = 15
add_tags = php

# You can override how an issue's description is created by entering
# a one-line Jinja template like the below; in addition to the default
Expand Down
9 changes: 8 additions & 1 deletion bugwarrior/config.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import codecs
from ConfigParser import ConfigParser
import optparse
import os
Expand Down Expand Up @@ -142,7 +143,13 @@ def load_config():
opts, args = parse_args()

config = ConfigParser({'log.level': "DEBUG", 'log.file': None})
config.read(os.path.expanduser(opts.config))
config.readfp(
codecs.open(
os.path.expanduser(opts.config),
"r",
"utf-8",
)
)
config.interactive = opts.interactive
validate_config(config)

Expand Down
24 changes: 17 additions & 7 deletions bugwarrior/db.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,17 +75,27 @@ def get_normalized_annotation(annotation):
def tasks_differ(left, right):
if set(left) - set(right):
return True
for k in left:
all_keys = set(left.keys()) | set(right.keys())
for k in all_keys:
if k in ('annotations', 'urgency', 'priority', ):
continue
if (
isinstance(left[k], (list, tuple))
and isinstance(right[k], (list, tuple))
isinstance(left.get(k), (list, tuple))
and isinstance(right.get(k), (list, tuple))
):
left[k] = set(left[k])
right[k] = set(right[k])
if unicode(left[k]) != unicode(right[k]):
return True
if set(left.get(k, [])) != set(right.get(k, [])):
return True
else:
if unicode(left.get(k)) != unicode(right.get(k)):
log.name('db').debug(
"%s:%s has changed from '%s' to '%s'." % (
left['uuid'],
k,
left.get(k),
right.get(k)
)
)
return True
return False


Expand Down
35 changes: 23 additions & 12 deletions bugwarrior/services/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import copy
import multiprocessing
import time

Expand Down Expand Up @@ -47,6 +48,13 @@ def __init__(self, config, target):
self.target, 'description_template'
)

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')
Expand Down Expand Up @@ -80,6 +88,7 @@ def get_issue_for_record(self, record, extra=None):
'target': self.target,
'bitly_api_key': self.bitly_api_key,
'bitly_api_user': self.bitly_api_user,
'add_tags': self.add_tags,
}
origin.update(self.get_service_metadata())
return self.ISSUE_CLASS(record, origin=origin, extra=extra)
Expand Down Expand Up @@ -214,10 +223,16 @@ def get_default_description(self):
"""
raise NotImplementedError()

def _get_taskwarrior_record(self):
def get_taskwarrior_record(self, with_description=True):
if not getattr(self, '_taskwarrior_record', None):
self._taskwarrior_record = self.to_taskwarrior()
return self._taskwarrior_record
record = copy.deepcopy(self._taskwarrior_record)
if with_description:
record['description'] = self.get_rendered_description()
if not 'tags' in record:
record['tags'] = []
record['tags'].extend(self.origin['add_tags'])
return record

def get_priority(self):
return self.PRIORITY_MAP.get(
Expand Down Expand Up @@ -269,15 +284,15 @@ def build_default_description(
)

def _get_unique_identifier(self):
record = self._get_taskwarrior_record()
record = self.get_taskwarrior_record()
return dict([
(key, record[key],) for key in self.UNIQUE_KEY
])

def get_rendered_description(self):
if not hasattr(self, '_description'):
if self.origin['description_template']:
record = self._get_taskwarrior_record()
record = self.get_taskwarrior_record(with_description=False)
context = record.copy()
context.update(self.extra)
template = Template(self.origin['description_template'])
Expand All @@ -286,8 +301,7 @@ def get_rendered_description(self):
return self._description

def __iter__(self):
record = self._get_taskwarrior_record()
record['description'] = self['description']
record = self.get_taskwarrior_record()
for key in six.iterkeys(record):
yield key

Expand All @@ -298,12 +312,11 @@ def iterkeys(self):
return self.__iter__()

def items(self):
record = self._get_taskwarrior_record()
record['description'] = self['description']
record = self.get_taskwarrior_record()
return list(six.iteritems(record))

def iteritems(self):
record = self._get_taskwarrior_record()
record = self.get_taskwarrior_record()
for item in six.iteritems(record):
yield item

Expand All @@ -319,9 +332,7 @@ def get(self, attribute, default=None):
return default

def __getitem__(self, attribute):
record = self._get_taskwarrior_record()
if attribute == 'description':
return self.get_rendered_description()
record = self.get_taskwarrior_record()
return record[attribute]

def __setitem__(self, attribute, value):
Expand Down

0 comments on commit 64e6b26

Please sign in to comment.