class TestClient(TestCase): def setUp(self): self.c = Client() def test_set_credentials_with_valid(self): self.c.set_credentials('login', 'password') self.assertEqual(self.c.requester.auth, ('login', 'password')) def test_set_credentials_with_invalid(self): self.c.set_credentials('', '') self.assertIsNone(self.c.requester.auth) def test_set_token_with_valid(self): self.c.set_token('tokenize') self.assertEqual(self.c.requester.params['access_token'], 'tokenize') def test_set_token_with_invalid(self): self.c.set_token('') self.assertIsNone(self.c.requester.params.get('access_token')) def test_INIT_client_with_another_config_args(self): new_c = Client(base_url='url', per_page=10, user='******', repo='myrepo', verbose='stream') self.assertEqual(new_c.config['base_url'], 'url') self.assertEqual(new_c.requester.params['per_page'], 10) self.assertEqual(new_c.user, 'me') self.assertEqual(new_c.repo, 'myrepo') self.assertEqual(new_c.requester.config['verbose'], 'stream') @patch.object(requests.sessions.Session, 'request') def test_PARSE_args_in_request_without_params(self, request_method): extra = dict(arg1='arg1', arg2='arg2') self.c.request('', '', data='data', **extra) request_method.assert_called_with('', self.c.config['base_url'], data='data', params=extra) @patch.object(requests.sessions.Session, 'request') def test_PARSE_args_in_request_with_params(self, request_method): extra = dict(arg1='arg1', arg2='arg2') self.c.request('', '', params=dict(arg0='arg0'), **extra) request_method.assert_called_with('', self.c.config['base_url'], params=dict(arg0='arg0', **extra)) @patch.object(Client, 'request') def test_DELEGATES_methods(self, request_method): request_method.return_value = mock_response() self.c.get('') request_method.assert_called_with('get', '') request_method.return_value = mock_response('post') self.c.post('') request_method.assert_called_with('post', '') request_method.return_value = mock_response('patch') self.c.patch('') request_method.assert_called_with('patch', '') self.c.put('') request_method.assert_called_with('put', '') request_method.return_value = mock_response('delete') self.c.delete('') request_method.assert_called_with('delete', '') self.c.head('') request_method.assert_called_with('head', '')
class Service(object): """ You can configure each service with this keyword variables: :param str login: Username to authenticate :param str password: Username to authenticate :param str user: Default username in requests :param str repo: Default repository in requests :param str token: Token to OAuth :param int per_page: Items in each page of multiple returns :param str base_url: To support another github-related API (untested) :param stream verbose: Stream to write debug logs You can configure the **authentication** with BasicAuthentication (login and password) and with `OAuth <http://developer.github.com/v3/oauth/>`_ ( token). If you include ``login``, ``password`` and ``token`` in config; Oauth has precedence Some API requests need ``user`` and/or ``repo`` arguments (e.g :ref:`repos service <config precedence>`). You can configure the default value here to avoid repeating Some API requests return multiple resources with pagination. You can configure how many items has each page. You can configure ``verbose`` logging like `requests library <http://docs. python-requests.org/en/v0.10.6/user/advanced/#verbose-logging>`_ """ def __init__(self, **config): self._client = Client(**config) self.request_builder = Factory() def _normalize_date(self, key, _dict): """ If ``key`` comes as ``datetime``, it'll normalize it """ try: key = str(key) date = datetime.strftime(_dict.get(key), GITHUB_DATE_FORMAT) _dict.update({key: date}) except: pass @property def remaining_requests(self): return Client.remaining_requests def get_user(self): return self._client.user def set_user(self, user): """ Set user :param str user: Default username in requests """ self._client.user = user def get_repo(self): return self._client.repo def set_repo(self, repo): """ Set repository :param str repo: Default repository in requests """ self._client.repo = repo def set_credentials(self, login, password): """ Set Basic Authentication :param str login: Username to authenticate :param str password: Username to authenticate """ self._client.set_credentials(login, password) def set_token(self, token): """ Set OAuth token :param str token: Token to OAuth """ self._client.set_token(token) #TODO: Refact as decorator:: """ Reason: make_request and request_builder ... are confusing names @precedence('user') def list(self, sha, user=None): """ def make_request(self, request, **kwargs): if 'user' in kwargs: kwargs['user'] = kwargs['user'] or self.get_user() if 'repo' in kwargs: kwargs['repo'] = kwargs['repo'] or self.get_repo() return self.request_builder(request, **kwargs) def _request(self, verb, request, **kwargs): self._client.request(verb, request, **kwargs) def _bool(self, request, **kwargs): try: self._client.head(request, **kwargs) return True except NotFound: return False def _patch(self, request, **kwargs): input_data = request.get_body() response = self._client.patch(request, data=input_data, **kwargs) return request.resource.loads(response.content) def _put(self, request, **kwargs): """ Bug in Github API? requests library? 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 - merge-pull request send data For that reason I must do a conditional because I don't want to return an empty string on follow-user request because it could be confused Related: https://github.com/github/developer.github.com/pull/52 """ 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) def _delete(self, request, **kwargs): input_data = request.get_body() self._client.delete(request, data=input_data, **kwargs) def _post(self, request, **kwargs): input_data = request.get_body() response = self._client.post(request, data=input_data, **kwargs) return request.resource.loads(response.content) def _get(self, request, **kwargs): response = self._client.get(request, **kwargs) return request.resource.loads(response.content) def _get_result(self, request, **kwargs): method = smart.Method(self._client.get, request, **kwargs) return smart.Result(method) def _get_normal_result(self, request, **kwargs): method = normal.Method(self._client.get, request, **kwargs) return normal.Result(method)
class TestClient(TestCase): def setUp(self): self.c = Client() def test_set_credentials_with_valid(self): self.c.set_credentials('login', 'password') self.assertEqual(self.c.requester.auth, ('login', 'password')) def test_set_credentials_with_invalid(self): self.c.set_credentials('', '') self.assertIsNone(self.c.requester.auth) def test_set_token_with_valid(self): self.c.set_token('tokenize') self.assertEqual(dict(self.c.requester.params)['access_token'], 'tokenize') def test_set_token_with_invalid(self): self.c.set_token('') self.assertIsNone(dict(self.c.requester.params).get('access_token')) def test_INIT_client_with_another_config_args(self): new_c = Client(base_url='url', per_page=10, user='******', repo='myrepo', verbose='stream') self.assertEqual(new_c.config['base_url'], 'url') self.assertEqual(dict(new_c.requester.params)['per_page'], 10) self.assertEqual(new_c.user, 'me') self.assertEqual(new_c.repo, 'myrepo') self.assertEqual(new_c.requester.config['verbose'], 'stream') @patch.object(requests.sessions.Session, 'request') def test_PARSE_args_in_request_without_params(self, request_method): extra = dict(arg1='arg1', arg2='arg2') self.c.request('', '', data='data', **extra) request_method.assert_called_with('', self.c.config['base_url'], data='data', params=extra) @patch.object(requests.sessions.Session, 'request') def test_PARSE_args_in_request_with_params(self, request_method): extra = dict(arg1='arg1', arg2='arg2') self.c.request('', '', params=dict(arg0='arg0'), **extra) request_method.assert_called_with('', self.c.config['base_url'], params=dict(arg0='arg0', **extra)) @patch.object(Client, 'request') def test_DELEGATES_methods(self, request_method): request_method.return_value = mock_response() self.c.get('') request_method.assert_called_with('get', '') request_method.return_value = mock_response('post') self.c.post('') request_method.assert_called_with('post', '') request_method.return_value = mock_response('patch') self.c.patch('') request_method.assert_called_with('patch', '') self.c.put('') request_method.assert_called_with('put', '') request_method.return_value = mock_response('delete') self.c.delete('') request_method.assert_called_with('delete', '') self.c.head('') request_method.assert_called_with('head', '')