aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README.md (renamed from README.rst)49
-rw-r--r--github3/api.py29
-rw-r--r--github3/errors.py3
-rw-r--r--github3/handlers/users.py9
-rw-r--r--github3/tests/test_core.py115
5 files changed, 156 insertions, 49 deletions
diff --git a/README.rst b/README.md
index c07cbc9..334b975 100644
--- a/README.rst
+++ b/README.md
@@ -1,45 +1,34 @@
Fork
-======================================
+====
Refactor and complete api wrapper. Intensive work in progress
Use with auth user
----------------------
+------------------
-```python
-from github3.api import Github
+ from github3.api import Github
-gh = Github('user', 'password')
+ 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'}})
-```
+ 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.
-
+To install Github3, simply:
+ $ pip -e git+https://copitux@github.com/copitux/python-github3#egg=python-github3
License
-------
-ISC License. ::
+ISC License.
Copyright (c) 2011, Kenneth Reitz <me@kennethreitz.com>
@@ -59,10 +48,9 @@ ISC License. ::
Contribute
----------
-If you'd like to contribute, simply fork `the repository`_, commit your changes
+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_.
-
+sure you add yourself to `AUTHORS`.
Roadmap
@@ -70,9 +58,6 @@ Roadmap
- Unittests
- Handlers
-- Get it Started
-- HTTP BASIC
-- Get it working
-- Sphinx Documetnation
+- Sphinx Documentation
- 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')