Merge branch 'develop'

This commit is contained in:
Vincent Jacques
2012-03-12 22:53:18 +01:00
15 changed files with 1261 additions and 345 deletions
+1 -1
View File
@@ -3,4 +3,4 @@ GithubCredentials.py
.coverage
/dist
/MANIFEST
ReplayDataForIntegrationTest.txt
ReplayDataForIntegrationTest*.txt
+507 -202
View File
@@ -1,5 +1,6 @@
#!/bin/env python
import re
import time
import sys
import httplib
@@ -7,22 +8,25 @@ import base64
from github import Github
class RecordingHttpResponse( object ):
def __init__( self, file, res ):
self.status = res.status
self.__headers = res.getheaders()
self.__output = res.read()
file.write( str( self.status ) + "\n" )
file.write( str( self.__headers ) + "\n" )
file.write( str( self.__output ) + "\n" )
def getheaders( self ):
return self.__headers
def read( self ):
return self.__output
class RecordReplayException( Exception ):
pass
class RecordingHttpsConnection:
class HttpResponse( object ):
def __init__( self, file, res ):
self.status = res.status
self.__headers = res.getheaders()
self.__output = res.read()
file.write( str( self.status ) + "\n" )
file.write( str( self.__headers ) + "\n" )
file.write( str( self.__output ) + "\n" )
def getheaders( self ):
return self.__headers
def read( self ):
return self.__output
__realHttpsConnection = httplib.HTTPSConnection
def __init__( self, file, *args, **kwds ):
@@ -30,238 +34,539 @@ class RecordingHttpsConnection:
self.__cnx = self.__realHttpsConnection( *args, **kwds )
def request( self, verb, url, input, headers ):
print verb, url
self.__cnx.request( verb, url, input, headers )
del headers[ "Authorization" ] # Do not let sensitive info in git :-p
self.__file.write( verb + " " + url + " " + str( headers ) + " " + input + "\n" )
def getresponse( self ):
return RecordingHttpResponse( self.__file, self.__cnx.getresponse() )
return RecordingHttpsConnection.HttpResponse( self.__file, self.__cnx.getresponse() )
def close( self ):
self.__file.write( "\n" )
return self.__cnx.close()
class ReplayingHttpResponse( object ):
def __init__( self, file ):
self.status = int( file.readline().strip() )
self.__headers = eval( file.readline().strip() )
self.__output = file.readline().strip()
def getheaders( self ):
return self.__headers
def read( self ):
return self.__output
class ReplayingHttpsConnection:
class HttpResponse( object ):
def __init__( self, file ):
self.status = int( file.readline().strip() )
self.__headers = eval( file.readline().strip() )
self.__output = file.readline().strip()
def getheaders( self ):
return self.__headers
def read( self ):
return self.__output
def __init__( self, file ):
self.__file = file
def request( self, verb, url, input, headers ):
del headers[ "Authorization" ]
assert self.__file.readline().strip() == verb + " " + url + " " + str( headers ) + " " + input
if( self.__file.readline().strip() != verb + " " + url + " " + str( headers ) + " " + input ):
raise RecordReplayException( "This test has been changed since last record. Please re-run this script with argument '--record'" )
def getresponse( self ):
return ReplayingHttpResponse( self.__file )
return ReplayingHttpsConnection.HttpResponse( self.__file )
def close( self ):
self.__file.readline()
class IntegrationTest:
__fileName = "ReplayDataForIntegrationTest.txt"
cobayeUser = "Lyloa"
cobayeOrganization = "BeaverSoftware"
def main( self ):
if len( sys.argv ) == 2 and sys.argv[ 1 ] == "--record":
print "Record mode: I'm really going to do requests to github.com. Please type 'yes' and return"
sys.stdout.flush()
confirm = sys.stdin.readline().strip()
if confirm != "yes":
exit( 1 )
self.record()
def main( self, argv ):
record = False
if len( argv ) >= 1:
if argv[ 0 ] == "--record":
argv = argv[ 1: ]
record = True
elif argv[ 0 ] == "--list":
print "List of available tests:"
print "\n".join( self.listTests() )
return
if record:
print "Record mode: this script is really going to do requests to github.com"
else:
self.replay()
print "Replay mode: this script will use requests to and replies from github.com recorded in previous runs in record mode"
exit()
if len( argv ) == 0:
tests = self.listTests()
else:
tests = argv
self.runTests( tests, record )
def record( self ):
self.prepareRecord()
self.playScenario()
if self.succeeded:
self.analyseCoverage()
def replay( self ):
self.prepareReplay()
self.playScenario()
def prepareRecord( self ):
def prepareRecord( self, test ):
self.avoidError500FromGithub = lambda: time.sleep( 1 )
try:
import GithubCredentials
self.g = Github( GithubCredentials.login, GithubCredentials.password )
file = open( self.__fileName, "w" )
httplib.HTTPSConnection = lambda *args, **kwds: RecordingHttpsConnection( file, *args, **kwds )
self.__file = open( self.__fileName( test ), "w" )
httplib.HTTPSConnection = lambda *args, **kwds: RecordingHttpsConnection( self.__file, *args, **kwds )
except ImportError:
print "Please create a 'GithubCredentials.py' file containing:"
print "login = '<your github login>'"
print "password = '<your github password>'"
exit( 1 )
raise RecordReplayException( textwrap.dedent( """\
Please create a 'GithubCredentials.py' file containing:"
login = '<your github login>'"
password = '<your github password>'""" ) )
def prepareReplay( self ):
def prepareReplay( self, test ):
self.avoidError500FromGithub = lambda: 0
try:
file = open( self.__fileName )
httplib.HTTPSConnection = lambda *args, **kwds: ReplayingHttpsConnection( file )
self.__file = None
self.__file = open( self.__fileName( test ) )
httplib.HTTPSConnection = lambda *args, **kwds: ReplayingHttpsConnection( self.__file )
self.g = Github( "login", "password" )
except IOError:
print "Please re-run this script with argument '--record' to be able to replay the integration tests based on recorded first execution"
exit( 1 )
raise RecordReplayException( "This test has never been recorded. Please re-run this script with argument '--record'" )
def playScenario( self ):
self.doSomeReads()
self.doSomeWrites()
def __fileName( self, test ):
return "ReplayDataForIntegrationTest." + test + ".txt"
def doSomeReads( self ):
self.dumpUser( self.g.get_user(), doPrivateThings = True )
jacquev6 = self.g.get_user( "jacquev6" )
self.dumpUser( jacquev6, doPrivateThings = False )
self.dumpOrganization( self.g.get_organization( "github" ), doTeams = False )
self.dumpOrganization( self.g.get_organization( "BeaverSoftware" ), doTeams = True )
self.dumpRepository( jacquev6.get_repo( "PyGithub" ) )
def listTests( self ):
return [ f[ 4: ] for f in dir( self ) if f.startswith( "test" ) ]
def doSomeWrites( self ):
self.doSomeWritesToUser()
self.doSomeWritesToRepository()
def doSomeWritesToUser( self ):
u = self.g.get_user()
oldBio = u.bio
u.edit( bio = oldBio + " (Edited by PyGithub)" )
u.edit( bio = oldBio )
jacquev6 = self.g.get_user( "jacquev6" )
u.remove_from_following( jacquev6 )
u.add_to_following( jacquev6 )
PyGithub = jacquev6.get_repo( "PyGithub" )
u.remove_from_watched( PyGithub )
u.add_to_watched( PyGithub )
def doSomeWritesToRepository( self ):
u = self.g.get_user()
r = u.create_repo( name = "TestPyGithub", description = "Created by PyGithub", has_wiki = False )
self.avoidError500FromGithub()
# Git objects
b1 = r.create_git_blob( "This blob was created by PyGithub", encoding = "latin1" )
t1 = r.create_git_tree( [ { "path": "foo.bar", "mode": "100644", "type": "blob", "sha": b1.sha } ] )
c1 = r.create_git_commit( "This commit was created by PyGithub", t1.sha, [] )
master = r.create_git_ref( "refs/heads/master", c1.sha )
b2 = r.create_git_blob( "This blob was also created by PyGithub", encoding = "latin1" )
t2 = r.create_git_tree( [ { "path": "foo.bar", "mode": "100644", "type": "blob", "sha": b2.sha }, { "path": "old", "mode": "040000", "type": "tree", "sha": t1.sha } ] )
c2 = r.create_git_commit( "This commit was also created by PyGithub", t2.sha, [ c1.sha ] )
master.edit( c2.sha )
tag = r.create_git_tag( "a_tag", "This tag was created by PyGithub", c2.sha, "commit" )
r.create_git_ref( "refs/tags/a_tag", tag.sha )
c = r.get_commit( c2.sha )
c.create_comment( "Commented with PyGithub", c.sha, 1, "foo.bar", 1 )
# Issues and milestones
l = r.create_label( "Label created by PyGithub", "00FF00" )
l.edit( "Label created and modified by PyGithub", "FFFF00" )
m = r.create_milestone( title = "This milestone was created by PyGithub" )
m.edit( title = m.title, description = "And the description was modified by PyGithub as well" )
m = r.create_milestone( title = "This milestone was also created by PyGithub" )
m.delete()
i = r.create_issue( "Issue created by PyGithub" )
i.edit( body = "Body edited by PyGithub" )
la = r.create_label( "a", "00FF00" )
lb = r.create_label( "b", "00FF00" )
lc = r.create_label( "c", "00FF00" )
i.set_labels( la, lb )
i.remove_from_labels( lb )
i.delete_labels()
i.add_to_labels( lc )
i.create_comment( "Commented from PyGithub" )
# Downloads
r.create_download( "MyDownloadCreatedByPyGithub", 1000 )
# Forking, commiting and requesting merge
o = self.g.get_organization( "BeaverSoftware" )
rf = o.create_fork( r )
self.avoidError500FromGithub()
b3 = rf.create_git_blob( "This blob was ter created by PyGithub", encoding = "latin1" )
t3 = rf.create_git_tree( [ { "path": "foo.bar", "mode": "100644", "type": "blob", "sha": b3.sha } ] )
c3 = rf.create_git_commit( "This commit was ter created by PyGithub", t3.sha, [ c2.sha ] )
rf.get_git_ref( "refs/heads/master" ).edit( c3.sha )
p = r.create_pull( "Pull request created by PyGithub", "", "jacquev6:master", "BeaverSoftware:master" )
self.dumpRepository( r )
def dumpUser( self, u, doPrivateThings ):
print u.login, "(", u.name, ")"
print " Repos:"
for r in u.get_repos():
print " ", r.name,
if r.fork:
print "<-", r.parent.owner.login + "/" + r.parent.name,
print "<-", r.source.owner.login + "/" + r.source.name,
def runTests( self, tests, record ):
self.succeeded = True
for test in tests:
print
if doPrivateThings:
print " Emails:", ", ".join( u.get_emails() )
print " Watched:", ", ".join( r.name for r in u.get_watched() )
print " Organizations:", ", ".join( o.login for o in u.get_orgs() )
print " Following:", ", ".join( f.login for f in u.get_following() )
if doPrivateThings:
print " Is following jacquev6:", u.has_in_following( self.g.get_user( "jacquev6" ) )
print " Followers:", ", ".join( f.login for f in u.get_followers() )
print
sys.stdout.flush()
print test
print "=" * len( test )
try:
if record:
self.prepareRecord( test )
else:
self.prepareReplay( test )
getattr( self, "test" + test )()
if not record:
if self.__file.readline():
raise RecordReplayException( "This test has been changed since last record. Please re-run this script with argument '--record'" )
except RecordReplayException, e:
print "*" * len( str( e ) )
print e
print "*" * len( str( e ) )
self.succeeded = False
finally:
if self.__file is not None:
self.__file.close()
def dumpOrganization( self, o, doTeams ):
print o.login, "(", o.name, ")"
print " Members:", ", ".join( u.login for u in o.get_members() )
print " Repos:", ", ".join( r.name for r in o.get_repos() )
if doTeams:
print " Teams:"
for team in o.get_teams():
print " ", team.name, "(" + team.permission + "):", ", ".join( u.login for u in team.get_members() ), "->", ", ".join( r.name for r in team.get_repos() )
print
sys.stdout.flush()
def analyseCoverage( self ):
coveredUrls = dict()
for test in self.listTests():
with open( self.__fileName( test ) ) as file:
requests = [ line.strip() for line in file.readlines() ][ 0 : : 5 ]
for request in requests:
verb, url = request.split( " " )[ 0 : 2 ]
if url not in coveredUrls:
coveredUrls[ url ] = set()
coveredUrls[ url ].add( verb )
def dumpRepository( self, r ):
print r.owner.login + "/" + r.name
print " Collaborators:", ", ".join( u.login for u in r.get_collaborators() )
print " Contributors:", ", ".join( u.login for u in r.get_contributors() )
print " Watchers:", ", ".join( u.login for u in r.get_watchers() )
print " Forks:", ", ".join( f.owner.login + "/" + f.name for f in r.get_forks() )
print " Languages:", r.get_languages()
print " Downloads:", ", ".join( d.name for d in r.get_downloads() )
print " Tags:", ", ".join( t.name + " (" + t.commit.sha + ")" for t in r.get_tags() )
print " Branches:", ", ".join( b.name + " (" + b.commit.sha + ")" for b in r.get_branches() )
print " Commits:", ", ".join( c.commit.message + " (" + str( c.stats ) + " ".join( comment.body for comment in c.get_comments() ) + ")" for c in r.get_commits()[ : 10 ] )
print " Git references:", ", ".join( ref.ref + " (" + ref.object[ "sha" ][ :7 ] + ")" for ref in r.get_git_refs() )
masterCommitSha = r.get_git_ref( "refs/heads/master" ).object[ "sha" ]
masterCommit = r.get_git_commit( masterCommitSha )
masterTreeSha = masterCommit.tree[ "sha" ]
masterTree = r.get_git_tree( masterTreeSha )
uncoveredMethods = set()
uncoveredApis = set()
with open( "ReferenceOfApis.md" ) as file:
for line in file.readlines():
line = line.strip()
if line.startswith( "API" ):
currentApi = line[ 5 : -1 ]
apiRegex = re.sub( ":\w+", "\w+", currentApi )
if line.startswith( "* " ):
verb = line[ 2 : line.find( ":" ) ]
for url, verbs in coveredUrls.iteritems():
if re.match( apiRegex, url ) and verb in verbs:
break
else:
if "`" in line:
uncoveredMethods.add( line[ line.find( "`" ) + 1 : -1 ] )
else:
uncoveredApis.add( verb + " " + currentApi )
print
if len( uncoveredMethods ) != 0:
print "Not covered (" + str( len( uncoveredMethods ) ) + "):"
print "\n".join( sorted( uncoveredMethods ) )
if len( uncoveredApis ) != 0:
print "Not implemented (" + str( len( uncoveredApis ) ) + "):"
print "\n".join( sorted( uncoveredApis ) )
def testAuthenticatedUserDetails( self ):
u = self.g.get_user()
self.printList( "Organizations", u.get_orgs(), lambda o: o.login )
def testColaborators( self ):
r = self.g.get_user().get_repo( "TestPyGithub" )
cobaye = self.g.get_user( self.cobayeUser )
self.printList( "Collaborators", r.get_collaborators(), lambda m: m.login )
r.add_to_collaborators( cobaye )
assert r.has_in_collaborators( cobaye )
self.printList( "Collaborators", r.get_collaborators(), lambda m: m.login )
r.remove_from_collaborators( cobaye )
assert not r.has_in_collaborators( cobaye )
self.printList( "Collaborators", r.get_collaborators(), lambda m: m.login )
def testCommentCommit( self ):
r = self.g.get_user().get_repo( "TestPyGithub" )
c = r.get_commits()[ 0 ]
self.printList( "Comments", c.get_comments(), lambda c: c.body )
com1 = c.create_comment( "Comment created by PyGithub" )
self.printList( "Comments", c.get_comments(), lambda c: c.body )
com2 = c.create_comment( "Comment also created by PyGithub", path = "ReadMe.md", line = 1 )
self.printList( "Comments", c.get_comments(), lambda c: c.body )
com2.delete()
com1.edit( body = "Comment edited by PyGithub" )
self.printList( "Comments", c.get_comments(), lambda c: c.body )
def testCreateForkForOrganization( self ):
o = self.g.get_organization( self.cobayeOrganization )
r = self.g.get_user().get_repo( "TestPyGithub" )
rf = o.create_fork( r )
print r.owner.login + "/" + r.name, "->", rf.owner.login + "/" + rf.name
def testCreateRepoForOrganization( self ):
o = self.g.get_organization( self.cobayeOrganization )
self.printList( "Repos", o.get_repos(), lambda r: r.name )
r = o.create_repo( "CreatedByPyGithub", has_wiki = False )
self.printList( "Repos", o.get_repos(), lambda r: r.name )
def testCreateRepoForUser( self ):
u = self.g.get_user()
self.printList( "Repos", u.get_repos(), lambda r: r.name )
r = u.create_repo( "CreatedByPyGithub", has_wiki = False )
self.printList( "Repos", u.get_repos(), lambda r: r.name )
def testDownloads( self ):
r = self.g.get_user().get_repo( "TestPyGithub" )
self.printList( "Downloads", r.get_downloads(), lambda d: d.name )
d = r.create_download( "DownloadCreatedByPyGithub.txt", 1024 )
self.printList( "Downloads", r.get_downloads(), lambda d: d.name )
sameDownload = r.get_download( d.id )
sameDownload.delete()
self.printList( "Downloads", r.get_downloads(), lambda d: d.name )
def testEditAuthenticatedUser( self ):
u = self.g.get_user()
originalName = u.name
print u.name
u.edit( name = u.name + " (edited by PyGithub)" )
print u.name
u.edit( name = originalName )
print u.name
def testEditOrganization( self ):
o = self.g.get_organization( self.cobayeOrganization )
originalName = o.name
print o.name
o.edit( name = str( o.name ) + " (edited by PyGithub)" )
print o.name
o.edit( name = originalName )
print o.name
def testEditOrganizationTeamAndMembers( self ):
o = self.g.get_organization( self.cobayeOrganization )
r = o.get_repo( "TestPyGithub" )
self.printList( "Teams", o.get_teams(), lambda t: t.name )
t = o.create_team( "PyGithubTesters" )
t.edit( "PyGithubTesters", permission = "push" )
self.printList( "Teams", o.get_teams(), lambda t: t.name )
u = self.g.get_user( self.cobayeUser )
self.printList( "Team members", t.get_members(), lambda m: m.login )
self.printList( "Team repos", t.get_repos(), lambda r: r.name )
assert not t.has_in_repos( r )
assert not t.has_in_members( u )
t.add_to_members( u )
t.add_to_repos( r )
assert t.has_in_repos( r )
assert t.has_in_members( u )
self.printList( "Team members", t.get_members(), lambda m: m.login )
self.printList( "Team repos", t.get_repos(), lambda r: r.name )
self.printList( "Public members", o.get_public_members(), lambda m: m.login )
o.add_to_public_members( u )
assert o.has_in_public_members( u )
self.printList( "Public members", o.get_public_members(), lambda m: m.login )
o.remove_from_public_members( u )
assert not o.has_in_public_members( u )
self.printList( "Public members", o.get_public_members(), lambda m: m.login )
self.printList( "Members", o.get_members(), lambda m: m.login )
assert o.has_in_members( u )
o.remove_from_members( u )
assert not o.has_in_members( u )
self.printList( "Members", o.get_members(), lambda m: m.login )
self.printList( "Team members", t.get_members(), lambda m: m.login )
self.printList( "Team repos", t.get_repos(), lambda r: r.name )
t.remove_from_members( u )
t.remove_from_repos( r )
assert not t.has_in_repos( r )
assert not t.has_in_members( u )
self.printList( "Team members", t.get_members(), lambda m: m.login )
self.printList( "Team repos", t.get_repos(), lambda r: r.name )
t.delete()
self.printList( "Teams", o.get_teams(), lambda t: t.name )
def testEvents( self ):
self.printList( "User events", self.g.get_user( self.cobayeUser ).get_events(), lambda e: e.type )
self.printList( "User public events", self.g.get_user( self.cobayeUser ).get_public_events(), lambda e: e.type )
self.printList( "User public received events", self.g.get_user( self.cobayeUser ).get_public_received_events(), lambda e: e.type )
self.printList( "User received events", self.g.get_user( self.cobayeUser ).get_received_events(), lambda e: e.type )
self.printList( "Organization events", self.g.get_organization( self.cobayeOrganization ).get_events(), lambda e: e.type )
self.printList( "User events", self.g.get_user().get_events(), lambda e: e.type )
o = self.g.get_organization( self.cobayeOrganization )
self.printList( "Organization events", self.g.get_user().get_organization_events( o ), lambda e: e.type )
self.printList( "Repo events", self.g.get_user().get_repo( "TestPyGithub" ).get_events(), lambda e: e.type )
self.printList( "Repo issues events", self.g.get_user().get_repo( "TestPyGithub" ).get_issues_events(), lambda e: e.event )
print self.g.get_user().get_repo( "TestPyGithub" ).get_issues_event( 10693379 ).event
self.printList( "Repo network events", self.g.get_user().get_repo( "TestPyGithub" ).get_network_events(), lambda e: e.type )
self.printList( "Issue events", self.g.get_user().get_repo( "TestPyGithub" ).get_issue( 23 ).get_events(), lambda e: e.event )
def testFollow( self ):
cobaye = self.g.get_user( self.cobayeUser )
u = self.g.get_user()
u.remove_from_following( cobaye )
assert not u.has_in_following( cobaye )
u.add_to_following( cobaye )
assert u.has_in_following( cobaye )
self.printList( "Following", u.get_following(), lambda f: f.login )
self.printList( "Followers", u.get_followers(), lambda f: f.login )
def testGists( self ):
u = self.g.get_user()
self.printList( "Gists", u.get_gists(), lambda g: g.description )
g = u.create_gist( public = True, description = "Gist created by PyGithub", files = { "foo.bar": { "content": "This gist was created by PyGithub" } } )
self.printList( "Gists", u.get_gists(), lambda g: g.description )
g.edit( description = "Gist edited by PyGithub" )
self.printList( "Gists", u.get_gists(), lambda g: g.description )
self.printList( "Starred gists", u.get_starred_gists(), lambda g: g.description )
g.set_starred()
assert g.is_starred()
self.printList( "Starred gists", u.get_starred_gists(), lambda g: g.description )
g.reset_starred()
self.printList( "Starred gists", u.get_starred_gists(), lambda g: g.description )
self.printList( "Gist comments", g.get_comments(), lambda c: c.body )
c = g.create_comment( "Comment created by PyGithub" )
self.printList( "Gist comments", g.get_comments(), lambda c: c.body )
c.edit( "Comment edited by PyGithub" )
self.printList( "Gist comments", g.get_comments(), lambda c: c.body )
sameComment = g.get_comment( c.id )
c.delete()
self.printList( "Gist comments", g.get_comments(), lambda c: c.body )
otherGist = self.g.get_gist( 1965703 ).create_fork() # Origin gist picked up randomly
self.printList( "Gists", u.get_gists(), lambda g: g.description or "None" )
otherGist.delete()
self.printList( "Gists", u.get_gists(), lambda g: g.description )
g.delete()
self.printList( "Gists", u.get_gists(), lambda g: g.description )
def testGitObjects( self ):
o = self.g.get_organization( self.cobayeOrganization )
r = o.get_repo( "TestPyGithub" )
masterRef = r.get_git_ref( "refs/heads/master" )
masterCommit = r.get_git_commit( masterRef.object[ "sha" ] )
masterTree = r.get_git_tree( masterCommit.tree.sha )
readmeBlob = None
for element in masterTree.tree:
if element[ "type" ] == "blob":
blobSha = element[ "sha" ]
if element[ "path" ] == "ReadMe.md":
readmeBlob = r.get_git_blob( element[ "sha" ] )
break
blob = r.get_git_blob( blobSha )
print " Master:", masterCommitSha, masterCommit.message, ", ".join( element[ "path" ] + " (" + element[ "type" ] + ")" for element in masterTree.tree )
print " blob:", blob.content, blob.encoding,
if blob.encoding == "base64":
print base64.b64decode( blob.content ),
print
print " Labels:", ", ".join( l.name + " (" + l.color + ")" for l in r.get_labels() )
print " Issues:", ", ".join( i.title + " (" + ", ".join( l.name for l in i.get_labels() ) + ") (" + ", ".join( c.body for c in i.get_comments() ) + ")" for i in r.get_issues() )
print " Milestones:", ", ".join( m.title + " (created by " + m.creator.login + ", " + ", ".join( l.name for l in m.get_labels() ) + ")" for m in r.get_milestones() )
print " Closed milestones:", ", ".join( m.title for m in r.get_milestones( state = "closed" ) )
print " Merge requests:", ", ".join( p.title + "(" + ", ".join( f.filename for f in p.get_files() ) + ")" for p in r.get_pulls() )
print
sys.stdout.flush()
IntegrationTest().main()
blob = r.create_git_blob( "This blob was created by PyGithub", encoding = "latin1" )
tree = r.create_git_tree( [ { "path": "foo.bar", "mode": "100644", "type": "blob", "sha": blob.sha }, { "path": "ReadMe.md", "mode": "100644", "type": "blob", "sha": readmeBlob.sha } ] )
commit = r.create_git_commit( "This commit was created by PyGithub", tree.sha, [ masterCommit.sha ] )
r.create_git_ref( "refs/heads/previous_master", masterRef.object[ "sha" ] )
masterRef.edit( commit.sha )
tag = r.create_git_tag( "tagCreatedByPyGithub", "This tag was created by PyGithub", commit.sha, "commit" )
r.create_git_ref( "refs/tags/tagCreatedByPyGithub", tag.sha )
reTag = r.get_git_tag( tag.sha )
def testHooks( self ):
u = self.g.get_user()
r = u.get_repo( "TestPyGithub" )
self.printList( "Hooks", r.get_hooks(), lambda h: h.name + str( h.config ) )
h = r.create_hook( "web", { "url": "http://www.invalid.org" } )
self.printList( "Hooks", r.get_hooks(), lambda h: h.name + str( h.config ) )
h.edit( "web", { "url": "http://www.postbin.org/w5cgjr" } )
self.printList( "Hooks", r.get_hooks(), lambda h: h.name + str( h.config ) )
sameHook = r.get_hook( h.id )
h.test()
h.delete()
self.printList( "Hooks", r.get_hooks(), lambda h: h.name + str( h.config ) )
def testIssuesAndMilestones( self ):
u = self.g.get_user()
r = u.get_repo( "TestPyGithub" )
self.printList( "Issues", r.get_issues(), lambda i: i.title )
i = r.create_issue( "Issue created by PyGithub" )
self.printList( "Issues", r.get_issues(), lambda i: i.title )
i.edit( body = "Issue edited by PyGithub" )
self.printList( "Comments on issue", i.get_comments(), lambda c: c.body )
c = i.create_comment( "Comment created by PyGithub" )
self.printList( "Comments on issue", i.get_comments(), lambda c: c.body )
c.edit( "Comment edited by PyGithub" )
sameComment = i.get_comment( c.id )
self.printList( "Comments on issue", i.get_comments(), lambda c: c.body )
c.delete()
self.printList( "Comments on issue", i.get_comments(), lambda c: c.body )
self.printList( "Milestones", r.get_milestones(), lambda m: m.title )
m = r.create_milestone( "Milestone created by PyGithub" )
self.printList( "Milestones", r.get_milestones(), lambda m: m.title )
m.edit( title = "Milestone edited by PyGithub" )
self.printList( "Milestones", r.get_milestones(), lambda m: m.title )
self.printList( "Issues of milestone", r.get_issues( milestone = m.number ), lambda i: i.title )
i.edit( milestone = m.number )
self.printList( "Issues of milestone", r.get_issues( milestone = m.number ), lambda i: i.title )
self.printList( "Repository labels", r.get_labels(), lambda l: l.name )
labelD = r.create_label( "D", "FF0000" )
self.printList( "Repository labels", r.get_labels(), lambda l: l.name )
labelD.edit( "Dada", "00FF00" )
self.printList( "Repository labels", r.get_labels(), lambda l: l.name )
labelD.delete()
self.printList( "Repository labels", r.get_labels(), lambda l: l.name )
labelA = r.get_label( "bug" )
labelB = r.get_label( "duplicate" )
labelC = r.get_label( "invalid" )
self.printList( "Labels", i.get_labels(), lambda l: l.name )
i.set_labels( labelA, labelB )
self.printList( "Labels", i.get_labels(), lambda l: l.name )
i.remove_from_labels( labelB )
self.printList( "Labels", i.get_labels(), lambda l: l.name )
i.delete_labels()
self.printList( "Labels", i.get_labels(), lambda l: l.name )
i.add_to_labels( labelB, labelC )
self.printList( "Labels", i.get_labels(), lambda l: l.name )
self.printList( "Milestone labels", r.get_milestone( m.number ).get_labels(), lambda l: l.name )
m.delete()
self.printList( "Milestones", r.get_milestones(), lambda m: m.title )
def testKeys( self ):
u = self.g.get_user()
self.printList( "Keys", u.get_keys(), lambda k: k.title )
k = u.create_key( u.login + "@PyGithub", "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAvborozfBBn2a+JETqPekTWZ1tmYjpfH9wTKFPLjIXQmxXjNye6HVgvi+iMI436RdoLsPEFDe3cjrQ6CJa7KzhRJKNTPh5EZbKI13CXfMGr7V1i3tOokXBFSRQKnDx2dj2hnswqxGUk2jXpgC/KA1q71yqnL45CBlWr50eDpwUIEPnmqSrPpRV/0ZGwIlh4o7+6HwPUF9aBhWj945WSkjZubR4UFWlDZl7ROafpkJHs2cQzaxtmBOZnu6dzmfyro0zJsvhZKD2K6d9eKgpDeKaw5rWr6FeOZPd4xyDaV1gctG0YEui8uuSPKhpcykgREUAFf+vmOKt+yXnOoq8P4vIQ==" )
self.printList( "Keys", u.get_keys(), lambda k: k.title )
k.edit( title = u.login + "@PyGithub2" )
k = u.get_key( k.id )
self.printList( "Keys", u.get_keys(), lambda k: k.title )
k.delete()
self.printList( "Keys", u.get_keys(), lambda k: k.title )
def testMergePullRequest( self ):
r = self.g.get_user().get_repo( "TestPyGithub" )
p = r.get_pull( 26 )
assert not p.is_merged()
p.merge()
assert p.is_merged()
def testNamedUserDetails( self ):
u = self.g.get_user( "jacquev6" )
print u.login, "(" + u.name + ") is from", u.location
self.printList( "Repos", u.get_repos(), lambda r: r.name )
self.printList( "Followers", u.get_followers(), lambda m: m.login )
self.printList( "Following", u.get_following(), lambda m: m.login )
self.printList( "Watched", u.get_watched(), lambda r: r.owner.login + "/" + r.name )
self.printList( "Organizations", u.get_orgs(), lambda o: o.login )
self.printList( "Gists", u.get_gists(), lambda g: g.description )
def testOrganizationDetails( self ):
o = self.g.get_organization( "github" )
print o.login, "(" + o.name + ") is in", o.location
def testPullRequest( self ):
r = self.g.get_user().get_repo( "TestPyGithub" )
self.printList( "Pull requests", r.get_pulls(), lambda p: p.title )
p1 = r.create_pull( "Pull request created by PyGithub", "", "master", "BeaverSoftware:master" )
self.printList( "Pull requests", r.get_pulls(), lambda p: p.title )
p1.edit( state = "closed" )
self.printList( "Pull requests", r.get_pulls(), lambda p: p.title )
p2 = r.create_pull( "Pull request also created by PyGithub", "", "master", "BeaverSoftware:master" )
self.printList( "Pull requests", r.get_pulls(), lambda p: p.title )
self.printList( "Files", p2.get_files(), lambda f: f.filename )
self.printList( "Commits", p2.get_commits(), lambda c: c.commit.message )
self.printList( "Comments", p2.get_comments(), lambda c: c.body )
com = p2.create_comment( "Comment created by PyGithub", "e4e84560cb5e87f3c0e9f710dae1ddab0eef487b", "foo.bar", 1 )
self.printList( "Comments", p2.get_comments(), lambda c: c.body )
com.edit( body = "Comment edited by PyGithub" )
self.printList( "Comments", p2.get_comments(), lambda c: c.body )
sameCom = p2.get_comment( com.id )
sameCom.delete()
self.printList( "Comments", p2.get_comments(), lambda c: c.body )
p2.edit( state = "closed" )
self.printList( "Pull requests", r.get_pulls(), lambda p: p.title )
def testRepositoryDetails( self ):
r1 = self.g.get_user().get_repo( "PyGithub" )
r2 = self.g.get_user().get_repo( "TestPyGithub" )
self.printList( "Branches", r1.get_branches(), lambda b: b.name )
self.printList( "Comments", r2.get_comments(), lambda c: c.body )
r2.get_comment( r2.get_comments()[ 0 ].id )
self.printList( "Contributors", r1.get_contributors(), lambda m: m.login )
self.printList( "Forks", r2.get_forks(), lambda r: r.owner.login )
print "Languages:", r1.get_languages()
self.printList( "Tags", r1.get_tags(), lambda t: t.name )
self.printList( "Watchers", r1.get_watchers(), lambda m: m.login )
r3 = self.g.get_organization( "BeaverSoftware" ).get_repo( "TestPyGithub" )
self.printList( "Teams", r3.get_teams(), lambda t: t.name )
def testRepositoryKeys( self ):
r = self.g.get_user().get_repo( "TestPyGithub" )
self.printList( "Keys", r.get_keys(), lambda k: k.title )
k = r.create_key( "Key created by PyGithub", "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAvborozfBBn2a+JETqPekTWZ1tmYjpfH9wTKFPLjIXQmxXjNye6HVgvi+iMI436RdoLsPEFDe3cjrQ6CJa7KzhRJKNTPh5EZbKI13CXfMGr7V1i3tOokXBFSRQKnDx2dj2hnswqxGUk2jXpgC/KA1q71yqnL45CBlWr50eDpwUIEPnmqSrPpRV/0ZGwIlh4o7+6HwPUF9aBhWj945WSkjZubR4UFWlDZl7ROafpkJHs2cQzaxtmBOZnu6dzmfyro0zJsvhZKD2K6d9eKgpDeKaw5rWr6FeOZPd4xyDaV1gctG0YEui8uuSPKhpcykgREUAFf+vmOKt+yXnOoq8P4vIQ==" )
self.printList( "Keys", r.get_keys(), lambda k: k.title )
k.edit( "Key edited by PyGithub", "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAvborozfBBn2a+JETqPekTWZ1tmYjpfH9wTKFPLjIXQmxXjNye6HVgvi+iMI436RdoLsPEFDe3cjrQ6CJa7KzhRJKNTPh5EZbKI13CXfMGr7V1i3tOokXBFSRQKnDx2dj2hnswqxGUk2jXpgC/KA1q71yqnL45CBlWr50eDpwUIEPnmqSrPpRV/0ZGwIlh4o7+6HwPUF9aBhWj945WSkjZubR4UFWlDZl7ROafpkJHs2cQzaxtmBOZnu6dzmfyro0zJsvhZKD2K6d9eKgpDeKaw5rWr6FeOZPd4xyDaV1gctG0YEui8uuSPKhpcykgREUAFf+vmOKt+yXnOoq8P4vIQ==" )
self.printList( "Keys", r.get_keys(), lambda k: k.title )
sameKey = r.get_key( k.id )
sameKey.delete()
self.printList( "Keys", r.get_keys(), lambda k: k.title )
def testWatch( self ):
r = self.g.get_user( "jacquev6" ).get_repo( "PyGithub" )
u = self.g.get_user()
u.remove_from_watched( r )
assert not u.has_in_watched( r )
u.add_to_watched( r )
assert u.has_in_watched( r )
self.printList( "Watched", u.get_watched(), lambda r: r.name )
def testEmails( self ):
u = self.g.get_user()
self.printList( "Emails", u.get_emails() )
u.add_to_emails( "ab@xxx.com", "cd@xxx.com" )
self.printList( "Emails", u.get_emails() )
u.remove_from_emails( "ab@xxx.com", "cd@xxx.com" )
self.printList( "Emails", u.get_emails() )
def printList( self, title, iterable, f = lambda x: x ):
print title + ":", ", ".join( str( f( x ) ) for x in iterable[ :10 ] ), "..." if len( iterable ) > 10 else ""
IntegrationTest().main( sys.argv[ 1: ] )
+1 -1
View File
@@ -1,4 +1,4 @@
This is a Python library to access the [Gitub API v3](http://developer.github.com/v3).
This is a Python library to access the [Github API v3](http://developer.github.com/v3).
With it, you can manage your Github resources (repositories, user profiles, organizations, etc.) from Python scripts.
+56 -56
View File
@@ -1,57 +1,57 @@
API `/authorizations`
=====================
* GET: (TODO)
* POST: (TODO)
* GET: `AuthenticatedUser.get_authorizations`
* POST: `AuthenticatedUser.create_authorization`
API `/authorizations/:id`
=========================
* GET: (TODO)
* PATCH: (TODO)
* DELETE: (TODO)
* GET: `AuthenticatedUser.get_authorization`
* PATCH: `Authorization.edit`
* DELETE: `Authorization.delete`
API `/events`
=============
* GET: (TODO)
* GET: `AuthenticatedUser.get_events`
API `/gists`
============
* GET: (TODO)
* POST: (TODO)
API `/gists/:gist_id/comments`
==============================
* GET: (TODO)
* POST: (TODO)
* GET: `AuthenticatedUser.get_gists`
* POST: `AuthenticatedUser.create_gist`
API `/gists/:id`
================
* GET: (TODO)
* PATCH: (TODO)
* DELETE: (TODO)
* GET: `Github.get_gist`
* PATCH: `Gist.edit`
* DELETE: `Gist.delete`
API `/gists/:id/comments`
==============================
* GET: `Gist.get_comments`
* POST: `Gist.create_comment`
API `/gists/:id/fork`
=====================
* POST: (TODO)
* POST: `Gist.create_fork`
API `/gists/:id/star`
=====================
* GET: (TODO)
* PUT: (TODO)
* DELETE: (TODO)
* GET: `Gist.is_starred`
* PUT: `Gist.set_starred`
* DELETE: `Gist.reset_starred`
API `/gists/comments/:id`
=========================
* GET: (TODO)
* PATCH: (TODO)
* DELETE: (TODO)
* GET: `Gist.get_comment`
* PATCH: `GistComment.edit`
* DELETE: `GistComment.delete`
API `/gists/public`
===================
* GET: (TODO)
* GET: (TODO) (Almost useless: huge fast-changing list, so I will have to re-re-implement pagination, with detection of duplicates caused by shifts, and a real iteration, not construction of the full list...)
API `/gists/starred`
====================
* GET: (TODO)
* GET: `AuthenticatedUser.get_starred_gists`
API `/issues`
=============
@@ -59,7 +59,7 @@ API `/issues`
API `/networks/:user/:repo/events`
==================================
* GET: (TODO)
* GET: `Repository.get_network_events`
API `/orgs/:org`
================
@@ -68,7 +68,7 @@ API `/orgs/:org`
API `/orgs/:org/events`
=======================
* GET: (TODO)
* GET: `Organization.get_events`
API `/orgs/:org/members`
========================
@@ -161,7 +161,7 @@ API `/repos/:user/:repo/downloads/:id`
API `/repos/:user/:repo/events`
===============================
* GET: (TODO)
* GET: `Repository.get_events`
API `/repos/:user/:repo/forks`
==============================
@@ -208,7 +208,7 @@ API `/repos/:user/:repo/git/trees`
API `/repos/:user/:repo/git/trees?base_tree=`
=============================================
* POST: `GitTree.create_update` (TODO)
* POST: (TODO)
API `/repos/:user/:repo/git/trees/:sha`
=======================================
@@ -220,18 +220,18 @@ API `/repos/:user/:repo/git/trees/:sha?recursive=1`
API `/repos/:user/:repo/hooks`
==============================
* GET: (TODO)
* POST: (TODO)
* GET: `Repository.get_hooks`
* POST: `Repository.create_hook`
API `/repos/:user/:repo/hooks/:id`
==================================
* GET: (TODO)
* PATCH: (TODO)
* DELETE: (TODO)
* GET: `Repository.get_hook`
* PATCH: `Hook.edit`
* DELETE: `Hook.delete`
API `/repos/:user/:repo/hooks/:id/test`
=======================================
* POST: (TODO)
* POST: `Hook.test`
API `/repos/:user/:repo/issues`
===============================
@@ -261,7 +261,7 @@ API `/repos/:user/:repo/issues/:id/labels/:name`
API `/repos/:user/:repo/issues/:id/events`
==========================================
* GET: (TODO)
* GET: `Issue.get_events`
API `/repos/:user/:repo/issues/comments/:id`
============================================
@@ -271,22 +271,22 @@ API `/repos/:user/:repo/issues/comments/:id`
API `/repos/:user/:repo/issues/events`
======================================
* GET: (TODO)
* GET: `Repository.get_issues_events`
API `/repos/:user/:repo/issues/events/:id`
==========================================
* GET: (TODO)
* GET: `Repository.get_issues_event`
API `/repos/:user/:repo/keys`
=============================
* GET: (TODO)
* POST: (TODO)
* GET: `Repository.get_keys`
* POST: `Repository.create_key`
API `/repos/:user/:repo/keys/:id`
=================================
* GET: (TODO)
* PATCH: (TODO)
* DELETE: (TODO)
* GET: `Repository.get_key`
* PATCH: `RepositoryKey.edit`
* DELETE: `RepositoryKey.delete`
API `/repos/:user/:repo/labels`
===============================
@@ -343,8 +343,8 @@ API `/repos/:user/:repo/pulls/:id/files`
API `/repos/:user/:repo/pulls/:id/merge`
========================================
* GET: (TODO)
* PUT: (TODO)
* GET: `PullRequest.is_merged`
* PUT: `PullRequest.merge`
API `/repos/:user/:repo/pulls/comments/:id`
===========================================
@@ -417,14 +417,14 @@ API `/user/following/:user`
API `/user/keys`
================
* GET: (TODO)
* POST: (TODO)
* GET: `AuthenticatedUser.get_keys`
* POST: `AuthenticatedUser.create_key`
API `/user/keys/:id`
====================
* GET: (TODO)
* PATCH: (TODO)
* DELETE: (TODO)
* GET: `AuthenticatedUser.get_key`
* PATCH: `UserKey.edit`
* DELETE: `UserKey.delete`
API `/user/orgs`
================
@@ -451,15 +451,15 @@ API `/users/:user`
API `/users/:user/events`
=========================
* GET: (TODO)
* GET: `NamedUser.get_events`
API `/users/:user/events/orgs/:org`
===================================
* GET: (TODO)
* GET: `AuthenticatedUser.get_organization_events`
API `/users/:user/events/public`
================================
* GET: (TODO)
* GET: `NamedUser.get_public_events`
API `/users/:user/followers`
============================
@@ -471,7 +471,7 @@ API `/users/:user/following`
API `/users/:user/gists`
========================
* GET: (TODO)
* GET: `NamedUser.get_gists`
API `/users/:user/orgs`
=======================
@@ -479,11 +479,11 @@ API `/users/:user/orgs`
API `/users/:user/received_events`
==================================
* GET: (TODO)
* GET: `NamedUser.get_received_events`
API `/users/:user/received_events/public`
=========================================
* GET: (TODO)
* GET: `NamedUser.get_public_received_events`
API `/users/:user/repos`
========================
+229 -4
View File
@@ -58,6 +58,22 @@ Emails
* `remove_from_emails( email, ... )`
* `email`: string
Authorizations
--------------
* `get_authorizations()`: list of `Authorization`
* `get_authorization( id )`: `Authorization`
* `create_authorization( [scopes, note, note_url] )`: `Authorization`
Keys
----
* `get_keys()`: list of `UserKey`
* `get_key( id )`: `UserKey`
* `create_key( title, key )`: `UserKey`
Events
------
* `get_events()`: list of `Event`
Followers
---------
* `get_followers()`: list of `NamedUser`
@@ -96,6 +112,35 @@ Forking
-------
* `create_fork( repo )`: `Repository`
Gists
-----
* `get_gists()`: list of `Gist`
* `create_gist( public, files, [description] )`: `Gist`
* `get_starred_gists()`: list of `Gist`
Class `Authorization`
=====================
Attributes
----------
* `id`
* `url`
* `scopes`
* `token`
* `app`
* `note`
* `note_url`
* `updated_at`
* `created_at`
Modification
------------
* `edit( [scopes, add_scopes, remove_scopes, note, note_url] )`
Deletion
--------
* `delete()`
Class `Branch`
==============
@@ -121,7 +166,7 @@ Attributes
Comments
--------
* `get_comments()`: list of `CommitComment`
* `create_comment( body, commit_id, line, path, position )`: `CommitComment`
* `create_comment( body, [commit_id, line, path, position] )`: `CommitComment`
Class `CommitComment`
=====================
@@ -178,6 +223,83 @@ Deletion
--------
* `delete()`
Class `Event`
=============
Attributes
----------
* `type`
* `public`
* `payload`
* `created_at`
* `repo`: `Repository`
* `actor`: `NamedUser`
* `org`: `Organization`
Class `Gist`
============
Attributes
----------
* `url`
* `id`
* `description`
* `public`
* `files`
* `comments`
* `html_url`
* `git_pull_url`
* `git_push_url`
* `created_at`
* `forks`
* `history`
* `updated_at`
* `user`: `NamedUser`
Modification
------------
* `edit( [description, files] )`
Deletion
--------
* `delete()`
Comments
--------
* `get_comments()`: list of `GistComment`
* `get_comment( id )`: `GistComment`
* `create_comment( body )`: `GistComment`
Starring
--------
* `is_starred()`: bool
* `set_starred()`
* `reset_starred()`
Forking
-------
* `create_fork()`: `Gist`
Class `GistComment`
===================
Attributes
----------
* `id`
* `url`
* `body`
* `created_at`
* `updated_at`
* `user`: `NamedUser`
Modification
------------
* `edit( body )`
Deletion
--------
* `delete()`
Class `GitBlob`
===============
@@ -197,10 +319,10 @@ Attributes
* `sha`
* `url`
* `message`
* `parents`
* `author`
* `committer`
* `tree`
* `parents`
* `tree`: `GitTree`
Class `GitRef`
==============
@@ -236,6 +358,33 @@ Attributes
* `url`
* `tree`
Class `Hook`
============
Attributes
----------
* `url`
* `updated_at`
* `created_at`
* `name`
* `events`
* `active`
* `config`
* `id`
* `last_response`
Modification
------------
* `edit( name, config, [events, add_events, remove_events, active] )`
Deletion
--------
* `delete()`
Testing
-------
* `test()`
Class `Issue`
=============
@@ -280,6 +429,10 @@ Comments
* `get_comment( id )`: `IssueComment`
* `create_comment( body )`: `IssueComment`
Events
------
* `get_events()`: list of `Event`
Class `IssueComment`
====================
@@ -385,6 +538,13 @@ Following
---------
* `get_following()`: list of `NamedUser`
Events
------
* `get_events()`: list of `Event`
* `get_public_events()`: list of `Event`
* `get_received_events()`: list of `Event`
* `get_public_received_events()`: list of `Event`
Orgs
----
* `get_orgs()`: list of `Organization`
@@ -398,6 +558,10 @@ Watched
-------
* `get_watched()`: list of `Repository`
Gists
-----
* `get_gists()`: list of `Gist`
Class `Organization`
====================
@@ -449,6 +613,10 @@ Members
* `has_in_members( member )`: `bool`
* `member`: `NamedUser`
Events
------
* `get_events()`: list of `Event`
Repos
-----
* `get_repos( [type] )`: list of `Repository`
@@ -492,6 +660,9 @@ Attributes
* `changed_files`
* `head`
* `base`
* `merged_by`
* `review_comments`
* `user`: `NamedUser`
Modification
------------
@@ -586,6 +757,12 @@ Attributes
* `parent`: `Repository`
* `source`: `Repository`
Events
------
* `get_events()`: list of `Event`
* `get_network_events()`: list of `Event`
* `get_issues_events()`: list of `Event`
Forks
-----
* `get_forks()`: list of `Repository`
@@ -598,6 +775,18 @@ Languages
---------
* `get_languages()`: dictionary of strings to integers
Hooks
-----
* `get_hooks()`: list of `Hook`
* `get_hook( id )`: `Hook`
* `create_hook( name, config, [events, active] )`: `Hook`
Keys
----
* `get_keys()`: list of `RepositoryKey`
* `get_key( id )`: `RepositoryKey`
* `create_key( title, key )`: `RepositoryKey`
Collaborators
-------------
* `get_collaborators()`: list of `NamedUser`
@@ -625,7 +814,7 @@ Git refs
Git commits
-----------
* `get_git_commit( sha )`: `GitCommit`
* `create_git_commit( message, tree, parents, [author, commiter] )`: `GitCommit`
* `create_git_commit( message, tree, parents, [author, committer] )`: `GitCommit`
Git trees
---------
@@ -694,6 +883,24 @@ Teams
-----
* `get_teams()`: list of `Team`
Class `RepositoryKey`
=====================
Attributes
----------
* `url`
* `id`
* `title`
* `key`
Modification
------------
* `edit( title, key )`
Deletion
--------
* `delete()`
Class `Tag`
===========
@@ -744,4 +951,22 @@ Repos
* `has_in_repos( repo )`: `bool`
* `repo`: `Repository`
Class `UserKey`
===============
Attributes
----------
* `url`
* `id`
* `title`
* `key`
Modification
------------
* `edit( [title, key] )`
Deletion
--------
* `delete()`
+66
View File
@@ -37,4 +37,70 @@ class TestCase( unittest.TestCase ):
self.assertFalse( self.g.get_user().has_in_following( self.g.get_user( "xxx" ) ) )
self.assertTrue( self.g.get_user().has_in_following( self.g.get_user( "yyy" ) ) )
def testGist( self ):
self.requester.expect.dataRequest( "GET", "/gists/123456", None, None ).andReturn( { "description": "xxx" } )
g = self.g.get_gist( 123456 )
self.assertEqual( g.description, "xxx" )
self.requester.expect.statusRequest( "GET", "/gists/123456/star", None, None ).andReturn( 404 )
self.assertFalse( g.is_starred() )
self.requester.expect.statusRequest( "PUT", "/gists/123456/star", None, None ).andReturn( 204 )
g.set_starred()
self.requester.expect.statusRequest( "DELETE", "/gists/123456/star", None, None ).andReturn( 204 )
g.reset_starred()
self.requester.expect.dataRequest( "POST", "/gists/123456/fork", None, None ).andReturn( { "description": "yyy" } )
self.assertEqual( g.create_fork().description, "yyy" )
self.requester.expect.dataRequest( "GET", "/gists/starred", None, None ).andReturn( [ { "description": "xxx" }, { "description": "yyy" } ] )
self.assertEqual( len( self.g.get_user().get_starred_gists() ), 2 )
def testRepositoryReference( self ):
self.requester.expect.dataRequest( "GET", "/user", None, None ).andReturn( { "login": "xxx" } )
self.requester.expect.dataRequest( "GET", "/repos/xxx/yyy", None, None ).andReturn( { "name": "yyy", "owner": { "login": "xxx" } } )
r = self.g.get_user().get_repo( "yyy" )
self.requester.expect.dataRequest( "GET", "/repos/xxx/yyy/milestones/1", None, None ).andReturn( { "number": 1 } )
self.requester.expect.dataRequest( "GET", "/repos/xxx/yyy/milestones/1/labels", {}, None ).andReturn( [ { "name": "a" } ] )
self.assertIs( r.get_milestone( 1 ).get_labels()[ 0 ]._repo, r )
def testHooks( self ):
self.requester.expect.dataRequest( "GET", "/user", None, None ).andReturn( { "login": "xxx" } )
self.requester.expect.dataRequest( "GET", "/repos/xxx/yyy", None, None ).andReturn( { "name": "yyy", "owner": { "login": "xxx" } } )
self.requester.expect.dataRequest( "GET", "/repos/xxx/yyy/hooks/1", None, None ).andReturn( { "name": "web", "id": 1 } )
h = self.g.get_user().get_repo( "yyy" ).get_hook( 1 )
self.requester.expect.statusRequest( "POST", "/repos/xxx/yyy/hooks/1/test", None, None ).andReturn( 204 )
h.test()
def testUserEvents( self ):
self.requester.expect.dataRequest( "GET", "/users/xxx", None, None ).andReturn( { "login": "xxx" } )
self.requester.expect.dataRequest( "GET", "/users/xxx/events/public", None, None ).andReturn( [] )
self.requester.expect.dataRequest( "GET", "/users/xxx/received_events/public", None, None ).andReturn( [] )
u = self.g.get_user( "xxx" )
u.get_public_events()
u.get_public_received_events()
def testRepoEvents( self ):
self.requester.expect.dataRequest( "GET", "/user", None, None ).andReturn( { "login": "xxx" } )
self.requester.expect.dataRequest( "GET", "/repos/xxx/yyy", None, None ).andReturn( { "name": "yyy", "owner": { "login": "xxx" } } )
self.requester.expect.dataRequest( "GET", "/networks/xxx/yyy/events", None, None ).andReturn( [] )
r = self.g.get_user().get_repo( "yyy" )
r.get_network_events()
def testOrgEvents( self ):
self.requester.expect.dataRequest( "GET", "/orgs/ooo", None, None ).andReturn( { "login": "ooo" } )
self.requester.expect.dataRequest( "GET", "/user", None, None ).andReturn( { "login": "xxx" } )
self.requester.expect.dataRequest( "GET", "/users/xxx/events/orgs/ooo", None, None ).andReturn( [] )
u = self.g.get_user()
o = self.g.get_organization( "ooo" )
u.get_organization_events( o )
def testMergePullRequest( self ):
self.requester.expect.dataRequest( "GET", "/user", None, None ).andReturn( { "login": "xxx" } )
self.requester.expect.dataRequest( "GET", "/repos/xxx/yyy", None, None ).andReturn( { "name": "yyy", "owner": { "login": "xxx" } } )
self.requester.expect.dataRequest( "GET", "/repos/xxx/yyy/pulls/42", None, None ).andReturn( { "number": 42 } )
self.requester.expect.statusRequest( "GET", "/repos/xxx/yyy/pulls/42/merge", None, None ).andReturn( 404 )
self.requester.expect.statusRequest( "PUT", "/repos/xxx/yyy/pulls/42/merge", None, {} ).andReturn( 204 )
self.requester.expect.statusRequest( "GET", "/repos/xxx/yyy/pulls/42/merge", None, None ).andReturn( 204 )
p = self.g.get_user().get_repo( "yyy" ).get_pull( 42 )
self.assertFalse( p.is_merged() )
p.merge()
self.assertTrue( p.is_merged() )
unittest.main()
+3
View File
@@ -19,3 +19,6 @@ class Github:
def get_organization( self, login ):
return Organization( self, { "login": login }, lazy = False )
def get_gist( self, id ):
return Gist( self, { "id": id }, lazy = False )
+72
View File
@@ -17,6 +17,7 @@ class TestCaseWithGithubTestObject( unittest.TestCase ):
unittest.TestCase.setUp( self )
self.g = MockMockMock.Mock( "github" )
self.o = self.GithubTestObject( self.g.object, { "a1": 1, "a2": 2 }, lazy = True )
self.GithubTestObject._autoDocument() # Only for coverage
def tearDown( self ):
self.g.tearDown()
@@ -43,6 +44,32 @@ class TestCaseWithGithubTestObject( unittest.TestCase ):
def expectStatusDelete( self, url, data = None ):
return self.g.expect._statusRequest( "DELETE", url, None, data )
class GithubObjectWithDocumentationCoveringSpecialCases( TestCaseWithGithubTestObject ):
GithubTestObject = GithubObject(
"GithubTestObject",
BaseUrl( lambda obj: "/test" ),
InternalSimpleAttributes( "a1", "a2", "_a3" ),
MethodFromCallable( "myMethod", [ "mock", "arg" ], [], lambda obj: 42, ObjectTypePolicy( GithubObject ) ),
AttributeFromCallable( "myAttr", lambda obj: 42 )
)
def testNothing( self ):
pass
class GithubObjectWithBaseUrlDependingOnAttribute( TestCaseWithGithubTestObject ):
GithubTestObject = GithubObject(
"GithubTestObject",
BaseUrl( lambda obj: "/test/" + str( obj.a1 ) ),
InternalSimpleAttributes( "a1", "a2", "a3", "a4" ),
Editable( [ "a1" ], [] )
)
def test( self ):
self.expectDataPatch( "/test/1", { "a1": 11 } ).andReturn( { "a1": 110 } )
self.expectDataPatch( "/test/110", { "a1": 111 } ).andReturn( { "a1": 1110 } )
self.o.edit( 11 )
self.o.edit( 111 )
class GithubObjectWithOnlyInternalSimpleAttributes( TestCaseWithGithubTestObject ):
GithubTestObject = GithubObject(
"GithubTestObject",
@@ -228,6 +255,51 @@ class GithubObjectWithListGetableExternalListOfObjects( TestCaseWithGithubTestOb
a3s = self.o.get_a3s( "foobar" )
self.assertEqual( len( a3s ), 3 )
class GithubObjectWithListGetableExternalListOfObjectsWithOtherUrl( TestCaseWithGithubTestObject ):
ContainedObject = GithubObject(
"ContainedObject",
BaseUrl( lambda obj: "/other/" + obj.id ),
InternalSimpleAttributes( "id", "name" )
)
GithubTestObject = GithubObject(
"GithubTestObject",
BaseUrl( lambda obj: "/test" ),
InternalSimpleAttributes( "a1", "a2" ),
ExternalListOfObjects( "a3s", "a3", ContainedObject, ListGetable( [], [ "type" ] ), url = "/other" )
)
def testGetList( self ):
self.expectDataGet( "/other", {} ).andReturn( [ { "id": "id1" }, { "id": "id2" }, { "id": "id3" } ] )
a3s = self.o.get_a3s()
self.assertEqual( len( a3s ), 3 )
self.assertEqual( a3s[ 0 ].id, "id1" )
self.expectDataGet( "/other/id1" ).andReturn( { "name": "name1" } )
self.assertEqual( a3s[ 0 ].name, "name1" )
class GithubObjectWithListGetableExternalListOfObjectsWithAttributeModifier( TestCaseWithGithubTestObject ):
ContainedObject = GithubObject(
"ContainedObject",
BaseUrl( lambda obj: "/test/a3s/" + obj.id ),
InternalSimpleAttributes( "id", "name", "_a" )
)
GithubTestObject = GithubObject(
"GithubTestObject",
BaseUrl( lambda obj: "/test" ),
InternalSimpleAttributes( "a1", "a2" ),
ExternalListOfObjects( "a3s", "a3", ContainedObject, ListGetable( [], [ "type" ], { "_a": lambda obj: 42 } ) )
)
def testGetList( self ):
self.expectDataGet( "/test/a3s", {} ).andReturn( [ { "id": "id1" }, { "id": "id2" }, { "id": "id3" } ] )
a3s = self.o.get_a3s()
self.assertEqual( len( a3s ), 3 )
self.assertEqual( a3s[ 0 ].id, "id1" )
self.assertEqual( a3s[ 0 ]._a, 42 )
self.expectDataGet( "/test/a3s/id1" ).andReturn( { "name": "name1" } )
self.assertEqual( a3s[ 0 ].name, "name1" )
class GithubObjectWithElementAddableExternalListOfObjects( TestCaseWithGithubTestObject ):
ContainedObject = GithubObject(
"ContainedObject",
+3 -3
View File
@@ -21,20 +21,20 @@ def ExternalSimpleAttribute( attributeName, type ):
return ExternalAttribute( attributeName, SimpleTypePolicy( type ) )
def BaseUrl( baseUrl ):
return AttributeFromCallable( "_baseUrl", baseUrl )
return MethodFromCallable( "_baseUrl", [], [], baseUrl, SimpleTypePolicy( None ) )
def Identity( identity ):
return AttributeFromCallable( "_identity", identity )
def Editable( mandatoryParameters, optionalParameters ):
def __execute( obj, **data ):
attributes = obj._github._dataRequest( "PATCH", obj._baseUrl, None, data )
attributes = obj._github._dataRequest( "PATCH", obj._baseUrl(), None, data )
obj._updateAttributes( attributes )
return SeveralAttributePolicies( [ MethodFromCallable( "edit", mandatoryParameters, optionalParameters, __execute, SimpleTypePolicy( None ) ) ], "Modification" )
def Deletable():
def __execute( obj ):
obj._github._statusRequest( "DELETE", obj._baseUrl, None, None )
obj._github._statusRequest( "DELETE", obj._baseUrl(), None, None )
return SeveralAttributePolicies( [ MethodFromCallable( "delete", [], [], __execute, SimpleTypePolicy( None ) ) ], "Deletion" )
def GithubObject( className, *attributePolicies ):
+271 -33
View File
@@ -3,6 +3,50 @@ import urllib
from GithubObject import *
Event = GithubObject(
"Event",
InternalSimpleAttributes(
"type", "public", "payload", "created_at", "id", "commit_id", "url",
"event", "issue",
),
)
def __testHook( hook ):
hook._github._statusRequest( "POST", hook._baseUrl() + "/test", None, None )
Hook = GithubObject(
"Hook",
BaseUrl( lambda obj: obj._repo._baseUrl() + "/hooks/" + str( obj.id ) ),
InternalSimpleAttributes(
"url", "updated_at", "created_at", "name", "events", "active", "config",
"id", "last_response",
"_repo", ### Ugly hack
),
Editable( [ "name", "config" ], [ "events", "add_events", "remove_events", "active" ] ),
Deletable(),
SeveralAttributePolicies( [ MethodFromCallable( "test", [], [], __testHook, SimpleTypePolicy( None ) ) ], "Testing" )
)
Authorization = GithubObject(
"Authorization",
BaseUrl( lambda obj: "/authorizations/" + str( obj.id ) ), ### @todo make the lambda return a tuple, and BaseUrl convert elements to strings and join them with "/"
InternalSimpleAttributes(
"id", "url", "scopes", "token", "app", "note", "note_url", "updated_at",
"created_at",
),
Editable( [], [ "scopes", "add_scopes", "remove_scopes", "note", "note_url" ] ),
Deletable(),
)
UserKey = GithubObject(
"UserKey",
BaseUrl( lambda obj: "/user/keys/" + str( obj.id ) ),
InternalSimpleAttributes(
"url", "id", "title", "key",
),
Editable( [], [ "title", "key" ] ),
Deletable(),
)
AuthenticatedUser = GithubObject(
"AuthenticatedUser",
BaseUrl( lambda obj: "/user" ),
@@ -20,6 +64,21 @@ AuthenticatedUser = GithubObject(
SeveralElementsAddable(),
SeveralElementsRemovable()
),
ExternalListOfObjects( "authorizations", "authorization", Authorization,
ListGetable( [], [] ),
ElementGetable( [ "id" ], [] ),
ElementCreatable( [], [ "scopes", "note", "note_url" ] ),
url = "/authorizations",
),
ExternalListOfObjects( "keys", "key", UserKey,
ListGetable( [], [] ),
ElementGetable( [ "id" ], [] ),
ElementCreatable( [ "title", "key" ], [] ),
),
ExternalListOfObjects( "events", "event", Event,
ListGetable( [], [] ),
url = "/events"
),
)
NamedUser = GithubObject(
@@ -63,6 +122,34 @@ NamedUser._addAttributePolicy(
ListGetable( [], [] )
)
)
NamedUser._addAttributePolicy(
ExternalListOfObjects( "events", "event", Event,
ListGetable( [], [] )
),
)
def __getPublicEvents( user ):
return [
Event( user._github, attributes, lazy = True )
for attributes
in user._github._dataRequest( "GET", user._baseUrl() + "/events/public", None, None )
]
NamedUser._addAttributePolicy(
MethodFromCallable( "get_public_events", [], [], __getPublicEvents, SimpleTypePolicy( "list of `Event`" ) )
)
NamedUser._addAttributePolicy(
ExternalListOfObjects( "received_events", "received_event", Event,
ListGetable( [], [] )
)
)
def __getPublicReceivedEvents( user ):
return [
Event( user._github, attributes, lazy = True )
for attributes
in user._github._dataRequest( "GET", user._baseUrl() + "/received_events/public", None, None )
]
NamedUser._addAttributePolicy(
MethodFromCallable( "get_public_received_events", [], [], __getPublicReceivedEvents, SimpleTypePolicy( "list of `Event`" ) )
)
Organization = GithubObject(
"Organization",
@@ -71,7 +158,7 @@ Organization = GithubObject(
InternalSimpleAttributes(
"login", "id", "url", "avatar_url", "name", "company", "blog",
"location", "email", "public_repos", "public_gists", "followers",
"following", "html_url", "created_at", "type",
"following", "html_url", "created_at", "type", "gravatar_id",
# Seen only by owners
"disk_usage", "collaborators", "billing_email", "plan", "private_gists",
"total_private_repos", "owned_private_repos",
@@ -88,6 +175,9 @@ Organization = GithubObject(
ElementRemovable(),
ElementHasable()
),
ExternalListOfObjects( "events", "event", Event,
ListGetable( [], [] )
),
)
AuthenticatedUser._addAttributePolicy(
@@ -101,9 +191,19 @@ NamedUser._addAttributePolicy(
)
)
def __getOrganizationEvents( user, org ):
return [
Event( user._github, attributes, lazy = True )
for attributes
in user._github._dataRequest( "GET", "/users/" + user.login + "/events/orgs/" + org.login, None, None )
]
AuthenticatedUser._addAttributePolicy(
MethodFromCallable( "get_organization_events", [ "org" ], [], __getOrganizationEvents, SimpleTypePolicy( "list of `Event`" ) )
)
GitRef = GithubObject(
"GitRef",
BaseUrl( lambda obj: obj._repo._baseUrl + "/git/" + obj.ref ),
BaseUrl( lambda obj: obj._repo._baseUrl() + "/git/" + obj.ref ),
InternalSimpleAttributes(
"ref", "url",
"object", ### @todo Structure
@@ -112,22 +212,9 @@ GitRef = GithubObject(
Editable( [ "sha" ], [ "force" ] ),
)
GitCommit = GithubObject(
"GitCommit",
BaseUrl( lambda obj: obj._repo._baseUrl + "/git/commits/" + obj.sha ),
InternalSimpleAttributes(
"sha", "url", "message",
"author", ### @todo Structure
"committer", ### @todo Structure
"tree", ### @todo Structure
"parents", ### @todo Structure
"_repo", ### Ugly hack
),
)
GitTree = GithubObject(
"GitTree",
BaseUrl( lambda obj: obj._repo._baseUrl + "/git/trees/" + obj.sha ),
BaseUrl( lambda obj: obj._repo._baseUrl() + "/git/trees/" + obj.sha ),
InternalSimpleAttributes(
"sha", "url",
"tree", ### @todo Structure
@@ -135,9 +222,21 @@ GitTree = GithubObject(
),
)
GitCommit = GithubObject(
"GitCommit",
BaseUrl( lambda obj: obj._repo._baseUrl() + "/git/commits/" + obj.sha ),
InternalSimpleAttributes(
"sha", "url", "message",
"parents", ### @todo Structure
"author", "committer",
"_repo", ### Ugly hack
),
InternalObjectAttribute( "tree", GitTree ),
)
GitBlob = GithubObject(
"GitBlob",
BaseUrl( lambda obj: obj._repo._baseUrl + "/git/blobs/" + obj.sha ),
BaseUrl( lambda obj: obj._repo._baseUrl() + "/git/blobs/" + obj.sha ),
InternalSimpleAttributes(
"sha", "size", "url",
"content", "encoding",
@@ -147,7 +246,7 @@ GitBlob = GithubObject(
GitTag = GithubObject(
"GitTag",
BaseUrl( lambda obj: obj._repo._baseUrl + "/git/tags/" + obj.sha ),
BaseUrl( lambda obj: obj._repo._baseUrl() + "/git/tags/" + obj.sha ),
InternalSimpleAttributes(
"tag", "sha", "url",
"message",
@@ -159,7 +258,7 @@ GitTag = GithubObject(
Label = GithubObject(
"Label",
BaseUrl( lambda obj: obj._repo._baseUrl + "/labels/" + obj._identity ),
BaseUrl( lambda obj: obj._repo._baseUrl() + "/labels/" + obj._identity ),
Identity( lambda obj: urllib.quote( obj.name ) ),
InternalSimpleAttributes(
"url", "name", "color",
@@ -173,7 +272,7 @@ __modifyAttributesForObjectsReferingReferedRepo = { "_repo": lambda obj: obj._re
Milestone = GithubObject(
"Milestone",
BaseUrl( lambda obj: obj._repo._baseUrl + "/milestones/" + str( obj.number ) ),
BaseUrl( lambda obj: obj._repo._baseUrl() + "/milestones/" + str( obj.number ) ),
InternalSimpleAttributes(
"url", "number", "state", "title", "description", "open_issues",
"closed_issues", "created_at", "due_on",
@@ -189,7 +288,7 @@ Milestone = GithubObject(
IssueComment = GithubObject(
"IssueComment",
BaseUrl( lambda obj: obj._repo._baseUrl + "/issues/comment" + str( obj.id ) ),
BaseUrl( lambda obj: obj._repo._baseUrl() + "/issues/comments/" + str( obj.id ) ),
InternalSimpleAttributes(
"url", "body", "created_at", "updated_at", "id",
"_repo", ### Ugly hack
@@ -199,9 +298,19 @@ IssueComment = GithubObject(
Deletable(),
)
IssueEvent = GithubObject(
"IssueEvent",
BaseUrl( lambda obj: obj._repo._baseUrl() + "/issues/events/" + str( obj.id ) ),
InternalSimpleAttributes(
"id", "url", "created_at", "issue", "event", "commit_id",
"_repo", # Ugly hack
),
InternalObjectAttribute( "actor", NamedUser ),
)
Issue = GithubObject(
"Issue",
BaseUrl( lambda obj: obj._repo._baseUrl + "/issues/" + str( obj.number ) ),
BaseUrl( lambda obj: obj._repo._baseUrl() + "/issues/" + str( obj.number ) ),
InternalSimpleAttributes(
"url", "html_url", "number", "state", "title", "body", "labels",
"comments", "closed_at", "created_at", "updated_at", "id", "closed_by",
@@ -224,11 +333,14 @@ Issue = GithubObject(
ElementGetable( [ "id" ], [], __modifyAttributesForObjectsReferingReferedRepo ),
ElementCreatable( [ "body" ], [], __modifyAttributesForObjectsReferingReferedRepo ),
),
ExternalListOfObjects( "events", "event", IssueEvent,
ListGetable( [], [], __modifyAttributesForObjectsReferingReferedRepo )
),
)
Download = GithubObject(
"Download",
BaseUrl( lambda obj: obj._repo._baseUrl + "/downloads/" + str( obj.id ) ),
BaseUrl( lambda obj: obj._repo._baseUrl() + "/downloads/" + str( obj.id ) ),
InternalSimpleAttributes(
"url", "html_url", "id", "name", "description", "size",
"download_count", "content_type", "policy", "signature", "bucket",
@@ -241,7 +353,7 @@ Download = GithubObject(
CommitComment = GithubObject(
"CommitComment",
BaseUrl( lambda obj: obj._repo._baseUrl + "/comments/" + str( obj.id ) ),
BaseUrl( lambda obj: obj._repo._baseUrl() + "/comments/" + str( obj.id ) ),
InternalSimpleAttributes(
"url", "id", "body", "path", "position", "commit_id",
"created_at", "updated_at", "html_url", "line",
@@ -254,7 +366,7 @@ CommitComment = GithubObject(
Commit = GithubObject(
"Commit",
BaseUrl( lambda obj: obj._repo._baseUrl + "/commits/" + str( obj.sha ) ),
BaseUrl( lambda obj: obj._repo._baseUrl() + "/commits/" + str( obj.sha ) ),
InternalSimpleAttributes(
"sha", "url",
"parents", ### @todo Structure
@@ -266,8 +378,8 @@ Commit = GithubObject(
InternalObjectAttribute( "author", NamedUser ),
InternalObjectAttribute( "committer", NamedUser ),
ExternalListOfObjects( "comments", "comment", CommitComment,
ListGetable( [], [] ),
ElementCreatable( [ "body", "commit_id", "line", "path", "position" ], [] ),
ListGetable( [], [], __modifyAttributesForObjectsReferingReferedRepo ),
ElementCreatable( [ "body" ], [ "commit_id", "line", "path", "position" ], __modifyAttributesForObjectsReferingReferedRepo ),
),
)
@@ -300,7 +412,7 @@ PullRequestFile = GithubObject(
PullRequestComment = GithubObject(
"PullRequestComment",
BaseUrl( lambda obj: obj._repo._baseUrl + "/pulls/comments/" + str( obj.id ) ),
BaseUrl( lambda obj: obj._repo._baseUrl() + "/pulls/comments/" + str( obj.id ) ),
InternalSimpleAttributes(
"url", "id", "body", "path", "position", "commit_id",
"created_at", "updated_at", "html_url", "line",
@@ -311,9 +423,13 @@ PullRequestComment = GithubObject(
Deletable(),
)
def __pullRequestIsMerged( r ):
return r._github._statusRequest( "GET", r._baseUrl() + "/merge", None, None ) == 204
def __mergePullRequest( r, **data ):
r._github._statusRequest( "PUT", r._baseUrl() + "/merge", None, data )
PullRequest = GithubObject(
"PullRequest",
BaseUrl( lambda obj: obj._repo._baseUrl + "/pulls/" + str( obj.number ) ),
BaseUrl( lambda obj: obj._repo._baseUrl() + "/pulls/" + str( obj.number ) ),
InternalSimpleAttributes(
"id", "url", "html_url", "diff_url", "patch_url", "issue_url", "number",
"state", "title", "body", "created_at", "updated_at", "closed_at",
@@ -335,6 +451,19 @@ PullRequest = GithubObject(
ElementGetable( [ "id" ], [], __modifyAttributesForObjectsReferingReferedRepo ),
ElementCreatable( [ "body", "commit_id", "path", "position" ], [], __modifyAttributesForObjectsReferingReferedRepo ),
),
MethodFromCallable( "is_merged", [], [], __pullRequestIsMerged, SimpleTypePolicy( "bool" ) ),
MethodFromCallable( "merge", [], [ "commit_message" ], __mergePullRequest, SimpleTypePolicy( None ) ),
)
RepositoryKey = GithubObject(
"RepositoryKey",
BaseUrl( lambda obj: obj._repo._baseUrl() + "/keys/" + str( obj.id ) ),
InternalSimpleAttributes(
"url", "id", "title", "key",
"_repo", ### Ugly hack
),
Editable( [ "title", "key" ], [] ),
Deletable()
)
Repository = GithubObject(
@@ -354,6 +483,26 @@ Repository = GithubObject(
)
Repository._addAttributePolicy( InternalObjectAttribute( "parent", Repository ) )
Repository._addAttributePolicy( InternalObjectAttribute( "source", Repository ) )
Repository._addAttributePolicy(
ExternalListOfObjects( "events", "event", Event,
ListGetable( [], [] )
),
)
def __getNetworkEvents( repo ):
return [
Event( repo._github, attributes, lazy = True )
for attributes
in repo._github._dataRequest( "GET", "/networks/" + repo.owner.login + "/" + repo.name + "/events", None, None )
]
Repository._addAttributePolicy(
MethodFromCallable( "get_network_events", [], [], __getNetworkEvents, SimpleTypePolicy( "list of `Event`" ) )
)
Repository._addAttributePolicy(
ExternalListOfObjects( "issues/events", "issues_event", IssueEvent,
ListGetable( [], [], __modifyAttributesForObjectsReferingRepo ),
ElementGetable( [ "id" ], [], __modifyAttributesForObjectsReferingRepo ),
)
)
Repository._addAttributePolicy(
ExternalListOfObjects( "forks", "fork", Repository,
ListGetable( [], [] )
@@ -366,6 +515,16 @@ Repository._addAttributePolicy(
SeveralAttributePolicies( [ ExternalSimpleAttribute( "languages", "dictionary of strings to integers" ) ], "Languages" )
)
Repository._addAttributePolicy( SeveralAttributePolicies( [
ExternalListOfObjects( "hooks", "hook", Hook,
ListGetable( [], [], __modifyAttributesForObjectsReferingRepo ),
ElementGetable( [ "id" ], [], __modifyAttributesForObjectsReferingRepo ),
ElementCreatable( [ "name", "config" ], [ "events", "active" ], __modifyAttributesForObjectsReferingRepo ),
),
ExternalListOfObjects( "keys", "key", RepositoryKey,
ListGetable( [], [], __modifyAttributesForObjectsReferingRepo ),
ElementGetable( [ "id" ], [], __modifyAttributesForObjectsReferingRepo ),
ElementCreatable( [ "title", "key" ], [], __modifyAttributesForObjectsReferingRepo ),
),
ExternalListOfObjects( "collaborators", "collaborator", NamedUser,
ListGetable( [], [] ),
ElementAddable(),
@@ -385,7 +544,7 @@ Repository._addAttributePolicy( SeveralAttributePolicies( [
),
ExternalListOfObjects( "git/commits", "git_commit", GitCommit,
ElementGetable( [ "sha" ], [], __modifyAttributesForObjectsReferingRepo ),
ElementCreatable( [ "message", "tree", "parents" ], [ "author", "commiter" ], __modifyAttributesForObjectsReferingRepo )
ElementCreatable( [ "message", "tree", "parents" ], [ "author", "committer" ], __modifyAttributesForObjectsReferingRepo )
),
ExternalListOfObjects( "git/trees", "git_tree", GitTree,
ElementGetable( [ "sha" ], [], __modifyAttributesForObjectsReferingRepo ),
@@ -435,7 +594,7 @@ Repository._addAttributePolicy( SeveralAttributePolicies( [
),
ExternalListOfObjects( "pulls", "pull", PullRequest,
ListGetable( [], [ "state" ], __modifyAttributesForObjectsReferingRepo ),
ElementGetable( [ "id" ], [], __modifyAttributesForObjectsReferingRepo ),
ElementGetable( [ "number" ], [], __modifyAttributesForObjectsReferingRepo ),
ElementCreatable( [ "title", "body", "base", "head" ], [], __modifyAttributesForObjectsReferingRepo ),
),
] ) )
@@ -480,11 +639,11 @@ NamedUser._addAttributePolicy(
def __createForkForUser( user, repo ):
assert isinstance( repo, Repository )
return Repository( user._github, user._github._dataRequest( "POST", repo._baseUrl + "/forks", None, None ), lazy = True )
return Repository( user._github, user._github._dataRequest( "POST", repo._baseUrl() + "/forks", None, None ), lazy = True )
AuthenticatedUser._addAttributePolicy( SeveralAttributePolicies( [ MethodFromCallable( "create_fork", [ "repo" ], [], __createForkForUser, ObjectTypePolicy( Repository ) ) ], "Forking" ) )
def __createForkForOrg( org, repo ):
assert isinstance( repo, Repository )
return Repository( org._github, org._github._dataRequest( "POST", repo._baseUrl + "/forks", { "org": org.login }, None ), lazy = True )
return Repository( org._github, org._github._dataRequest( "POST", repo._baseUrl() + "/forks", { "org": org.login }, None ), lazy = True )
Organization._addAttributePolicy( SeveralAttributePolicies( [ MethodFromCallable( "create_fork", [ "repo" ], [], __createForkForOrg, ObjectTypePolicy( Repository ) ) ], "Forking" ) )
Team = GithubObject(
@@ -521,3 +680,82 @@ Repository._addAttributePolicy(
ListGetable( [], [] )
)
)
GistComment = GithubObject(
"GistComment",
BaseUrl( lambda obj: "/gists/comments/" + str( obj.id ) ),
InternalSimpleAttributes(
"id", "url", "body", "created_at",
"updated_at",
),
InternalObjectAttribute( "user", NamedUser ),
Editable( [ "body" ], [] ),
Deletable(),
)
def __isStarred( gist ):
return gist._github._statusRequest( "GET", gist._baseUrl() + "/star", None, None ) == 204
def __setStarred( gist ):
gist._github._statusRequest( "PUT", gist._baseUrl() + "/star", None, None )
def __resetStarred( gist ):
gist._github._statusRequest( "DELETE", gist._baseUrl() + "/star", None, None )
Gist = GithubObject(
"Gist",
BaseUrl( lambda obj: "/gists/" + str( obj.id ) ),
InternalSimpleAttributes(
"url", "id", "description", "public", "files", "comments", "html_url",
"git_pull_url", "git_push_url", "created_at", "forks", "history",
"updated_at",
),
InternalObjectAttribute( "user", NamedUser ),
Editable( [], [ "description", "files" ] ),
Deletable(),
ExternalListOfObjects( "comments", "comment", GistComment,
ListGetable( [], [] ),
ElementGetable( [ "id" ], [] ),
ElementCreatable( [ "body" ], [] ),
),
SeveralAttributePolicies( [
MethodFromCallable( "is_starred", [], [], __isStarred, SimpleTypePolicy( "bool" ) ),
MethodFromCallable( "set_starred", [], [], __setStarred, SimpleTypePolicy( None ) ),
MethodFromCallable( "reset_starred", [], [], __resetStarred, SimpleTypePolicy( None ) ),
], "Starring" ),
)
def __createFork( gist ):
return Gist( gist._github, gist._github._dataRequest( "POST", gist._baseUrl() + "/fork", None, None ), lazy = True )
Gist._addAttributePolicy( SeveralAttributePolicies( [
MethodFromCallable( "create_fork", [], [], __createFork, ObjectTypePolicy( Gist ) ),
], "Forking" ),
)
NamedUser._addAttributePolicy(
ExternalListOfObjects( "gists", "gist", Gist,
ListGetable( [], [] ),
)
)
AuthenticatedUser._addAttributePolicy(
ExternalListOfObjects( "gists", "gist", Gist,
ListGetable( [], [] ),
ElementCreatable( [ "public", "files", ], [ "description" ] ),
url = "/gists",
)
)
def __getStaredGists( user ):
return [
Gist( user._github, attributes, lazy = True )
for attributes in user._github._dataRequest( "GET", "/gists/starred", None, None )
]
AuthenticatedUser._addAttributePolicy(
MethodFromCallable( "get_starred_gists", [], [], __getStaredGists, SimpleTypePolicy( "list of `Gist`" ) ),
)
Event._addAttributePolicy(
InternalObjectAttribute( "repo", Repository ),
)
Event._addAttributePolicy(
InternalObjectAttribute( "actor", NamedUser ),
)
Event._addAttributePolicy(
InternalObjectAttribute( "org", Organization ),
)
+2 -3
View File
@@ -24,7 +24,6 @@ class AttributeFromCallable:
def autoDocument( self ):
return ""
return "* `" + self.__name + "`\n"
### @todo include the ArgumentsChecker
class MethodFromCallable:
@@ -60,7 +59,7 @@ class InternalAttribute:
return self.__typePolicy.createLazy( obj, rawValue )
def updateAttributes( self, obj ):
attributes = obj._github._dataRequest( "GET", obj._baseUrl, None, None )
attributes = obj._github._dataRequest( "GET", obj._baseUrl(), None, None )
obj._updateAttributes( attributes )
obj._markAsCompleted()
@@ -94,7 +93,7 @@ class ExternalAttribute:
def __execute( self, obj ):
return self.__typePolicy.createLazy(
obj,
obj._github._dataRequest( "GET", obj._baseUrl + "/" + self.__attributeName, None, None )
obj._github._dataRequest( "GET", obj._baseUrl() + "/" + self.__attributeName, None, None )
)
def autoDocument( self ):
+39 -37
View File
@@ -5,12 +5,19 @@ from TypePolicies import *
from ArgumentsChecker import *
class ListCapacity:
def setList( self, attributeName, singularName, typePolicy ):
def setList( self, attributeName, singularName, typePolicy, url = None ):
self.attributeName = attributeName
self.singularName = singularName
self.safeAttributeName = attributeName.replace( "/", "_" )
self.safeSingularName = singularName.replace( "/", "_" )
self.typePolicy = typePolicy
self.__url = url
def baseUrl( self, obj ):
if self.__url is None:
return obj._baseUrl() + "/" + self.attributeName
else:
return self.__url
class ElementAddable( ListCapacity ):
def apply( self, cls ):
@@ -19,7 +26,7 @@ class ElementAddable( ListCapacity ):
def __execute( self, obj, toBeAdded ):
obj._github._statusRequest(
"PUT",
obj._baseUrl + "/" + self.attributeName + "/" + self.typePolicy.getIdentity( toBeAdded ),
self.baseUrl( obj ) + "/" + self.typePolicy.getIdentity( toBeAdded ),
None,
None
)
@@ -34,7 +41,7 @@ class ElementRemovable( ListCapacity ):
def __execute( self, obj, toBeDeleted ):
obj._github._statusRequest(
"DELETE",
obj._baseUrl + "/" + self.attributeName + "/" + self.typePolicy.getIdentity( toBeDeleted ),
self.baseUrl( obj ) + "/" + self.typePolicy.getIdentity( toBeDeleted ),
None,
None
)
@@ -49,48 +56,53 @@ class ElementHasable( ListCapacity ):
def __execute( self, obj, toBeQueried ):
return obj._github._statusRequest(
"GET",
obj._baseUrl + "/" + self.attributeName + "/" + self.typePolicy.getIdentity( toBeQueried ),
self.baseUrl( obj ) + "/" + self.typePolicy.getIdentity( toBeQueried ),
None,
None
) == 204
def autoDocument( self ):
### @todo `bool` -> bool
return "* `has_in_" + self.safeAttributeName + "( " + self.singularName + " )`: `bool`\n * `" + self.singularName + "`: " + self.typePolicy.documentTypeName() + "\n"
class ElementCreatable( ListCapacity ):
def __init__( self, mandatoryParameters, optionalParameters, attributeModifiers = {} ):
self.__argumentsChecker = ArgumentsChecker( mandatoryParameters, optionalParameters )
class ListCapacityWithModifier( ListCapacity ):
def __init__( self, attributeModifiers ):
self.__attributeModifiers = attributeModifiers
def _modifyAttributes( self, obj, attributes ):
for attributeName, attributeModifier in self.__attributeModifiers.iteritems():
attributes[ attributeName ] = attributeModifier( obj )
return attributes
class ElementCreatable( ListCapacityWithModifier ):
def __init__( self, mandatoryParameters, optionalParameters, attributeModifiers = {} ):
ListCapacityWithModifier.__init__( self, attributeModifiers )
self.__argumentsChecker = ArgumentsChecker( mandatoryParameters, optionalParameters )
def apply( self, cls ):
cls._addMethod( "create_" + self.singularName, self.__execute )
def __execute( self, obj, *args, **kwds ):
return self.typePolicy.createLazy(
obj,
self.__modifyAttributes(
self._modifyAttributes(
obj,
obj._github._dataRequest(
"POST",
obj._baseUrl + "/" + self.attributeName,
self.baseUrl( obj ),
None,
self.__argumentsChecker.check( args, kwds )
)
)
)
def __modifyAttributes( self, obj, attributes ):
for attributeName, attributeModifier in self.__attributeModifiers.iteritems():
attributes[ attributeName ] = attributeModifier( obj )
return attributes
def autoDocument( self ):
return "* `create_" + self.singularName + "(" + self.__argumentsChecker.documentParameters() + ")`: " + self.typePolicy.documentTypeName() + "\n"
class ElementGetable( ListCapacity ):
class ElementGetable( ListCapacityWithModifier ):
def __init__( self, mandatoryParameters, optionalParameters, attributeModifiers = {} ):
ListCapacityWithModifier.__init__( self, attributeModifiers )
self.__argumentsChecker = ArgumentsChecker( mandatoryParameters, optionalParameters )
self.__attributeModifiers = attributeModifiers
def apply( self, cls ):
cls._addMethod( "get_" + self.singularName, self.__execute )
@@ -98,17 +110,12 @@ class ElementGetable( ListCapacity ):
def __execute( self, obj, *args, **kwds ):
return self.typePolicy.createNonLazy(
obj,
self.__modifyAttributes(
self._modifyAttributes(
obj,
self.__argumentsChecker.check( args, kwds )
)
)
def __modifyAttributes( self, obj, attributes ):
for attributeName, attributeModifier in self.__attributeModifiers.iteritems():
attributes[ attributeName ] = attributeModifier( obj )
return attributes
def autoDocument( self ):
return "* `get_" + self.singularName + "(" + self.__argumentsChecker.documentParameters() + ")`: " + self.typePolicy.documentTypeName() + "\n"
@@ -119,7 +126,7 @@ class SeveralElementsAddable( ListCapacity ):
def __execute( self, obj, *toBeAddeds ):
obj._github._statusRequest(
"POST",
obj._baseUrl + "/" + self.attributeName,
self.baseUrl( obj ),
None,
[
self.typePolicy.getIdentity( toBeAdded )
@@ -137,7 +144,7 @@ class SeveralElementsRemovable( ListCapacity ):
def __execute( self, obj, *toBeDeleteds ):
obj._github._statusRequest(
"DELETE",
obj._baseUrl + "/" + self.attributeName,
self.baseUrl( obj ),
None,
[
self.typePolicy.getIdentity( toBeDeleted )
@@ -148,10 +155,10 @@ class SeveralElementsRemovable( ListCapacity ):
def autoDocument( self ):
return "* `remove_from_" + self.safeAttributeName + "( " + self.singularName + ", ... )`\n * `" + self.singularName + "`: " + self.typePolicy.documentTypeName() + "\n"
class ListGetable( ListCapacity ):
class ListGetable( ListCapacityWithModifier ):
def __init__( self, mandatoryParameters, optionalParameters, attributeModifiers = {} ):
ListCapacityWithModifier.__init__( self, attributeModifiers )
self.__argumentsChecker = ArgumentsChecker( mandatoryParameters, optionalParameters )
self.__attributeModifiers = attributeModifiers
def apply( self, cls ):
cls._addMethod( "get_" + self.safeAttributeName, self.__execute )
@@ -161,11 +168,11 @@ class ListGetable( ListCapacity ):
return [
self.typePolicy.createLazy(
obj,
self.__modifyAttributes( obj, attributes )
self._modifyAttributes( obj, attributes )
)
for attributes in obj._github._dataRequest(
"GET",
obj._baseUrl + "/" + self.attributeName,
self.baseUrl( obj ),
params,
None
)
@@ -174,11 +181,6 @@ class ListGetable( ListCapacity ):
def autoDocument( self ):
return "* `get_" + self.safeAttributeName + "(" + self.__argumentsChecker.documentParameters() + ")`: list of " + self.typePolicy.documentTypeName() + "\n"
def __modifyAttributes( self, obj, attributes ):
for attributeName, attributeModifier in self.__attributeModifiers.iteritems():
attributes[ attributeName ] = attributeModifier( obj )
return attributes
class ListSetable( ListCapacity ):
def apply( self, cls ):
cls._addMethod( "set_" + self.safeAttributeName, self.__execute )
@@ -186,7 +188,7 @@ class ListSetable( ListCapacity ):
def __execute( self, obj, *toBeSets ):
obj._github._statusRequest(
"PUT",
obj._baseUrl + "/" + self.attributeName,
self.baseUrl( obj ),
None,
[
self.typePolicy.getIdentity( toBeSet )
@@ -204,7 +206,7 @@ class ListDeletable( ListCapacity ):
def __execute( self, obj ):
obj._github._statusRequest(
"DELETE",
obj._baseUrl + "/" + self.attributeName,
self.baseUrl( obj ),
None,
None
)
@@ -212,9 +214,9 @@ class ListDeletable( ListCapacity ):
def autoDocument( self ):
return "* `delete_" + self.safeAttributeName + "()`\n"
def ExternalListOfObjects( attributeName, singularName, type, *capacities ):
def ExternalListOfObjects( attributeName, singularName, type, *capacities, **kwds ):
for capacity in capacities:
capacity.setList( attributeName, singularName, ObjectTypePolicy( type ) )
capacity.setList( attributeName, singularName, ObjectTypePolicy( type ), **kwds )
return SeveralAttributePolicies( capacities, attributeName.capitalize().replace( "_", " " ).replace( "/", " " ) )
def ExternalListOfSimpleTypes( attributeName, singularName, type, *capacities ):
+1 -4
View File
@@ -19,10 +19,7 @@ class ObjectTypePolicy:
self.__type = type
def createLazy( self, obj, attributes ):
if isinstance( attributes, self.__type ):
return attributes
else:
return self.__type( obj._github, attributes, lazy = True )
return self.__type( obj._github, attributes, lazy = True )
def createNonLazy( self, obj, attributes ):
return self.__type( obj._github, attributes, lazy = False )
+6
View File
@@ -55,4 +55,10 @@ class TestCase( unittest.TestCase ):
self.expect( "GET", "/test?page=3", 'null', 200, [ ( "link", "xxx; prev, xxx; first" ) ], '[ 5, 6 ]' )
self.assertEqual( self.r.dataRequest( "GET", "/test", None, None ), [ 1, 2, 3, 4, 5, 6 ] )
def testPaginationObviouslyFinished( self ):
self.expect( "GET", "/test", 'null', 200, [ ( "link", "<xxx?page=2>; next, xxx; last" ) ], '[ 1, 2 ]' )
self.expect( "GET", "/test?page=2", 'null', 200, [ ( "link", "xxx; prev, xxx; first, <xxx?page=3>; next, xxx; last" ) ], '[ 3, 4 ]' )
self.expect( "GET", "/test?page=3", 'null', 200, [ ( "link", "xxx; prev, xxx; first" ) ], '[]' )
self.assertEqual( self.r.dataRequest( "GET", "/test", None, None ), [ 1, 2, 3, 4 ] )
unittest.main()
+4 -1
View File
@@ -18,7 +18,8 @@ class Requester:
headers, output = self.__statusCheckedRequest( verb, url, parameters, input )
while "link" in headers and "next" in headers[ "link" ]:
obviouslyFinished = False
while "link" in headers and "next" in headers[ "link" ] and not obviouslyFinished:
for link in headers[ "link" ].split( "," ):
if "next" in link:
linkUrl = link.split( ";" )[ 0 ][ : -1 ]
@@ -26,6 +27,8 @@ class Requester:
parameters.update( dict( p.split( "=" ) for p in params.split( "&" ) ) )
break
headers, newOutput = self.__statusCheckedRequest( verb, url, parameters, input )
if len( newOutput ) == 0:
obviouslyFinished = True
output += newOutput
return output