Correct API for NamedUser.get_organization_membership (#1277)

NamedUser.get_organization_membership() was calling the API method for
fetching the currently authenticated user only, which is incorrect. The
method was not tested directly, so add tests.  Furthermore, Membership
had some errors which had slipped through review, so correct them.

Sadly, this is an API break, since passing the organization as an int
made no sense in this case.

Fixes #1276
This commit is contained in:
Steve Kowalik
2019-10-31 20:56:46 +11:00
committed by GitHub
parent 6ad592b1b6
commit 077c80ba2d
5 changed files with 52 additions and 6 deletions
+3 -3
View File
@@ -45,7 +45,7 @@ import github.GithubObject
class Membership(github.GithubObject.CompletableGithubObject):
"""
This class represents Organizations. The reference can be found here http://developer.github.com/v3/orgs/
This class represents Membership of an organization. The reference can be found here http://developer.github.com/v3/orgs/
"""
def __repr__(self):
@@ -94,7 +94,7 @@ class Membership(github.GithubObject.CompletableGithubObject):
@property
def user(self):
"""
:type: :class:`github.AuthenticatedUser.AuthenticatedUser`
:type: :class:`github.NamedUser.NamedUser`
"""
self._completeIfNotSet(self._user)
return self._user.value
@@ -119,4 +119,4 @@ class Membership(github.GithubObject.CompletableGithubObject):
if "organization" in attributes: # pragma no branch
self._organization = self._makeClassAttribute(github.Organization.Organization, attributes["organization"])
if "user" in attributes: # pragma no branch
self._user = self._makeClassAttribute(github.AuthenticatedUser.AuthenticatedUser, attributes["user"])
self._user = self._makeClassAttribute(github.NamedUser.NamedUser, attributes["user"])
+6 -3
View File
@@ -626,13 +626,16 @@ class NamedUser(github.GithubObject.CompletableGithubObject):
def get_organization_membership(self, org):
"""
:calls: `GET /user/memberships/orgs/:org <https://developer.github.com/v3/orgs/members/#get-your-organization-membership>`_
:calls: `GET /orgs/:org/memberships/:username <https://developer.github.com/v3/orgs/members/#get-organization-membership>`_
:param org: string or :class:`github.Organization.Organization`
:rtype: :class:`github.Membership.Membership`
"""
assert isinstance(org, int)
assert isinstance(org, (str, six.text_type)) or isinstance(org, github.Organization.Organization), org
if isinstance(org, github.Organization.Organization):
org = org.login
headers, data = self._requester.requestJsonAndCheck(
"GET",
"/user/memberships/orgs/" + str(org)
"/orgs/" + org + "/memberships/" + self.login
)
return github.Membership.Membership(self._requester, headers, data, completed=True)
+11
View File
@@ -127,6 +127,17 @@ class NamedUser(Framework.TestCase):
def testGetOrgs(self):
self.assertListKeyEqual(self.user.get_orgs(), lambda o: o.login, ["BeaverSoftware"])
def testGetOrganizationMembership(self):
o = self.user.get_orgs()
membership = self.user.get_organization_membership(o[0])
self.assertEqual(self.user.login, membership.user.login)
self.assertEqual(membership.state, "active")
self.assertEqual(membership.role, "member")
def testGetOrganizationMembershipNotMember(self):
from github import UnknownObjectException
self.assertRaises(UnknownObjectException, self.user.get_organization_membership, "BeaverSoftware")
def testGetRepo(self):
self.assertEqual(self.user.get_repo("PyGithub").description, "Python library implementing the full Github API v3")
@@ -0,0 +1,22 @@
https
GET
api.github.com
None
/users/jacquev6/orgs
{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python'}
None
200
[('status', '200 OK'), ('x-ratelimit-remaining', '4949'), ('content-length', '262'), ('server', 'nginx/1.0.13'), ('connection', 'keep-alive'), ('x-ratelimit-limit', '5000'), ('etag', '"82deae94305d8c551e4874e06f6efd48"'), ('date', 'Tue, 29 Oct 2019 06:37:43 GMT'), ('content-type', 'application/json; charset=utf-8')]
[{"avatar_url":"https://secure.gravatar.com/avatar/d563e337cac2fdc644e2aaaad1e23266?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-orgs.png","url":"https://api.github.com/orgs/BeaverSoftware","login":"BeaverSoftware","id":1424031}]
https
GET
api.github.com
None
/orgs/BeaverSoftware/memberships/jacquev6
{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python'}
None
200
[('vary', 'Accept, Authorization, Cookie, X-GitHub-OTP, Accept-Encoding'), ('x-oauth-scopes', 'admin:enterprise, admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, delete:packages, delete_repo, gist, notifications, read:packages, repo, user, workflow, write:discussion, write:packages'), ('x-xss-protection', '1; mode=block'), ('x-content-type-options', 'nosniff'), ('x-accepted-oauth-scopes', 'admin:org, read:org, repo, user, write:org'), ('etag', 'W/"a48fb9108de1ab30ca11a7d7b676b7d0"'), ('cache-control', 'private, max-age=60, s-maxage=60'), ('referrer-policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('status', '200 OK'), ('x-ratelimit-remaining', '4997'), ('x-github-media-type', 'github.v3; 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'), ('transfer-encoding', 'chunked'), ('x-github-request-id', '965A:5675:180111:1B9D26:5DB7F14D'), ('date', 'Tue, 29 Oct 2019 07:59:15 GMT'), ('access-control-allow-origin', '*'), ('content-security-policy', "default-src 'none'"), ('content-encoding', 'gzip'), ('strict-transport-security', 'max-age=31536000; includeSubdomains; preload'), ('server', 'GitHub.com'), ('x-ratelimit-limit', '5000'), ('x-frame-options', 'deny'), ('content-type', 'application/json; charset=utf-8'), ('x-ratelimit-reset', '1572339549')]
{"url":"https://api.github.com/orgs/BeaverSoftware/memberships/jacquev6","state":"active","role":"member","user":{"following_url":"https://api.github.com/users/jacquev6/following{/other_user}","events_url":"https://api.github.com/users/jacquev6/events{/privacy}","avatar_url":"https://avatars0.githubusercontent.com/u/15225059?v=4","url":"https://api.github.com/users/jacquev6","gists_url":"https://api.github.com/users/jacquev6/gists{/gist_id}","html_url":"https://github.com/jacquev6","subscriptions_url":"https://api.github.com/users/jacquev6/subscriptions","node_id":"MDQ6VXNlcjE1MjI1MDU5","repos_url":"https://api.github.com/users/jacquev6/repos","received_events_url":"https://api.github.com/users/jacquev6/received_events","gravatar_id":"","starred_url":"https://api.github.com/users/jacquev6/starred{/owner}{/repo}","site_admin":false,"login":"jacquev6","type":"User","id":15225059,"followers_url":"https://api.github.com/users/jacquev6/followers","organizations_url":"https://api.github.com/users/jacquev6/orgs"},"organization":{"issues_url":"https://api.github.com/orgs/BeaverSoftware/issues","members_url":"https://api.github.com/orgs/BeaverSoftware/members{/member}","description":null,"public_members_url":"https://api.github.com/orgs/BeaverSoftware/public_members{/member}","url":"https://api.github.com/orgs/BeaverSoftware","events_url":"https://api.github.com/orgs/BeaverSoftware/events","avatar_url":"https://avatars0.githubusercontent.com/u/1553906?v=4","node_id":"MDEyOk9yZ2FuaXphdGlvbjE1NTM5MDY=","repos_url":"https://api.github.com/orgs/BeaverSoftware/repos","login":"BeaverSoftware","id":1553906,"hooks_url":"https://api.github.com/orgs/BeaverSoftware/hooks"},"organization_url":"https://api.github.com/orgs/BeaverSoftware"}
@@ -0,0 +1,10 @@
https
GET
api.github.com
None
/orgs/BeaverSoftware/memberships/jacquev6
{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python'}
None
404
[('status', '404 Not Found'), ('x-ratelimit-remaining', '4994'), ('x-github-media-type', 'github.v3; format=json'), ('content-security-policy', "default-src 'none'"), ('x-content-type-options', 'nosniff'), ('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'), ('transfer-encoding', 'chunked'), ('x-github-request-id', 'A8C4:4363:18B898:1CC4F3:5DB80872'), ('strict-transport-security', 'max-age=31536000; includeSubdomains; preload'), ('server', 'GitHub.com'), ('access-control-allow-origin', '*'), ('x-ratelimit-limit', '5000'), ('x-xss-protection', '1; mode=block'), ('content-encoding', 'gzip'), ('date', 'Tue, 29 Oct 2019 09:38:04 GMT'), ('x-frame-options', 'deny'), ('x-oauth-scopes', 'admin:enterprise, admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, delete:packages, delete_repo, gist, notifications, read:packages, repo, user, workflow, write:discussion, write:packages'), ('referrer-policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('content-type', 'application/json; charset=utf-8'), ('x-accepted-oauth-scopes', 'admin:org, read:org, repo, user, write:org'), ('x-ratelimit-reset', '1572345425')]
{"documentation_url": "https://developer.github.com/v3/orgs/members/#get-organization-membership", "message": "Not Found"}