From eb6b5e45f461c4967e25c64c904f0d3b2051a854 Mon Sep 17 00:00:00 2001 From: David Medina Date: Thu, 10 Nov 2011 23:20:30 +0100 Subject: Init test enviroment Also rename user handler module to 'users' --- github3/api.py | 29 +++++- github3/handlers/__init__.py | 2 + github3/handlers/gists.py | 3 + github3/handlers/user.py | 205 ------------------------------------------- github3/handlers/users.py | 205 +++++++++++++++++++++++++++++++++++++++++++ github3/tests/base_test.py | 29 ++++++ github3/tests/gist_tests.py | 98 +++++++++++++++++++++ 7 files changed, 365 insertions(+), 206 deletions(-) delete mode 100644 github3/handlers/user.py create mode 100644 github3/handlers/users.py create mode 100644 github3/tests/base_test.py create mode 100644 github3/tests/gist_tests.py (limited to 'github3') diff --git a/github3/api.py b/github3/api.py index b7435ff..e9eebb5 100644 --- a/github3/api.py +++ b/github3/api.py @@ -6,6 +6,7 @@ import requests import json from errors import GithubError +from handlers import users, gists RESOURCES_PER_PAGE = 100 @@ -126,4 +127,30 @@ class GithubCore(object): return response class Github(GithubCore): - pass + """ Library enter """ + + def __init__(self, *args): + super(Github, self).__init__() + self.authenticated = False + auth = len(args) + if auth == 2: # Basic auth + self.session.auth = tuple(map(str,args)) + self.authenticated = True + elif auth == 1: # Token oauth + raise NotImplementedError + elif auth > 2: + raise TypeError("user, password or token") + + @property + def users(self): + if self.authenticated: + return users.AuthUser(self) + else: + return users.User(self) + + @property + def gists(self): + if self.authenticated: + return gists.AuthGist(self) + else: + return gists.Gist(self) diff --git a/github3/handlers/__init__.py b/github3/handlers/__init__.py index e69de29..3ac5fdc 100644 --- a/github3/handlers/__init__.py +++ b/github3/handlers/__init__.py @@ -0,0 +1,2 @@ +import users +import gists diff --git a/github3/handlers/gists.py b/github3/handlers/gists.py index 15f215c..fa961b2 100644 --- a/github3/handlers/gists.py +++ b/github3/handlers/gists.py @@ -20,6 +20,9 @@ class Gist(Handler): return self._get_resource(gist_id, model=models.Gist) + +class AuthGist(Gist): + def create_gist(self, description, public=True, files={}): """ Create a gist """ data = {'description': description, diff --git a/github3/handlers/user.py b/github3/handlers/user.py deleted file mode 100644 index fb893b4..0000000 --- a/github3/handlers/user.py +++ /dev/null @@ -1,205 +0,0 @@ -#!/usr/bin/env python -# -*- encoding: utf-8 -*- -# -# author: David Medina - -from .base import Handler -import github3.models as models -from github3.converters import Rawlizer - -class User(Handler): - """ User handler with public access """ - - prefix = 'users' - - def __repr__(self): - return ' %s>' % getattr(self, 'username', 'without user') - - def set_username(self, user): - """ - Set username to query public handler - - :param `user`: User model or username string - """ - - parse_user = str(getattr(user, 'login', user)) - self.username = parse_user - self.prefix = '/'.join((self.prefix, parse_user)) - - def get(self): - """ Return user """ - - return self._get_resource('', model=models.User) - - def get_followers(self): - """ Return user's followers """ - - return self._get_resources('followers', model=models.User) - - def get_following(self): - """ Return users that follow """ - - return self._get_resources('following', model=models.User) - - def get_repos(self): - """ Return user's public repositories """ - - return self._get_resources('repos', model=models.Repo) - - def get_watched(self): - """ Return repositories that user whatch """ - - return self._get_resources('watched', model=models.Repo) - - def get_orgs(self): - """ Return user's public organizations """ - - return self._get_resources('orgs', model=models.Org) - - def get_gists(self): - """ Return user's gists """ - - return self._get_resources('gists', model=models.Gist) - -class AuthUser(User): - """ User handler with public and private access """ - - prefix = 'user' - - def __repr__(self): - return ' %s>' % self._gh.session.auth[0] - - def get(self): - return self._get_resource('', model=models.AuthUser) - - def get_emails(self): - """ Return list of emails """ - - # Ignore converter, it must be Rawlizer - emails = self._get_resource('emails', converter=Rawlizer()) - return emails - - def create_emails(self, *args): - """ - Add emails - - :param args: Collection of emails - create_emails(*('test1@example.com', 'test2@example.cm')) - """ - parsed_emails = map(str, args) - all_mails = self._post_resource( - 'emails', data=parsed_emails, converter=Rawlizer()) - return all_mails - - def delete_emails(self, *args): - """ - Delete emails - - :param args: Collection of emails - create_emails(*('test1@example.com', 'test2@example.cm')) - """ - parsed_emails = map(str, args) - return self._delete('emails', data=parsed_emails) - - def is_following(self, user): - """ - Return true if you are following the user - - :param `user`: User model or username string - """ - - parse_user = str(getattr(user, 'login', user)) - return self._bool('following/%s' % parse_user) - - def follow(self, user): - """ - Follow user - - :param `user`: User model or username string - """ - - parse_user = str(getattr(user, 'login', user)) - return self._put('following/%s' % parse_user) - - def unfollow(self, user): - """ - Unfollow user - - :param `user`: User model or username string - """ - - parse_user = str(getattr(user, 'login', 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): - """ Get public key by id """ - - return self._get_resource('keys/%s' % key_id, model=models.Key) - - def create_key(self, **kwargs): - """ - Create public key - - :param title - :param key: Key string - """ - - #TODO: render key.pub file - key = { - 'title': kwargs.get('title',''), - 'key': kwargs.get('key','') - } - return self._post_resource('keys', data=key, model=models.Key) - - def delete_key(self, key_id): - """ Delete public key """ - - return self._delete('keys/%s' % key_id) - - def get_repos(self, filter='all'): - """ - Return user's public repositories - - param: filter: 'all', 'public', 'private' or 'member' - """ - - return self._get_resources('repos', model=models.Repo, - type=str(filter)) - - def is_watching_repo(self, owner, repo): - """ - Return true if you are watching the user repository - - :param owner: username - :param repo: repository name - is_watching_repo('copitux', 'python-github3') - """ - - owner = getattr(owner, 'login', owner) - repo = getattr(repo, 'name', repo) - return self._bool('watched/%s/%s' % (owner, repo)) - - def watch_repo(self, owner, repo): - """ - Watch the repository - - :param owner: username - :param repo: repository name - """ - - return self._put('watched/%s/%s' % (owner, repo)) - - def unwatch_repo(self, owner, repo): - """ - Unwatch the repository - - :param owner: username - :param repo: repository name - """ - - return self._delete('watched/%s/%s' % (owner, repo)) diff --git a/github3/handlers/users.py b/github3/handlers/users.py new file mode 100644 index 0000000..fb893b4 --- /dev/null +++ b/github3/handlers/users.py @@ -0,0 +1,205 @@ +#!/usr/bin/env python +# -*- encoding: utf-8 -*- +# +# author: David Medina + +from .base import Handler +import github3.models as models +from github3.converters import Rawlizer + +class User(Handler): + """ User handler with public access """ + + prefix = 'users' + + def __repr__(self): + return ' %s>' % getattr(self, 'username', 'without user') + + def set_username(self, user): + """ + Set username to query public handler + + :param `user`: User model or username string + """ + + parse_user = str(getattr(user, 'login', user)) + self.username = parse_user + self.prefix = '/'.join((self.prefix, parse_user)) + + def get(self): + """ Return user """ + + return self._get_resource('', model=models.User) + + def get_followers(self): + """ Return user's followers """ + + return self._get_resources('followers', model=models.User) + + def get_following(self): + """ Return users that follow """ + + return self._get_resources('following', model=models.User) + + def get_repos(self): + """ Return user's public repositories """ + + return self._get_resources('repos', model=models.Repo) + + def get_watched(self): + """ Return repositories that user whatch """ + + return self._get_resources('watched', model=models.Repo) + + def get_orgs(self): + """ Return user's public organizations """ + + return self._get_resources('orgs', model=models.Org) + + def get_gists(self): + """ Return user's gists """ + + return self._get_resources('gists', model=models.Gist) + +class AuthUser(User): + """ User handler with public and private access """ + + prefix = 'user' + + def __repr__(self): + return ' %s>' % self._gh.session.auth[0] + + def get(self): + return self._get_resource('', model=models.AuthUser) + + def get_emails(self): + """ Return list of emails """ + + # Ignore converter, it must be Rawlizer + emails = self._get_resource('emails', converter=Rawlizer()) + return emails + + def create_emails(self, *args): + """ + Add emails + + :param args: Collection of emails + create_emails(*('test1@example.com', 'test2@example.cm')) + """ + parsed_emails = map(str, args) + all_mails = self._post_resource( + 'emails', data=parsed_emails, converter=Rawlizer()) + return all_mails + + def delete_emails(self, *args): + """ + Delete emails + + :param args: Collection of emails + create_emails(*('test1@example.com', 'test2@example.cm')) + """ + parsed_emails = map(str, args) + return self._delete('emails', data=parsed_emails) + + def is_following(self, user): + """ + Return true if you are following the user + + :param `user`: User model or username string + """ + + parse_user = str(getattr(user, 'login', user)) + return self._bool('following/%s' % parse_user) + + def follow(self, user): + """ + Follow user + + :param `user`: User model or username string + """ + + parse_user = str(getattr(user, 'login', user)) + return self._put('following/%s' % parse_user) + + def unfollow(self, user): + """ + Unfollow user + + :param `user`: User model or username string + """ + + parse_user = str(getattr(user, 'login', 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): + """ Get public key by id """ + + return self._get_resource('keys/%s' % key_id, model=models.Key) + + def create_key(self, **kwargs): + """ + Create public key + + :param title + :param key: Key string + """ + + #TODO: render key.pub file + key = { + 'title': kwargs.get('title',''), + 'key': kwargs.get('key','') + } + return self._post_resource('keys', data=key, model=models.Key) + + def delete_key(self, key_id): + """ Delete public key """ + + return self._delete('keys/%s' % key_id) + + def get_repos(self, filter='all'): + """ + Return user's public repositories + + param: filter: 'all', 'public', 'private' or 'member' + """ + + return self._get_resources('repos', model=models.Repo, + type=str(filter)) + + def is_watching_repo(self, owner, repo): + """ + Return true if you are watching the user repository + + :param owner: username + :param repo: repository name + is_watching_repo('copitux', 'python-github3') + """ + + owner = getattr(owner, 'login', owner) + repo = getattr(repo, 'name', repo) + return self._bool('watched/%s/%s' % (owner, repo)) + + def watch_repo(self, owner, repo): + """ + Watch the repository + + :param owner: username + :param repo: repository name + """ + + return self._put('watched/%s/%s' % (owner, repo)) + + def unwatch_repo(self, owner, repo): + """ + Unwatch the repository + + :param owner: username + :param repo: repository name + """ + + return self._delete('watched/%s/%s' % (owner, repo)) diff --git a/github3/tests/base_test.py b/github3/tests/base_test.py new file mode 100644 index 0000000..59d474a --- /dev/null +++ b/github3/tests/base_test.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python +# -*- encoding: utf-8 -*- + +from unittest import TestCase +import github3 +from github3 import api +from github3 import handlers + + +class TestGetHandlers(TestCase): + + def setUp(self): + self.anom_gh = api.Github() + self.auth_gh = api.Github('test', 'password') + + def test_get_user(self): + anom_user = self.anom_gh.users + auth_user = self.auth_gh.users + + self.assertEquals(isinstance(anom_user, handlers.users.User), True) + self.assertEquals(isinstance(auth_user, handlers.users.AuthUser), True) + + def test_get_gists(self): + anom_gists = self.anom_gh.gists + auth_gists = self.auth_gh.gists + + self.assertEquals(isinstance(anom_gists, handlers.gists.Gist), True) + self.assertEquals( + isinstance(auth_gists, handlers.gists.AuthGist), True) diff --git a/github3/tests/gist_tests.py b/github3/tests/gist_tests.py new file mode 100644 index 0000000..1218772 --- /dev/null +++ b/github3/tests/gist_tests.py @@ -0,0 +1,98 @@ +#!/usr/bin/env python +# -*- encoding: utf-8 -*- +# +# author: Antti Kaihola + +from datetime import datetime +import json +from mock import MagicMock, Mock, patch +import unittest + +import github3.api +import github3.handlers.gists +import github3.handlers.user +import github3.models + + +GIST_RESPONSE = '{"user":{"gravatar_id":"123","url":"https://api.github.com/users/testuser","avatar_url":"https://secure.gravatar.com/avatar/123?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-1.png","login":"testuser","id":12345},"url":"https://api.github.com/gists/791920","history":[{"version":"deadbeefdeadbeefdeadbeefdeadbeefdeadbeef","url":"https://api.github.com/gists/791920/deadbeefdeadbeefdeadbeefdeadbeefdeadbeef","user":{"gravatar_id":"123","url":"https://api.github.com/users/testuser","avatar_url":"https://secure.gravatar.com/avatar/123?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-1.png","login":"testuser","id":12345},"committed_at":"2011-11-09T08:50:53Z","change_status":{"deletions":0,"additions":1,"total":1}}],"description":"description","created_at":"2011-11-09T08:50:53Z","public":true,"comments":0,"updated_at":"2011-11-09T08:50:53Z","git_pull_url":"git://gist.github.com/791920.git","forks":[],"git_push_url":"git@gist.github.com:791920.git","html_url":"https://gist.github.com/791920","id":"791920","files":{"filename.ext":{"raw_url":"https://gist.github.com/raw/791920/badafadacadafadabadacadafadabadabadacada/filename.ext","type":"text/plain","content":"content","size":7,"language":null,"filename":"filename.ext"}}}' + + +class GistsTestCase(unittest.TestCase): + def test_create_gist(self): + """The HTTP request for creating a gist is correct""" + g = github3.api.Github() + g.session.auth = ('testuser', 'password') + u = github3.handlers.user.AuthUser(g) + gists = github3.handlers.gists.AuthGist(g) + OpenerDirector = MagicMock(name='OpenerDirector') + opener = OpenerDirector.return_value + response = opener.open.return_value + response.read.return_value = GIST_RESPONSE + response.code = 201 + + with patch('urllib2.OpenerDirector', OpenerDirector): + + gist = gists.create_gist( + 'description', + files={'filename.ext': {'content': 'content'}}) + + request = opener.open.call_args[0][0] + self.assertEqual(request.method, 'POST') + self.assertEqual(request.get_full_url(), + 'https://api.github.com/gists?per_page=100') + self.assertEqual(request.headers['Authorization'], + 'Basic dGVzdHVzZXI6cGFzc3dvcmQ=') + self.assertEqual(json.loads(request.data), + {u'description': u'description', + u'files': {u'filename.ext': {u'content': u'content'}}, + u'public': True}) + + +class GistHandlerTestCase(unittest.TestCase): + def test_response_conversion(self): + """A gist response is decoded correctly to a Gist object""" + g = github3.api.Github() + handler = github3.handlers.gists.Gist(g) + converter = handler._get_converter() + converter.inject(github3.models.Gist) + + gist = converter.loads(json.loads(GIST_RESPONSE)) + + self.assertEqual( + {filename: value.__dict__ + for filename, value in gist.files.iteritems()}, + {u'filename.ext': { + 'content': u'content', + 'filename': u'filename.ext', + 'raw_url': (u'https://gist.github.com/' + u'raw/791920/' + u'badafadacadafadabadacadafadabadabadacada/' + u'filename.ext'), + 'size': 7, + 'type': u'text/plain'}}) + self.assertEqual(gist.description, u'description') + self.assertEqual(gist.url, u'https://api.github.com/gists/791920') + self.assertEqual(gist.created_at, datetime(2011, 11, 9, 8, 50, 53)) + self.assertEqual(gist.html_url, u'https://gist.github.com/791920') + self.assertEqual(gist.public, True) + self.assertEqual( + gist.user.__dict__, + {'avatar_url': (u'https://secure.gravatar.com/avatar/123' + u'?d=https://a248.e.akamai.net/' + u'assets.github.com%2Fimages%2Fgravatars' + u'%2Fgravatar-1.png'), + 'id': 12345, + 'login': u'testuser', + 'url': u'https://api.github.com/users/testuser'}) + self.assertEqual(gist.git_pull_url, u'git://gist.github.com/791920.git') + self.assertEqual(gist.git_push_url, u'git@gist.github.com:791920.git') + self.assertEqual(gist.id, u'791920') + self.assertEqual(len(gist.history), 1) + h = gist.history[0] + self.assertEqual(h.change_status.__dict__, {'additions': 1, 'total': 1}) + self.assertEqual(h.committed_at, datetime(2011, 11, 9, 8, 50, 53)) + self.assertEqual(h.url, + u'https://api.github.com/gists/791920/' + u'deadbeefdeadbeefdeadbeefdeadbeefdeadbeef') + self.assertEqual(h.user.__dict__, gist.user.__dict__) + self.assertEqual(h.version, u'deadbeefdeadbeefdeadbeefdeadbeefdeadbeef') -- cgit v1.3-14-g43fede