Permalink
Browse files

Start working on this finally.

So far, we have basic gist support. Not much else. Not shabby for a
couple hours of work though.
  • Loading branch information...
1 parent c44706e commit 774fb912e7db51d06cda5be0d3dc823b0efde200 @sigmavirus24 committed May 19, 2012
Showing with 511 additions and 37 deletions.
  1. +1 −0 .gitignore
  2. +23 −0 LICENSE
  3. +0 −37 README.md
  4. +36 −0 README.rst
  5. +15 −0 github3/__init__.py
  6. +36 −0 github3/api.py
  7. +125 −0 github3/gist.py
  8. +72 −0 github3/github.py
  9. +17 −0 github3/models.py
  10. +186 −0 github3/user.py
View
1 .gitignore
@@ -0,0 +1 @@
+*.pyc
View
23 LICENSE
@@ -0,0 +1,23 @@
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+1. Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+3. The name of the author may not be used to endorse or promote products
+derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
View
37 README.md
@@ -1,37 +0,0 @@
-# github3.py
-
-Eventually this will be a python module to access the GitHub v3 API.
-
-## Easy Cloning
-
-Assuming you have git 1.7.x (although I'm not entirely certain what version
-it was introduced in) you can perform `git clone --recursive
-git://github.com/sigmavirus24/github3.py.git github3.py` to clone this and
-the submodule at the same time. Otherwise you have to do:
-
-```
-$ git clone git://github.com/sigmavirus24/github3.py.git
-$ cd github3.py
-$ git submodule init
-$ git submodule update
-```
-
-# Dependencies
-
- * [requests](https://github.com/kennethreitz/requests)
-
-# License
-
-Undecided. I use GPL for a lot of things, but this is likely not going to be
-GPL'd. Probably BSD or MIT since this would allow a lot more people to use it
-with greater freedom. I'll likely open an issue to discuss this with myself. (No
-one else is contributing to/watching this project yet, so why would I discuss it
-with them.)
-
-# Examples
-
-*None yet*
-
-# Authors
-
- * SigmaVirus24
View
36 README.rst
@@ -0,0 +1,36 @@
+github3.py
+==========
+
+Eventually this will be a python module to access the GitHub v3 API.
+
+Easy Cloning
+------------
+
+Assuming you have git 1.7.x (although I'm not entirely certain what version
+it was introduced in) you can perform ``git clone --recursive
+git://github.com/sigmavirus24/github3.py.git github3.py`` to clone this
+and the submodule at the same time. Otherwise you have to do:
+
+::
+
+ $ git clone git://github.com/sigmavirus24/github3.py.git
+ $ cd github3.py
+ $ git submodule init
+ $ git submodule update
+
+Dependencies
+------------
+
+- requests_
+
+.. _requests: https://github.com/kennethreitz/requests
+
+License
+=======
+
+Modified BSD license
+
+Examples
+========
+
+*None yet*
View
15 github3/__init__.py
@@ -0,0 +1,15 @@
+"""
+github3
+=======
+
+:copyright: (c) 2012 by Sigmavirus24
+:license: Modified BSD, see LICENSE for more details
+
+"""
+
+__title__ = 'github3'
+__author__ = 'sigmavirus24'
+__license__ = 'Modified BSD'
+__copyright__ = 'Copyright 2012 Sigmavirus24'
+
+from .api import login, gist, gists, create_gist
View
36 github3/api.py
@@ -0,0 +1,36 @@
+"""
+github3.api
+===========
+
+:copyright: (c) 2012 by SigmaVirus24
+:license: Modified BSD, see LICENSE for more details
+
+"""
+
+from .github import GitHub
+
+def login(username, password):
+ """Constructs and returns a GitHub session with the username and
+ password"""
+ gh = GitHub()
+ gh.login(username, password)
+ return gh
+
+def gist(id_num):
+ gh = GitHub()
+ return gh.gist(id_num)
+
+def gists(username=None):
+ gh = GitHub()
+ return gh.gists(username)
+
+def create_gist(description, files):
+ """Creates an anonymous public gist.
+
+ :param description: short description of the gist
+ :param files: dictionary containing file names with associated
+ dictionaries for content, e.g.
+ {'spam.txt': {'content': 'File contents ...'}}
+ """
+ gh = GitHub()
+ return gh.create_gist(description, files)
View
125 github3/gist.py
@@ -0,0 +1,125 @@
+"""
+gist.py
+=======
+
+Module which contains all the gist related material.
+"""
+
+from datetime import datetime
+from .models import GitHubCore
+from .user import User
+
+class GistFile(object):
+ def __init__(self, attributes):
+ super(GistFile, self).__init__()
+
+ self._raw = attributes.get('raw_url')
+ self._name = attributes.get('filename')
+ self._language = attributes.get('language')
+ self._size = attributes.get('size')
+ self._content = attributes.get('content')
+
+ def __repr__(self):
+ return '<Gist File [%s]>' % self._name
+
+ @property
+ def content(self):
+ return self._content
+
+ @content.setter
+ def content(self, value):
+ self._content = value
+
+ @property
+ def name(self):
+ return self._name
+
+ @property
+ def lang(self):
+ return self._language
+
+ @property
+ def raw_url(self):
+ return self._raw
+
+ @property
+ def size(self):
+ return self._size
+
+
+class Gist(GitHubCore):
+ def __init__(self, data):
+ super(Gist, self).__init__()
+
+ # The gist identifier
+ self._id = data['id']
+ self._desc = data['description']
+
+ # e.g. https://api.github.com/gists/1
+ self._api_url = data['url']
+ # e.g. https://gist.github.com/1
+ self._url = data['html_url']
+ self._public = data['public']
+ # a list of all the forks of that gist
+ self._forks = data.get('forks', [])
+ # e.g. git://gist.github.com/1.git
+ self._pull = data['git_pull_url']
+ # e.g. git@gist.github.com/1.git
+ self._push = data['git_push_url']
+ # date the gist was created
+ self._created = datetime.strptime(data['created_at'],
+ self._time_format)
+ self._updated = datetime.strptime(data['updated_at'],
+ self._time_format)
+ self._user = User(data['user'])
+
+ # Create a list of files in the gist
+ self._files = []
+ for file in data['files']:
+ self._files.append(GistFile(data['files'][file]))
+
+ def __repr__(self):
+ return '<Gist [%s]>' % self._id
+
+ @property
+ def created(self):
+ return self._created
+
+ @property
+ def description(self):
+ return self._desc
+
+ @property
+ def forks(self):
+ return self._forks
+
+ def get(self):
+ """GET /gists/:id"""
+ req = self._session.get(self._api_url)
+
+ @property
+ def git_pull(self):
+ return self._pull
+
+ @property
+ def git_push(self):
+ return self._push
+
+ @property
+ def html_url(self):
+ return self._url
+
+ def is_public(self):
+ return self._public
+
+ @property
+ def updated(self):
+ return self._updated
+
+ @property
+ def user(self):
+ return self._user
+
+ @property
+ def files(self):
+ return self._files
View
72 github3/github.py
@@ -0,0 +1,72 @@
+"""
+github3.github
+==============
+
+This module contains the main GitHub session object.
+
+"""
+
+from requests import session
+from json import loads, dumps
+from .models import GitHubCore
+from .gist import Gist
+
+class GitHub(GitHubCore):
+ """Stores all the session information."""
+ def __init__(self):
+ super(GitHub, self).__init__()
+ self._session = session()
+ self._session.headers.update({'Accept': 'application/json'})
+
+ def __repr__(self):
+ return '<github3-session at 0x%x>' % id(self)
+
+ def login(self, username, password):
+ """Logs the user into GitHub for protected API calls."""
+ self._session.auth = (username, password)
+
+ def gist(self, id_num):
+ """Gets the gist using the specified id number."""
+ url = '/'.join([self._github_url, 'gists', str(id_num)])
+ req = self._session.get(url)
+ data = loads(req.content)
+ _gist = Gist(data)
+ _gist._session = self._session
+ return _gist
+
+ def gists(self, username=None):
+ """If no username is specified, GET /gists, otherwise GET
+ /users/:username/gists"""
+ if username:
+ url = '/'.join([self._github_url, 'users', username,
+ 'gists'])
+ else:
+ url = '/'.join([self._github_url, 'gists'])
+
+ req = self._session.get(url)
+ data = loads(req.content)
+
+ _gists = []
+ for d in data:
+ _gist = Gist(d)
+ _gist._session = self._session
+ _gists.append(_gist)
+
+ return _gists
+
+ def create_gist(self, description, files, public=True):
+ """Create a new gist.
+
+ If no login was provided, it will be anonymous.
+ """
+ new_gist = {'description': description, 'public': public,
+ 'files': files}
+
+ _url = '/'.join([self._github_url, 'gists'])
+ response = self._session.post(_url, dumps(new_gist))
+
+ gist = None
+ if response.status_code == 201:
+ gist = Gist(loads(response.content))
+
+ return gist
View
17 github3/models.py
@@ -0,0 +1,17 @@
+"""
+github3.models
+==============
+
+This module provides the basic models used in github3.py
+
+"""
+
+class GitHubCore(object):
+ """A basic class for the other classes."""
+ def __init__(self):
+ self._session = None
+ self._github_url = 'https://api.github.com'
+ self._time_format = '%Y-%m-%dT%H:%M:%SZ'
+
+ def __repr__(self):
+ return '<github3-core at 0x%x>' % id(self)
View
186 github3/user.py
@@ -0,0 +1,186 @@
+"""
+github3.user
+============
+
+This module contains the classes related to user information.
+
+"""
+
+from .models import GitHubCore
+
+class Plan(object):
+ def __init__(self, data):
+ super(Plan, self).__init__()
+ self._collab = data.get('collaborators')
+ self._name = data.get('name')
+ self._private = data.get('private_repos')
+ self._space = data.get('space')
+
+ def collaborators(self):
+ return self._collab
+
+ def is_free(self):
+ return self._name == 'free'
+
+ def name(self):
+ return self._name
+
+ def private_repos(self):
+ return self._private
+
+ def space(self):
+ return self._space
+
+
+_large = Plan({'name': 'large', 'private_repos': 50,
+ 'collaborators': 25, 'space': 0})
+_medium = Plan({'name': 'medium', 'private_repos': 20,
+ 'collaborators': 10, 'space': 0})
+_small = Plan({'name': 'small', 'private_repos': 10,
+ 'collaborators': 5, 'space': 0})
+_micro = Plan({'name': 'micro', 'private_repos': 5,
+ 'collaborators': 1, 'space': 0})
+_free = Plan({'name': 'free', 'private_repos': 0,
+ 'collaborators': 0, 'space': 0})
+
+plans = {'large': _large, 'medium': _medium, 'small': _small,
+ 'micro': _micro, 'free': _free}
+
+
+class User(GitHubCore):
+ def __init__(self, data):
+ super(User, self).__init__()
+
+ # Public information
+ ## e.g. https://api.github.com/users/self._login
+ self._api_url = data.get('url')
+
+ self._avatar = data.get('avatar_url')
+ self._bio = data.get('bio')
+ self._blog = data.get('blog')
+ self._company = data.get('company')
+ self._email = data.get('email')
+
+ ## The number of people following this user
+ self._followers = data.get('followers')
+
+ ## The number of people this user follows
+ self._following = data.get('following')
+
+ ## The number of people this user folows
+ self._grav_id = data.get('gravatar_id')
+
+ self._hire = data.get('hireable')
+ self._id = data.get('id')
+ self._location = data.get('location')
+ self._login = data.get('login')
+
+ ## e.g. first_name last_name
+ self._name = data.get('name')
+
+ ## The number of public_gists
+ self._public_gists = data.get('public_gists')
+
+ ## The number of public_repos
+ self._public_repos = data.get('public_repos')
+
+ ## e.g. https://github.com/self._login
+ self._url = data.get('html_url')
+
+ # Private information
+ self._disk = data.get('disk_usage')
+ if data.get('plan'):
+ _plan = data.get('plan')
+ self._plan = plans[_plan['name'].lower()]
+ self._plan._space = _plan['space']
+ else:
+ self._plan = None
+
+ ## The number of private repos
+ self._private_repos = data.get('total_private_repos')
+ self._private_gists = data.get('total_private_gists')
+
+ self._owned_private_repos = data.get('owned_private_repos')
+
+ def __repr__(self):
+ return '<User [%s:%s]>' % (self._login, self._name)
+
+ @property
+ def avatar(self):
+ return self._avatar
+
+ @property
+ def bio(self):
+ return self._bio
+
+ @property
+ def blog(self):
+ return self._blog
+
+ @property
+ def company(self):
+ return self._company
+
+ @property
+ def disk_usage(self):
+ return self._disk
+
+ @property
+ def email(self):
+ return self._email
+
+ @property
+ def followers(self):
+ return self._followers
+
+ @property
+ def following(self):
+ return self._following
+
+ @property
+ def for_hire(self):
+ return self._hire
+
+ @property
+ def html_url(self):
+ return self._url
+
+ @property
+ def id(self):
+ return self._id
+
+ @property
+ def location(self):
+ return self._location
+
+ @property
+ def login(self):
+ return self._login
+
+ @property
+ def name(self):
+ return self._name
+
+ @property
+ def owned_private_repos(self):
+ return self._owned_private_repos
+
+ @property
+ def private_gists(self):
+ return self._private_gists
+
+ @property
+ def plan(self):
+ return self._plan
+
+ @property
+ def public_gists(self):
+ return self._public_gists
+
+ @property
+ def public_repos(self):
+ return self._public_repos
+
+ @property
+ def total_private_repos(self):
+ return self._private_repos

0 comments on commit 774fb91

Please sign in to comment.