Skip to content

Commit

Permalink
Add two new types of exceptions (issue #152)
Browse files Browse the repository at this point in the history
  • Loading branch information
jacquev6 committed May 17, 2013
1 parent 79365fe commit db2a9db
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 6 deletions.
14 changes: 13 additions & 1 deletion github/GithubException.py
Expand Up @@ -53,5 +53,17 @@ class BadCredentialsException(GithubException):

class UnknownObjectException(GithubException):
"""
Exception raised a non-existing object is requested (when Github API replies with a 404 HTML status)
Exception raised when a non-existing object is requested (when Github API replies with a 404 HTML status)
"""


class BadUserAgentException(GithubException):
"""
Exception raised when request is sent with a bad user agent header (when Github API replies with a 403 bad user agent HTML status)
"""


class RateLimitExceededException(GithubException):
"""
Exception raised when the rate limit is exceeded (when Github API replies with a 403 rate limit exceeded HTML status)
"""
14 changes: 10 additions & 4 deletions github/Requester.py
Expand Up @@ -105,10 +105,16 @@ def __check(self, status, responseHeaders, output):

def __createException(self, status, output):
if status == 401 and output["message"] == "Bad credentials":
return GithubException.BadCredentialsException(status, output)
if status == 404 and output["message"] == "Not Found":
return GithubException.UnknownObjectException(status, output)
return GithubException.GithubException(status, output)
cls = GithubException.BadCredentialsException
elif status == 403 and output["message"].startswith("Missing or invalid User Agent string"):
cls = GithubException.BadUserAgentException
elif status == 403 and output["message"].startswith("API Rate Limit Exceeded"):
cls = GithubException.RateLimitExceededException
elif status == 404 and output["message"] == "Not Found":
cls = GithubException.UnknownObjectException
else:
cls = GithubException.GithubException
return cls(status, output)

def __structuredFromJson(self, data):
if len(data) == 0:
Expand Down
2 changes: 1 addition & 1 deletion github/__init__.py
Expand Up @@ -25,7 +25,7 @@
import logging

from MainClass import Github
from GithubException import GithubException, BadCredentialsException, UnknownObjectException
from GithubException import GithubException, BadCredentialsException, UnknownObjectException, BadUserAgentException, RateLimitExceededException
from InputFileContent import InputFileContent
from InputGitAuthor import InputGitAuthor
from InputGitTreeElement import InputGitTreeElement
Expand Down
12 changes: 12 additions & 0 deletions github/tests/Exceptions.py
Expand Up @@ -96,3 +96,15 @@ def testBadCredentials(self):

def testUnknownObject(self):
self.assertRaises(github.UnknownObjectException, lambda: self.g.get_user().get_repo("Xxx"))

def testBadUserAgent(self):
self.assertRaises(github.BadUserAgentException, lambda: github.Github(self.login, self.password, user_agent="").get_user().name)

def testRateLimitExceeded(self):
g = github.Github()

def exceed():
for i in range(100):
g.get_user("jacquev6")

self.assertRaises(github.RateLimitExceededException, exceed)
11 changes: 11 additions & 0 deletions github/tests/ReplayData/SpecificExceptions.testBadUserAgent.txt
@@ -0,0 +1,11 @@
https
GET
api.github.com
None
/user
{'Authorization': 'Basic login_and_password_removed', 'User-Agent': ''}
null
403
[('date', 'Fri, 17 May 2013 12:16:34 GMT'), ('content-length', '107'), ('content-type', 'application/octet-stream'), ('connection', 'keep-alive'), ('server', 'GitHub.com')]
{"message":"Missing or invalid User Agent string. See http://developer.github.com/v3/#user-agent-required"}

@@ -0,0 +1,55 @@
https
GET
api.github.com
None
/users/jacquev6
{'User-Agent': 'PyGithub/Python'}
null
200
[('status', '200 OK'), ('x-ratelimit-remaining', '2'), ('x-github-media-type', 'github.beta; format=json'), ('x-content-type-options', 'nosniff'), ('access-control-expose-headers', 'Link, X-RateLimit-Limit, X-RateLimit-Remaining, X-OAuth-Scopes, X-Accepted-OAuth-Scopes'), ('access-control-allow-credentials', 'true'), ('vary', 'Accept, Accept-Encoding'), ('content-length', '1299'), ('server', 'GitHub.com'), ('last-modified', 'Fri, 17 May 2013 12:09:51 GMT'), ('connection', 'keep-alive'), ('x-ratelimit-limit', '60'), ('etag', '"de9347ae9c0c83b44d6c81d05aba4877"'), ('cache-control', 'public, max-age=60, s-maxage=60'), ('date', 'Fri, 17 May 2013 12:23:52 GMT'), ('access-control-allow-origin', '*'), ('content-type', 'application/json; charset=utf-8')]
{"login":"jacquev6","id":327146,"avatar_url":"https://secure.gravatar.com/avatar/b68de5ae38616c296fa345d2b9df2225?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png","gravatar_id":"b68de5ae38616c296fa345d2b9df2225","url":"https://api.github.com/users/jacquev6","html_url":"https://github.com/jacquev6","followers_url":"https://api.github.com/users/jacquev6/followers","following_url":"https://api.github.com/users/jacquev6/following{/other_user}","gists_url":"https://api.github.com/users/jacquev6/gists{/gist_id}","starred_url":"https://api.github.com/users/jacquev6/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jacquev6/subscriptions","organizations_url":"https://api.github.com/users/jacquev6/orgs","repos_url":"https://api.github.com/users/jacquev6/repos","events_url":"https://api.github.com/users/jacquev6/events{/privacy}","received_events_url":"https://api.github.com/users/jacquev6/received_events","type":"User","name":"Vincent Jacques","company":"Criteo","blog":"http://vincent-jacques.net","location":"Paris, France","email":"vincent@vincent-jacques.net","hireable":false,"bio":"","public_repos":16,"followers":27,"following":39,"created_at":"2010-07-09T06:10:06Z","updated_at":"2013-05-17T12:09:51Z","public_gists":3}

https
GET
api.github.com
None
/users/jacquev6
{'User-Agent': 'PyGithub/Python'}
null
200
[('status', '200 OK'), ('x-ratelimit-remaining', '1'), ('x-github-media-type', 'github.beta; format=json'), ('x-content-type-options', 'nosniff'), ('access-control-expose-headers', 'Link, X-RateLimit-Limit, X-RateLimit-Remaining, X-OAuth-Scopes, X-Accepted-OAuth-Scopes'), ('access-control-allow-credentials', 'true'), ('vary', 'Accept, Accept-Encoding'), ('content-length', '1299'), ('server', 'GitHub.com'), ('last-modified', 'Fri, 17 May 2013 12:09:51 GMT'), ('connection', 'keep-alive'), ('x-ratelimit-limit', '60'), ('etag', '"de9347ae9c0c83b44d6c81d05aba4877"'), ('cache-control', 'public, max-age=60, s-maxage=60'), ('date', 'Fri, 17 May 2013 12:23:53 GMT'), ('access-control-allow-origin', '*'), ('content-type', 'application/json; charset=utf-8')]
{"login":"jacquev6","id":327146,"avatar_url":"https://secure.gravatar.com/avatar/b68de5ae38616c296fa345d2b9df2225?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png","gravatar_id":"b68de5ae38616c296fa345d2b9df2225","url":"https://api.github.com/users/jacquev6","html_url":"https://github.com/jacquev6","followers_url":"https://api.github.com/users/jacquev6/followers","following_url":"https://api.github.com/users/jacquev6/following{/other_user}","gists_url":"https://api.github.com/users/jacquev6/gists{/gist_id}","starred_url":"https://api.github.com/users/jacquev6/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jacquev6/subscriptions","organizations_url":"https://api.github.com/users/jacquev6/orgs","repos_url":"https://api.github.com/users/jacquev6/repos","events_url":"https://api.github.com/users/jacquev6/events{/privacy}","received_events_url":"https://api.github.com/users/jacquev6/received_events","type":"User","name":"Vincent Jacques","company":"Criteo","blog":"http://vincent-jacques.net","location":"Paris, France","email":"vincent@vincent-jacques.net","hireable":false,"bio":"","public_repos":16,"followers":27,"following":39,"created_at":"2010-07-09T06:10:06Z","updated_at":"2013-05-17T12:09:51Z","public_gists":3}

https
GET
api.github.com
None
/users/jacquev6
{'User-Agent': 'PyGithub/Python'}
null
200
[('status', '200 OK'), ('x-ratelimit-remaining', '0'), ('x-github-media-type', 'github.beta; format=json'), ('x-content-type-options', 'nosniff'), ('access-control-expose-headers', 'Link, X-RateLimit-Limit, X-RateLimit-Remaining, X-OAuth-Scopes, X-Accepted-OAuth-Scopes'), ('access-control-allow-credentials', 'true'), ('vary', 'Accept, Accept-Encoding'), ('content-length', '1299'), ('server', 'GitHub.com'), ('last-modified', 'Fri, 17 May 2013 12:09:51 GMT'), ('connection', 'keep-alive'), ('x-ratelimit-limit', '60'), ('etag', '"de9347ae9c0c83b44d6c81d05aba4877"'), ('cache-control', 'public, max-age=60, s-maxage=60'), ('date', 'Fri, 17 May 2013 12:23:54 GMT'), ('access-control-allow-origin', '*'), ('content-type', 'application/json; charset=utf-8')]
{"login":"jacquev6","id":327146,"avatar_url":"https://secure.gravatar.com/avatar/b68de5ae38616c296fa345d2b9df2225?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png","gravatar_id":"b68de5ae38616c296fa345d2b9df2225","url":"https://api.github.com/users/jacquev6","html_url":"https://github.com/jacquev6","followers_url":"https://api.github.com/users/jacquev6/followers","following_url":"https://api.github.com/users/jacquev6/following{/other_user}","gists_url":"https://api.github.com/users/jacquev6/gists{/gist_id}","starred_url":"https://api.github.com/users/jacquev6/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jacquev6/subscriptions","organizations_url":"https://api.github.com/users/jacquev6/orgs","repos_url":"https://api.github.com/users/jacquev6/repos","events_url":"https://api.github.com/users/jacquev6/events{/privacy}","received_events_url":"https://api.github.com/users/jacquev6/received_events","type":"User","name":"Vincent Jacques","company":"Criteo","blog":"http://vincent-jacques.net","location":"Paris, France","email":"vincent@vincent-jacques.net","hireable":false,"bio":"","public_repos":16,"followers":27,"following":39,"created_at":"2010-07-09T06:10:06Z","updated_at":"2013-05-17T12:09:51Z","public_gists":3}

https
GET
api.github.com
None
/users/jacquev6
{'User-Agent': 'PyGithub/Python'}
null
200
[('status', '200 OK'), ('x-ratelimit-remaining', '0'), ('x-github-media-type', 'github.beta; format=json'), ('x-content-type-options', 'nosniff'), ('access-control-expose-headers', 'Link, X-RateLimit-Limit, X-RateLimit-Remaining, X-OAuth-Scopes, X-Accepted-OAuth-Scopes'), ('access-control-allow-credentials', 'true'), ('vary', 'Accept, Accept-Encoding'), ('content-length', '1299'), ('server', 'GitHub.com'), ('last-modified', 'Fri, 17 May 2013 12:09:51 GMT'), ('connection', 'keep-alive'), ('x-ratelimit-limit', '60'), ('etag', '"de9347ae9c0c83b44d6c81d05aba4877"'), ('cache-control', 'public, max-age=60, s-maxage=60'), ('date', 'Fri, 17 May 2013 12:23:55 GMT'), ('access-control-allow-origin', '*'), ('content-type', 'application/json; charset=utf-8')]
{"login":"jacquev6","id":327146,"avatar_url":"https://secure.gravatar.com/avatar/b68de5ae38616c296fa345d2b9df2225?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png","gravatar_id":"b68de5ae38616c296fa345d2b9df2225","url":"https://api.github.com/users/jacquev6","html_url":"https://github.com/jacquev6","followers_url":"https://api.github.com/users/jacquev6/followers","following_url":"https://api.github.com/users/jacquev6/following{/other_user}","gists_url":"https://api.github.com/users/jacquev6/gists{/gist_id}","starred_url":"https://api.github.com/users/jacquev6/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jacquev6/subscriptions","organizations_url":"https://api.github.com/users/jacquev6/orgs","repos_url":"https://api.github.com/users/jacquev6/repos","events_url":"https://api.github.com/users/jacquev6/events{/privacy}","received_events_url":"https://api.github.com/users/jacquev6/received_events","type":"User","name":"Vincent Jacques","company":"Criteo","blog":"http://vincent-jacques.net","location":"Paris, France","email":"vincent@vincent-jacques.net","hireable":false,"bio":"","public_repos":16,"followers":27,"following":39,"created_at":"2010-07-09T06:10:06Z","updated_at":"2013-05-17T12:09:51Z","public_gists":3}

https
GET
api.github.com
None
/users/jacquev6
{'User-Agent': 'PyGithub/Python'}
null
403
[('status', '403 Forbidden'), ('x-ratelimit-remaining', '0'), ('x-github-media-type', 'github.beta; format=json'), ('x-content-type-options', 'nosniff'), ('access-control-expose-headers', 'Link, X-RateLimit-Limit, X-RateLimit-Remaining, X-OAuth-Scopes, X-Accepted-OAuth-Scopes'), ('content-length', '56'), ('server', 'GitHub.com'), ('connection', 'keep-alive'), ('x-ratelimit-limit', '60'), ('access-control-allow-credentials', 'true'), ('date', 'Fri, 17 May 2013 12:23:56 GMT'), ('access-control-allow-origin', '*'), ('content-type', 'application/json; charset=utf-8')]
{"message":"API Rate Limit Exceeded for 92.104.200.119"}

0 comments on commit db2a9db

Please sign in to comment.