Created
September 11, 2012 13:05
-
-
Save ymmt2005/3698314 to your computer and use it in GitHub Desktop.
GitHub v3 API client in Python
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
''' | |
GitHub API v3 client. | |
@see http://developer.github.com/v3/ | |
@see https://support.enterprise.github.com/entries/21391237-using-the-api | |
''' | |
from argparse import ArgumentParser, REMAINDER | |
import base64 | |
from getpass import getpass | |
import httplib | |
import json | |
import sys | |
### Constants | |
OFFICIAL = 'api.github.com' | |
PREFIX = '/api/v3' | |
### Implementation | |
def u2s(o): | |
if isinstance(o, list): | |
return [u2s(i) for i in o] | |
if isinstance(o, dict): | |
t = {} | |
for k, v in o.iteritems(): | |
t[u2s(k)] = u2s(v) | |
return t | |
if isinstance(o, unicode): | |
return o.encode('utf-8') | |
return o | |
def basic_auth(user, password): | |
return 'Basic ' + base64.b64encode('%s:%s' % (user, password)) | |
class GitHub(object): | |
def __init__(self, endpoint, user, password, ssl=False): | |
self._endpoint = endpoint | |
self._auth = basic_auth(user, password) | |
if ssl or endpoint == OFFICIAL: | |
self._conn = httplib.HTTPSConnection | |
else: | |
self._conn = httplib.HTTPConnection | |
def request(self, method, api, body=None): | |
if self._endpoint == OFFICIAL: | |
path = api | |
else: | |
path = PREFIX + api | |
conn = self._conn(self._endpoint, timeout=5) | |
headers = {'Authorization': self._auth} | |
if body is None: | |
conn.request(method, path, headers=headers) | |
else: | |
conn.request(method, path, body, headers) | |
r = conn.getresponse() | |
data = u2s(json.loads(r.read())) | |
status = r.status | |
if status < 200 or status >= 300: | |
raise RuntimeError('%s failed. status=%d, data:\n%s' % | |
(api, status, data)) | |
conn.close() | |
return (status, data) | |
def createPullRequest(self, repo, title, base, head, msg=None): | |
api = '/repos/%s/pulls' % repo | |
body = {'title': title, 'head': head, 'base': base} | |
if msg is not None: | |
body['body'] = msg | |
status, data = self.request('POST', api, json.dumps(body)) | |
return data | |
def cmd_new_request(github, args, p): | |
if len(args) < 4: | |
p.exit(1, '''Too few arguments. | |
Usage: github new_request repo title base head [message] | |
''') | |
if len(args) == 5: | |
msg = args[4] | |
else: | |
msg = None | |
data = github.createPullRequest(args[0], args[1], args[2], args[3], msg) | |
print data['html_url'] | |
### Main | |
def main(): | |
commands = {'new_request': cmd_new_request} | |
p = ArgumentParser(description='GitHub API command-line client.', | |
prog='github', add_help=False) | |
p.add_argument('API', choices=commands.keys(), nargs='?') | |
p.add_argument('args', nargs=REMAINDER) | |
p.add_argument('-u', '--user', metavar='USER', required=True, | |
help='GitHub user name') | |
p.add_argument('-p', '--password', metavar='PASSWORD', | |
help='GitHub password') | |
p.add_argument('-h', '--host', default=OFFICIAL, metavar='HOST', | |
help='GitHub hostname') | |
p.add_argument('-s', '--ssl', action='store_true', default=False, | |
help='Enable SSL') | |
ns = p.parse_args() | |
if ns.API is None: | |
p.print_help() | |
sys.exit(0) | |
if ns.password is None: | |
passwd = getpass('GitHub password: ') | |
else: | |
passwd = ns.password | |
github = GitHub(ns.host, ns.user, passwd, ns.ssl) | |
cmd = commands[ns.API] | |
cmd(github, ns.args, p) | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment