Skip to content

Commit

Permalink
Merge 2d283e3 into 0f03007
Browse files Browse the repository at this point in the history
  • Loading branch information
mathstuf committed Aug 12, 2016
2 parents 0f03007 + 2d283e3 commit 3dfb246
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 37 deletions.
6 changes: 3 additions & 3 deletions bugwarrior/docs/services/bitbucket.rst
Expand Up @@ -63,14 +63,14 @@ In this example, ``noisy_repository`` is the repository you would
Please note that the API returns all lowercase names regardless of
the case of the repository in the web interface.

Filter Pull Requests
++++++++++++++++++++
Filter Merge Requests
+++++++++++++++++++++

Although you can filter issues using :ref:`common_configuration_options`,
pull requests are not filtered by default. You can filter pull requests
by adding the following configuration option::

bitbucket.filter_pull_requests = True
bitbucket.filter_merge_requests = True

Provided UDA Fields
-------------------
Expand Down
16 changes: 16 additions & 0 deletions bugwarrior/docs/services/gitlab.rst
Expand Up @@ -83,6 +83,20 @@ by adding the following configuration option::

gitlab.filter_merge_requests = True

Include Todo Items
++++++++++++++++++

By default todo items are not included. You may include them by adding the
following configuration option::

gitlab.include_todos = True

If todo items are included, by default, todo items for all projects are
included. To only fetch todo items for projects which are being fetched, you
may set::

gitlab.include_all_todos = False

Use HTTP
++++++++

