From bb540725ce15dcafd5ac5e5bb93e5a232ff4f33a Mon Sep 17 00:00:00 2001 From: David Medina Date: Fri, 4 Nov 2011 01:21:50 +0100 Subject: Refactor base to handler design --- github3/errors.py | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 github3/errors.py (limited to 'github3/errors.py') diff --git a/github3/errors.py b/github3/errors.py new file mode 100644 index 0000000..6932360 --- /dev/null +++ b/github3/errors.py @@ -0,0 +1,34 @@ +#!/usr/bin/env python +# -*- encoding: utf-8 -*- +# +# author: David Medina + +import json +import github3.exceptions as exceptions + +class GithubError(object): + """ Handler for API errors """ + + def __init__(self, response): + self._parser = json + self.status_code = response.status_code + self.debug = self._parser.loads(response.content) + + def error_400(self): + return exceptions.BadRequest("400 - %s" % self.debug.get('message')) + + def error_404(self) + return exceptions.NotFound("404 - %s" % self.debug.get('message')) + + def error_422(self): + errors = self.debug.get('errors') + if errors: + errors = ['{resource}: {code} => {field}'.format(**error) + for error in errors] + return exceptions.UnprocessableEntity( + '422 - %s %s' % (self.debug.get('message'), errors)) + + def process(self): + raise_error = getattr(self, 'error_%s' % self.status_code, False) + if raise_error: + raise raise_error() -- cgit v1.2.3-59-g8ed1b From bdc593ac5ae97f4f9d65df15fcc18b632fae7666 Mon Sep 17 00:00:00 2001 From: David Medina Date: Sat, 5 Nov 2011 20:47:14 +0100 Subject: Fix litle bugs and args to request --- github3/api.py | 33 ++++++++++++++++++++++++++++----- github3/errors.py | 7 +++++-- 2 files changed, 33 insertions(+), 7 deletions(-) (limited to 'github3/errors.py') diff --git a/github3/api.py b/github3/api.py index 3376bea..d82bd3a 100644 --- a/github3/api.py +++ b/github3/api.py @@ -14,16 +14,21 @@ class GithubCore(object): """ Wrapper for requests """ requests_remaining = None + base_url = 'https://api.github.com/' def __init__(self): self.session = requests.session() self.session.params = {'per_page': RESOURCES_PER_PAGE} self._parser = json - #@paginate to slice a generator after - def get(self, request, **kwargs): + def get(self, request, paginate=False, **kwargs): + print '\nGET %s %s\n' % (request, kwargs) response = self._request('GET', request, **kwargs) - return self._parser.loads(response.content) + content = self._parser.loads(response.content) + if paginate: + return response.headers.get('link'), content + else: + return content def head(self, request, **kwargs): return self._request('HEAD', request, **kwargs).headers @@ -56,10 +61,28 @@ class GithubCore(object): response = self._request('DELETE', request, **kwargs) assert response.status_code == 204 + def _parse_args(self, request_args): + request_core = ( + 'params','data','headers','cookies','files','auth','tiemout', + 'allow_redirects','proxies','return_response','config') + request_params = request_args.get('params') + extra_params = {} + for k, v in request_args.items(): + if k in request_core: continue + extra_params.update({k: v}) + del request_args[k] + if request_params: + request_args['params'].update(extra_params) + else: + request_args['params'] = extra_params + + return request_args + def _request(self, verb, request, **kwargs): - request = settings.base_url + request - response = self.session.request(verb, request, **kwargs) + request = self.base_url + request + parsed_args = self._parse_args(kwargs) + response = self.session.request(verb, request, **parsed_args) self.requests_remaining = response.headers.get( 'x-ratelimit-remaining',-1) error = GithubError(response) diff --git a/github3/errors.py b/github3/errors.py index 6932360..96693be 100644 --- a/github3/errors.py +++ b/github3/errors.py @@ -12,12 +12,15 @@ class GithubError(object): def __init__(self, response): self._parser = json self.status_code = response.status_code - self.debug = self._parser.loads(response.content) + if response.content: + self.debug = self._parser.loads(response.content) + else: + self.debug = {} def error_400(self): return exceptions.BadRequest("400 - %s" % self.debug.get('message')) - def error_404(self) + def error_404(self): return exceptions.NotFound("404 - %s" % self.debug.get('message')) def error_422(self): -- cgit v1.2.3-59-g8ed1b From 40cbe596f0d726461d65d6473c2d197f63232641 Mon Sep 17 00:00:00 2001 From: David Medina Date: Wed, 9 Nov 2011 02:10:29 +0100 Subject: Fixing bugs. Crazy night :S --- github3/api.py | 8 +++++++- github3/errors.py | 6 +++--- github3/handlers/base.py | 16 +++++++--------- github3/handlers/user.py | 26 +++++++++++++------------- github3/models/orgs.py | 2 +- github3/models/repos.py | 4 ++-- 6 files changed, 33 insertions(+), 29 deletions(-) (limited to 'github3/errors.py') diff --git a/github3/api.py b/github3/api.py index 2066e94..b7435ff 100644 --- a/github3/api.py +++ b/github3/api.py @@ -43,7 +43,7 @@ class GithubCore(object): def head(self, request, **kwargs): """ HEAD request """ - return self._request('HEAD', request, **kwargs).headers + return self._request('HEAD', request, **kwargs) def post(self, request, data=None, **kwargs): """ @@ -71,11 +71,17 @@ class GithubCore(object): """ PUT request """ response = self._request('PUT', request, **kwargs) assert response.status_code == 204 + return response def delete(self, request, **kwargs): """ DELETE request """ + + data = kwargs.get('data') + if data: + kwargs['data'] = self._parser.dumps(data) response = self._request('DELETE', request, **kwargs) assert response.status_code == 204 + return response def _parse_args(self, request_args): """ diff --git a/github3/errors.py b/github3/errors.py index 96693be..09e616b 100644 --- a/github3/errors.py +++ b/github3/errors.py @@ -12,10 +12,10 @@ class GithubError(object): def __init__(self, response): self._parser = json self.status_code = response.status_code - if response.content: + try: self.debug = self._parser.loads(response.content) - else: - self.debug = {} + except ValueError: + self.debug = {'message': response.content} def error_400(self): return exceptions.BadRequest("400 - %s" % self.debug.get('message')) diff --git a/github3/handlers/base.py b/github3/handlers/base.py index 6bf13bf..50e2df8 100644 --- a/github3/handlers/base.py +++ b/github3/handlers/base.py @@ -15,9 +15,9 @@ class Handler(object): def _prefix_resource(self, resource): prefix = getattr(self, 'prefix', '') - return '/'.join((prefix, resource)) + return '/'.join((prefix, resource)).rstrip('/') - def _get_converter(self, kwargs): + def _get_converter(self, **kwargs): converter = kwargs.get( 'converter', # 1. in kwargs getattr(self, 'converter', # 2. in handler @@ -28,13 +28,11 @@ class Handler(object): def _put(self, resource, **kwargs): """ Put proxy request""" - resource = self._prefix_resource(resource) return self._bool(resource, method='put', **kwargs) def _delete(self, resource, **kwargs): """ Delete proxy request""" - resource = self._prefix_resource(resource) return self._bool(resource, method='delete', **kwargs) def _bool(self, resource, **kwargs): @@ -43,7 +41,7 @@ class Handler(object): from github3.exceptions import NotFound resource = self._prefix_resource(resource) try: - callback = getattr(self._gh, kwargs.get(method,''), self._gh.head) + callback = getattr(self._gh, kwargs.get('method',''), self._gh.head) response = callback(resource, **kwargs) except NotFound: return False @@ -55,13 +53,13 @@ class Handler(object): """ Hander request to multiple resources """ resource = self._prefix_resource(resource) - page_resources = Paginate(resource, self._gh.get, kwargs) + page_resources = Paginate(resource, self._gh.get, **kwargs) counter = 1 for page in page_resources: for raw_resource in page: if limit and counter > limit: break counter += 1 - converter = self._get_converter(kwargs) + converter = self._get_converter(**kwargs) converter.inject(model) yield converter.loads(raw_resource) else: @@ -73,7 +71,7 @@ class Handler(object): resource = self._prefix_resource(resource) raw_resource = self._gh.get(resource) - converter = self._get_converter(kwargs) + converter = self._get_converter(**kwargs) converter.inject(model) return converter.loads(raw_resource) @@ -82,6 +80,6 @@ class Handler(object): resource = self._prefix_resource(resource) raw_resource = self._gh.post(resource, data=data) - converter = self._get_converter(kwargs) + converter = self._get_converter(**kwargs) converter.inject(model) return converter.loads(raw_resource) diff --git a/github3/handlers/user.py b/github3/handlers/user.py index 75a0d3f..fb893b4 100644 --- a/github3/handlers/user.py +++ b/github3/handlers/user.py @@ -29,37 +29,37 @@ class User(Handler): def get(self): """ Return user """ - self._get_resource('', model=models.User) + return self._get_resource('', model=models.User) def get_followers(self): """ Return user's followers """ - self._get_resources('followers', model=models.User) + return self._get_resources('followers', model=models.User) def get_following(self): """ Return users that follow """ - self._get_resources('following', model=models.User) + return self._get_resources('following', model=models.User) def get_repos(self): """ Return user's public repositories """ - self._get_resources('repos', model=models.Repo) + return self._get_resources('repos', model=models.Repo) def get_watched(self): """ Return repositories that user whatch """ - self._get_resources('watched', model=models.Repo) + return self._get_resources('watched', model=models.Repo) def get_orgs(self): """ Return user's public organizations """ - self._get_resources('orgs', model=models.Org) + return self._get_resources('orgs', model=models.Org) def get_gists(self): """ Return user's gists """ - self._get_resources('gists', model=models.Gist) + return self._get_resources('gists', model=models.Gist) class AuthUser(User): """ User handler with public and private access """ @@ -70,7 +70,7 @@ class AuthUser(User): return ' %s>' % self._gh.session.auth[0] def get(self): - self._get_resource('', model=models.AuthUser) + return self._get_resource('', model=models.AuthUser) def get_emails(self): """ Return list of emails """ @@ -119,9 +119,9 @@ class AuthUser(User): """ parse_user = str(getattr(user, 'login', user)) - return self._put('following/%s', % parse_user) + return self._put('following/%s' % parse_user) - def unfollow(self, user) + def unfollow(self, user): """ Unfollow user @@ -129,14 +129,14 @@ class AuthUser(User): """ parse_user = str(getattr(user, 'login', user)) - return self._delete('following/%s', % parse_user) + return self._delete('following/%s' % parse_user) def get_keys(self): """ Get public keys """ return self._get_resources('keys', model=models.Key) - def get_key(self, key_id) + def get_key(self, key_id): """ Get public key by id """ return self._get_resource('keys/%s' % key_id, model=models.Key) @@ -151,7 +151,7 @@ class AuthUser(User): #TODO: render key.pub file key = { - 'title': kwargs.get('title','') + 'title': kwargs.get('title',''), 'key': kwargs.get('key','') } return self._post_resource('keys', data=key, model=models.Key) diff --git a/github3/models/orgs.py b/github3/models/orgs.py index 840b51a..5e66c35 100644 --- a/github3/models/orgs.py +++ b/github3/models/orgs.py @@ -18,7 +18,7 @@ class Org(BaseResource): 'following', 'total_private_repos', 'owned_private_repos', 'private_gists', 'disk_usage', 'collaborators'], 'dates': ['created_at'], - 'maps': {'plan': plan} + 'maps': {'plan': Plan} } def __repr__(self): diff --git a/github3/models/repos.py b/github3/models/repos.py index ba6ac33..d1b7b75 100644 --- a/github3/models/repos.py +++ b/github3/models/repos.py @@ -22,8 +22,8 @@ class Repo(BaseResource): 'maps': { 'owner': User, 'organization': Org, - 'parent': 'self', - 'source': 'self', + 'parent': self.__class__, + 'source': self.__class__, } } -- cgit v1.2.3-59-g8ed1b From 2ed172774e179dbf7020e1898cb1bcc4e485e9e9 Mon Sep 17 00:00:00 2001 From: David Medina Date: Sat, 12 Nov 2011 02:55:52 +0100 Subject: Added core_test and fix some bugs / pep8 Readme to Markdown --- README.md | 63 +++++++++++++++++++++++++ README.rst | 78 ------------------------------ github3/api.py | 29 ++++++------ github3/errors.py | 3 +- github3/handlers/users.py | 9 +++- github3/tests/test_core.py | 115 +++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 202 insertions(+), 95 deletions(-) create mode 100644 README.md delete mode 100644 README.rst create mode 100644 github3/tests/test_core.py (limited to 'github3/errors.py') diff --git a/README.md b/README.md new file mode 100644 index 0000000..334b975 --- /dev/null +++ b/README.md @@ -0,0 +1,63 @@ +Fork +==== +Refactor and complete api wrapper. Intensive work in progress + +Use with auth user +------------------ + + from github3.api import Github + + gh = Github('user', 'password') + + users_handler = gh.users + for repo in users_handler.get_repos(): + print repo + + gists_handler = gh.gists + gists_handler.create_gist( + u'Description', + files={'file1.txt': {'content': u'Content of first file'}}) + +Installation +------------ + +To install Github3, simply: + + $ pip -e git+https://copitux@github.com/copitux/python-github3#egg=python-github3 + +License +------- + +ISC License. + + Copyright (c) 2011, Kenneth Reitz + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + +Contribute +---------- + +If you'd like to contribute, simply fork `the repository`, commit your changes +to the **develop** branch (or branch off of it), and send a pull request. Make +sure you add yourself to `AUTHORS`. + + +Roadmap +------- + +- Unittests +- Handlers +- Sphinx Documentation +- Examples +- OAuth Last (how?) diff --git a/README.rst b/README.rst deleted file mode 100644 index c07cbc9..0000000 --- a/README.rst +++ /dev/null @@ -1,78 +0,0 @@ -Fork -====================================== -Refactor and complete api wrapper. Intensive work in progress - -Use with auth user ---------------------- - -```python -from github3.api import Github - -gh = Github('user', 'password') - -users_handler = gh.users -for repo in users_handler.get_repos(): - print repo - -gists_handler = gh.gists -gists_handler.create_gist( - u'Description', - files={'file1.txt': {'content': u'Content of first file'}}) -``` - - -Installation ------------- - -To install Github3, simply: :: - - $ pip install github3 - -Or, if you absolutely must: :: - - $ easy_install github3 - -But, you really shouldn't do that. - - - -License -------- - -ISC License. :: - - Copyright (c) 2011, Kenneth Reitz - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - - -Contribute ----------- - -If you'd like to contribute, simply fork `the repository`_, commit your changes -to the **develop** branch (or branch off of it), and send a pull request. Make -sure you add yourself to AUTHORS_. - - - -Roadmap -------- - -- Unittests -- Handlers -- Get it Started -- HTTP BASIC -- Get it working -- Sphinx Documetnation -- Examples -- OAuth Last (how?) diff --git a/github3/api.py b/github3/api.py index e9eebb5..9dbe52f 100644 --- a/github3/api.py +++ b/github3/api.py @@ -10,6 +10,7 @@ from handlers import users, gists RESOURCES_PER_PAGE = 100 + class GithubCore(object): """ Wrapper to github api requests @@ -88,22 +89,21 @@ class GithubCore(object): """ Arg's parser to `_request` method - It check keyword args to parse extra request args to params - Sample: - _parse_args(arg1=1, arg2=2) => params = {'arg1': 1, 'arg2': 2} + Put extra request_args in params """ request_core = ( - 'params','data','headers','cookies','files','auth','tiemout', - 'allow_redirects','proxies','return_response','config') + 'params', 'data', 'headers', 'cookies', 'files', 'auth', 'tiemout', + 'allow_redirects', 'proxies', 'return_response', 'config') request_params = request_args.get('params') extra_params = {} for k, v in request_args.items(): - if k in request_core: continue + if k in request_core: + continue extra_params.update({k: v}) del request_args[k] - if request_params: + if request_params and getattr(request_params, 'update'): request_args['params'].update(extra_params) - else: + elif extra_params: request_args['params'] = extra_params return request_args @@ -117,15 +117,16 @@ class GithubCore(object): :param kwargs: Keyword args to request """ request = self.base_url + request - parsed_args = self._parse_args(kwargs) - response = self.session.request(verb, request, **parsed_args) + self._parse_args(kwargs) + response = self.session.request(verb, request, **kwargs) self.requests_remaining = response.headers.get( - 'x-ratelimit-remaining',-1) + 'x-ratelimit-remaining', -1) error = GithubError(response) error.process() return response + class Github(GithubCore): """ Library enter """ @@ -133,10 +134,10 @@ class Github(GithubCore): super(Github, self).__init__() self.authenticated = False auth = len(args) - if auth == 2: # Basic auth - self.session.auth = tuple(map(str,args)) + if auth == 2: # Basic auth + self.session.auth = tuple(map(str, args)) self.authenticated = True - elif auth == 1: # Token oauth + elif auth == 1: # Token oauth raise NotImplementedError elif auth > 2: raise TypeError("user, password or token") diff --git a/github3/errors.py b/github3/errors.py index 09e616b..bd85483 100644 --- a/github3/errors.py +++ b/github3/errors.py @@ -6,6 +6,7 @@ import json import github3.exceptions as exceptions + class GithubError(object): """ Handler for API errors """ @@ -14,7 +15,7 @@ class GithubError(object): self.status_code = response.status_code try: self.debug = self._parser.loads(response.content) - except ValueError: + except (ValueError, TypeError): self.debug = {'message': response.content} def error_400(self): diff --git a/github3/handlers/users.py b/github3/handlers/users.py index fb893b4..b990c65 100644 --- a/github3/handlers/users.py +++ b/github3/handlers/users.py @@ -7,6 +7,7 @@ from .base import Handler import github3.models as models from github3.converters import Rawlizer + class User(Handler): """ User handler with public access """ @@ -25,6 +26,7 @@ class User(Handler): parse_user = str(getattr(user, 'login', user)) self.username = parse_user self.prefix = '/'.join((self.prefix, parse_user)) + return self def get(self): """ Return user """ @@ -61,6 +63,7 @@ class User(Handler): return self._get_resources('gists', model=models.Gist) + class AuthUser(User): """ User handler with public and private access """ @@ -116,6 +119,8 @@ class AuthUser(User): Follow user :param `user`: User model or username string + + NOTE: Maybe bug in API, return text/html. Waitingf for answer """ parse_user = str(getattr(user, 'login', user)) @@ -151,8 +156,8 @@ class AuthUser(User): #TODO: render key.pub file key = { - 'title': kwargs.get('title',''), - 'key': kwargs.get('key','') + 'title': kwargs.get('title', ''), + 'key': kwargs.get('key', '') } return self._post_resource('keys', data=key, model=models.Key) diff --git a/github3/tests/test_core.py b/github3/tests/test_core.py new file mode 100644 index 0000000..258a737 --- /dev/null +++ b/github3/tests/test_core.py @@ -0,0 +1,115 @@ +#!/usr/bin/env python +# -*- encoding: utf-8 -*- + +from mock import Mock, patch +from unittest import TestCase +from github3 import api +from github3.exceptions import * +import json +import requests + + +@patch.object(requests.sessions.Session, 'request') +class TestGithubCore(TestCase): + + def setUp(self): + self.gh = api.GithubCore() + self.assertEquals(self.gh.base_url, 'https://api.github.com/') + self.assertEquals(self.gh._parser, json) + self.base_url = self.gh.base_url + self.parser = self.gh._parser + + def test_parse_args(self, request_method): + args = { + 'data': {'some': 'data'}, + 'params': {'arg0': 'some'}, + 'headers': 'out', + 'auth': 'out', + 'arg1': 'some', + 'arg2': 'some', + 'arg3': {'some': 'data', 'are': {'nested': 'true'}}, + } + self.gh._parse_args(args) + self.assertEquals(args, { + 'data': {'some': 'data'}, + 'params': {'arg0': 'some', 'arg1': 'some', 'arg2': 'some', + 'arg3': {'some': 'data', 'are': {'nested': 'true'}}}, + 'headers': 'out', + 'auth': 'out', + }) + + def test_raise_errors(self, request_method): + real_request = (self.gh._request, 'GET', 'test') + request_method.return_value.status_code = 404 + self.assertRaises(NotFound, *real_request) + + request_method.return_value.status_code = 400 + self.assertRaises(BadRequest, *real_request) + + request_method.return_value.status_code = 422 + self.assertRaises(UnprocessableEntity, *real_request) + + request_method.return_value.status_code = 401 + self.assertRaises(Unauthorized, *real_request) + + def test_get(self, request_method): + response = request_method.return_value + response.content = self.parser.dumps({'test': 'test'}) + content = self.gh.get('core') + request_method.assert_called_with('GET', self.base_url + 'core') + self.assertEquals(content, {'test': 'test'}) + + response = request_method.return_value + response.headers = {'link': 'url_with_links'} + response.content = self.parser.dumps({'test': 'test'}) + header, content = self.gh.get('core', paginate=True) + request_method.assert_called_with('GET', self.base_url + 'core') + self.assertEquals(header, 'url_with_links') + self.assertEquals(content, {'test': 'test'}) + + def test_head(self, request_method): + pass # It has no sense using mocks + + def test_post_and_patch(self, request_method): + data = {'login': 'test', 'bio': 'test'} + response = request_method.return_value + response.status_code = 201 + response.content = self.parser.dumps({'post': 'done'}) + + content = self.gh.post('core', data=data) + request_method.assert_called_with( + 'POST', self.base_url + 'core', + data=self.parser.dumps(data)) + self.assertEquals(content, {'post': 'done'}) + + content = self.gh.post('core') + request_method.assert_called_with( + 'POST', self.base_url + 'core', + data=self.parser.dumps(None)) + self.assertEquals(content, {'post': 'done'}) + + response.status_code = 200 + content = self.gh.patch('core', data=data) + request_method.assert_called_with( + 'PATCH', self.base_url + 'core', + data=self.parser.dumps(data)) + self.assertEquals(content, {'post': 'done'}) + + content = self.gh.patch('core') + request_method.assert_called_with( + 'PATCH', self.base_url + 'core', + data=self.parser.dumps(None)) + self.assertEquals(content, {'post': 'done'}) + + def test_delete(self, request_method): + data = {'test': 'test'} + response = request_method.return_value + response.status_code = 204 + response.content = self.parser.dumps({'delete': 'done'}) + delete = self.gh.delete('core', data=data) + request_method.assert_called_with( + 'DELETE', self.base_url + 'core', + data=self.parser.dumps(data)) + delete = self.gh.delete('core') + request_method.assert_called_with( + 'DELETE', self.base_url + 'core') -- cgit v1.2.3-59-g8ed1b From c205c277fa5d8af9bd43ed55138e2a0552fb3e55 Mon Sep 17 00:00:00 2001 From: David Medina Date: Sat, 12 Nov 2011 03:12:55 +0100 Subject: Catch unauthorized requests. Bad credentials --- github3/errors.py | 3 +++ github3/exceptions.py | 3 +-- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'github3/errors.py') diff --git a/github3/errors.py b/github3/errors.py index bd85483..eed1e6c 100644 --- a/github3/errors.py +++ b/github3/errors.py @@ -21,6 +21,9 @@ class GithubError(object): def error_400(self): return exceptions.BadRequest("400 - %s" % self.debug.get('message')) + def error_401(self): + return exceptions.Unauthorized("401 - %s" % self.debug.get('message')) + def error_404(self): return exceptions.NotFound("404 - %s" % self.debug.get('message')) diff --git a/github3/exceptions.py b/github3/exceptions.py index b0894a9..b033001 100644 --- a/github3/exceptions.py +++ b/github3/exceptions.py @@ -9,6 +9,5 @@ class UnprocessableEntity(Exception): pass class NotFound(Exception): pass -class AnomUser(Exception): - """ Exception for AnomUser handler """ +class Unauthorized(Exception): pass -- cgit v1.2.3-59-g8ed1b From b04156007fa3411c2ae8228e7dbc01da64193eef Mon Sep 17 00:00:00 2001 From: David Medina Date: Thu, 17 Nov 2011 00:16:23 +0100 Subject: Del authors on code. Delegate it to AUTHORS ;) --- github3/api.py | 2 - github3/core.py | 2 - github3/errors.py | 2 - github3/exceptions.py | 2 - github3/handlers/base.py | 2 - github3/handlers/gists.py | 2 - github3/handlers/users.py | 2 - github3/helpers.py | 188 ---------------------------------------- github3/models/base.py | 8 +- github3/models/gists.py | 2 - github3/models/orgs.py | 2 - github3/models/repos.py | 2 - github3/models/user.py | 2 - github3/packages/link_header.py | 3 +- 14 files changed, 4 insertions(+), 217 deletions(-) delete mode 100644 github3/helpers.py (limited to 'github3/errors.py') diff --git a/github3/api.py b/github3/api.py index a4ee4a9..d8d2ffb 100644 --- a/github3/api.py +++ b/github3/api.py @@ -1,7 +1,5 @@ #!/usr/bin/env python # -*- encoding: utf-8 -*- -# -# author: David Medina import requests import json diff --git a/github3/core.py b/github3/core.py index b838bf1..ab71943 100644 --- a/github3/core.py +++ b/github3/core.py @@ -1,7 +1,5 @@ #!/usr/bin/env python # -*- encoding: utf-8 -*- -# -# author: David Medina class Paginate: diff --git a/github3/errors.py b/github3/errors.py index eed1e6c..e96e2da 100644 --- a/github3/errors.py +++ b/github3/errors.py @@ -1,7 +1,5 @@ #!/usr/bin/env python # -*- encoding: utf-8 -*- -# -# author: David Medina import json import github3.exceptions as exceptions diff --git a/github3/exceptions.py b/github3/exceptions.py index dbc4d2c..b9070d7 100644 --- a/github3/exceptions.py +++ b/github3/exceptions.py @@ -1,7 +1,5 @@ #!/usr/bin/env python # -*- encoding: utf-8 -*- -# -# author: David Medina class BadRequest(Exception): pass diff --git a/github3/handlers/base.py b/github3/handlers/base.py index 0b3fa8a..4e9198f 100644 --- a/github3/handlers/base.py +++ b/github3/handlers/base.py @@ -1,7 +1,5 @@ #!/usr/bin/env python # -*- encoding: utf-8 -*- -# -# author: David Medina from github3.core import Paginate from github3.converters import Modelizer diff --git a/github3/handlers/gists.py b/github3/handlers/gists.py index fa961b2..38418ca 100644 --- a/github3/handlers/gists.py +++ b/github3/handlers/gists.py @@ -1,7 +1,5 @@ #!/usr/bin/env python # -*- encoding: utf-8 -*- -# -# author: Antti Kaihola from .base import Handler from .. import models diff --git a/github3/handlers/users.py b/github3/handlers/users.py index 84180b5..34ed013 100644 --- a/github3/handlers/users.py +++ b/github3/handlers/users.py @@ -1,7 +1,5 @@ #!/usr/bin/env python # -*- encoding: utf-8 -*- -# -# author: David Medina from .base import Handler import github3.models as models diff --git a/github3/helpers.py b/github3/helpers.py deleted file mode 100644 index 205e097..0000000 --- a/github3/helpers.py +++ /dev/null @@ -1,188 +0,0 @@ -# -*- coding: utf-8 -*- - -""" -github3.helpers -~~~~~~~~~~~~~~~~ - -This module provides various helper functions to the rest of the package. -""" - -import inspect -from datetime import datetime - -from dateutil.parser import parse as parse_datetime - - -def is_collection(obj): - """Tests if an object is a collection.""" - - col = getattr(obj, '__getitem__', False) - val = False if (not col) else True - - if isinstance(obj, basestring): - val = False - - return val - - -def key_diff(source, update, pack=False): - """Given two dictionaries, returns a list of the changed keys.""" - - source = dict(source) - update = dict(update) - - changed = [] - - for (k, v) in source.items(): - u_v = update.get(k) - - if (v != u_v) and (u_v is not None): - changed.append(k) - - if pack is False: - return changed - - d = dict() - - for k in changed: - d[k] = update[k] - - return d - - -# from arc90/python-readability-api -def to_python(obj, - in_dict, - str_keys=None, - date_keys=None, - int_keys=None, - object_map=None, - list_map=None, - bool_keys=None, **kwargs): - """Extends a given object for API Consumption. - - :param obj: Object to extend. - :param in_dict: Dict to extract data from. - :param string_keys: List of in_dict keys that will be extracted as strings. - :param date_keys: List of in_dict keys that will be extrad as datetimes. - :param object_map: Dict of {key, obj} map, for nested object results. - """ - - d = dict() - - if str_keys: - for in_key in str_keys: - d[in_key] = in_dict.get(in_key) - - if date_keys: - for in_key in date_keys: - in_date = in_dict.get(in_key) - try: - out_date = datetime.strptime(in_date, '%Y-%m-%dT%H:%M:%SZ') - except TypeError: - out_date = None - - d[in_key] = out_date - - if int_keys: - for in_key in int_keys: - if (in_dict is not None) and (in_dict.get(in_key) is not None): - d[in_key] = int(in_dict.get(in_key)) - - if bool_keys: - for in_key in bool_keys: - if in_dict.get(in_key) is not None: - d[in_key] = bool(in_dict.get(in_key)) - - if object_map: - for (k, v) in object_map.items(): - if in_dict.get(k): - if v == 'self': - v = obj.__class__ - d[k] = v.new_from_dict(in_dict.get(k)) - - if list_map: - for k, model in list_map.items(): - nested_map = in_dict.get(k) - if nested_map: - if getattr(nested_map, 'items', False): - map_dict = {} - for nested_item, nested_dict in nested_map.items(): - map_dict[nested_item] = model.new_from_dict(nested_dict) - d[k] = map_dict - else: - map_list = [] - for item_map in nested_map: - map_list.append(model.new_from_dict(item_map)) - d[k] = map_list - - obj.__dict__.update(d) - obj.__dict__.update(kwargs) - - # Save the dictionary, for write comparisons. - obj._cache = d - obj.__cache = in_dict - obj.post_map() - - return obj - - -# from arc90/python-readability-api -def to_api(in_dict, int_keys=None, date_keys=None, bool_keys=None): - """Extends a given object for API Production.""" - - # Cast all int_keys to int() - if int_keys: - for in_key in int_keys: - if (in_key in in_dict) and (in_dict.get(in_key, None) is not None): - in_dict[in_key] = int(in_dict[in_key]) - - # Cast all date_keys to datetime.isoformat - if date_keys: - for in_key in date_keys: - if (in_key in in_dict) and (in_dict.get(in_key, None) is not None): - - _from = in_dict[in_key] - - if isinstance(_from, basestring): - dtime = parse_datetime(_from) - - elif isinstance(_from, datetime): - dtime = _from - - in_dict[in_key] = dtime.isoformat() - - elif (in_key in in_dict) and in_dict.get(in_key, None) is None: - del in_dict[in_key] - - # Remove all Nones - for k, v in in_dict.items(): - if v is None: - del in_dict[k] - - return in_dict - - - -# from kennethreitz/showme -def get_scope(f, args=None): - """Get scope of given function for Exception scopes.""" - - if args is None: - args=list() - - scope = inspect.getmodule(f).__name__ - # guess that function is a method of it's class - try: - if f.func_name in dir(args[0].__class__): - scope += '.' + args[0].__class__.__name__ - scope += '.' + f.__name__ - else: - scope += '.' + f.__name__ - except IndexError: - scope += '.' + f.__name__ - - # scrub readability.models namespace - scope = scope.replace('readability.api.', '') - - return scope diff --git a/github3/models/base.py b/github3/models/base.py index bd07650..5295d07 100644 --- a/github3/models/base.py +++ b/github3/models/base.py @@ -1,9 +1,5 @@ -""" -github3.models -~~~~~~~~~~~~~~ - -This package provides the Github3 object model. -""" +#!/usr/bin/env python +# -*- encoding: utf-8 -*- class BaseResource(object): """A BaseResource object.""" diff --git a/github3/models/gists.py b/github3/models/gists.py index d1b416d..b317f57 100644 --- a/github3/models/gists.py +++ b/github3/models/gists.py @@ -1,7 +1,5 @@ #!/usr/bin/env python # -*- encoding: utf-8 -*- -# -# author: David Medina from .base import BaseResource from .user import User diff --git a/github3/models/orgs.py b/github3/models/orgs.py index 5e66c35..b2dacbd 100644 --- a/github3/models/orgs.py +++ b/github3/models/orgs.py @@ -1,7 +1,5 @@ #!/usr/bin/env python # -*- encoding: utf-8 -*- -# -# author: David Medina from .base import BaseResource from .user import Plan diff --git a/github3/models/repos.py b/github3/models/repos.py index d1b7b75..882fb37 100644 --- a/github3/models/repos.py +++ b/github3/models/repos.py @@ -1,7 +1,5 @@ #!/usr/bin/env python # -*- encoding: utf-8 -*- -# -# author: David Medina from .base import BaseResource from .user import User diff --git a/github3/models/user.py b/github3/models/user.py index e2d82b6..93201bd 100644 --- a/github3/models/user.py +++ b/github3/models/user.py @@ -1,7 +1,5 @@ #!/usr/bin/env python # -*- encoding: utf-8 -*- -# -# author: David Medina from .base import BaseResource diff --git a/github3/packages/link_header.py b/github3/packages/link_header.py index 3959604..5ad20f1 100644 --- a/github3/packages/link_header.py +++ b/github3/packages/link_header.py @@ -1,4 +1,5 @@ #!/usr/bin/env python +# -*- encoding: utf-8 -*- """ HTTP Link Header Parsing @@ -86,4 +87,4 @@ def parse_link_value(instr): if __name__ == '__main__': import sys if len(sys.argv) > 1: - print parse_link_value(sys.argv[1]) \ No newline at end of file + print parse_link_value(sys.argv[1]) -- cgit v1.2.3-59-g8ed1b