diff options
Diffstat (limited to 'pygithub3')
-rw-r--r-- | pygithub3/github.py | 8 | ||||
-rw-r--r-- | pygithub3/requests/orgs/__init__.py | 27 | ||||
-rw-r--r-- | pygithub3/requests/orgs/members.py | 34 | ||||
-rw-r--r-- | pygithub3/requests/orgs/teams.py | 74 | ||||
-rw-r--r-- | pygithub3/requests/repos/__init__.py | 3 | ||||
-rw-r--r-- | pygithub3/resources/orgs.py | 16 | ||||
-rw-r--r-- | pygithub3/resources/repos.py | 7 | ||||
-rw-r--r-- | pygithub3/services/base.py | 10 | ||||
-rw-r--r-- | pygithub3/services/orgs/__init__.py | 58 | ||||
-rw-r--r-- | pygithub3/services/orgs/members.py | 92 | ||||
-rw-r--r-- | pygithub3/services/orgs/teams.py | 136 | ||||
-rw-r--r-- | pygithub3/tests/services/test_core.py | 2 | ||||
-rw-r--r-- | pygithub3/tests/services/test_orgs.py | 172 |
13 files changed, 625 insertions, 14 deletions
diff --git a/pygithub3/github.py b/pygithub3/github.py index 87c4a6d..d135865 100644 --- a/pygithub3/github.py +++ b/pygithub3/github.py @@ -19,11 +19,13 @@ class Github(object): from pygithub3.services.gists import Gist from pygithub3.services.git_data import GitData from pygithub3.services.pull_requests import PullRequests + from pygithub3.services.orgs import Org self._users = User(**config) self._repos = Repo(**config) self._gists = Gist(**config) self._git_data = GitData(**config) self._pull_requests = PullRequests(**config) + self._orgs = Org(**config) @property def remaining_requests(self): @@ -65,3 +67,9 @@ class Github(object): :ref:`Pull Requests service <Pull Requests service>` """ return self._pull_requests + + def orgs(self): + """ + :ref:`Orgs service <Orgs service>` + """ + return self._orgs diff --git a/pygithub3/requests/orgs/__init__.py b/pygithub3/requests/orgs/__init__.py new file mode 100644 index 0000000..deba5ef --- /dev/null +++ b/pygithub3/requests/orgs/__init__.py @@ -0,0 +1,27 @@ +# -*- encoding: utf-8 -*- + +from pygithub3.requests.base import Request +from pygithub3.resources.orgs import Org + + +class List(Request): + uri = 'users/{user}/orgs' + resource = Org + + def clean_uri(self): + if not self.user: + return 'user/orgs' + + +class Get(Request): + uri = 'orgs/{org}' + resource = Org + + +class Update(Request): + uri = 'orgs/{org}' + resource = Org + body_schema = { + 'schema': ('billing_email', 'company', 'email', 'location', 'name'), + 'required': (), + } diff --git a/pygithub3/requests/orgs/members.py b/pygithub3/requests/orgs/members.py new file mode 100644 index 0000000..a6b05c2 --- /dev/null +++ b/pygithub3/requests/orgs/members.py @@ -0,0 +1,34 @@ +# -*- encoding: utf-8 -*- + +from pygithub3.resources.orgs import Member +from . import Request + + +class List(Request): + uri = 'orgs/{org}/members' + resource = Member + + +class Is_member(Request): + uri = 'orgs/{org}/members/{user}' + + +class Delete(Request): + uri = 'orgs/{org}/members/{user}' + + +class Listpublic(Request): + uri = 'orgs/{org}/public_members' + resource = Member + + +class Is_public_member(Request): + uri = 'orgs/{org}/public_members/{user}' + + +class Publicize(Request): + uri = 'orgs/{org}/public_members/{user}' + + +class Conceal(Request): + uri = 'orgs/{org}/public_members/{user}' diff --git a/pygithub3/requests/orgs/teams.py b/pygithub3/requests/orgs/teams.py new file mode 100644 index 0000000..cc92f9c --- /dev/null +++ b/pygithub3/requests/orgs/teams.py @@ -0,0 +1,74 @@ +# -*- encoding: utf-8 -*- + +from pygithub3.resources.orgs import Member, Team +from pygithub3.resources.repos import Repo +from . import Request + + +class List(Request): + uri = 'orgs/{org}/teams' + resource = Team + + +class Get(Request): + uri = 'teams/{id}' + resource = Team + + +class Create(Request): + uri = 'orgs/{org}/teams' + resource = Team + body_schema = { + 'schema': ('name', 'repo_names', 'permission',), + 'required': ('name',), + } + + # TODO: Check if this request fails with invalid permission + #def clean_body(self): + + +class Update(Request): + uri = 'teams/{id}' + resource = Team + body_schema = { + 'schema': ('name', 'permission',), + 'required': ('name',), + } + + +class Delete(Request): + uri = 'teams/{id}' + + +class List_members(Request): + uri = 'teams/{id}/members' + resource = Member + + +class Is_member(Request): + uri = 'teams/{id}/members/{user}' + + +class Add_member(Request): + uri = 'teams/{id}/members/{user}' + + +class Remove_member(Request): + uri = 'teams/{id}/members/{user}' + + +class List_repos(Request): + uri = 'teams/{id}/repos' + resource = Repo + + +class Contains_repo(Request): + uri = 'teams/{id}/repos/{user}/{repo}' + + +class Add_repo(Request): + uri = 'teams/{id}/repos/{user}/{repo}' + + +class Remove_repo(Request): + uri = 'teams/{id}/repos/{user}/{repo}' diff --git a/pygithub3/requests/repos/__init__.py b/pygithub3/requests/repos/__init__.py index cd920fe..7bbcf3e 100644 --- a/pygithub3/requests/repos/__init__.py +++ b/pygithub3/requests/repos/__init__.py @@ -1,8 +1,9 @@ # -*- encoding: utf-8 -*- from pygithub3.requests.base import Request, ValidationError +from pygithub3.resources.orgs import Team +from pygithub3.resources.repos import Repo, Tag, Branch from pygithub3.resources.users import User -from pygithub3.resources.repos import Repo, Team, Tag, Branch class List(Request): diff --git a/pygithub3/resources/orgs.py b/pygithub3/resources/orgs.py index 3996172..f0a9804 100644 --- a/pygithub3/resources/orgs.py +++ b/pygithub3/resources/orgs.py @@ -2,6 +2,7 @@ # -*- encoding: utf-8 -*- from .base import Resource +from .users import Plan __all__ = ('Org', ) @@ -9,6 +10,19 @@ __all__ = ('Org', ) class Org(Resource): _dates = ('created_at', ) + _maps = {'plan': Plan} def __str__(self): - return '<Org (%s)>' % getattr(self, 'name', '') + return '<Org (%s)>' % getattr(self, 'login', '') + + +class Team(Resource): + + def __str__(self): + return '<Team (%s)>' % getattr(self, 'name', '') + + +class Member(Resource): + + def __str__(self): + return '<TeamMember (%s)>' % getattr(self, 'login', '') diff --git a/pygithub3/resources/repos.py b/pygithub3/resources/repos.py index efd5b13..85e24c7 100644 --- a/pygithub3/resources/repos.py +++ b/pygithub3/resources/repos.py @@ -18,12 +18,6 @@ class Repo(Resource): return '<Repo (%s)>' % getattr(self, 'name', '') -class Team(Resource): - - def __str__(self): - return '<Team (%s)>' % getattr(self, 'name', '') - - class Author(Resource): _dates = ('date') @@ -115,6 +109,7 @@ class Download(Resource): 'Policy': self.policy, 'Signature': self.signature, 'Content-Type': self.mime_type}) + class Hook(Resource): _dates = ('created_at', 'pushed_at') diff --git a/pygithub3/services/base.py b/pygithub3/services/base.py index 1059371..649b2b3 100644 --- a/pygithub3/services/base.py +++ b/pygithub3/services/base.py @@ -111,10 +111,10 @@ class Service(object): def _put(self, request, **kwargs): """ Bug in Github API? requests library? - I must send data as empty string when the specifications' of some PUT - request are 'Not send input data'. If I don't do that and send data as - None, the requests library doesn't send 'Content-length' header and the - server returns 411 - Required Content length (at least 0) + I must send data when the specifications' of some PUT request are 'Not + send input data'. If I don't do that and send data as None, the + requests library doesn't send 'Content-length' header and the server + returns 411 - Required Content length (at least 0) For instance: - follow-user request doesn't send input data @@ -125,7 +125,7 @@ class Service(object): Related: https://github.com/github/developer.github.com/pull/52 """ - input_data = request.get_body() or '' + input_data = request.get_body() or 'PLACEHOLDER' response = self._client.put(request, data=input_data, **kwargs) if response.status_code != 204: # != NO_CONTENT return request.resource.loads(response.content) diff --git a/pygithub3/services/orgs/__init__.py b/pygithub3/services/orgs/__init__.py new file mode 100644 index 0000000..8499719 --- /dev/null +++ b/pygithub3/services/orgs/__init__.py @@ -0,0 +1,58 @@ +# -*- encoding: utf-8 -*- + +from pygithub3.services.base import Service +from .members import Members +from .teams import Teams + + +class Org(Service): + """ Consume `Orgs API <http://developer.github.com/v3/orgs>`_ """ + + def __init__(self, **config): + self.members = Members(**config) + self.teams = Teams(**config) + super(Org, self).__init__(**config) + + def list(self, user=None): + """ Get user's orgs + + :param str user: Username + :returns: A :doc:`result` + + If you call it without user and you are authenticated, get the + authenticated user's orgs, public and private. + + If you call it with a user, get the user's public orgs. + + :: + + org_service.list('copitux') + org_service.list() + """ + request = self.request_builder('orgs.list', user=user) + return self._get_result(request) + + def get(self, org): + """ Get a single org + + :param str org: Org name + """ + request = self.request_builder('orgs.get', org=org) + return self._get(request) + + def update(self, org, data): + """ Update a single org + + :param str org: Org name + :param dict data: Input. See `github orgs doc`_ + + .. warning :: + You must be authenticated + + :: + + org_service.update(dict(company='ACME Development', + location='Timbuctoo')) + """ + request = self.request_builder('orgs.update', org=org, body=data) + return self._patch(request) diff --git a/pygithub3/services/orgs/members.py b/pygithub3/services/orgs/members.py new file mode 100644 index 0000000..fb0da03 --- /dev/null +++ b/pygithub3/services/orgs/members.py @@ -0,0 +1,92 @@ +# -*- encoding: utf-8 -*- + +from . import Service + + +class Members(Service): + """ Consume `Members API <http://developer.github.com/v3/orgs/members/>`_ + """ + + def list(self, org): + """ Get org's members + + :param str org: Organisation name + :returns: A :doc:`result` + + If you call it authenticated, and are a member of the org, public and + private members will be visible. + + If not, only public members will be visible. + """ + request = self.request_builder('orgs.members.list', org=org) + return self._get_result(request) + + def is_member(self, org, user): + """ Determine if user is a member of org + + :param str org: Organisation name + :param str user: User name + """ + request = self.request_builder('orgs.members.is_member', org=org, + user=user) + return self._bool(request) + + def remove_member(self, org, user): + """ Remove user from all teams in org + + :param str org: Organisation name + :param str user: User name + + .. warning :: + You must be authenticated and an owner of org + + """ + request = self.request_builder('orgs.members.delete', org=org, user=user) + return self._delete(request) + + def list_public(self, org): + """ Get org's public members + + :param str org: Organisation name + :returns: A :doc:`result` + """ + request = self.request_builder('orgs.members.listpublic', org=org) + return self._get_result(request) + + def is_public_member(self, org, user): + """ Determine if user is a public member of org + + :param str org: Organisation name + :param str user: User name + """ + request = self.request_builder('orgs.members.is_public_member', + org=org, user=user) + return self._bool(request) + + def publicize_membership(self, org, user): + """ Publicize user's membership in org + + :param str org: Organisation name + :param str user: User name + + .. warning :: + You must be authenticated and the user, or an owner of the org + + """ + request = self.request_builder('orgs.members.publicize', + org=org, user=user) + return self._put(request) + + def conceal_membership(self, org, user): + """ Conceal user's membership in org + + :param str org: Organisation name + :param str user: User name + + .. warning :: + You must be authenticated and the user, or an owner of the org + + """ + request = self.request_builder('orgs.members.conceal', + org=org, user=user) + return self._delete(request) diff --git a/pygithub3/services/orgs/teams.py b/pygithub3/services/orgs/teams.py new file mode 100644 index 0000000..84aa855 --- /dev/null +++ b/pygithub3/services/orgs/teams.py @@ -0,0 +1,136 @@ +# -*- encoding: utf-8 -*- + +from . import Service + + +class Teams(Service): + """ Consume `Teams API <http://developer.github.com/v3/orgs/teams/>`_ + + .. warning :: + You must be authenticated as an owner of the org + """ + + def list(self, org): + """ Get org's teams + + :param str org: Organisation name + :returns: A :doc:`result` + """ + request = self.request_builder('orgs.teams.list', org=org) + return self._get_result(request) + + def get(self, id): + """ Get a team + + :param int id: The team id + :returns: A :doc:`result` + """ + request = self.request_builder('orgs.teams.get', id=id) + return self._get(request) + + def create(self, org, data): + """ Create a new team + + :param str org: Organisation name + :param dict data: Input. See `github orgs teams doc`_ + """ + request = self.request_builder('orgs.teams.create', org=org, body=data) + return self._post(request) + + def update(self, id, data): + """ Update a team + + :param int id: The team id + :param dict data: Input. See `github orgs teams doc`_ + """ + request = self.request_builder('orgs.teams.update', id=id, body=data) + return self._patch(request) + + def delete(self, id): + """ Delete a team + + :param int id: The team id + """ + request = self.request_builder('orgs.teams.delete', id=id) + return self._delete(request) + + def list_members(self, id): + """ List the members of a team + + :param int id: The team id + :returns: A :doc:`result` + """ + request = self.request_builder('orgs.teams.list_members', id=id) + return self._get_result(request) + + def is_member(self, id, user): + """ Determine if user is a member of a team + + :param int id: The team id + :param str user: User name + """ + request = self.request_builder('orgs.teams.is_member', + id=id, user=user) + return self._bool(request) + + def add_member(self, id, user): + """ Add a user to a team + + :param int id: The team id + :param str user: User name + """ + request = self.request_builder('orgs.teams.add_member', + id=id, user=user) + return self._put(request) + + def remove_member(self, id, user): + """ Remove a member from a team + + :param int id: The team id + :param str user: User name + """ + request = self.request_builder('orgs.teams.remove_member', + id=id, user=user) + return self._delete(request) + + def list_repos(self, id): + """ List the repos that a team's members get access to + + :param int id: The team id + :returns: A :doc:`result` + """ + request = self.request_builder('orgs.teams.list_repos', id=id) + return self._get_result(request) + + def contains_repo(self, id, user, repo): + """ Determine if user is a member of a team + + :param int id: The team id + :param str user: User name + :param str repo: Repo name + """ + request = self.request_builder('orgs.teams.contains_repo', + id=id, user=user, repo=repo) + return self._bool(request) + + def add_repo(self, id, user, repo): + """ Give team members access to a repo + + :param int id: The team id + :param str user: User name + :param str repo: Repo name + """ + request = self.request_builder('orgs.teams.add_repo', + id=id, user=user, repo=repo) + return self._put(request) + + def remove_repo(self, id, user, repo): + """ Remove a repo from the a team + + :param int id: The team id + :param str user: User name + :param str repo: Repo name + """ + request = self.request_builder('orgs.teams.remove_repo', + id=id, user=user, repo=repo) + return self._delete(request) diff --git a/pygithub3/tests/services/test_core.py b/pygithub3/tests/services/test_core.py index bd95b34..8a2bbbe 100644 --- a/pygithub3/tests/services/test_core.py +++ b/pygithub3/tests/services/test_core.py @@ -27,7 +27,7 @@ class TestServiceCalls(TestCase): def test_PUT(self, request_method): self.s._put(self.r, **self.args) - data = '' # See _put + data = 'PLACEHOLDER' # See _put request_method.assert_called_with('put', _('dummyrequest'), data=data, params=self.args) diff --git a/pygithub3/tests/services/test_orgs.py b/pygithub3/tests/services/test_orgs.py new file mode 100644 index 0000000..7f5f7af --- /dev/null +++ b/pygithub3/tests/services/test_orgs.py @@ -0,0 +1,172 @@ +#!/usr/bin/env python +# -*- encoding: utf-8 -*- + +import requests +from mock import patch, Mock + +from pygithub3.tests.utils.core import TestCase +from pygithub3.resources.base import json +from pygithub3.services.orgs import Org, Members, Teams +from pygithub3.tests.utils.base import (mock_response, mock_response_result, + mock_json) +from pygithub3.tests.utils.services import _ + +json.dumps = Mock(side_effect=mock_json) +json.loads = Mock(side_effect=mock_json) + + +@patch.object(requests.sessions.Session, 'request') +class TestOrgService(TestCase): + def setUp(self): + self.org = Org() + + def test_LIST_without_user(self, request_method): + request_method.return_value = mock_response_result() + self.org.list().all() + self.assertEqual(request_method.call_args[0], ('get', _('user/orgs'))) + + def test_LIST_with_user(self, request_method): + request_method.return_value = mock_response_result() + self.org.list('octocat').all() + self.assertEqual(request_method.call_args[0], + ('get', _('users/octocat/orgs'))) + + def test_GET(self, request_method): + request_method.return_value = mock_response() + self.org.get('acme') + self.assertEqual(request_method.call_args[0], ('get', _('orgs/acme'))) + + def test_UPDATE(self, request_method): + request_method.return_value = mock_response('patch') + self.org.update('acme', {'company': 'ACME Widgets'}) + self.assertEqual(request_method.call_args[0], + ('patch', _('orgs/acme'))) + + +@patch.object(requests.sessions.Session, 'request') +class TestMemberService(TestCase): + def setUp(self): + self.ms = Members() + + def test_LIST(self, request_method): + request_method.return_value = mock_response_result() + self.ms.list('acme').all() + self.assertEqual(request_method.call_args[0], + ('get', _('orgs/acme/members'))) + + def test_IS_MEMBER(self, request_method): + request_method.return_value = mock_response() + self.ms.is_member('acme', 'octocat') + self.assertEqual(request_method.call_args[0], + ('head', _('orgs/acme/members/octocat'))) + + def test_REMOVE_MEMBER(self, request_method): + request_method.return_value = mock_response('delete') + self.ms.remove_member('acme', 'octocat') + self.assertEqual(request_method.call_args[0], + ('delete', _('orgs/acme/members/octocat'))) + + def test_LIST_PUBLIC(self, request_method): + request_method.return_value = mock_response_result() + self.ms.list_public('acme').all() + self.assertEqual(request_method.call_args[0], + ('get', _('orgs/acme/public_members'))) + + def test_IS_PUBLIC_MEMBER(self, request_method): + request_method.return_value = mock_response() + self.ms.is_public_member('acme', 'octocat') + self.assertEqual(request_method.call_args[0], + ('head', _('orgs/acme/public_members/octocat'))) + + def test_PUBLICIZE_MEMBERSHIP(self, request_method): + request_method.return_value = mock_response() + self.ms.publicize_membership('acme', 'octocat') + self.assertEqual(request_method.call_args[0], + ('put', _('orgs/acme/public_members/octocat'))) + + def test_CONCEAL_MEMBERSHIP(self, request_method): + request_method.return_value = mock_response('delete') + self.ms.conceal_membership('acme', 'octocat') + self.assertEqual(request_method.call_args[0], + ('delete', _('orgs/acme/public_members/octocat'))) + + +@patch.object(requests.sessions.Session, 'request') +class TestTeamsService(TestCase): + def setUp(self): + self.ts = Teams() + + def test_LIST(self, request_method): + request_method.return_value = mock_response_result() + self.ts.list('acme').all() + self.assertEqual(request_method.call_args[0], + ('get', _('orgs/acme/teams'))) + + def test_GET(self, request_method): + request_method.return_value = mock_response_result() + self.ts.get(1) + self.assertEqual(request_method.call_args[0], ('get', _('teams/1'))) + + def test_CREATE(self, request_method): + request_method.return_value = mock_response_result('post') + self.ts.create('acme', dict(name='new')) + self.assertEqual(request_method.call_args[0], + ('post', _('orgs/acme/teams'))) + + def test_UPDATE(self, request_method): + request_method.return_value = mock_response_result() + self.ts.update(1, dict(name='edited')) + self.assertEqual(request_method.call_args[0], ('patch', _('teams/1'))) + + def test_DELETE(self, request_method): + request_method.return_value = mock_response_result('delete') + self.ts.delete(1) + self.assertEqual(request_method.call_args[0], ('delete', _('teams/1'))) + + def test_LIST_MEMBERS(self, request_method): + request_method.return_value = mock_response_result() + self.ts.list_members(1).all() + self.assertEqual(request_method.call_args[0], + ('get', _('teams/1/members'))) + + def test_IS_MEMBER(self, request_method): + request_method.return_value = mock_response_result() + self.ts.is_member(1, 'octocat') + self.assertEqual(request_method.call_args[0], + ('head', _('teams/1/members/octocat'))) + + def test_ADD_MEMBER(self, request_method): + request_method.return_value = mock_response_result() + self.ts.add_member(1, 'octocat') + self.assertEqual(request_method.call_args[0], + ('put', _('teams/1/members/octocat'))) + + def test_REMOVE_MEMBER(self, request_method): + request_method.return_value = mock_response_result('delete') + self.ts.remove_member(1, 'octocat') + self.assertEqual(request_method.call_args[0], + ('delete', _('teams/1/members/octocat'))) + + def test_LIST_REPOS(self, request_method): + request_method.return_value = mock_response_result() + self.ts.list_repos(1).all() + self.assertEqual(request_method.call_args[0], + ('get', _('teams/1/repos'))) + + def test_CONTAINS_REPO(self, request_method): + request_method.return_value = mock_response_result() + self.ts.contains_repo(1, 'octocat', 're_oct') + self.assertEqual(request_method.call_args[0], + ('head', _('teams/1/repos/octocat/re_oct'))) + + def test_ADD_TEAM_REPO(self, request_method): + request_method.return_value = mock_response_result() + self.ts.add_repo(1, 'octocat', 're_oct') + self.assertEqual(request_method.call_args[0], + ('put', _('teams/1/repos/octocat/re_oct'))) + + def test_REMOVE_TEAM_REPO(self, request_method): + request_method.return_value = mock_response_result('delete') + self.ts.remove_repo(1, 'octocat', 're_oct') + self.assertEqual(request_method.call_args[0], + ('delete', _('teams/1/repos/octocat/re_oct'))) |