diff --git a/github/Membership.py b/github/Membership.py index c6cf4b65..f2a6f60d 100644 --- a/github/Membership.py +++ b/github/Membership.py @@ -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"]) diff --git a/github/NamedUser.py b/github/NamedUser.py index b52bc804..6c096ec4 100644 --- a/github/NamedUser.py +++ b/github/NamedUser.py @@ -626,13 +626,16 @@ class NamedUser(github.GithubObject.CompletableGithubObject): def get_organization_membership(self, org): """ - :calls: `GET /user/memberships/orgs/:org `_ + :calls: `GET /orgs/:org/memberships/:username `_ + :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) diff --git a/tests/NamedUser.py b/tests/NamedUser.py index 650eb68b..6c53a3cf 100644 --- a/tests/NamedUser.py +++ b/tests/NamedUser.py @@ -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") diff --git a/tests/ReplayData/NamedUser.testGetOrganizationMembership.txt b/tests/ReplayData/NamedUser.testGetOrganizationMembership.txt new file mode 100644 index 00000000..75d12c51 --- /dev/null +++ b/tests/ReplayData/NamedUser.testGetOrganizationMembership.txt @@ -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"} + diff --git a/tests/ReplayData/NamedUser.testGetOrganizationMembershipNotMember.txt b/tests/ReplayData/NamedUser.testGetOrganizationMembershipNotMember.txt new file mode 100644 index 00000000..62b76aa5 --- /dev/null +++ b/tests/ReplayData/NamedUser.testGetOrganizationMembershipNotMember.txt @@ -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"}