diff --git a/bugwarrior/services/bitbucket.py b/bugwarrior/services/bitbucket.py index 8b68ae45c..072013734 100644 --- a/bugwarrior/services/bitbucket.py +++ b/bugwarrior/services/bitbucket.py @@ -41,7 +41,7 @@ def to_taskwarrior(self): 'annotations': self.extra['annotations'], self.URL: self.extra['url'], - self.FOREIGN_ID: self.record['local_id'], + self.FOREIGN_ID: self.record['id'], self.TITLE: self.record['title'], } @@ -49,7 +49,7 @@ def get_default_description(self): return self.build_default_description( title=self.record['title'], url=self.get_processed_url(self.extra['url']), - number=self.record['local_id'], + number=self.record['id'], cls='issue' ) @@ -102,7 +102,9 @@ def get_keyring_service(cls, config, section): username = config.get(section, cls._get_key('username')) return "bitbucket://%s@bitbucket.org/%s" % (login, username) - def filter_repos(self, repo): + def filter_repos(self, repo_tag): + repo = repo_tag.split('/').pop() + if self.exclude_repos: if repo in self.exclude_repos: return False @@ -115,25 +117,9 @@ def filter_repos(self, repo): return True - def get_data2(self, url): - response = requests.get(self.BASE_API2 + url, auth=self.auth) - - # And.. if we didn't get good results, just bail. - if response.status_code != 200: - raise IOError( - "Non-200 status code %r; %r; %r" % ( - response.status_code, url, response.text, - ) - ) - if callable(response.json): - # Newer python-requests - return response.json() - else: - # Older python-requests - return response.json - - def get_data(self, url): - response = requests.get(self.BASE_API + url, auth=self.auth) + def get_data(self, url, **kwargs): + api = kwargs.get('api', self.BASE_API2) + response = requests.get(api + url, auth=self.auth) # And.. if we didn't get good results, just bail. if response.status_code != 200: @@ -158,16 +144,16 @@ def validate_config(cls, config, target): def fetch_issues(self, tag): response = self.get_data('/repositories/%s/issues/' % (tag)) - return [(tag, issue) for issue in response['issues']] + return [(tag, issue) for issue in response['values']] def fetch_pull_requests(self, tag): - response = self.get_data2('/repositories/%s/pullrequests/' % tag) + response = self.get_data('/repositories/%s/pullrequests/' % tag) return [(tag, issue) for issue in response['values']] def get_annotations(self, tag, issue, issue_obj, url): response = self.get_data( - '/repositories/%s/issues/%i/comments' % (tag, issue['local_id']) - ) + '/repositories/%s/issues/%i/comments' % (tag, issue['id']), + api=self.BASE_API) return self.build_annotations( (( comment['author_info']['username'], @@ -177,7 +163,7 @@ def get_annotations(self, tag, issue, issue_obj, url): ) def get_annotations2(self, tag, issue, issue_obj, url): - response = self.get_data2( + response = self.get_data( '/repositories/%s/pullrequests/%i/comments' % (tag, issue['id']) ) return self.build_annotations( @@ -194,14 +180,13 @@ def get_owner(self, issue): def issues(self): user = self.config.get(self.target, 'bitbucket.username') - response = self.get_data('/users/' + user + '/') - all_repos = [ - repo.get('slug') for repo in response.get('repositories') + response = self.get_data('/repositories/' + user + '/') + repo_tags = filter(self.filter_repos, [ + repo['full_name'] for repo in response.get('values') if repo.get('has_issues') - ] - repos = filter(self.filter_repos, all_repos) + ]) - issues = sum([self.fetch_issues(user + "/" + repo) for repo in repos], []) + issues = sum([self.fetch_issues(repo) for repo in repo_tags], []) log.name(self.target).debug(" Found {0} total.", len(issues)) closed = ['resolved', 'duplicate', 'wontfix', 'invalid', 'closed'] @@ -212,9 +197,7 @@ def issues(self): for tag, issue in issues: issue_obj = self.get_issue_for_record(issue) - url = self.BASE_URL + '/'.join( - issue['resource_uri'].split('/')[3:] - ).replace('issues', 'issue') + url = issue['links']['html']['href'] extras = { 'project': tag.split('/')[1], 'url': url, @@ -224,7 +207,8 @@ def issues(self): yield issue_obj if not self.filter_merge_requests: - pull_requests = sum([self.fetch_pull_requests(user + "/" + repo) for repo in repos], []) + pull_requests = sum( + [self.fetch_pull_requests(repo) for repo in repo_tags], []) log.name(self.target).debug(" Found {0} total.", len(pull_requests)) closed = ['rejected', 'fulfilled'] @@ -234,10 +218,6 @@ def issues(self): log.name(self.target).debug(" Pruned down to {0}", len(pull_requests)) for tag, issue in pull_requests: - # Pull requests are only accessible over API v2.0 which has - # this difference. - issue['local_id'] = issue['id'] - issue_obj = self.get_issue_for_record(issue) url = self.BASE_URL + '/'.join( issue['links']['html']['href'].split('/')[3:] diff --git a/tests/test_bitbucket.py b/tests/test_bitbucket.py index fb3cb256d..c2c13b19f 100644 --- a/tests/test_bitbucket.py +++ b/tests/test_bitbucket.py @@ -15,7 +15,7 @@ def setUp(self): def test_to_taskwarrior(self): arbitrary_issue = { 'priority': 'trivial', - 'local_id': '100', + 'id': '100', 'title': 'Some Title', } arbitrary_extra = { @@ -36,7 +36,7 @@ def test_to_taskwarrior(self): 'annotations': arbitrary_extra['annotations'], issue.URL: arbitrary_extra['url'], - issue.FOREIGN_ID: arbitrary_issue['local_id'], + issue.FOREIGN_ID: arbitrary_issue['id'], issue.TITLE: arbitrary_issue['title'], } actual_output = issue.to_taskwarrior()