Title: [284128] trunk/Tools
Revision
284128
Author
[email protected]
Date
2021-10-13 15:09:42 -0700 (Wed, 13 Oct 2021)

Log Message

[webkitscmpy] List reviewers for pull-request
https://bugs.webkit.org/show_bug.cgi?id=231577
<rdar://problem/84146807>

Reviewed by Dewei Zhu.

* Scripts/libraries/webkitscmpy/setup.py: Bump version.
* Scripts/libraries/webkitscmpy/webkitscmpy/__init__.py: Ditto.
* Scripts/libraries/webkitscmpy/webkitscmpy/mocks/remote/bitbucket.py:
(BitBucket.request): Add state to created pull-reqest.
* Scripts/libraries/webkitscmpy/webkitscmpy/mocks/remote/git_hub.py:
(GitHub):
(GitHub._users): Vend json representation of user for username.
(GitHub.request): Filter review details, add users endpoint.
* Scripts/libraries/webkitscmpy/webkitscmpy/program/pull_request.py:
(PullRequest.main): Match both closed and opened pull-requests.
* Scripts/libraries/webkitscmpy/webkitscmpy/pull_request.py:
(PullRequest): Remove state.
(PullRequest.__init__): Add opened flag, reviewers and generator.
(PullRequest.reviewers): List the users who are reviewing this change.
(PullRequest.approvers): List the users who have aproved this change.
(PullRequest.blockers): List the users that are blocking this change from landing.
(PullRequest.opened): Check the pull-request is opened.
(PullRequest.State): Deleted.
* Scripts/libraries/webkitscmpy/webkitscmpy/remote/bitbucket.py:
(BitBucket.PRGenerator.PullRequest): Set opened flag, specify reviewers.
(BitBucket.PRGenerator.find): Filter by opened flag instead of state.
(BitBucket.PRGenerator.update): Set generator.
(BitBucket.PRGenerator.reviewers): Set reviewer lists.
* Scripts/libraries/webkitscmpy/webkitscmpy/remote/git_hub.py:
(GitHub.PRGenerator.PullRequest): Set opened flag, pass generator.
(GitHub.PRGenerator.find): Filter by opened flag instead of state.
(GitHub.PRGenerator.update): Set generator and opened flag.
(GitHub.PRGenerator._contributor): Find contributor matching username.
(GitHub.PRGenerator.reviewers): Populate lists of reviewers for a pull-request.
* Scripts/libraries/webkitscmpy/webkitscmpy/remote/scm.py:
(Scm.PRGenerator.find): Filter via opened flag instead of state.
(Scm.PRGenerator.reviewers): Function which populates reviewer lists for a pull-request.
* Scripts/libraries/webkitscmpy/webkitscmpy/test/pull_request_unittest.py:

Modified Paths

Diff

Modified: trunk/Tools/ChangeLog (284127 => 284128)


