aboutsummaryrefslogtreecommitdiffstats
path: root/github3/handlers
diff options
context:
space:
mode:
Diffstat (limited to 'github3/handlers')
-rw-r--r--github3/handlers/base.py76
-rw-r--r--github3/handlers/gists.py145
-rw-r--r--github3/handlers/users.py299
3 files changed, 502 insertions, 18 deletions
diff --git a/github3/handlers/base.py b/github3/handlers/base.py
index 50e2df8..565978f 100644
--- a/github3/handlers/base.py
+++ b/github3/handlers/base.py
@@ -1,11 +1,43 @@
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
-#
-# author: David Medina
from github3.core import Paginate
from github3.converters import Modelizer
+
+class MimeTypeMixin(object):
+
+ VERSION = 'beta'
+
+ def __init__(self):
+ self.mimetypes = set()
+
+ def _parse_mime_type(self, type):
+ return 'application/vnd.github.%s.%s+json' % (
+ self.VERSION, type)
+
+ def add_raw(self):
+ self.mimetypes.add(self._parse_mime_type('raw'))
+ return self
+
+ def add_text(self):
+ self.mimetypes.add(self._parse_mime_type('text'))
+ return self
+
+ def add_html(self):
+ self.mimetypes.add(self._parse_mime_type('html'))
+ return self
+
+ def add_full(self):
+ self.mimetypes.add(self._parse_mime_type('full'))
+ return self
+
+ def mime_header(self):
+ if self.mimetypes:
+ return {'Accept': ', '.join(self.mimetypes)}
+ return None
+
+
class Handler(object):
""" Handler base. Requests to API and modelize responses """
@@ -13,17 +45,23 @@ class Handler(object):
self._gh = gh
super(Handler, self).__init__()
+ def _inject_handler(self, handler, prefix=''):
+ import inspect
+ for method, callback in inspect.getmembers(handler):
+ if method.startswith(prefix) and inspect.ismethod(callback):
+ setattr(self, method, callback)
+
def _prefix_resource(self, resource):
prefix = getattr(self, 'prefix', '')
- return '/'.join((prefix, resource)).rstrip('/')
+ return '/'.join((prefix, str(resource))).strip('/')
- def _get_converter(self, **kwargs):
- converter = kwargs.get(
- 'converter', # 1. in kwargs
- getattr(self, 'converter', # 2. in handler
- Modelizer())) # 3. Default
+ def _get_converter(self, kwargs={}):
+ converter = kwargs.pop(
+ 'converter', # 1. in kwargs
+ getattr(self, 'converter', # 2. in handler
+ Modelizer)) # 3. Default
- return converter
+ return converter()
def _put(self, resource, **kwargs):
""" Put proxy request"""
@@ -41,27 +79,29 @@ 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
assert response.status_code == 204
return True
- #TODO: if limit is multiple of per_page... it do another request for nothing
def _get_resources(self, resource, model=None, limit=None, **kwargs):
""" Hander request to multiple resources """
+ if limit:
+ limit = abs(limit)
resource = self._prefix_resource(resource)
- page_resources = Paginate(resource, self._gh.get, **kwargs)
+ converter = self._get_converter(kwargs)
counter = 1
- for page in page_resources:
+ for page in Paginate(resource, self._gh.get, **kwargs):
for raw_resource in page:
- if limit and counter > limit: break
counter += 1
- converter = self._get_converter(**kwargs)
converter.inject(model)
yield converter.loads(raw_resource)
+ if limit and counter > limit:
+ break
else:
continue
break
@@ -70,8 +110,8 @@ class Handler(object):
""" Handler request to single resource """
resource = self._prefix_resource(resource)
- raw_resource = self._gh.get(resource)
- converter = self._get_converter(**kwargs)
+ converter = self._get_converter(kwargs)
+ raw_resource = self._gh.get(resource, **kwargs)
converter.inject(model)
return converter.loads(raw_resource)
@@ -80,6 +120,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/gists.py b/github3/handlers/gists.py
new file mode 100644
index 0000000..ed03c31
--- /dev/null
+++ b/github3/handlers/gists.py
@@ -0,0 +1,145 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8 -*-
+
+from .base import Handler, MimeTypeMixin
+from github3 import models
+
+
+class Gist(Handler, MimeTypeMixin):
+ """ Gist handler with public access """
+
+ prefix = 'gists'
+
+ def __repr__(self):
+ return '<Gist handler>'
+
+ def all_gists(self, limit=None):
+ """ Return all public gists
+
+ NOTE: It returns all gists in github environment. Maybe you
+ want to use `limit` parameter
+ """
+
+ return self._get_resources('', model=models.Gist, limit=limit)
+
+ def get(self, gist_id):
+ """ Return gist
+
+ param `gist_id`: Gist id
+ """
+
+ return self._get_resource(gist_id, model=models.Gist)
+
+ def get_comments(self, gist_id, limit=None):
+ """ Return gist's comments
+
+ param `gist_id`: Gist id
+ param `limit`: Number of comments
+ """
+
+ return self._get_resources('%s/comments' % gist_id,
+ model=models.GistComment, limit=limit,
+ headers=self.mime_header())
+
+ def get_comment(self, comment_id):
+ """ Return gist's comment
+
+ param `comment_id`: Comment id
+ """
+
+ return self._get_resource('comments/%s' % comment_id,
+ model=models.GistComment, headers=self.mime_header())
+
+
+class AuthGist(Gist):
+
+ def all_gists(self, limit=None):
+ """ Return all public gists
+
+ NOTE: It returns all gists in github environment. Maybe you
+ want to use `limit` parameter
+ """
+
+ return self._get_resources('public', model=models.Gist, limit=limit)
+
+ def my_gists(self, limit=None):
+ """ Return authenticated user's gists
+
+ param `limit`: Number of gists
+ """
+
+ return self._get_resources('', model=models.Gist, limit=limit)
+
+ def my_starred_gists(self, limit=None):
+ """ Return authenticated user's starred gists
+
+ param `limit`: Number of gists
+ """
+
+ return self._get_resources('starred', model=models.Gist, limit=limit)
+
+ def create_gist(self, is_public, files, desc=None):
+ """ Create and return a gist """
+
+ data = {
+ 'public': bool(is_public),
+ 'files': files, # TODO: Issue #1
+ 'desc': desc or '',
+ }
+ return self._post_resource('', data=data, model=models.Gist)
+
+ def star_gist(self, gist_id):
+ """ Star a gist
+
+ param `gist_id`: Gist id to star
+ """
+
+ return self._put('%s/star' % gist_id)
+
+ def unstar_gist(self, gist_id):
+ """ Unstar a gist
+
+ param `gist_id`: Gist id to unstar
+ """
+
+ return self._delete('%s/star' % gist_id)
+
+ def is_starred(self, gist_id):
+ """ True if gist is starred
+
+ param `gist_id`: Gist id
+ """
+
+ return self._bool('%s/star' % gist_id)
+
+ def fork_gist(self, gist_id):
+ """ Return forked gist from id
+
+ param `gist_id`: Gist id to be forked...
+ """
+
+ return self._post_resource('%s/fork' % gist_id, data=None,
+ model=models.Gist)
+
+ def delete_gist(self, gist_id):
+ """ Delete the gist
+
+ param `gist_id`: Gist id
+ """
+
+ return self._delete(str(gist_id))
+
+ def create_comment(self, gist_id, comment):
+ """ Create comment into gist """
+
+ data = {'body': comment}
+ return self._post_resource('%s/comments' % gist_id, data=data,
+ model=models.GistComment)
+
+ def delete_comment(self, comment_id):
+ """ Delete comment
+
+ param `comment_id`: Comment id
+ """
+
+ return self._delete('comments/%s' % comment_id)
diff --git a/github3/handlers/users.py b/github3/handlers/users.py
new file mode 100644
index 0000000..2f12184
--- /dev/null
+++ b/github3/handlers/users.py
@@ -0,0 +1,299 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8 -*-
+
+from .base import Handler
+from github3 import models
+from github3.converters import Rawlizer
+from github3.exceptions import UserIsAnonymous
+
+
+class User(Handler):
+ """ User handler with public access """
+
+ prefix = 'users'
+
+ def __repr__(self):
+ return '<User handler> %s>' % getattr(self, 'username', 'without user')
+
+ def _parse_user(self, user):
+ """ Parse user, and if it fails then try with username in handler
+
+ :param user: It can be a `models.User` or alphanumeric user string
+
+ """
+ username = getattr(user, 'login', user)
+ if not username or not str(username).isalpha():
+ username = getattr(self, 'username', False)
+ if not username:
+ raise UserIsAnonymous('%s user is not valid' % username)
+ return str(username)
+
+ def set_username(self, user):
+ """ Set username to query public handler
+ Helper to less writing
+
+ :param user: It can be a `models.User` or alphanumeric user string
+
+ """
+ self.username = self._parse_user(user)
+ return self
+
+ def get(self, user=None):
+ """ Return user
+
+ :param `user`: User model or username string
+
+ """
+ user = self._parse_user(user)
+ return self._get_resource(user, model=models.User)
+
+ def get_followers(self, user=None, limit=None):
+ """ Return user's followers
+
+ :param `user`: User model or username string
+
+ """
+ user = self._parse_user(user)
+ return self._get_resources('%s/followers' % user, model=models.User,
+ limit=limit)
+
+ def get_following(self, user=None, limit=None):
+ """ Return users that follow
+
+ :param `user`: User model or username string
+
+ """
+ user = self._parse_user(user)
+ return self._get_resources('%s/following' % user, model=models.User,
+ limit=limit)
+
+ def get_repos(self, user=None, limit=None):
+ """ Return user's public repositories
+
+ :param `user`: User model or username string
+
+ """
+ user = self._parse_user(user)
+ return self._get_resources('%s/repos' % user, model=models.Repo,
+ limit=limit)
+
+ def get_watched(self, user=None, limit=None):
+ """ Return repositories that user watch
+
+ :param `user`: User model or username string
+
+ """
+ user = self._parse_user(user)
+ return self._get_resources('%s/watched' % user, model=models.Repo,
+ limit=limit)
+
+ def get_orgs(self, user=None, limit=None):
+ """ Return user's public organizations
+
+ :param `user`: User model or username string
+
+ """
+ user = self._parse_user(user)
+ return self._get_resources('%s/orgs' % user, model=models.Org,
+ limit=limit)
+
+ def get_gists(self, user=None, limit=None):
+ """ Return user's gists
+
+ :param `user`: User model or username string
+
+ """
+ user = self._parse_user(user)
+ return self._get_resources('%s/gists' % user, model=models.Gist,
+ limit=limit)
+
+
+class AuthUser(Handler):
+ """ User handler with public and private access """
+
+ prefix = 'user'
+
+ def __init__(self, gh):
+ super(AuthUser, self).__init__(gh)
+ self._inject_handler(User(gh), prefix='get')
+
+ def __repr__(self):
+ return '<AuthUser handler> %s>' % self._gh.session.auth[0]
+
+ def me(self):
+ """ Return authenticated user """
+
+ return self._get_resource('', model=models.AuthUser)
+
+ def my_followers(self, limit=None):
+ """ Return authenticated user followers """
+
+ return self._get_resources('followers', model=models.User,
+ limit=limit)
+
+ def my_following(self, limit=None):
+ """ Return authenticated user following """
+
+ return self._get_resources('following', model=models.User,
+ limit=limit)
+
+ 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 = 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 = 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 = getattr(user, 'login', user)
+ return self._delete('following/%s' % parse_user)
+
+ def get_keys(self, limit=None):
+ """ Get public keys """
+
+ return self._get_resources('keys', model=models.Key,
+ limit=limit)
+
+ def get_key(self, key):
+ """ Get public key
+
+ :param `key`: Key model or key id
+
+ """
+
+ parse_key_id = getattr(key, 'id', key)
+ return self._get_resource('keys/%s' % parse_key_id, model=models.Key)
+
+ def create_key(self, **kwargs):
+ """
+ Create public key
+
+ :param title
+ :param key: Key string (It must starts with 'ssh-rsa')
+ """
+
+ #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):
+ """ Delete public key
+
+ :param `key`: Key model or key id
+
+ """
+
+ parse_key_id = getattr(key, 'id', key)
+ return self._delete('keys/%s' % parse_key_id)
+
+ def my_repos(self, filter='all', limit=None):
+ """
+ Return user's public repositories
+
+ param: filter: 'all', 'owner', 'public', 'private' or 'member'
+ """
+
+ return self._get_resources('repos', model=models.Repo,
+ limit=limit, type=str(filter))
+
+ def my_watched(self, limit=None):
+ """ Return authenticated user repos that he watch """
+
+ return self._get_resources('watched', model=models.Repo,
+ limit=limit)
+
+ def is_watching_repo(self, owner, repo):
+ """
+ Return true if you are watching the user repository
+
+ :param owner: Model user or username string
+ :param repo: Model repo or repo name string
+ 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: Model user or username string
+ :param repo: Model repo or repo name string
+ """
+
+ owner = getattr(owner, 'login', owner)
+ repo = getattr(repo, 'name', repo)
+ return self._put('watched/%s/%s' % (owner, repo))
+
+ def unwatch_repo(self, owner, repo):
+ """
+ Unwatch the repository
+
+ :param owner: Model user or username string
+ :param repo: Model repo or repo name string
+ """
+
+ owner = getattr(owner, 'login', owner)
+ repo = getattr(repo, 'name', repo)
+ return self._delete('watched/%s/%s' % (owner, repo))
+
+ def my_orgs(self, limit=None):
+ """ List public and private organizations
+ for the authenticated user
+ """
+
+ return self._get_resources('orgs', model=models.Org, limit=limit)