Expand Down Expand Up @@ -118,6 +132,8 @@ Provided UDA Fields
+-----------------------+-----------------------+---------------------+
| ``gitlabupdatedat`` | Updated | Date & Time |
+-----------------------+-----------------------+---------------------+
| ``gitlabduedate`` | Due Date | Date |
+-----------------------+-----------------------+---------------------+
| ``gitlaburl`` | URL | Text (string) |
+-----------------------+-----------------------+---------------------+
| ``gitlabrepo`` | username/reponame | Text (string) |
Expand Down
1 change: 1 addition & 0 deletions bugwarrior/services/__init__.py
Expand Up @@ -374,6 +374,7 @@ def build_default_description(
'issue': 'Is',
'pull_request': 'PR',
'merge_request': 'MR',
'todo': '',
'task': '',
'subtask': 'Subtask #',
}
Expand Down
134 changes: 102 additions & 32 deletions bugwarrior/services/gitlab.py
Expand Up @@ -17,6 +17,7 @@ class GitlabIssue(Issue):
DESCRIPTION = 'gitlabdescription'
CREATED_AT = 'gitlabcreatedon'
UPDATED_AT = 'gitlabupdatedat'
DUEDATE = 'gitlabduedate'
MILESTONE = 'gitlabmilestone'
URL = 'gitlaburl'
REPO = 'gitlabrepo'
Expand Down Expand Up @@ -46,6 +47,10 @@ class GitlabIssue(Issue):
'type': 'date',
'label': 'Gitlab Updated',
},
DUEDATE: {
'type': 'date',
'label': 'Gitlab Due Date',
},
MILESTONE: {
'type': 'string',
'label': 'Gitlab Milestone',
Expand Down Expand Up @@ -97,40 +102,49 @@ def _normalize_label_to_tag(self, label):
return re.sub(r'[^a-zA-Z0-9]', '_', label)

def to_taskwarrior(self):
if self.extra['type'] == 'merge_request':
priority = 'H'
milestone = self.record['milestone']
created = self.record['created_at']
updated = self.record['updated_at']
state = self.record['state']
upvotes = self.record['upvotes']
downvotes = self.record['downvotes']
work_in_progress = self.record.get('work_in_progress', 0)
author = self.record['author']
assignee = self.record['assignee']
else:
priority = self.origin['default_priority']
milestone = self.record['milestone']
created = self.record['created_at']
updated = self.record['updated_at']
state = self.record['state']
upvotes = 0
downvotes = 0
work_in_progress = 0
author = self.record['author']
assignee = self.record['assignee']

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 = self.record.get('work_in_progress', 0)
assignee = self.record.get('assignee')
duedate = self.record.get('due_date')
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, 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,
Expand All @@ -140,12 +154,13 @@ def to_taskwarrior(self):
self.URL: self.extra['issue_url'],
self.REPO: self.extra['project'],
self.TYPE: self.extra['type'],
self.TITLE: self.record['title'],
self.DESCRIPTION: self.record['description'],
self.TITLE: title,
self.DESCRIPTION: description,
self.MILESTONE: milestone,
self.NUMBER: self.record['iid'],
self.NUMBER: number,
self.CREATED_AT: created,
self.UPDATED_AT: updated,
self.DUEDATE: duedate,
self.STATE: state,
self.UPVOTES: upvotes,
self.DOWNVOTES: downvotes,
Expand Down Expand Up @@ -175,9 +190,9 @@ def get_tags(self):

def get_default_description(self):
return self.build_default_description(
title=self.record['title'],
title=self.title,
url=self.get_processed_url(self.extra['issue_url']),
number=self.record['iid'],
number=self.record.get('iid', ''),
cls=self.extra['type'],
)

Expand Down Expand Up @@ -227,6 +242,12 @@ def __init__(self, *args, **kw):
self.filter_merge_requests = self.config_get_default(
'filter_merge_requests', default=False, to_type=asbool
)
self.include_todos = self.config_get_default(
'include_todos', default=False, to_type=asbool
)
self.include_all_todos = self.config_get_default(
'include_all_todos', default=True, to_type=asbool
)

@classmethod
def get_keyring_service(cls, config, section):
Expand Down Expand Up @@ -320,9 +341,9 @@ def get_repo_issues(self, rid):
issues = {}
try:
repo_issues = self._fetch_paged(tmpl)
except:
except IOError:
# Projects may have issues disabled.
return []
return {}
for issue in repo_issues:
if issue['state'] not in ('opened', 'reopened'):
continue
Expand All @@ -334,15 +355,37 @@ def get_repo_merge_requests(self, rid):
issues = {}
try:
repo_merge_requests = self._fetch_paged(tmpl)
except:
except IOError:
# Projects may have merge requests disabled.
return []
return {}
for issue in repo_merge_requests:
if issue['state'] not in ('opened', 'reopened'):
continue
issues[issue['id']] = (rid, issue)
return issues

def get_todos(self):
tmpl = '{scheme}://{host}/api/v3/todos'
todos = {}
try:
fetched_todos = self._fetch_paged(tmpl)
except IOError:
# Older gitlab versions do not have todo items.
return {}
for todo in fetched_todos:
if todo['state'] == 'done':
continue
todos[todo['id']] = (todo.get('project'), todo)
return todos

def include_todo(self, repos):
ids = list(r['id'] for r in repos)

def include_todo(todo):
project, todo = todo
return project is None or project['id'] in ids
return include_todo

def issues(self):
tmpl = '{scheme}://{host}/api/v3/projects'
all_repos = self._fetch_paged(tmpl)
Expand Down Expand Up @@ -401,6 +444,33 @@ def issues(self):
issue_obj.update_extra(extra)
yield issue_obj

if self.include_todos:
todos = self.get_todos()
log.debug(" Found %i todo items.", len(todos))
if not self.include_all_todos:
todos = filter(self.include_todo(repos), todos.values())
log.debug(" Pruned down to %i todos.", len(todos))

for project, todo in todos:
if project is not None:
repo = project
else:
repo = {
'path': 'the instance',
}
todo['repo'] = repo['path']

todo_obj = self.get_issue_for_record(todo)
todo_url = todo['target_url']
extra = {
'issue_url': todo_url,
'project': repo['path'],
'type': 'todo',
'annotations': [],
}
todo_obj.update_extra(extra)
yield todo_obj

@classmethod
def validate_config(cls, config, target):
if not config.has_option(target, 'gitlab.host'):
Expand Down
9 changes: 7 additions & 2 deletions tests/test_gitlab.py
Expand Up @@ -41,6 +41,10 @@ class TestGitlabIssue(AbstractServiceTest, ServiceTest):
).replace(tzinfo=pytz.UTC, microsecond=0)
arbitrary_updated = datetime.datetime.utcnow().replace(
tzinfo=pytz.UTC, microsecond=0)
arbitrary_duedate = (
datetime.datetime.combine(datetime.date.today(),
datetime.datetime.min.time())
).replace(tzinfo=pytz.UTC)
arbitrary_issue = {
"id": 42,
"iid": 3,
Expand All @@ -54,7 +58,7 @@ class TestGitlabIssue(AbstractServiceTest, ServiceTest):
"id": 1,
"title": "v1.0",
"description": "",
"due_date": "2012-07-20",
"due_date": arbitrary_duedate.date().isoformat(),
"state": "closed",
"updated_at": "2012-07-04T13:42:48Z",
"created_at": "2012-07-04T13:42:48Z"
Expand All @@ -78,7 +82,6 @@ class TestGitlabIssue(AbstractServiceTest, ServiceTest):
"state": "opened",
"updated_at": arbitrary_updated.isoformat(),
"created_at": arbitrary_created.isoformat(),
"work_in_progress": True
}
arbitrary_extra = {
'issue_url': 'https://gitlab.example.com/arbitrary_username/project/issues/3',
Expand Down Expand Up @@ -118,6 +121,7 @@ def test_to_taskwarrior(self):
issue.NUMBER: self.arbitrary_issue['iid'],
issue.UPDATED_AT: self.arbitrary_updated.replace(microsecond=0),
issue.CREATED_AT: self.arbitrary_created.replace(microsecond=0),
issue.DUEDATE: self.arbitrary_duedate,
issue.DESCRIPTION: self.arbitrary_issue['description'],
issue.MILESTONE: self.arbitrary_issue['milestone']['title'],
issue.UPVOTES: 0,
Expand Down Expand Up @@ -169,6 +173,7 @@ def test_issues(self):
'gitlabtitle': u'Add user settings',
'gitlabtype': 'issue',
'gitlabupdatedat': self.arbitrary_updated,
'gitlabduedate': self.arbitrary_duedate,
'gitlabupvotes': 0,
'gitlaburl': u'example.com/issues/3',
'gitlabwip': 0,
Expand Down

0 comments on commit 3dfb246

Please sign in to comment.