--- trunk/Tools/ChangeLog	2021-10-13 21:40:32 UTC (rev 284127)
+++ trunk/Tools/ChangeLog	2021-10-13 22:09:42 UTC (rev 284128)
@@ -1,3 +1,45 @@
+2021-10-13  Jonathan Bedard  <[email protected]>
+
+        [webkitscmpy] List reviewers for pull-request
+        https://bugs.webkit.org/show_bug.cgi?id=231577
+        <rdar://problem/84146807>
+
+        Reviewed by Dewei Zhu.
+
+        * Scripts/libraries/webkitscmpy/setup.py: Bump version.
+        * Scripts/libraries/webkitscmpy/webkitscmpy/__init__.py: Ditto.
+        * Scripts/libraries/webkitscmpy/webkitscmpy/mocks/remote/bitbucket.py:
+        (BitBucket.request): Add state to created pull-reqest.
+        * Scripts/libraries/webkitscmpy/webkitscmpy/mocks/remote/git_hub.py:
+        (GitHub):
+        (GitHub._users): Vend json representation of user for username.
+        (GitHub.request): Filter review details, add users endpoint.
+        * Scripts/libraries/webkitscmpy/webkitscmpy/program/pull_request.py:
+        (PullRequest.main): Match both closed and opened pull-requests.
+        * Scripts/libraries/webkitscmpy/webkitscmpy/pull_request.py:
+        (PullRequest): Remove state.
+        (PullRequest.__init__): Add opened flag, reviewers and generator.
+        (PullRequest.reviewers): List the users who are reviewing this change.
+        (PullRequest.approvers): List the users who have aproved this change.
+        (PullRequest.blockers): List the users that are blocking this change from landing.
+        (PullRequest.opened): Check the pull-request is opened.
+        (PullRequest.State): Deleted.
+        * Scripts/libraries/webkitscmpy/webkitscmpy/remote/bitbucket.py:
+        (BitBucket.PRGenerator.PullRequest): Set opened flag, specify reviewers.
+        (BitBucket.PRGenerator.find): Filter by opened flag instead of state.
+        (BitBucket.PRGenerator.update): Set generator.
+        (BitBucket.PRGenerator.reviewers): Set reviewer lists.
+        * Scripts/libraries/webkitscmpy/webkitscmpy/remote/git_hub.py:
+        (GitHub.PRGenerator.PullRequest): Set opened flag, pass generator.
+        (GitHub.PRGenerator.find): Filter by opened flag instead of state.
+        (GitHub.PRGenerator.update): Set generator and opened flag.
+        (GitHub.PRGenerator._contributor): Find contributor matching username.
+        (GitHub.PRGenerator.reviewers): Populate lists of reviewers for a pull-request.
+        * Scripts/libraries/webkitscmpy/webkitscmpy/remote/scm.py:
+        (Scm.PRGenerator.find): Filter via opened flag instead of state.
+        (Scm.PRGenerator.reviewers): Function which populates reviewer lists for a pull-request.
+        * Scripts/libraries/webkitscmpy/webkitscmpy/test/pull_request_unittest.py:
+
 2021-10-13  Alex Christensen  <[email protected]>
 
         Remove WTF::Variant and WTF::get

Modified: trunk/Tools/Scripts/libraries/webkitscmpy/setup.py (284127 => 284128)


--- trunk/Tools/Scripts/libraries/webkitscmpy/setup.py	2021-10-13 21:40:32 UTC (rev 284127)
+++ trunk/Tools/Scripts/libraries/webkitscmpy/setup.py	2021-10-13 22:09:42 UTC (rev 284128)
@@ -29,7 +29,7 @@
 
 setup(
     name='webkitscmpy',
-    version='2.2.8',
+    version='2.2.9',
     description='Library designed to interact with git and svn repositories.',
     long_description=readme(),
     classifiers=[

Modified: trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/__init__.py (284127 => 284128)


--- trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/__init__.py	2021-10-13 21:40:32 UTC (rev 284127)
+++ trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/__init__.py	2021-10-13 22:09:42 UTC (rev 284128)
@@ -46,7 +46,7 @@
         "Please install webkitcorepy with `pip install webkitcorepy --extra-index-url <package index URL>`"
     )
 
-version = Version(2, 2, 8)
+version = Version(2, 2, 9)
 
 AutoInstall.register(Package('fasteners', Version(0, 15, 0)))
 AutoInstall.register(Package('monotonic', Version(1, 5)))

Modified: trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/mocks/remote/bitbucket.py (284127 => 284128)


--- trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/mocks/remote/bitbucket.py	2021-10-13 21:40:32 UTC (rev 284127)
+++ trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/mocks/remote/bitbucket.py	2021-10-13 22:09:42 UTC (rev 284128)
@@ -222,6 +222,7 @@
             json['id'] = 1 + max([0] + [pr.get('id', 0) for pr in self.pull_requests])
             json['fromRef']['displayId'] = json['fromRef']['id'].split('/')[-2:]
             json['toRef']['displayId'] = json['toRef']['id'].split('/')[-2:]
+            json['state'] = 'OPEN'
             self.pull_requests.append(json)
             return mocks.Response.fromJson(json)
 

Modified: trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/mocks/remote/git_hub.py (284127 => 284128)


--- trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/mocks/remote/git_hub.py	2021-10-13 21:40:32 UTC (rev 284127)
+++ trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/mocks/remote/git_hub.py	2021-10-13 22:09:42 UTC (rev 284128)
@@ -59,6 +59,7 @@
         self.head = self.commits[self.default_branch][-1]
         self.tags = {}
         self.pull_requests = []
+        self.users = dict()
         self._environment = None
 
     def __enter__(self):
@@ -281,6 +282,15 @@
             ), url=""
         )
 
