diff --git a/AUTHORS.rst b/AUTHORS.rst index ac8946c..9a2d4d7 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -31,3 +31,4 @@ Patches and Suggestions - Ralph Bean - Jason A. Donenfeld - Brad Montgomery +- Thomas Whitton diff --git a/docs/repos.rst b/docs/repos.rst index c065671..4f0fca5 100644 --- a/docs/repos.rst +++ b/docs/repos.rst @@ -128,6 +128,14 @@ Watchers .. autoclass:: pygithub3.services.repos.Watchers :members: +.. _Stargazers service: + +Stargazers +--------- + +.. autoclass:: pygithub3.services.repos.Stargazers + :members: + .. _Hooks service: Hooks diff --git a/pygithub3/core/client.py b/pygithub3/core/client.py index 139bee8..d4b8cd5 100644 --- a/pygithub3/core/client.py +++ b/pygithub3/core/client.py @@ -24,6 +24,8 @@ def __init__(self, **kwargs): self.config.update(kwargs) self.set_credentials(self.config.get('login'), self.config.get('password')) + self.set_oauth_credentials(self.config.get('client_id'), + self.config.get('client_secret')) self.set_token(self.config.get('token')) self.__set_params(self.config) @@ -47,6 +49,11 @@ def set_credentials(self, login, password): if login and password: self.requester.auth = (login, password) + def set_oauth_credentials(self, client_id, client_secret): + if client_id and client_secret: + self.requester.params.append(('client_id', client_id)) + self.requester.params.append(('client_secret', client_secret)) + def set_token(self, token): if token: self.requester.params.append(('access_token', token)) diff --git a/pygithub3/requests/repos/stargazers.py b/pygithub3/requests/repos/stargazers.py new file mode 100644 index 0000000..b1feb2a --- /dev/null +++ b/pygithub3/requests/repos/stargazers.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python +# -*- encoding: utf-8 -*- + +from . import Request +from pygithub3.resources.users import User +from pygithub3.resources.repos import Repo + + +class List(Request): + + uri = 'repos/{user}/{repo}/stargazers' + resource = User + + +class List_repos(Request): + + uri = 'users/{user}/starred' + resource = Repo + + def clean_uri(self): + if not self.user: + return 'user/starred' + + +class Is_starring(Request): + + uri = 'user/starred/{user}/{repo}' + + +class Star(Request): + + uri = 'user/starred/{user}/{repo}' + + +class Unstar(Request): + + uri = 'user/starred/{user}/{repo}' diff --git a/pygithub3/requests/repos/watchers.py b/pygithub3/requests/repos/watchers.py index 46e01d7..0889847 100644 --- a/pygithub3/requests/repos/watchers.py +++ b/pygithub3/requests/repos/watchers.py @@ -8,30 +8,30 @@ class List(Request): - uri = 'repos/{user}/{repo}/watchers' + uri = 'repos/{user}/{repo}/subscribers' resource = User class List_repos(Request): - uri = 'users/{user}/watched' + uri = 'users/{user}/subscriptions' resource = Repo def clean_uri(self): if not self.user: - return 'user/watched' + return 'user/subscriptions' class Is_watching(Request): - uri = 'user/watched/{user}/{repo}' + uri = 'user/subscriptions/{user}/{repo}' class Watch(Request): - uri = 'user/watched/{user}/{repo}' + uri = 'user/subscriptions/{user}/{repo}' class Unwatch(Request): - uri = 'user/watched/{user}/{repo}' + uri = 'user/subscriptions/{user}/{repo}' diff --git a/pygithub3/services/base.py b/pygithub3/services/base.py index def9d0a..0a9ed85 100644 --- a/pygithub3/services/base.py +++ b/pygithub3/services/base.py @@ -12,6 +12,8 @@ class Service(object): :param str login: Username to authenticate :param str password: Username to authenticate + :param str client_id: Client id to prevent rate limiting + :param str client_key: Client key to prevent rate limiting :param str user: Default username in requests :param str repo: Default repository in requests :param str token: Token to OAuth @@ -73,6 +75,14 @@ def set_credentials(self, login, password): """ self._client.set_credentials(login, password) + def set_oauth_credentials(self, client_id, client_key): + """ Set Oauth Identification + + :param str client_id: Client id to prevent rate limiting + :param str client_key: Client key to prevent rate limiting + """ + self._client.set_oauth_credentials(client_id, client_key) + def set_token(self, token): """ Set OAuth token diff --git a/pygithub3/services/repos/__init__.py b/pygithub3/services/repos/__init__.py index 3cfdb79..1e00051 100644 --- a/pygithub3/services/repos/__init__.py +++ b/pygithub3/services/repos/__init__.py @@ -8,6 +8,7 @@ from .forks import Forks from .keys import Keys from .watchers import Watchers +from .stargazers import Stargazers from .hooks import Hooks @@ -21,6 +22,7 @@ def __init__(self, **config): self.forks = Forks(**config) self.keys = Keys(**config) self.watchers = Watchers(**config) + self.stargazers = Stargazers(**config) self.hooks = Hooks(**config) super(Repo, self).__init__(**config) diff --git a/pygithub3/services/repos/stargazers.py b/pygithub3/services/repos/stargazers.py new file mode 100644 index 0000000..535dd8d --- /dev/null +++ b/pygithub3/services/repos/stargazers.py @@ -0,0 +1,92 @@ +#!/usr/bin/env python +# -*- encoding: utf-8 -*- + +from . import Service + + +class Stargazers(Service): + """ Consume `starring API + `_ """ + + def list(self, user=None, repo=None): + """ Get repository's stargazers + + :param str user: Username + :param str repo: Repository + :returns: A :doc:`result` + + .. note:: + Remember :ref:`config precedence` + """ + request = self.make_request('repos.stargazers.list', + user=user, repo=repo) + return self._get_result(request) + + def list_repos(self, user=None): + """ Get repositories being starred by a user + + :param str user: Username + :returns: A :doc:`result` + + If you call it without user and you are authenticated, get the + repositories being starred by the authenticated user. + + .. warning:: + If you aren't authenticated and call without user, it returns 403 + + :: + + stargazers_service.list_repos('copitux') + stargazers_service.list_repos() + """ + request = self.request_builder('repos.stargazers.list_repos', + user=user) + return self._get_result(request) + + def is_starring(self, user=None, repo=None): + """ Check if authenticated user is starring a repository + + :param str user: Username + :param str repo: Repository + + .. note:: + Remember :ref:`config precedence` + + .. warning:: + You must be authenticated + """ + request = self.make_request('repos.stargazers.is_starring', + user=user, repo=repo) + return self._bool(request) + + def star(self, user=None, repo=None): + """ Star a repository + + :param str user: Username + :param str repo: Repository + + .. note:: + Remember :ref:`config precedence` + + .. warning:: + You must be authenticated + """ + request = self.make_request('repos.stargazers.star', + user=user, repo=repo) + self._put(request) + + def unstar(self, user=None, repo=None): + """ Stop starring a repository + + :param str user: Username + :param str repo: Repository + + .. note:: + Remember :ref:`config precedence` + + .. warning:: + You must be authenticated + """ + request = self.make_request('repos.stargazers.unstar', + user=user, repo=repo) + self._delete(request) diff --git a/pygithub3/services/repos/watchers.py b/pygithub3/services/repos/watchers.py index cdc3624..b193f64 100644 --- a/pygithub3/services/repos/watchers.py +++ b/pygithub3/services/repos/watchers.py @@ -6,7 +6,7 @@ class Watchers(Service): """ Consume `Watching API - `_ """ + `_ """ def list(self, user=None, repo=None): """ Get repository's watchers @@ -19,7 +19,7 @@ def list(self, user=None, repo=None): Remember :ref:`config precedence` """ request = self.make_request('repos.watchers.list', - user=user, repo=repo) + user=user, repo=repo) return self._get_result(request) def list_repos(self, user=None): @@ -55,7 +55,7 @@ def is_watching(self, user=None, repo=None): You must be authenticated """ request = self.make_request('repos.watchers.is_watching', - user=user, repo=repo) + user=user, repo=repo) return self._bool(request) def watch(self, user=None, repo=None): @@ -71,7 +71,7 @@ def watch(self, user=None, repo=None): You must be authenticated """ request = self.make_request('repos.watchers.watch', - user=user, repo=repo) + user=user, repo=repo) self._put(request) def unwatch(self, user=None, repo=None): @@ -87,5 +87,5 @@ def unwatch(self, user=None, repo=None): You must be authenticated """ request = self.make_request('repos.watchers.unwatch', - user=user, repo=repo) + user=user, repo=repo) self._delete(request) diff --git a/pygithub3/tests/core/test_client.py b/pygithub3/tests/core/test_client.py index 4abfae9..9dc3950 100644 --- a/pygithub3/tests/core/test_client.py +++ b/pygithub3/tests/core/test_client.py @@ -24,10 +24,22 @@ def test_set_credentials_with_invalid(self): self.c.set_credentials('', '') self.assertIsNone(self.c.requester.auth) + def test_set_oauth_credentials_with_valid(self): + self.c.set_oauth_credentials('id', 'secret') + self.assertEqual(dict(self.c.requester.params)['client_id'], + 'id') + self.assertEqual(dict(self.c.requester.params)['client_secret'], + 'secret') + + def test_set_credentials_with_invalid(self): + self.c.set_oauth_credentials('', '') + self.assertIsNone(dict(self.c.requester.params).get('client_id')) + self.assertIsNone(dict(self.c.requester.params).get('client_secret')) + def test_set_token_with_valid(self): self.c.set_token('tokenize') self.assertEqual(dict(self.c.requester.params)['access_token'], - 'tokenize') + 'tokenize') def test_set_token_with_invalid(self): self.c.set_token('') diff --git a/pygithub3/tests/services/test_repos.py b/pygithub3/tests/services/test_repos.py index 9295960..5623722 100644 --- a/pygithub3/tests/services/test_repos.py +++ b/pygithub3/tests/services/test_repos.py @@ -4,7 +4,7 @@ from mock import patch from pygithub3.services.repos import (Repo, Collaborators, Commits, Downloads, - Forks, Keys, Watchers, Hooks) + Forks, Keys, Watchers, Stargazers, Hooks) from pygithub3.tests.utils.base import (dummy_json, mock_response, mock_response_result) from pygithub3.tests.utils.core import TestCase @@ -336,36 +336,79 @@ def test_LIST(self, request_method): request_method.return_value = mock_response_result() self.ws.list().all() self.assertEqual(request_method.call_args[0], - ('get', _('repos/oct/re_oct/watchers'))) + ('get', _('repos/oct/re_oct/subscribers'))) def test_LIST_repos(self, request_method): request_method.return_value = mock_response_result() self.ws.list_repos().all() self.assertEqual(request_method.call_args[0], - ('get', _('user/watched'))) + ('get', _('user/subscriptions'))) def test_LIST_repos_with_user(self, request_method): request_method.return_value = mock_response_result() self.ws.list_repos('oct').all() self.assertEqual(request_method.call_args[0], - ('get', _('users/oct/watched'))) + ('get', _('users/oct/subscriptions'))) def test_IS_watching(self, request_method): request_method.return_value = mock_response() self.assertTrue(self.ws.is_watching()) self.assertEqual(request_method.call_args[0], - ('head', _('user/watched/oct/re_oct'))) + ('head', _('user/subscriptions/oct/re_oct'))) def test_WATCH(self, request_method): self.ws.watch() self.assertEqual(request_method.call_args[0], - ('put', _('user/watched/oct/re_oct'))) + ('put', _('user/subscriptions/oct/re_oct'))) def test_UNWATCH(self, request_method): request_method.return_value = mock_response('delete') self.ws.unwatch() self.assertEqual(request_method.call_args[0], - ('delete', _('user/watched/oct/re_oct'))) + ('delete', _('user/subscriptions/oct/re_oct'))) + + +@dummy_json +@patch.object(requests.sessions.Session, 'request') +class TestStargazersService(TestCase): + + def setUp(self): + self.sg = Stargazers(user='oct', repo='re_oct') + + def test_LIST(self, request_method): + request_method.return_value = mock_response_result() + self.sg.list().all() + self.assertEqual(request_method.call_args[0], + ('get', _('repos/oct/re_oct/stargazers'))) + + def test_LIST_repos(self, request_method): + request_method.return_value = mock_response_result() + self.sg.list_repos().all() + self.assertEqual(request_method.call_args[0], + ('get', _('user/starred'))) + + def test_LIST_repos_with_user(self, request_method): + request_method.return_value = mock_response_result() + self.sg.list_repos('oct').all() + self.assertEqual(request_method.call_args[0], + ('get', _('users/oct/starred'))) + + def test_IS_starring(self, request_method): + request_method.return_value = mock_response() + self.assertTrue(self.sg.is_starring()) + self.assertEqual(request_method.call_args[0], + ('head', _('user/starred/oct/re_oct'))) + + def test_STAR(self, request_method): + self.sg.watch() + self.assertEqual(request_method.call_args[0], + ('put', _('user/starred/oct/re_oct'))) + + def test_STAR(self, request_method): + request_method.return_value = mock_response('delete') + self.sg.unstar() + self.assertEqual(request_method.call_args[0], + ('delete', _('user/starred/oct/re_oct'))) @dummy_json