commit a62e4789516aec688b1375d7ce7bc3117ba769c5 Author: Ask Solem Date: Sat Apr 18 17:29:55 2009 +0200 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5aba821 --- /dev/null +++ b/.gitignore @@ -0,0 +1,14 @@ +.DS_Store +*.pyc +*~ +*.sqlite +*.sqlite-journal +settings_local.py +local_settings.py +.*.sw[po] +dist/ +*.egg-info +doc/__build/* +build/ +locale/ +pip-log.txt diff --git a/github2/__init__.py b/github2/__init__.py new file mode 100644 index 0000000..a3fdd46 --- /dev/null +++ b/github2/__init__.py @@ -0,0 +1,6 @@ +VERSION = (0, 1, 0) +__author__ = "Ask Solem" +__contact__ = "askh@opera.com" +__homepage__ = "http://github.com/ask/pygithub-issues" +__version__ = ".".join(map(str, VERSION)) + diff --git a/github2/client.py b/github2/client.py new file mode 100644 index 0000000..b5aeb50 --- /dev/null +++ b/github2/client.py @@ -0,0 +1,124 @@ +from github2.request import GithubRequest + +class GithubData(object): + def __init__(self, **kwargs): + for attr_name in self.attributes: + if attr_name in kwargs: + setattr(self, attr_name, kwargs[attr_name]) + else: + setattr(self, attr_name, None) + + def to_dict(self): + dict_ = {} + for attr_name in self.attributes: + attr_value = getattr(self, attr_name, None) + if attr_value is not None: + dict_[attr_name] = attr_value + return dict_ + + +class Issue(GithubData): + attributes = ("position", "number", "votes", "body", "title", + "created_at", "updated_at", "user", "state") + +class User(GithubData): + attributes = ("id", "login", "name", "company", "location", "email", + "blog", "following_count", "followers_count", + "public_gist_count", "public_repo_count", + "total_private_repo_count", "collaborators", "disk_usage", + "owned_private_repo_count", "private_gist_count", + "plan") + + def is_authenticated(self): + return self.plan is not None + + +class GithubCommand(object): + + def __init__(self, request): + self.request = request + + def make_request(self, command, *args, **kwargs): + filter = kwargs.get("filter") + post_data = kwargs.get("post_data") + if post_data: + response = self.request.post(self.domain, command, *args, + **post_data) + else: + response = self.request.get(self.domain, command, *args) + if filter: + return response[filter] + return response + + +class Users(GithubCommand): + domain = "user" + + def search(self, query): + return self.make_request("search", query, filter="users") + + def show(self, username): + user_data = self.make_request("show", username, filter="user") + return User(**user_data) + + def followers(self, username): + return self.make_request("show", username, "followers") + + def following(self, username): + return self.make_request("show", username, "following") + + def follow(self, other_user): + return self.make_request("follow", other_user) + + def unfollow(self, other_user): + return self.make_request("unfollow", other_user) + +class Issues(GithubCommand): + domain = "issues" + + def list(self, project, state="open"): + """Get all issues for project' with state'. + + ``project`` is a string with the project owner username and repository + name separated by ``/`` (e.g. ``ask/pygithub2``). + ``state`` can be either ``open`` or ``closed``. + """ + return [Issue(**issue) + for issue in self.make_request("list", project, state, + filter="issues")] + + def show(self, project, number): + """Get all the data for issue by issue-number.""" + issue_data = self.make_request("show", project, str(number), + filter="issue") + return Issue(**issue_data) + + def open(self, project, title, body): + """Open up a new issue.""" + issue_data = {"title": title, "body": body} + r = self.make_request("open", project, post_data=issue_data, + filter="issue") + return Issue(**r) + + def close(self, project, number): + issue_data = self.make_request("close", project, str(number), + filter="issue") + return Issue(**issue_data) + + def add_label(self, project, number, label): + return self.make_request("label/add", project, label, str(number), + filter="labels") + + def remove_label(self, project, number, label): + return self.make_request("label/remove", project, label, str(number), + filter="labels") +class Github(object): + + def __init__(self, username, api_token): + self.request = GithubRequest(username=username, api_token=api_token) + self.issues = Issues(self.request) + self.users = Users(self.request) + + def project_for_user_repo(self, user, repo): + return "/".join([user, repo]) + diff --git a/github2/request.py b/github2/request.py new file mode 100644 index 0000000..acb976c --- /dev/null +++ b/github2/request.py @@ -0,0 +1,63 @@ +import sys +import httplib +import simplejson +from urlparse import urlparse +from urllib import urlencode + +URL_PREFIX = "https://github.com/api/v2/json" + +class GithubError(Exception): + """An error occured when making a request to the Github API.""" + +class GithubRequest(object): + url_prefix = URL_PREFIX + GithubError = GithubError + + connector_for_scheme = { + "http": httplib.HTTPConnection, + "https": httplib.HTTPSConnection, + } + + def __init__(self, username, api_token, url_prefix=None): + self.username = username + self.api_token = api_token + self.url_prefix = url_prefix or self.url_prefix + + def encode_authentication_data(self, extra_post_data): + post_data = {"user": self.username, + "token": self.api_token} + post_data.update(extra_post_data) + return urlencode(post_data) + + def get(self, *path_components): + return self.make_request("/".join(path_components)) + + def post(self, *path_components, **extra_post_data): + return self.make_request("/".join(path_components), extra_post_data) + + def make_request(self, path, extra_post_data=None): + extra_post_data = extra_post_data or {} + url = "/".join([self.url_prefix, path]) + print("URL: %s" % url) + resource = urlparse(url) + post_data = self.encode_authentication_data(extra_post_data) + print("POST_DATA: %s" % post_data) + connector = self.connector_for_scheme[resource.scheme] + headers = self.http_headers + headers["Accept"] = "text/html" + headers["Content-Length"] = str(len(post_data)) + connection = connector(resource.hostname, resource.port) + connection.request("POST", resource.path, post_data, headers) + response = connection.getresponse() + response_text = response.read() + print(response_text) + json = simplejson.loads(response_text) + if json.get("error"): + raise self.GithubError(json["error"][0]["error"]) + + return json + + @property + def http_headers(self): + return {"User-Agent": "pygithub2 v1", + "Accept-Encoding": "application/json"}