From 7e78f7506183770fda9bfb54ed75d97db9b871fe Mon Sep 17 00:00:00 2001 From: Adam Coddington Date: Thu, 6 Mar 2014 16:53:00 -0800 Subject: [PATCH] Adding option allowing one to specify tags that will be automaically added to all incoming issues of this type. --- bugwarrior/README.rst | 9 +++++++++ bugwarrior/db.py | 24 +++++++++++++++------- bugwarrior/services/__init__.py | 35 ++++++++++++++++++++++----------- 3 files changed, 49 insertions(+), 19 deletions(-) diff --git a/bugwarrior/README.rst b/bugwarrior/README.rst index 9d4c2a06d..18c574a88 100644 --- a/bugwarrior/README.rst +++ b/bugwarrior/README.rst @@ -96,6 +96,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 @@ -128,6 +129,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 @@ -161,6 +163,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 @@ -182,6 +185,7 @@ Create a ``~/.bugwarriorrc`` file with the following contents. bugzilla.base_uri = bugzilla.redhat.com bugzilla.username = rbean@redhat.com 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 @@ -201,6 +205,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 @@ -227,6 +232,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 @@ -245,6 +251,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 @@ -263,6 +270,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 @@ -293,6 +301,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 diff --git a/bugwarrior/db.py b/bugwarrior/db.py index 9d484789e..50f235bdc 100644 --- a/bugwarrior/db.py +++ b/bugwarrior/db.py @@ -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 diff --git a/bugwarrior/services/__init__.py b/bugwarrior/services/__init__.py index 327296fcd..66aa1b27d 100644 --- a/bugwarrior/services/__init__.py +++ b/bugwarrior/services/__init__.py @@ -1,3 +1,4 @@ +import copy import multiprocessing import time @@ -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') @@ -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) @@ -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( @@ -269,7 +284,7 @@ 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 ]) @@ -277,7 +292,7 @@ def _get_unique_identifier(self): 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']) @@ -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 @@ -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 @@ -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):