+    def _users(self, url, username):
+        user = self.users.get(username)
+        if not user:
+            return mocks.Response.create404(url)
+        return mocks.Response.fromJson(dict(
+            name=user.name,
+            email=user.email,
+        ), url=""
+
     def request(self, method, url, data="" params=None, auth=None, json=None, **kwargs):
         if not url.startswith('http://') and not url.startswith('https://'):
             return mocks.Response.create404(url)
@@ -357,8 +367,16 @@
         # Pull-request by number
         if method == 'GET' and stripped_url.startswith(pr_base):
             for candidate in self.pull_requests:
-                if stripped_url.split('/')[-1] == str(candidate['number']):
-                    return mocks.Response.fromJson(candidate, url=""
+                if stripped_url.split('/')[5] == str(candidate['number']):
+                    if len(stripped_url.split('/')) == 7:
+                        if stripped_url.split('/')[6] == 'requested_reviewers':
+                            return mocks.Response.fromJson(dict(users=candidate.get('requested_reviews', [])))
+                        if stripped_url.split('/')[6] == 'reviews':
+                            return mocks.Response.fromJson(candidate.get('reviews', []))
+                        return mocks.Response.create404(url)
+                    return mocks.Response.fromJson({
+                        key: value for key, value in candidate.items() if key not in ('requested_reviews', 'reviews')
+                    }, url=""
             return mocks.Response.create404(url)
 
         # Create/update pull-request
@@ -398,6 +416,10 @@
             if existing is None:
                 return mocks.Response.create404(url)
             self.pull_requests[existing].update(pr)
-            return mocks.Response.fromJson(self.pull_requests[i], url=""
+            return mocks.Response.fromJson(self.pull_requests[existing], url=""
 
+        # Access user
+        if method == 'GET' and stripped_url.startswith('{}/users'.format(self.api_remote.split('/')[0])):
+            return self._users(url, stripped_url.split('/')[-1])
+
         return mocks.Response.create404(url)

Modified: trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/program/pull_request.py (284127 => 284128)


--- trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/program/pull_request.py	2021-10-13 21:40:32 UTC (rev 284127)
+++ trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/program/pull_request.py	2021-10-13 22:09:42 UTC (rev 284128)
@@ -121,7 +121,7 @@
             sys.stderr.write("'{}' cannot generate pull-requests\n".format(rmt.url))
             return 1
         user, _ = rmt.credentials(required=True) if isinstance(rmt, remote.GitHub) else (repository.config()['user.email'], None)
-        candidates = list(rmt.pull_requests.find(head=repository.branch))
+        candidates = list(rmt.pull_requests.find(opened=None, head=repository.branch))
         commits = list(repository.commits(begin=dict(hash=branch_point.hash), end=dict(branch=repository.branch)))
 
         title = commits[0].message.splitlines()[0]

Modified: trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/pull_request.py (284127 => 284128)


--- trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/pull_request.py	2021-10-13 21:40:32 UTC (rev 284127)
+++ trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/pull_request.py	2021-10-13 22:09:42 UTC (rev 284128)
@@ -44,10 +44,6 @@
         '&': '&amp;',
     }
 
-    class State(object):
-        OPENED = 'opened'
-        CLOSED = 'closed'
-
     @classmethod
     def escape_html(cls, message):
         message = ''.join(cls.ESCAPE_TABLE.get(c, c) for c in message)
@@ -103,7 +99,7 @@
                     body = part.rstrip().lstrip()
         return body or None, commits
 
-    def __init__(self, number, title=None, body=None, author=None, head=None, base=None):
+    def __init__(self, number, title=None, body=None, author=None, head=None, base=None, opened=None, generator=None):
         self.number = number
         self.title = title
         self.body, self.commits = self.parse_body(body)
@@ -110,6 +106,35 @@
         self.author = author
         self.head = head
         self.base = base
+        self._opened = opened
+        self._reviewers = None
+        self._approvers = None
+        self._blockers = None
+        self.generator = generator
 
+    @property
+    def reviewers(self):
+        if self._reviewers is None and self.generator:
+            self.generator.reviewers(self)
+        return self._reviewers
+
+    @property
+    def approvers(self):
+        if self._approvers is None and self.generator:
+            self.generator.reviewers(self)
+        return self._approvers
+
+    @property
+    def blockers(self):
+        if self._blockers is None and self.generator:
+            self.generator.reviewers(self)
+        return self._blockers
+
+    @property
+    def opened(self):
+        if self._opened is None:
+            return '?'
+        return self._opened
+
     def __repr__(self):
         return 'PR {}{}'.format(self.number, ' | {}'.format(self.title) if self.title else '')

Modified: trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/remote/bitbucket.py (284127 => 284128)


--- trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/remote/bitbucket.py	2021-10-13 21:40:32 UTC (rev 284127)
+++ trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/remote/bitbucket.py	2021-10-13 22:09:42 UTC (rev 284128)
@@ -42,30 +42,52 @@
         def PullRequest(self, data):
             if not data:
                 return None
-            return PullRequest(
+            result = PullRequest(
                 number=data['id'],
                 title=data.get('title'),
                 body=data.get('description'),
                 author=self.repository.contributors.create(
                     data['author']['user']['displayName'],
-                    data['author']['user']['emailAddress'],
+                    data['author']['user'].get('emailAddress', None),
                 ), head=data['fromRef']['displayId'],
                 base=data['toRef']['displayId'],
+                opened=True if data.get('open') else (False if data.get('closed') else None),
+                generator=self,
             )
 
+            result._reviewers = []
+            result._approvers = []
+            result._blockers = []
+            for rdata in data.get('reviewers', []):
+                reviewer = self.repository.contributors.create(
+                    rdata['user']['displayName'],
+                    rdata['user'].get('emailAddress', None),
+                )
+                result._reviewers.append(reviewer)
+                if rdata.get('approved', False):
+                    result._approvers.append(reviewer)
+                if rdata.get('status') == 'NEEDS_WORK':
+                    result._blockers.append(reviewer)
+
+            result._reviewers = sorted(result._reviewers)
+            return result
+
         def get(self, number):
             return self.PullRequest(self.repository.request('pull-requests/{}'.format(int(number))))
 
-        def find(self, state=None, head=None, base=None):
+        def find(self, opened=True, head=None, base=None):
+            assert opened in (True, False, None)
+
             params = dict(
                 limit=100,
                 withProperties='false',
                 withAttributes='false',
             )
-            if state == PullRequest.State.OPENED:
+            if opened is True:
                 params['state'] = 'OPEN'
-            if state == PullRequest.State.CLOSED:
+            elif not opened:
                 params['state'] = ['DECLINED', 'MERGED', 'SUPERSEDED']
+
             if head:
                 params['direction'] = 'OUTGOING'
                 params['at'] = 'refs/heads/{}'.format(head)
@@ -75,6 +97,15 @@
                     continue
                 yield self.PullRequest(datum)
 
+            # Stash is bad at filter for open and closed PRs at the same time
+            if opened is None:
+                params['state'] = 'OPEN'
+                data = "" params=params)
+                for datum in data or []:
+                    if base and not datum['toRef']['id'].endswith(base):
+                        continue
+                    yield self.PullRequest(datum)
+
         def create(self, head, title, body=None, commits=None, base=None):
             for key, value in dict(head=head, title=title).items():
                 if not value:
@@ -173,9 +204,15 @@
                 pull_request.author = self.repository.contributors.create(user['displayName'], user['emailAddress'])
             pull_request.head = data.get('fromRef', {}).get('displayId', pull_request.base)
             pull_request.base = data.get('toRef', {}).get('displayId', pull_request.base)
+            pull_request.generator = self
 
             return pull_request
 
+        def reviewers(self, pull_request):
+            got = self.get(pull_request.number)
+            pull_request._reviewers = got._reviewers if got else []
+            pull_request._approvers = got._approvers if got else []
+            return pull_request
 
     @classmethod
     def is_webserver(cls, url):

Modified: trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/remote/git_hub.py (284127 => 284128)


--- trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/remote/git_hub.py	2021-10-13 21:40:32 UTC (rev 284127)
+++ trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/remote/git_hub.py	2021-10-13 22:09:42 UTC (rev 284128)
@@ -29,7 +29,7 @@
 from datetime import datetime
 from requests.auth import HTTPBasicAuth
 from webkitcorepy import credentials, decorators
-from webkitscmpy import Commit, PullRequest
+from webkitscmpy import Commit, Contributor, PullRequest
 from webkitscmpy.remote.scm import Scm
 from xml.dom import minidom
 
@@ -49,17 +49,26 @@
                 author=self.repository.contributors.create(data['user']['login']),
                 head=data['head']['ref'],
                 base=data['base']['ref'],
+                opened=dict(
+                    open=True,
+                    closed=False,
+                ).get(data.get('state'), None),
+                generator=self,
             )
 
         def get(self, number):
             return self.PullRequest(self.repository.request('pulls/{}'.format(int(number))))
 
-        def find(self, state=None, head=None, base=None):
-            if not state:
-                state = 'all'
+        def find(self, opened=True, head=None, base=None):
+            assert opened in (True, False, None)
+
             user, _ = self.repository.credentials()
             data = "" params=dict(
-                state=state,
+                state={
+                    None: 'all',
+                    True: 'open',
+                    False: 'closed',
+                }.get(opened),
                 base=base,
                 head='{}:{}'.format(user, head) if user and head else head,
             ))
@@ -129,10 +138,52 @@
                 pull_request.author = self.repository.contributors.create(data['user']['login'])
             pull_request.head = data.get('head', {}).get('displayId', pull_request.base)
             pull_request.base = data.get('base', {}).get('displayId', pull_request.base)
+            pull_request._opened = dict(
+                open=True,
+                closed=False,
+            ).get(data.get('state'), None),
+            pull_request.generator = self
 
             return pull_request
 
+        def _contributor(self, username):
+            result = self.repository.contributors.get(username, None)
+            if result:
+                return result
 
+            response = requests.get(
+                '{api_url}/users/{username}'.format(
+                    api_url=self.repository.api_url,
+                    username=username,
+                ), auth=HTTPBasicAuth(*self.repository.credentials(required=True)),
+                headers=dict(Accept='application/vnd.github.v3+json'),
+            )
+            if response.status_code // 100 != 2:
+                return Contributor(username)
+
+            data = ""
+            result = self.repository.contributors.create(data.get('name', username), data.get('email'))
+            result.github = username
+            self.repository.contributors[username] = result
+            return result
+
+        def reviewers(self, pull_request):
+            response = self.repository.request('pulls/{}/requested_reviewers'.format(pull_request.number))
+            pull_request._reviewers = [self._contributor(user['login']) for user in response.get('users', [])]
+            pull_request._approvers = []
+            pull_request._blockers = []
+            for review in self.repository.request('pulls/{}/reviews'.format(pull_request.number)):
+                contributor = self._contributor(review['user']['login'])
+                pull_request._reviewers.append(contributor)
+                if review.get('state') == 'APPROVED':
+                    pull_request._approvers.append(contributor)
+                elif review.get('state') == 'CHANGES_REQUESTED':
+                    pull_request._blockers.append(contributor)
+
+            pull_request._reviewers = sorted(pull_request._reviewers)
+            return pull_request
+
+
     @classmethod
     def is_webserver(cls, url):
         return True if cls.URL_RE.match(url) else False

Modified: trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/remote/scm.py (284127 => 284128)


--- trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/remote/scm.py	2021-10-13 21:40:32 UTC (rev 284127)
+++ trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/remote/scm.py	2021-10-13 22:09:42 UTC (rev 284128)
@@ -1,4 +1,4 @@
-# Copyright (C) 2020 Apple Inc. All rights reserved.
+# Copyright (C) 2020, 2021 Apple Inc. All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
 # modification, are permitted provided that the following conditions
@@ -33,7 +33,7 @@
         def get(self, number):
             raise NotImplementedError()
 
-        def find(self, state=None, head=None, base=None):
+        def find(self, opened=True, head=None, base=None):
             raise NotImplementedError()
 
         def create(self, head, title, body=None, commits=None, base=None):
@@ -42,7 +42,10 @@
         def update(self, pull_request, head=None, title=None, body=None, commits=None, base=None):
             raise NotImplementedError()
 
+        def reviewers(self, pull_request):
+            raise NotImplementedError()
 
+
     @classmethod
     def from_url(cls, url, contributors=None):
         from webkitscmpy import remote

Modified: trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/test/pull_request_unittest.py (284127 => 284128)


--- trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/test/pull_request_unittest.py	2021-10-13 21:40:32 UTC (rev 284127)
+++ trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/test/pull_request_unittest.py	2021-10-13 22:09:42 UTC (rev 284128)
@@ -25,7 +25,7 @@
 import unittest
 
 from webkitcorepy import OutputCapture, testing
-from webkitscmpy import Commit, PullRequest, program, mocks, remote
+from webkitscmpy import Contributor, Commit, PullRequest, program, mocks, remote
 
 
 class TestPullRequest(unittest.TestCase):
@@ -433,6 +433,12 @@
     @classmethod
     def webserver(cls):
         result = mocks.remote.GitHub()
+        result.users = dict(
+            ereviewer=Contributor('Eager Reviewer', ['[email protected]'], github='ereviewer'),
+            rreviewer=Contributor('Reluctant Reviewer', ['[email protected]'], github='rreviewer'),
+            sreviewer=Contributor('Suspicious Reviewer', ['[email protected]'], github='sreviewer'),
+            tcontributor=Contributor('Tim Contributor', ['[email protected]']),
+        )
         result.pull_requests = [dict(
             number=1,
             state='open',
@@ -450,6 +456,11 @@
 ''',
             head=dict(ref='eng/pull-request'),
             base=dict(ref='main'),
+            requested_reviews=[dict(login='rreviewer')],
+            reviews=[
+                dict(user=dict(login='ereviewer'), state='APPROVED'),
+                dict(user=dict(login='sreviewer'), state='CHANGES_REQUESTED'),
+            ],
         )]
         return result
 
@@ -466,11 +477,23 @@
         with self.webserver():
             pr = remote.GitHub(self.remote).pull_requests.get(1)
             self.assertEqual(pr.number, 1)
+            self.assertTrue(pr.opened)
             self.assertEqual(pr.title, 'Example Change')
             self.assertEqual(pr.head, 'eng/pull-request')
             self.assertEqual(pr.base, 'main')
 
+    def test_reviewers(self):
+        with self.webserver():
+            pr = remote.GitHub(self.remote).pull_requests.get(1)
+            self.assertEqual(pr.reviewers, [
+                Contributor('Eager Reviewer', ['[email protected]']),
+                Contributor('Reluctant Reviewer', ['[email protected]']),
+                Contributor('Suspicious Reviewer', ['[email protected]']),
+            ])
+            self.assertEqual(pr.approvers, [Contributor('Eager Reviewer', ['[email protected]'])])
+            self.assertEqual(pr.blockers, [Contributor('Suspicious Reviewer', ['[email protected]'])])
 
+
 class TestNetworkPullRequestBitBucket(unittest.TestCase):
     remote = 'https://bitbucket.example.com/projects/WEBKIT/repos/webkit'
 
@@ -480,6 +503,8 @@
         result.pull_requests = [dict(
             id=1,
             state='OPEN',
+            open=True,
+            closed=False,
             title='Example Change',
             author=dict(
                 user=dict(
@@ -499,6 +524,24 @@
 ''',
             fromRef=dict(displayId='eng/pull-request'),
             toRef=dict(displayId='main'),
+            reviewers=[
+                dict(
+                    user=dict(
+                        displayName='Reluctant Reviewer',
+                        emailAddress='[email protected]',
+                    ), approved=False,
+                ), dict(
+                    user=dict(
+                        displayName='Eager Reviewer',
+                        emailAddress='[email protected]',
+                    ), approved=True,
+                ), dict(
+                    user=dict(
+                        displayName='Suspicious Reviewer',
+                        emailAddress='[email protected]',
+                    ), status='NEEDS_WORK',
+                ),
+            ],
         )]
         return result
 
@@ -516,6 +559,18 @@
         with self.webserver():
             pr = remote.BitBucket(self.remote).pull_requests.get(1)
             self.assertEqual(pr.number, 1)
+            self.assertTrue(pr.opened)
             self.assertEqual(pr.title, 'Example Change')
             self.assertEqual(pr.head, 'eng/pull-request')
             self.assertEqual(pr.base, 'main')
+
+    def test_reviewers(self):
+        with self.webserver():
+            pr = remote.BitBucket(self.remote).pull_requests.get(1)
+            self.assertEqual(pr.reviewers, [
+                Contributor('Eager Reviewer', ['[email protected]']),
+                Contributor('Reluctant Reviewer', ['[email protected]']),
+                Contributor('Suspicious Reviewer', ['[email protected]']),
+            ])
+            self.assertEqual(pr.approvers, [Contributor('Eager Reviewer', ['[email protected]'])])
+            self.assertEqual(pr.blockers, [Contributor('Suspicious Reviewer', ['[email protected]'])])
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to