diff --git a/github/Consts.py b/github/Consts.py index 1a8abb13..7fed7ec7 100644 --- a/github/Consts.py +++ b/github/Consts.py @@ -120,3 +120,6 @@ issueTimelineEventsPreview = "application/vnd.github.mockingbird-preview" # https://developer.github.com/changes/2019-02-14-draft-pull-requests/ draftPullRequestPreview = "application/vnd.github.shadow-cat-preview+json" + +# https://developer.github.com/v3/teams/#check-if-a-team-manages-a-repository +teamRepositoryPermissions = "application/vnd.github.v3.repository+json" diff --git a/github/Team.py b/github/Team.py index ec8b6ea4..94da1a4f 100644 --- a/github/Team.py +++ b/github/Team.py @@ -47,6 +47,7 @@ import github.Organization import github.PaginatedList import github.Repository import github.TeamDiscussion +from github.GithubException import UnknownObjectException from . import Consts @@ -210,6 +211,29 @@ class Team(github.GithubObject.CompletableGithubObject): "PUT", self.url + "/repos/" + repo._identity ) + def get_repo_permission(self, repo): + """ + :calls: `GET /teams/:id/repos/:org/:repo `_ + :param repo: string or :class:`github.Repository.Repository` + :rtype: None or :class:`github.Permissions.Permissions` + """ + assert isinstance(repo, github.Repository.Repository) or isinstance( + repo, str + ), repo + if isinstance(repo, github.Repository.Repository): + repo = repo._identity + try: + headers, data = self._requester.requestJsonAndCheck( + "GET", + self.url + "/repos/" + repo, + headers={"Accept": Consts.teamRepositoryPermissions}, + ) + return github.Permissions.Permissions( + self._requester, headers, data["permissions"], completed=True + ) + except UnknownObjectException: + return None + def set_repo_permission(self, repo, permission): """ :calls: `PUT /teams/:id/repos/:org/:repo `_ diff --git a/tests/ReplayData/Team.testRepos.txt b/tests/ReplayData/Team.testRepos.txt index a223d021..df7ca747 100644 --- a/tests/ReplayData/Team.testRepos.txt +++ b/tests/ReplayData/Team.testRepos.txt @@ -31,6 +31,17 @@ None [('status', '404 Not Found'), ('x-ratelimit-remaining', '4961'), ('content-length', '23'), ('server', 'nginx/1.0.13'), ('connection', 'keep-alive'), ('x-ratelimit-limit', '5000'), ('etag', '"e66a7a6c91e2c26803f3f49feb7a883f"'), ('date', 'Sat, 26 May 2012 21:12:36 GMT'), ('content-type', 'application/json; charset=utf-8')] {"message":"Not Found"} +https +GET +api.github.com +None +/teams/189850/repos/BeaverSoftware/FatherBeaver +{'Accept': 'application/vnd.github.v3.repository+json', 'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python'} +None +404 +[('Date', 'Thu, 12 Mar 2020 09:53:56 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Transfer-Encoding', 'chunked'), ('Server', 'GitHub.com'), ('Status', '404 Not Found'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4957'), ('X-RateLimit-Reset', '1584009061'), ('X-OAuth-Scopes', 'admin:org, admin:org_hook, admin:repo_hook, gist, notifications, repo'), ('X-Accepted-OAuth-Scopes', 'admin:org, read:org, repo, user, write:org'), ('X-GitHub-Media-Type', 'github.v3; param=repository; format=json'), ('Access-Control-Expose-Headers', 'ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, Deprecation, Sunset'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '1; mode=block'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('Vary', 'Accept-Encoding, Accept, X-Requested-With'), ('Content-Encoding', 'gzip'), ('X-GitHub-Request-Id', '7531:2AC71:113BA58:14377AF:5E6A06B4')] +{"message":"Not Found","documentation_url":"https://developer.github.com/v3/teams/#check-if-a-team-manages-a-repository"} + https PUT api.github.com @@ -64,6 +75,17 @@ None [('status', '204 No Content'), ('x-ratelimit-remaining', '4958'), ('server', 'nginx/1.0.13'), ('connection', 'keep-alive'), ('x-ratelimit-limit', '5000'), ('etag', '"d41d8cd98f00b204e9800998ecf8427e"'), ('date', 'Sat, 26 May 2012 21:12:38 GMT')] +https +GET +api.github.com +None +/teams/189850/repos/BeaverSoftware/FatherBeaver +{'Accept': 'application/vnd.github.v3.repository+json', 'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python'} +None +200 +[('Date', 'Thu, 12 Mar 2020 09:53:58 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Transfer-Encoding', 'chunked'), ('Server', 'GitHub.com'), ('Status', '200 OK'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4953'), ('X-RateLimit-Reset', '1584009062'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP, Accept-Encoding, Accept, X-Requested-With'), ('ETag', 'W/"a31a36f26f6f48310a2ce1ad5ec9c01e"'), ('X-OAuth-Scopes', 'admin:org, admin:org_hook, admin:repo_hook, gist, notifications, repo'), ('X-Accepted-OAuth-Scopes', 'admin:org, read:org, repo, user, write:org'), ('X-GitHub-Media-Type', 'github.v3; param=repository; format=json'), ('Access-Control-Expose-Headers', 'ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, Deprecation, Sunset'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '1; mode=block'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('Content-Encoding', 'gzip'), ('X-GitHub-Request-Id', '7535:2AC72:191F312:1D8B844:5E6A06B5')] +{"id":246797574,"node_id":"MDEwOlJlcG9zaXRvcnkyNDY3OTc1NzQ=","name":"FatherBeaver","full_name":"BeaverSoftware/FatherBeaver","private":false,"owner":{"login":"BeaverSoftware","id":59395943,"node_id":"MDEyOk9yZ2FuaXphdGlvbjU5Mzk1OTQz","avatar_url":"https://avatars0.githubusercontent.com/u/59395943?v=4","gravatar_id":"","url":"https://api.github.com/users/BeaverSoftware","html_url":"https://github.com/BeaverSoftware","followers_url":"https://api.github.com/users/BeaverSoftware/followers","following_url":"https://api.github.com/users/BeaverSoftware/following{/other_user}","gists_url":"https://api.github.com/users/BeaverSoftware/gists{/gist_id}","starred_url":"https://api.github.com/users/BeaverSoftware/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/BeaverSoftware/subscriptions","organizations_url":"https://api.github.com/users/BeaverSoftware/orgs","repos_url":"https://api.github.com/users/BeaverSoftware/repos","events_url":"https://api.github.com/users/BeaverSoftware/events{/privacy}","received_events_url":"https://api.github.com/users/BeaverSoftware/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/BeaverSoftware/FatherBeaver","description":"Typed interactions with the GitHub API v3","fork":true,"url":"https://api.github.com/repos/BeaverSoftware/FatherBeaver","forks_url":"https://api.github.com/repos/BeaverSoftware/FatherBeaver/forks","keys_url":"https://api.github.com/repos/BeaverSoftware/FatherBeaver/keys{/key_id}","collaborators_url":"https://api.github.com/repos/BeaverSoftware/FatherBeaver/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/BeaverSoftware/FatherBeaver/teams","hooks_url":"https://api.github.com/repos/BeaverSoftware/FatherBeaver/hooks","issue_events_url":"https://api.github.com/repos/BeaverSoftware/FatherBeaver/issues/events{/number}","events_url":"https://api.github.com/repos/BeaverSoftware/FatherBeaver/events","assignees_url":"https://api.github.com/repos/BeaverSoftware/FatherBeaver/assignees{/user}","branches_url":"https://api.github.com/repos/BeaverSoftware/FatherBeaver/branches{/branch}","tags_url":"https://api.github.com/repos/BeaverSoftware/FatherBeaver/tags","blobs_url":"https://api.github.com/repos/BeaverSoftware/FatherBeaver/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/BeaverSoftware/FatherBeaver/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/BeaverSoftware/FatherBeaver/git/refs{/sha}","trees_url":"https://api.github.com/repos/BeaverSoftware/FatherBeaver/git/trees{/sha}","statuses_url":"https://api.github.com/repos/BeaverSoftware/FatherBeaver/statuses/{sha}","languages_url":"https://api.github.com/repos/BeaverSoftware/FatherBeaver/languages","stargazers_url":"https://api.github.com/repos/BeaverSoftware/FatherBeaver/stargazers","contributors_url":"https://api.github.com/repos/BeaverSoftware/FatherBeaver/contributors","subscribers_url":"https://api.github.com/repos/BeaverSoftware/FatherBeaver/subscribers","subscription_url":"https://api.github.com/repos/BeaverSoftware/FatherBeaver/subscription","commits_url":"https://api.github.com/repos/BeaverSoftware/FatherBeaver/commits{/sha}","git_commits_url":"https://api.github.com/repos/BeaverSoftware/FatherBeaver/git/commits{/sha}","comments_url":"https://api.github.com/repos/BeaverSoftware/FatherBeaver/comments{/number}","issue_comment_url":"https://api.github.com/repos/BeaverSoftware/FatherBeaver/issues/comments{/number}","contents_url":"https://api.github.com/repos/BeaverSoftware/FatherBeaver/contents/{+path}","compare_url":"https://api.github.com/repos/BeaverSoftware/FatherBeaver/compare/{base}...{head}","merges_url":"https://api.github.com/repos/BeaverSoftware/FatherBeaver/merges","archive_url":"https://api.github.com/repos/BeaverSoftware/FatherBeaver/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/BeaverSoftware/FatherBeaver/downloads","issues_url":"https://api.github.com/repos/BeaverSoftware/FatherBeaver/issues{/number}","pulls_url":"https://api.github.com/repos/BeaverSoftware/FatherBeaver/pulls{/number}","milestones_url":"https://api.github.com/repos/BeaverSoftware/FatherBeaver/milestones{/number}","notifications_url":"https://api.github.com/repos/BeaverSoftware/FatherBeaver/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/BeaverSoftware/FatherBeaver/labels{/name}","releases_url":"https://api.github.com/repos/BeaverSoftware/FatherBeaver/releases{/id}","deployments_url":"https://api.github.com/repos/BeaverSoftware/FatherBeaver/deployments","created_at":"2020-03-12T09:45:04Z","updated_at":"2020-03-12T09:45:06Z","pushed_at":"2020-03-11T18:51:42Z","git_url":"git://github.com/BeaverSoftware/FatherBeaver.git","ssh_url":"git@github.com:BeaverSoftware/FatherBeaver.git","clone_url":"https://github.com/BeaverSoftware/FatherBeaver.git","svn_url":"https://github.com/BeaverSoftware/FatherBeaver","homepage":"","size":12540,"stargazers_count":0,"watchers_count":0,"language":null,"has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"disabled":false,"open_issues_count":0,"license":{"key":"lgpl-3.0","name":"GNU Lesser General Public License v3.0","spdx_id":"LGPL-3.0","url":"https://api.github.com/licenses/lgpl-3.0","node_id":"MDc6TGljZW5zZTEy"},"forks":0,"open_issues":0,"watchers":0,"default_branch":"master","permissions":{"pull":true,"triage":false,"push":false,"maintain":false,"admin":false}} + https DELETE api.github.com @@ -96,4 +118,3 @@ None 404 [('status', '404 Not Found'), ('x-ratelimit-remaining', '4955'), ('content-length', '23'), ('server', 'nginx/1.0.13'), ('connection', 'keep-alive'), ('x-ratelimit-limit', '5000'), ('etag', '"e66a7a6c91e2c26803f3f49feb7a883f"'), ('date', 'Sat, 26 May 2012 21:12:39 GMT'), ('content-type', 'application/json; charset=utf-8')] {"message":"Not Found"} - diff --git a/tests/Team.py b/tests/Team.py index a81fe374..f9e3a248 100644 --- a/tests/Team.py +++ b/tests/Team.py @@ -114,11 +114,14 @@ class Team(Framework.TestCase): repo = self.org.get_repo("FatherBeaver") self.assertListKeyEqual(self.team.get_repos(), None, []) self.assertFalse(self.team.has_in_repos(repo)) + self.assertIsNone(self.team.get_repo_permission(repo)) self.team.add_to_repos(repo) self.assertListKeyEqual( self.team.get_repos(), lambda r: r.name, ["FatherBeaver"] ) self.assertTrue(self.team.has_in_repos(repo)) + permissions = self.team.get_repo_permission(repo) + self.assertTrue(permissions.pull) self.team.remove_from_repos(repo) self.assertListKeyEqual(self.team.get_repos(), None, []) self.assertFalse(self.team.has_in_repos(repo))