From ba8725ee45b92d8ff00549e62215285094708555 Mon Sep 17 00:00:00 2001 From: David Medina Date: Fri, 10 Feb 2012 08:04:48 +0100 Subject: Typo pep8 --- pygithub3/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pygithub3/__init__.py b/pygithub3/__init__.py index 3d68157..0841aec 100644 --- a/pygithub3/__init__.py +++ b/pygithub3/__init__.py @@ -4,6 +4,6 @@ __title__ = 'pygithub3' __version__ = '0.1' __author__ = 'David Medina' -__email__= 'davidmedina9@gmail.com' +__email__ = 'davidmedina9@gmail.com' __license__ = 'ISC' __copyright__ = 'Copyright 2012 David Medina' -- cgit v1.2.3-59-g8ed1b From 615f88abfbeb34a32cdea328305ab82846298f71 Mon Sep 17 00:00:00 2001 From: David Medina Date: Fri, 10 Feb 2012 08:04:55 +0100 Subject: Services tests services.core --- pygithub3/tests/services/__init__.py | 0 pygithub3/tests/services/test_core.py | 52 +++++++++++++++++++++++++++++++++++ pygithub3/tests/services/utils.py | 7 +++++ 3 files changed, 59 insertions(+) create mode 100644 pygithub3/tests/services/__init__.py create mode 100644 pygithub3/tests/services/test_core.py create mode 100644 pygithub3/tests/services/utils.py diff --git a/pygithub3/tests/services/__init__.py b/pygithub3/tests/services/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pygithub3/tests/services/test_core.py b/pygithub3/tests/services/test_core.py new file mode 100644 index 0000000..c52b044 --- /dev/null +++ b/pygithub3/tests/services/test_core.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python +# -*- encoding: utf-8 -*- + +from unittest import TestCase +from mock import patch + +import requests + +from pygithub3.services.base import Base +from pygithub3.core.result import Result +from pygithub3.tests.utils.base import DummyRequest +from .utils import _ + + +@patch.object(requests.sessions.Session, 'request') +class TestServiceCalls(TestCase): + + def setUp(self): + self.s = Base() + self.r = DummyRequest() + self.args = dict(arg1='arg1', arg2='arg2') + + def test_BOOL(self, request_method): + self.s._bool(self.r, **self.args) + request_method.assert_called_with('head', _('dummyrequest'), + params=self.args) + + def test_PUT(self, request_method): + self.s._put(self.r, **self.args) + data = '' # See _put + request_method.assert_called_with('put', _('dummyrequest'), + data=data, params=self.args) + + def test_DELETE(self, request_method): + self.s._delete(self.r, **self.args) + request_method.assert_called_with('delete', _('dummyrequest'), + data=None, params=self.args) + + def test_POST(self, request_method): + self.s._post(self.r, **self.args) + request_method.assert_called_with('post', _('dummyrequest'), + data=None, params=self.args) + + def test_GET(self, request_method): + self.s._get(self.r, **self.args) + request_method.assert_called_with('get', _('dummyrequest'), + params=self.args) + + def test_GET_result(self, request_method): + result = self.s._get_result(self.r, **self.args) + self.assertFalse(request_method.called) + self.assertIsInstance(result, Result) diff --git a/pygithub3/tests/services/utils.py b/pygithub3/tests/services/utils.py new file mode 100644 index 0000000..a981916 --- /dev/null +++ b/pygithub3/tests/services/utils.py @@ -0,0 +1,7 @@ +#!/usr/bin/env python +# -*- encoding: utf-8 -*- + +base_url = 'https://api.github.com/' + +def _(request): + return "%s%s" % (base_url, request) -- cgit v1.2.3-59-g8ed1b From 4dbd53a7b438d9d7b13bc0afe903c54cd85cb176 Mon Sep 17 00:00:00 2001 From: David Medina Date: Fri, 10 Feb 2012 08:40:40 +0100 Subject: WIP on resources.users tests --- pygithub3/resources/users.py | 2 +- pygithub3/tests/services/test_users.py | 27 +++++++++++++++++++++++++++ pygithub3/tests/services/utils.py | 7 ------- pygithub3/tests/utils/base.py | 4 ++++ pygithub3/tests/utils/requests.py | 5 +---- pygithub3/tests/utils/services.py | 10 ++++++++++ 6 files changed, 43 insertions(+), 12 deletions(-) create mode 100644 pygithub3/tests/services/test_users.py delete mode 100644 pygithub3/tests/services/utils.py create mode 100644 pygithub3/tests/utils/services.py diff --git a/pygithub3/resources/users.py b/pygithub3/resources/users.py index 5485bf6..1aed2bd 100644 --- a/pygithub3/resources/users.py +++ b/pygithub3/resources/users.py @@ -3,7 +3,7 @@ from .base import Resource -__all__ = ('Plan', 'User') +__all__ = ('Key', 'Plan', 'User') class Key(Resource): diff --git a/pygithub3/tests/services/test_users.py b/pygithub3/tests/services/test_users.py new file mode 100644 index 0000000..f2daa36 --- /dev/null +++ b/pygithub3/tests/services/test_users.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python +# -*- encoding: utf-8 -*- + +from unittest import TestCase + +import requests +from mock import patch, Mock + +from pygithub3.services.users import User +from pygithub3.resources.base import json +from pygithub3.tests.utils.services import _, mock_json + +json.dumps = Mock(side_effect=mock_json) +json.loads = Mock(side_effect=mock_json) + +@patch.object(requests.sessions.Session, 'request') +class TestUserService(TestCase): + + def setUp(self): + self.us = User() + + def test_GET_without_user(self, request_method): + response = Mock(name='response') + response.content = {'dummy': 'dummy'} + request_method.return_value = response + self.us.get() + request_method.assert_called_with('get', _('user'), params={}) diff --git a/pygithub3/tests/services/utils.py b/pygithub3/tests/services/utils.py deleted file mode 100644 index a981916..0000000 --- a/pygithub3/tests/services/utils.py +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env python -# -*- encoding: utf-8 -*- - -base_url = 'https://api.github.com/' - -def _(request): - return "%s%s" % (base_url, request) diff --git a/pygithub3/tests/utils/base.py b/pygithub3/tests/utils/base.py index 8b82b67..cda2b2c 100644 --- a/pygithub3/tests/utils/base.py +++ b/pygithub3/tests/utils/base.py @@ -7,6 +7,10 @@ from pygithub3.resources.base import Resource from pygithub3.requests import Request +def mock_json(content): + return content + + class DummyResource(Resource): pass diff --git a/pygithub3/tests/utils/requests.py b/pygithub3/tests/utils/requests.py index 92b4f1c..ead94a6 100644 --- a/pygithub3/tests/utils/requests.py +++ b/pygithub3/tests/utils/requests.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- encoding: utf-8 -*- -from .base import Request, DummyResource, DummyRequest +from .base import Request, DummyResource, DummyRequest, mock_json from pygithub3.exceptions import ValidationError @@ -30,6 +30,3 @@ class RequestCleanedBody(Request): def clean_body(self): raise ValidationError('test') - -def mock_json(content): - return content diff --git a/pygithub3/tests/utils/services.py b/pygithub3/tests/utils/services.py new file mode 100644 index 0000000..f4765b5 --- /dev/null +++ b/pygithub3/tests/utils/services.py @@ -0,0 +1,10 @@ +#!/usr/bin/env python +# -*- encoding: utf-8 -*- + +from .base import mock_json + +base_url = 'https://api.github.com/' + + +def _(request): + return "%s%s" % (base_url, request) -- cgit v1.2.3-59-g8ed1b From 2ce25481375904c9a0247e83ee3ef7b37ff53866 Mon Sep 17 00:00:00 2001 From: David Medina Date: Fri, 10 Feb 2012 20:16:27 +0100 Subject: Fix asserts bugs in client. Fixing something that is there to check what never happens... But tests doesn't lie, so funny :P --- pygithub3/core/client.py | 12 +++++------- pygithub3/tests/core/test_client.py | 13 ++++++++++++- pygithub3/tests/services/test_core.py | 5 ++++- pygithub3/tests/services/test_users.py | 5 ++--- pygithub3/tests/utils/base.py | 6 ++++++ 5 files changed, 29 insertions(+), 12 deletions(-) diff --git a/pygithub3/core/client.py b/pygithub3/core/client.py index 84d47ad..9c9d6c2 100644 --- a/pygithub3/core/client.py +++ b/pygithub3/core/client.py @@ -83,17 +83,17 @@ class Client(object): def get(self, request, **kwargs): response = self.request('get', request, **kwargs) - assert response.status_code != '200' + assert response.status_code == 200 return response def post(self, request, **kwargs): response = self.request('post', request, **kwargs) - assert response.status_code != '201' + assert response.status_code == 201 return response def patch(self, request, **kwargs): response = self.request('patch', request, **kwargs) - assert response.status_code != '200' + assert response.status_code == 200 return response def put(self, request, **kwargs): @@ -104,10 +104,8 @@ class Client(object): def delete(self, request, **kwargs): response = self.request('delete', request, **kwargs) - assert response.status_code != '204' + assert response.status_code == 204 return response def head(self, request, **kwargs): - response = self.request('head', request, **kwargs) - assert response.status_code != '200' - return response + return self.request('head', request, **kwargs) diff --git a/pygithub3/tests/core/test_client.py b/pygithub3/tests/core/test_client.py index b22b1fd..e5b1ea5 100644 --- a/pygithub3/tests/core/test_client.py +++ b/pygithub3/tests/core/test_client.py @@ -4,9 +4,11 @@ from unittest import TestCase import requests +from mock import patch + from pygithub3.core.client import Client from pygithub3.exceptions import NotFound, BadRequest, UnprocessableEntity -from mock import patch +from pygithub3.tests.utils.base import mock_response class TestClient(TestCase): @@ -55,16 +57,25 @@ class TestClient(TestCase): @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(201) self.c.post('') request_method.assert_called_with('post', '') + + request_method.return_value = mock_response(200) self.c.patch('') request_method.assert_called_with('patch', '') + self.c.put('') request_method.assert_called_with('put', '') + + request_method.return_value = mock_response(204) self.c.delete('') request_method.assert_called_with('delete', '') + self.c.head('') request_method.assert_called_with('head', '') diff --git a/pygithub3/tests/services/test_core.py b/pygithub3/tests/services/test_core.py index c52b044..cdfe176 100644 --- a/pygithub3/tests/services/test_core.py +++ b/pygithub3/tests/services/test_core.py @@ -8,7 +8,7 @@ import requests from pygithub3.services.base import Base from pygithub3.core.result import Result -from pygithub3.tests.utils.base import DummyRequest +from pygithub3.tests.utils.base import DummyRequest, mock_response from .utils import _ @@ -32,16 +32,19 @@ class TestServiceCalls(TestCase): data=data, params=self.args) def test_DELETE(self, request_method): + request_method.return_value = mock_response(204) self.s._delete(self.r, **self.args) request_method.assert_called_with('delete', _('dummyrequest'), data=None, params=self.args) def test_POST(self, request_method): + request_method.return_value = mock_response(201) self.s._post(self.r, **self.args) request_method.assert_called_with('post', _('dummyrequest'), data=None, params=self.args) def test_GET(self, request_method): + request_method.return_value = mock_response() self.s._get(self.r, **self.args) request_method.assert_called_with('get', _('dummyrequest'), params=self.args) diff --git a/pygithub3/tests/services/test_users.py b/pygithub3/tests/services/test_users.py index f2daa36..9c333ec 100644 --- a/pygithub3/tests/services/test_users.py +++ b/pygithub3/tests/services/test_users.py @@ -8,6 +8,7 @@ from mock import patch, Mock from pygithub3.services.users import User from pygithub3.resources.base import json +from pygithub3.tests.utils.base import mock_response from pygithub3.tests.utils.services import _, mock_json json.dumps = Mock(side_effect=mock_json) @@ -20,8 +21,6 @@ class TestUserService(TestCase): self.us = User() def test_GET_without_user(self, request_method): - response = Mock(name='response') - response.content = {'dummy': 'dummy'} - request_method.return_value = response + request_method.return_value = mock_response() self.us.get() request_method.assert_called_with('get', _('user'), params={}) diff --git a/pygithub3/tests/utils/base.py b/pygithub3/tests/utils/base.py index cda2b2c..571d8ac 100644 --- a/pygithub3/tests/utils/base.py +++ b/pygithub3/tests/utils/base.py @@ -11,6 +11,12 @@ def mock_json(content): return content +def mock_response(status_code=200, content={}): + response = Mock(name='response') + response.status_code = status_code + response.content = content + return response + class DummyResource(Resource): pass -- cgit v1.2.3-59-g8ed1b From 0cfd53700dd0379e9c7c18686e5df33d286be95e Mon Sep 17 00:00:00 2001 From: David Medina Date: Fri, 10 Feb 2012 21:54:38 +0100 Subject: Wip on services.users --- pygithub3/tests/core/test_client.py | 6 +- pygithub3/tests/requests/test_core.py | 18 ++-- pygithub3/tests/services/test_core.py | 4 +- pygithub3/tests/services/test_users.py | 150 ++++++++++++++++++++++++++++++++- pygithub3/tests/utils/base.py | 12 ++- 5 files changed, 174 insertions(+), 16 deletions(-) diff --git a/pygithub3/tests/core/test_client.py b/pygithub3/tests/core/test_client.py index e5b1ea5..4a68687 100644 --- a/pygithub3/tests/core/test_client.py +++ b/pygithub3/tests/core/test_client.py @@ -61,18 +61,18 @@ class TestClient(TestCase): self.c.get('') request_method.assert_called_with('get', '') - request_method.return_value = mock_response(201) + request_method.return_value = mock_response('post') self.c.post('') request_method.assert_called_with('post', '') - request_method.return_value = mock_response(200) + 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(204) + request_method.return_value = mock_response('delete') self.c.delete('') request_method.assert_called_with('delete', '') diff --git a/pygithub3/tests/requests/test_core.py b/pygithub3/tests/requests/test_core.py index f29ab1d..98c5f3f 100644 --- a/pygithub3/tests/requests/test_core.py +++ b/pygithub3/tests/requests/test_core.py @@ -34,6 +34,7 @@ class TestFactory(TestCase): request = self.f('users.get') self.assertIsInstance(request, Request) + class TestRequestUri(TestCase): def test_SIMPLE_with_correct_args(self): @@ -80,12 +81,17 @@ class TestRequestBody(TestCase): class TestBodyParsers(TestCase): - def setUp(self): - self.b = Body( + def test_only_valid_keys(self): + body = Body( dict(arg1='arg1', arg2='arg2', arg3='arg3', arg4='arg4'), ('arg1', 'arg3', 'arg4')) - - def test_RETURN_only_valid_keys(self): - get_body_returns = self.b.parse() - self.assertEqual(get_body_returns, dict(arg1='arg1', arg3='arg3', + self.assertEqual(body.parse(), dict(arg1='arg1', arg3='arg3', arg4='arg4')) + + def test_none(self): + body = Body({}, ('arg1', 'arg2')) + self.assertEqual(body.parse(), {}) + + def test_invalid_content(self): + body = Body('invalid', ('arg1',)) + self.assertRaises(ValidationError, body.parse) diff --git a/pygithub3/tests/services/test_core.py b/pygithub3/tests/services/test_core.py index cdfe176..6e5b2b4 100644 --- a/pygithub3/tests/services/test_core.py +++ b/pygithub3/tests/services/test_core.py @@ -32,13 +32,13 @@ class TestServiceCalls(TestCase): data=data, params=self.args) def test_DELETE(self, request_method): - request_method.return_value = mock_response(204) + request_method.return_value = mock_response('delete') self.s._delete(self.r, **self.args) request_method.assert_called_with('delete', _('dummyrequest'), data=None, params=self.args) def test_POST(self, request_method): - request_method.return_value = mock_response(201) + request_method.return_value = mock_response('post') self.s._post(self.r, **self.args) request_method.assert_called_with('post', _('dummyrequest'), data=None, params=self.args) diff --git a/pygithub3/tests/services/test_users.py b/pygithub3/tests/services/test_users.py index 9c333ec..f61d60c 100644 --- a/pygithub3/tests/services/test_users.py +++ b/pygithub3/tests/services/test_users.py @@ -6,14 +6,17 @@ from unittest import TestCase import requests from mock import patch, Mock -from pygithub3.services.users import User +from pygithub3.core.client import Client +from pygithub3.services.users import User, Emails, Followers, Keys +from pygithub3.exceptions import ValidationError from pygithub3.resources.base import json -from pygithub3.tests.utils.base import mock_response +from pygithub3.tests.utils.base import mock_response, mock_response_result from pygithub3.tests.utils.services import _, mock_json json.dumps = Mock(side_effect=mock_json) json.loads = Mock(side_effect=mock_json) + @patch.object(requests.sessions.Session, 'request') class TestUserService(TestCase): @@ -23,4 +26,145 @@ class TestUserService(TestCase): def test_GET_without_user(self, request_method): request_method.return_value = mock_response() self.us.get() - request_method.assert_called_with('get', _('user'), params={}) + self.assertEqual(request_method.call_args[0], ('get', _('user'))) + + def test_GET_with_user_in_arg(self, request_method): + request_method.return_value = mock_response() + self.us.get('octocat') + self.assertEqual(request_method.call_args[0], + ('get', _('users/octocat'))) + + def test_GET_with_user_in_service(self, request_method): + request_method.return_value = mock_response() + self.us.set_user('octocat_service') + self.us.get() + self.assertEqual(request_method.call_args[0], + ('get', _('users/octocat_service'))) + + def test_UPDATE_with_valid_data(self, request_method): + request_method.return_value = mock_response('patch') + self.us.update({'name': 'dummy'}) + self.assertEqual(request_method.call_args[0], ('patch', _('user'))) + + def test_UPDATE_without_data(self, request_method): + self.assertRaises(ValidationError, self.us.update, {}) + + +@patch.object(requests.sessions.Session, 'request') +class TestEmailsService(TestCase): + + def setUp(self): + self.es = Emails() + + def test_LIST(self, request_method): + request_method.return_value = mock_response_result() + self.es.list().all() + self.assertEqual(request_method.call_args[0], + ('get', _('user/emails'))) + + def test_ADD_without_emails(self, request_method): + self.assertRaises(ValidationError, self.es.add) + self.assertFalse(request_method.called) + + def test_ADD_with_emails(self, request_method): + request_method.return_value = mock_response('post') + self.es.add('test@example.com', 'test2@example.com') + self.assertEqual(request_method.call_args[0], + ('post', _('user/emails'))) + + @patch.object(Client, 'request') + def test_ADD_filter_emails(self, client_request, dummy): + client_request.return_value = mock_response('post') + self.es.add('invalidemail.com', 'inva@lid@xam.com', 'test@xample.com') + self.assertEqual(client_request.call_args[1], + dict(data=('test@xample.com', ))) + + def test_DELETE(self, request_method): + request_method.return_value = mock_response('delete') + self.es.delete('email_must_be_founded') # or 404 raises + self.assertEqual(request_method.call_args[0], + ('delete', _('user/emails'))) + + +@patch.object(requests.sessions.Session, 'request') +class TestFollowersService(TestCase): + + def setUp(self): + self.fs = Followers() + + def test_LIST_without_user(self, request_method): + request_method.return_value = mock_response_result() + self.fs.list().all() + self.assertEqual(request_method.call_args[0], + ('get', _('user/followers'))) + + def test_LIST_with_user_in_arg(self, request_method): + request_method.return_value = mock_response_result() + self.fs.list('octocat').all() + self.assertEqual(request_method.call_args[0], + ('get', _('users/octocat/followers'))) + + def test_LIST_with_user_in_service(self, request_method): + request_method.return_value = mock_response_result() + self.fs.set_user('octocat_service') + self.fs.list().all() + self.assertEqual(request_method.call_args[0], + ('get', _('users/octocat_service/followers'))) + + def test_LIST_FOLLOWING_without_user(self, request_method): + request_method.return_value = mock_response_result() + self.fs.list_following().all() + self.assertEqual(request_method.call_args[0], + ('get', _('user/following'))) + + def test_LIST_FOLLOWING_with_user_in_arg(self, request_method): + request_method.return_value = mock_response_result() + self.fs.list_following('octocat').all() + self.assertEqual(request_method.call_args[0], + ('get', _('users/octocat/following'))) + + def test_LIST_FOLLOWING_with_user_in_service(self, request_method): + request_method.return_value = mock_response_result() + self.fs.set_user('octocat_service') + self.fs.list_following().all() + self.assertEqual(request_method.call_args[0], + ('get', _('users/octocat_service/following'))) + + def test_IS_FOLLOWING(self, request_method): + self.fs.is_following('octocat') + self.assertEqual(request_method.call_args[0], + ('head', _('user/following/octocat'))) + + def test_FOLLOW(self, request_method): + #request_method.return_value = mock_response('put') + self.fs.follow('octocat') + self.assertEqual(request_method.call_args[0], + ('put', _('user/following/octocat'))) + + def test_UNFOLLOW(self, request_method): + request_method.return_value = mock_response('delete') + self.fs.unfollow('octocat') + self.assertEqual(request_method.call_args[0], + ('delete', _('user/following/octocat'))) + + +@patch.object(requests.sessions.Session, 'request') +class TestKeysService(TestCase): + + def setUp(self): + self.ks = Keys() + + def test_LIST(self, request_method): + request_method.return_value = mock_response_result() + self.ks.list().all() + self.assertEqual(request_method.call_args[0], + ('get', _('user/key'))) + + def test_GET(self, request_method): + request_method.return_value = mock_response() + self.ks.get(1) + self.assertEqual(request_method.call_args[0], + ('get', _('user/keys/1'))) + + def test_ADD(self, request_method): + request_method.return_value = mock_response('post') diff --git a/pygithub3/tests/utils/base.py b/pygithub3/tests/utils/base.py index 571d8ac..d9049c9 100644 --- a/pygithub3/tests/utils/base.py +++ b/pygithub3/tests/utils/base.py @@ -11,12 +11,20 @@ def mock_json(content): return content -def mock_response(status_code=200, content={}): +def mock_response(status_code='get', content={}): + CODES = dict(get=200, patch=200, post=201, delete=204) response = Mock(name='response') - response.status_code = status_code + response.status_code = CODES[str(status_code).lower()] or status_code response.content = content return response + +def mock_response_result(status_code='get'): + response = mock_response(status_code, content=[{}, {}]) + response.headers = {'link': ''} + return response + + class DummyResource(Resource): pass -- cgit v1.2.3-59-g8ed1b From 38e86799291b8e446aa7634f87b67feee7427b00 Mon Sep 17 00:00:00 2001 From: David Medina Date: Sat, 11 Feb 2012 17:55:06 +0100 Subject: Change requests.Body to suppor required attributes --- pygithub3/exceptions.py | 6 +++ pygithub3/requests/__init__.py | 34 +++++++++++++---- pygithub3/requests/users/keys.py | 10 ++++- pygithub3/requests/users/user.py | 7 +++- pygithub3/tests/requests/test_core.py | 72 +++++++++++++++++------------------ pygithub3/tests/utils/requests.py | 11 ++++-- 6 files changed, 89 insertions(+), 51 deletions(-) diff --git a/pygithub3/exceptions.py b/pygithub3/exceptions.py index 65881bb..c44c371 100644 --- a/pygithub3/exceptions.py +++ b/pygithub3/exceptions.py @@ -2,6 +2,12 @@ # -*- encoding: utf-8 -*- +class InvalidBodySchema(Exception): + """ Raised when the 'valids_body' attribute of Resource isn't in a + valid form (required.issubsetof(schema))""" + pass + + class DoesNotExists(Exception): """ Raised when `Request` factory can't find the subclass """ pass diff --git a/pygithub3/requests/__init__.py b/pygithub3/requests/__init__.py index 2209fc5..a734895 100644 --- a/pygithub3/requests/__init__.py +++ b/pygithub3/requests/__init__.py @@ -8,7 +8,8 @@ try: except ImportError: import json -from pygithub3.exceptions import DoesNotExists, UriInvalid, ValidationError +from pygithub3.exceptions import (DoesNotExists, UriInvalid, ValidationError, + InvalidBodySchema) from pygithub3.resources.base import Raw ABS_IMPORT_PREFIX = 'pygithub3.requests' @@ -16,9 +17,10 @@ ABS_IMPORT_PREFIX = 'pygithub3.requests' class Body(object): - def __init__(self, content, schema): + def __init__(self, content, schema, required): self.content = content self.schema = schema + self.required = required def dumps(self): if not self.content: @@ -26,13 +28,19 @@ class Body(object): return json.dumps(self.parse()) def parse(self): - if not self.schema: - return self.content - if not hasattr(self.content, 'items'): + if self.schema and not hasattr(self.content, 'items'): raise ValidationError("'%s' needs a content dictionary" % self.__class__.__name__) - return {key: self.content[key] for key in self.schema + parsed = {key: self.content[key] for key in self.schema if key in self.content} + for attr_required in self.required: + if attr_required not in parsed: + raise ValidationError("'%s' attribute is required" % + attr_required) + if not parsed[attr_required]: + raise ValidationError("'%s' attribute can't be empty" % + attr_required) + return parsed or self.content class Request(object): @@ -40,7 +48,7 @@ class Request(object): uri = '' resource = Raw - body_schema = () + body_schema = {} def __init__(self, **kwargs): """ """ @@ -50,7 +58,7 @@ class Request(object): def clean(self): self.uri = self.clean_uri() or self.uri - self.body = Body(self.clean_body(), self.body_schema) + self.body = Body(self.clean_body(), **self.clean_valid_body()) def clean_body(self): return self.body @@ -58,6 +66,16 @@ class Request(object): def clean_uri(self): return None + def clean_valid_body(self): + schema = set(self.body_schema.get('schema', ())) + required = set(self.body_schema.get('required', ())) + if not required.issubset(schema): + raise InvalidBodySchema( + "'%s:valid_body' attribute is invalid. " + "'%s required' isn't a subset of '%s schema'" % ( + self.__class__.__name__, required, schema)) + return dict(schema=schema, required=required) + def __getattr__(self, name): return self.args.get(name) diff --git a/pygithub3/requests/users/keys.py b/pygithub3/requests/users/keys.py index 9afa3cd..23a30d9 100644 --- a/pygithub3/requests/users/keys.py +++ b/pygithub3/requests/users/keys.py @@ -21,13 +21,19 @@ class Add(Request): resource = Key uri = 'user/keys' - body_schema = ('title', 'key') + body_schema = { + 'schema': ('title', 'key'), + 'required': ('title', 'key') + } class Update(Request): resource = Key - body_schema = ('title', 'key') + body_schema = { + 'schema': ('title', 'key'), + 'required': ('title', 'key') + } uri = 'user/keys/{key_id}' diff --git a/pygithub3/requests/users/user.py b/pygithub3/requests/users/user.py index 740b3dd..3267f76 100644 --- a/pygithub3/requests/users/user.py +++ b/pygithub3/requests/users/user.py @@ -21,8 +21,11 @@ class Update(Request): resource = User uri = 'user' - body_schema = ( - 'name', 'email', 'blog', 'company', 'location', 'hireable', 'bio') + body_schema = { + 'schema': ('name', 'email', 'blog', 'company', 'location', 'hireable', + 'bio'), + 'required': (), + } def clean_body(self): if not self.body: diff --git a/pygithub3/tests/requests/test_core.py b/pygithub3/tests/requests/test_core.py index 98c5f3f..a46c1d9 100644 --- a/pygithub3/tests/requests/test_core.py +++ b/pygithub3/tests/requests/test_core.py @@ -5,10 +5,12 @@ from unittest import TestCase from mock import Mock from pygithub3.requests import Factory, Body, json, Request -from pygithub3.exceptions import UriInvalid, DoesNotExists, ValidationError +from pygithub3.exceptions import (UriInvalid, DoesNotExists, ValidationError, + InvalidBodySchema) +from pygithub3.tests.utils.base import mock_json from pygithub3.tests.utils.requests import ( - RequestWithArgs, RequestCleanedUri, RequestBodyWithSchema, mock_json, - DummyRequest, RequestCleanedBody) + RequestWithArgs, RequestCleanedUri, RequestBodyInvalidSchema, DummyRequest, + RequestCleanedBody) json.dumps = Mock(side_effect=mock_json) json.loads = Mock(side_effect=mock_json) @@ -35,7 +37,7 @@ class TestFactory(TestCase): self.assertIsInstance(request, Request) -class TestRequestUri(TestCase): +class TestRequest(TestCase): def test_SIMPLE_with_correct_args(self): request = RequestWithArgs(arg1='arg1', arg2='arg2') @@ -51,47 +53,45 @@ class TestRequestUri(TestCase): request = RequestCleanedUri(notmatters='test') self.assertEqual(str(request), 'URI') + def test_with_cleaned_body(self): + self.assertRaises(ValidationError, RequestCleanedBody) -class TestRequestBody(TestCase): - - def test_with_schema_with_valid(self): - request = RequestBodyWithSchema(body=dict( - arg1='only', fake='t', fake1='t')) - self.assertEqual(request.get_body(), dict(arg1='only')) - - def test_with_schema_with_invalid(self): - request = RequestBodyWithSchema(body='invalid_data') - self.assertRaises(ValidationError, request.get_body) - - def test_with_schema_without_body(self): - request = RequestBodyWithSchema() - self.assertIsNone(request.get_body()) + def test_with_invalid_schema(self): + self.assertRaises(InvalidBodySchema, RequestBodyInvalidSchema) - def test_without_schema(self): + def test_body_without_schema(self): request = DummyRequest(body=dict(arg1='test')) self.assertEqual(request.get_body(), dict(arg1='test')) + self.assertEqual(request.body.schema, set(())) + self.assertEqual(request.body.required, set(())) - def test_without_schema_without_body(self): + def test_without_body_and_without_schema(self): request = DummyRequest() self.assertIsNone(request.get_body()) - def test_with_clean_body(self): - self.assertRaises(ValidationError, RequestCleanedBody) +class TestRequestBody(TestCase): + + def setUp(self): + valid_body = dict(schema=('arg1', 'arg2'), required=('arg1', )) + self.b = Body({}, **valid_body) + + def test_with_required(self): + self.b.content = dict(arg1='arg1') + self.assertEqual(self.b.dumps(), dict(arg1='arg1')) + + def test_without_required(self): + self.b.content = dict(arg2='arg2') + self.assertRaises(ValidationError, self.b.dumps) + + def test_with_invalid(self): + self.b.content = 'invalid' + self.assertRaises(ValidationError, self.b.dumps) -class TestBodyParsers(TestCase): + def test_without_body(self): + self.b.content = None + self.assertIsNone(self.b.dumps()) def test_only_valid_keys(self): - body = Body( - dict(arg1='arg1', arg2='arg2', arg3='arg3', arg4='arg4'), - ('arg1', 'arg3', 'arg4')) - self.assertEqual(body.parse(), dict(arg1='arg1', arg3='arg3', - arg4='arg4')) - - def test_none(self): - body = Body({}, ('arg1', 'arg2')) - self.assertEqual(body.parse(), {}) - - def test_invalid_content(self): - body = Body('invalid', ('arg1',)) - self.assertRaises(ValidationError, body.parse) + self.b.content = dict(arg1='arg1', arg2='arg2', fake='test') + self.assertEqual(self.b.dumps(), dict(arg1='arg1', arg2='arg2')) diff --git a/pygithub3/tests/utils/requests.py b/pygithub3/tests/utils/requests.py index ead94a6..cc92768 100644 --- a/pygithub3/tests/utils/requests.py +++ b/pygithub3/tests/utils/requests.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- encoding: utf-8 -*- -from .base import Request, DummyResource, DummyRequest, mock_json +from .base import Request, DummyResource, DummyRequest from pygithub3.exceptions import ValidationError @@ -19,9 +19,14 @@ class RequestCleanedUri(Request): return 'URI' -class RequestBodyWithSchema(Request): +class RequestBodyInvalidSchema(Request): + """ It's invalid because body_schema[required] isn't a subset of + body_schema[schema] """ uri = 'URI' - body_schema = ('arg1', 'arg2') + body_schema = { + 'schema': ('arg1', 'arg2'), + 'required': ('arg3', ) + } class RequestCleanedBody(Request): -- cgit v1.2.3-59-g8ed1b From eaa8b97e6b59703b2395f72e483be27af78907ad Mon Sep 17 00:00:00 2001 From: David Medina Date: Sat, 11 Feb 2012 19:28:32 +0100 Subject: Email pattern to requests.emails --- pygithub3/requests/users/emails.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/pygithub3/requests/users/emails.py b/pygithub3/requests/users/emails.py index 410bd9a..ae4d8b8 100644 --- a/pygithub3/requests/users/emails.py +++ b/pygithub3/requests/users/emails.py @@ -5,6 +5,14 @@ import re from . import Request, ValidationError +# Src: http://code.djangoproject.com/svn/django/trunk/django/core/validators.py +email_re = re.compile( + r"(^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*" # dot-atom + # quoted-string, see also http://tools.ietf.org/html/rfc2822#section-3.2.5 + r'|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-\011\013\014\016-\177])*"' + r')@((?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+[A-Z]{2,6}\.?$)' # domain + r'|\[(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}\]$', re.IGNORECASE) # literal form, ipv4 address (SMTP 4.1.3) + class List(Request): @@ -17,7 +25,7 @@ class Add(Request): def clean_body(self): def is_email(email): - return re.match(r'.*', email) # TODO: email regex ;) + return bool(email_re.match(email)) # TODO: email regex ;) if not self.body: raise ValidationError("'%s' request needs emails" % (self.__class__.__name__)) @@ -28,3 +36,9 @@ class Add(Request): class Delete(Request): uri = 'user/emails' + + def clean_body(self): + if not self.body: + raise ValidationError("'%s' request needs emails" + % (self.__class__.__name__)) + return self.body -- cgit v1.2.3-59-g8ed1b From fa4fc266bed067963bc6248c853fd3f770b76d8f Mon Sep 17 00:00:00 2001 From: David Medina Date: Sat, 11 Feb 2012 19:29:25 +0100 Subject: Services.users tests completed services.users.user services.users.emails services.users.keys services.users.followers --- pygithub3/requests/__init__.py | 8 ++++---- pygithub3/tests/requests/test_core.py | 11 ++++++++--- pygithub3/tests/services/test_users.py | 27 +++++++++++++++++++++++++-- 3 files changed, 37 insertions(+), 9 deletions(-) diff --git a/pygithub3/requests/__init__.py b/pygithub3/requests/__init__.py index a734895..b369565 100644 --- a/pygithub3/requests/__init__.py +++ b/pygithub3/requests/__init__.py @@ -23,12 +23,12 @@ class Body(object): self.required = required def dumps(self): - if not self.content: - return None + if not self.schema: + return self.content or None return json.dumps(self.parse()) def parse(self): - if self.schema and not hasattr(self.content, 'items'): + if not hasattr(self.content, 'items'): raise ValidationError("'%s' needs a content dictionary" % self.__class__.__name__) parsed = {key: self.content[key] for key in self.schema @@ -40,7 +40,7 @@ class Body(object): if not parsed[attr_required]: raise ValidationError("'%s' attribute can't be empty" % attr_required) - return parsed or self.content + return parsed class Request(object): diff --git a/pygithub3/tests/requests/test_core.py b/pygithub3/tests/requests/test_core.py index a46c1d9..68663c0 100644 --- a/pygithub3/tests/requests/test_core.py +++ b/pygithub3/tests/requests/test_core.py @@ -70,12 +70,17 @@ class TestRequest(TestCase): self.assertIsNone(request.get_body()) -class TestRequestBody(TestCase): +class TestRequestBodyWithSchema(TestCase): def setUp(self): valid_body = dict(schema=('arg1', 'arg2'), required=('arg1', )) self.b = Body({}, **valid_body) + def test_with_body_empty_and_schema_permissive(self): + self.b.schema = ('arg1', 'arg2', '...') + self.b.required = () + self.assertEqual(self.b.dumps(), {}) + def test_with_required(self): self.b.content = dict(arg1='arg1') self.assertEqual(self.b.dumps(), dict(arg1='arg1')) @@ -88,9 +93,9 @@ class TestRequestBody(TestCase): self.b.content = 'invalid' self.assertRaises(ValidationError, self.b.dumps) - def test_without_body(self): + def test_with_body_as_None(self): self.b.content = None - self.assertIsNone(self.b.dumps()) + self.assertRaises(ValidationError, self.b.dumps) def test_only_valid_keys(self): self.b.content = dict(arg1='arg1', arg2='arg2', fake='test') diff --git a/pygithub3/tests/services/test_users.py b/pygithub3/tests/services/test_users.py index f61d60c..0438f99 100644 --- a/pygithub3/tests/services/test_users.py +++ b/pygithub3/tests/services/test_users.py @@ -79,12 +79,15 @@ class TestEmailsService(TestCase): self.assertEqual(client_request.call_args[1], dict(data=('test@xample.com', ))) - def test_DELETE(self, request_method): + def test_DELETE_with_emails(self, request_method): request_method.return_value = mock_response('delete') self.es.delete('email_must_be_founded') # or 404 raises self.assertEqual(request_method.call_args[0], ('delete', _('user/emails'))) + def test_DELETE_without_emails(self, request_method): + self.assertRaises(ValidationError, self.es.delete) + @patch.object(requests.sessions.Session, 'request') class TestFollowersService(TestCase): @@ -166,5 +169,25 @@ class TestKeysService(TestCase): self.assertEqual(request_method.call_args[0], ('get', _('user/keys/1'))) - def test_ADD(self, request_method): + def test_ADD_with_required(self, request_method): request_method.return_value = mock_response('post') + self.ks.add({'key': 'ssh-rsa ...', 'title': 'test'}) + self.assertEqual(request_method.call_args[0], ('post', _('user/keys'))) + + def test_ADD_without_required(self, request_method): + self.assertRaises(ValidationError, self.ks.add, {}) + + def test_UPDATE_with_required(self, request_method): + request_method.return_value = mock_response('patch') + self.ks.update(1, {'key': 'ssh-rsa ...', 'title': 'test'}) + self.assertEqual(request_method.call_args[0], + ('patch', _('user/keys/1'))) + + def test_UPDATE_without_required(self, request_method): + self.assertRaises(ValidationError, self.ks.update, 1, {}) + + def test_DELETE(self, request_method): + request_method.return_value = mock_response('delete') + self.ks.delete(1) + self.assertEqual(request_method.call_args[0], + ('delete', _('user/keys/1'))) -- cgit v1.2.3-59-g8ed1b