Merge branch 'topic/AddIssues' into develop

This commit is contained in:
Vincent Jacques
2012-02-24 20:26:03 +00:00
8 changed files with 294 additions and 43 deletions
+27
View File
@@ -143,6 +143,8 @@ class IntegrationTest:
def doSomeWritesToRepository( self ):
u = self.g.get_user()
r = u.create_repo( name = "TestPyGithub", description = "Created by PyGithub", has_wiki = False )
# 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, [] )
@@ -153,6 +155,27 @@ class IntegrationTest:
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 )
# 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" )
self.dumpRepository( r )
def dumpUser( self, u ):
@@ -203,6 +226,10 @@ class IntegrationTest:
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
sys.stdout.flush()
+32 -32
View File
@@ -55,7 +55,7 @@ API `/gists/starred`
API `/issues`
=============
* GET: (TODO)
* GET: (TODO SOON)
API `/networks/:user/:repo/events`
==================================
@@ -235,39 +235,39 @@ API `/repos/:user/:repo/hooks/:id/test`
API `/repos/:user/:repo/issues`
===============================
* GET: (TODO)
* POST: (TODO)
* GET: `Repository.get_issues( ... )`: list of `Issue`
* POST: `Repository.create_issue( ... )`: `Issue`
API `/repos/:user/:repo/issues/:id`
===================================
* GET: (TODO)
* PATCH: (TODO)
* GET: `Repository.get_issue( id )`: `Issue`
* PATCH: `Issue.edit( ... )`
API `/repos/:user/:repo/issues/:id/comments`
============================================
* GET: (TODO)
* POST: (TODO)
* GET: `Issue.get_comments()`: list of `IssueComment`
* POST: `Issue.create_comment( ... )`: `IssueComment`
API `/repos/:user/:repo/issues/:id/labels`
==========================================
* GET: (TODO)
* POST: (TODO)
* PUT: (TODO)
* DELETE: (TODO)
* GET: `Issue.get_labels()`: list of `Label`
* POST: `Issue.add_to_labels( ... )`
* PUT: `Issue.set_labels( ... )`
* DELETE: `Issue.delete_labels()`
API `/repos/:user/:repo/issues/:id/labels/:id`
==============================================
* DELETE: (TODO)
API `/repos/:user/:repo/issues/:issue_id/events`
API `/repos/:user/:repo/issues/:id/labels/:name`
================================================
* DELETE: `Issue.remove_from_labels( name )`
API `/repos/:user/:repo/issues/:id/events`
==========================================
* GET: (TODO)
API `/repos/:user/:repo/issues/comments/:id`
============================================
* GET: (TODO)
* PATCH: (TODO)
* DELETE: (TODO)
* GET: `Issue.get_comment( id )`: `IssueComment`
* PATCH: `IssueComment.edit( ... )`
* DELETE: `IssueComment.delete( ... )`
API `/repos/:user/:repo/issues/events`
======================================
@@ -290,14 +290,14 @@ API `/repos/:user/:repo/keys/:id`
API `/repos/:user/:repo/labels`
===============================
* GET: (TODO)
* POST: (TODO)
* GET: `Repository.get_labels()`: list of `Label`
* POST: `Repository.create_label( ... )`: `Label`
API `/repos/:user/:repo/labels/:id`
===================================
* GET: (TODO)
* PATCH: (TODO)
* DELETE: (TODO)
* GET: `Repository.get_label( id )`: `Label`
* PATCH: `Label.edit( ... )`
* DELETE: `Label.delete()`
API `/repos/:user/:repo/languages`
==================================
@@ -305,18 +305,18 @@ API `/repos/:user/:repo/languages`
API `/repos/:user/:repo/milestones`
===================================
* GET: (TODO)
* POST: (TODO)
* GET: `Repository.get_milestones( ... )`: list of `Milestone`
* POST: `Repository.create_milestone( ... )`: `Milestone`
API `/repos/:user/:repo/milestones/:id`
API `/repos/:user/:repo/milestones/:number`
=======================================
* GET: (TODO)
* PATCH: (TODO)
* DELETE: (TODO)
* GET: `Repository.get_milestone( number )`: `Milestone`
* PATCH: `Milestone.edit( ... )`
* DELETE: `Milestone.delete()`
API `/repos/:user/:repo/milestones/:id/labels`
API `/repos/:user/:repo/milestones/:number/labels`
==============================================
* GET: (TODO)
* GET: `Milestone.get_labels()`: list of `Label`
API `/repos/:user/:repo/pulls`
==============================
+44
View File
@@ -137,6 +137,50 @@ Teams
-----
* `get_teams()`: list of `Team`
Issues and milestones
---------------------
* `get_labels()`: list of `Label`
* `create_label( ... )`: `Label`: see [API](http://developer.github.com/v3/issues/labels/#create-a-label) for parameters
* `get_label( id )`: `Label`
* `get_issues( ... )`: list of `Issue`: see [API](http://developer.github.com/v3/issues/#list-issues-for-a-repository) for parameters
* `create_issue( ... )`: `Issue`: see [API](http://developer.github.com/v3/issues/#create-an-issue) for parameters
* `get_issue( id )`: `Issue`
* `get_milestones( ... )`: list of `Milestone`: see [API](http://developer.github.com/v3/issues/milestones/#list-milestones-for-a-repository) for parameters
* `create_milestone( ... )`: `Milestone`: see [API](http://developer.github.com/v3/issues/milestones/#create-a-milestone) for parameters
* `get_milestone( number )`: `Milestone`
Class `Label`
=============
* Attributes: see [API](http://developer.github.com/v3/issues/labels/#get-a-single-label)
* `edit( ... )`: see [API](http://developer.github.com/v3/issues/labels/#update-a-label) for parameters
* `delete()`
Class `Issue`
=============
* Attributes: see [API](http://developer.github.com/v3/issues/#get-a-single-issue)
* `edit( ... )`: see [API](http://developer.github.com/v3/issues/#edit-an-issue) for parameters
* `get_labels()`: list of `Label`
* `add_to_labels( label, ... )`
* `set_labels( label, ... )`
* `delete_labels()`
* `remove_from_labels( label )`
* `get_comments()`: list of `IssueComment`
* `create_comment( ... )`: `IssueComment`: see [API](http://developer.github.com/v3/issues/comments/#create-a-comment) for parameters
* `get_comment( id )`: `IssueComment`
Class `IssueComment`
====================
* Attributes: see [API](http://developer.github.com/v3/issues/comments/#get-a-single-comment)
* `edit( ... )`: see [API](http://developer.github.com/v3/issues/comments/#edit-a-comment) for parameters
* `delete()`
Class `Milestone`
================
* Attributes: see [API](http://developer.github.com/v3/issues/milestones/#get-a-single-milestone)
* `edit( ... )`: see [API](http://developer.github.com/v3/issues/milestones/#update-a-milestone) for parameters
* `delete()`
* `get_labels()`: list of `Label`
Class `Team`
============
* Attributes: see [API](http://developer.github.com/v3/orgs/teams/#get-team)
+65 -2
View File
@@ -25,8 +25,8 @@ class TestCaseWithGithubTestObject( unittest.TestCase ):
def expectDataGet( self, url, arguments = None ):
return self.g.expect._dataRequest( "GET", url, arguments, None )
def expectStatusPut( self, url ):
return self.g.expect._statusRequest( "PUT", url, None, None )
def expectStatusPut( self, url, data = None ):
return self.g.expect._statusRequest( "PUT", url, None, data )
def expectStatusGet( self, url ):
return self.g.expect._statusRequest( "GET", url, None, None )
@@ -37,6 +37,9 @@ class TestCaseWithGithubTestObject( unittest.TestCase ):
def expectDataPost( self, url, data ):
return self.g.expect._dataRequest( "POST", url, None, data )
def expectStatusPost( self, url, data ):
return self.g.expect._statusRequest( "POST", url, None, data )
def expectStatusDelete( self, url ):
return self.g.expect._statusRequest( "DELETE", url, None, None )
@@ -194,6 +197,10 @@ class GithubObjectWithComplexAttribute( TestCaseWithGithubTestObject ):
self.expectDataGet( "/test/a3s/id1" ).andReturn( { "desc": "desc1" } )
self.assertEqual( self.o.a3.desc, "desc1" )
def testCompletionWithNone( self ):
self.expectDataGet( "/test" ).andReturn( { "a3": None } )
self.assertIsNone( self.o.a3 )
class GithubObjectWithListGetableList( TestCaseWithGithubTestObject ):
ContainedObject = GithubObject(
"ContainedObject",
@@ -322,6 +329,62 @@ class GithubObjectWithElementCreatableList( TestCaseWithGithubTestObject ):
with self.assertRaises( TypeError ):
self.o.create_a3( foobar = 42 )
class GithubObjectWithListAddableList( TestCaseWithGithubTestObject ):
ContainedObject = GithubObject(
"ContainedObject",
BaseUrl( lambda obj: "/test/a3s/" + obj.id ),
Identity( lambda obj: obj.id ),
BasicAttributes( "id", "name" )
)
GithubTestObject = GithubObject(
"GithubTestObject",
BaseUrl( lambda obj: "/test" ),
BasicAttributes( "a1", "a2" ),
ListAttribute( "a3s", ContainedObject, ListAddable() )
)
def testAddToList( self ):
self.expectStatusPost( "/test/a3s", [ "id1", "id2" ] )
self.o.add_to_a3s( self.ContainedObject( self.g, { "id": "id1" }, lazy = True ), self.ContainedObject( self.g, { "id": "id2" }, lazy = True ) )
class GithubObjectWithListSetableList( TestCaseWithGithubTestObject ):
ContainedObject = GithubObject(
"ContainedObject",
BaseUrl( lambda obj: "/test/a3s/" + obj.id ),
Identity( lambda obj: obj.id ),
BasicAttributes( "id", "name" )
)
GithubTestObject = GithubObject(
"GithubTestObject",
BaseUrl( lambda obj: "/test" ),
BasicAttributes( "a1", "a2" ),
ListAttribute( "a3s", ContainedObject, ListSetable() )
)
def testSetList( self ):
self.expectStatusPut( "/test/a3s", [ "id1", "id2" ] )
self.o.set_a3s( self.ContainedObject( self.g, { "id": "id1" }, lazy = True ), self.ContainedObject( self.g, { "id": "id2" }, lazy = True ) )
class GithubObjectWithListDeletableList( TestCaseWithGithubTestObject ):
ContainedObject = GithubObject(
"ContainedObject",
BaseUrl( lambda obj: "/test/a3s/" + obj.id ),
BasicAttributes( "id", "name" )
)
GithubTestObject = GithubObject(
"GithubTestObject",
BaseUrl( lambda obj: "/test" ),
BasicAttributes( "a1", "a2" ),
ListAttribute( "a3s", ContainedObject, ListDeletable() )
)
def testGetList( self ):
self.expectStatusDelete( "/test/a3s" )
self.o.delete_a3s()
class GithubObjectWithElementGetableList( TestCaseWithGithubTestObject ):
ContainedObject = GithubObject(
"ContainedObject",
+5 -2
View File
@@ -2,7 +2,7 @@ import itertools
import ObjectCapacities.ArgumentsChecker as ArgumentsChecker
from ObjectCapacities.Basic import AttributeFromCallable, MethodFromCallable
from ObjectCapacities.List import ListAttribute, ListGetable, ElementCreatable, ElementGetable, ElementAddable, ElementRemovable, ElementHasable
from ObjectCapacities.List import ListAttribute, ListGetable, ElementCreatable, ElementGetable, ElementAddable, ElementRemovable, ElementHasable, ListAddable, ListSetable, ListDeletable
class BadGithubObjectException( Exception ):
pass
@@ -38,7 +38,10 @@ class ComplexAttribute:
self.__type = type
def getValueFromRawValue( self, obj, rawValue ):
return self.__type( obj._github, rawValue, lazy = True )
if rawValue is None:
return None
else:
return self.__type( obj._github, rawValue, lazy = True )
def updateAttributes( self, obj ):
attributes = obj._github._dataRequest( "GET", obj._baseUrl, None, None )
+88 -7
View File
@@ -1,4 +1,5 @@
import itertools
import urllib
from GithubObject import *
@@ -115,7 +116,72 @@ GitTag = GithubObject(
),
)
__modifyAttributesForGitObjects = lambda obj, attributes: dict( itertools.chain( attributes.iteritems(), { "_repo": obj }.iteritems() ) )
Label = GithubObject(
"Label",
BaseUrl( lambda obj: obj._repo._baseUrl + "/labels/" + obj._identity ),
Identity( lambda obj: urllib.quote( obj.name ) ),
BasicAttributes(
"url", "name", "color",
"_repo", ### Ugly hack
),
Editable( [ "name", "color" ], [] ),
Deletable(),
)
Milestone = GithubObject(
"Milestone",
BaseUrl( lambda obj: obj._repo._baseUrl + "/milestones/" + str( obj.number ) ),
BasicAttributes(
"url", "number", "state", "title", "description", "open_issues",
"closed_issues", "created_at", "due_on",
"_repo", ### Ugly hack
),
ComplexAttribute( "creator", NamedUser ),
Editable( [ "title" ], [ "state", "description", "due_on" ] ),
Deletable(),
ListAttribute( "labels", Label, ListGetable( [], [], lambda obj, attributes: dict( itertools.chain( attributes.iteritems(), { "_repo": obj._repo }.iteritems() ) ) ) ),
)
IssueComment = GithubObject(
"IssueComment",
BaseUrl( lambda obj: obj._repo._baseUrl + "/issues/comment" + str( obj.id ) ),
BasicAttributes(
"url", "body", "created_at", "updated_at", "id",
"_repo", ### Ugly hack
),
ComplexAttribute( "user", NamedUser ),
Editable( [ "body" ], [] ),
Deletable(),
)
Issue = GithubObject(
"Issue",
BaseUrl( lambda obj: obj._repo._baseUrl + "/issues/" + str( obj.number ) ),
BasicAttributes(
"url", "html_url", "number", "state", "title", "body", "labels",
"comments", "closed_at", "created_at", "updated_at", "id", "closed_by",
"pull_request", ### @todo Structure
"_repo", ### Ugly hack
),
ComplexAttribute( "user", NamedUser ),
ComplexAttribute( "assignee", NamedUser ),
ComplexAttribute( "milestone", Milestone ),
Editable( [], [ "title", "body", "assignee", "state", "milestone", "labels" ] ),
ListAttribute( "labels", Label,
ListGetable( [], [], lambda obj, attributes: dict( itertools.chain( attributes.iteritems(), { "_repo": obj._repo }.iteritems() ) ) ),
ListAddable(),
ListSetable(),
ListDeletable(),
ElementRemovable(),
),
ListAttribute( "comments", IssueComment,
ListGetable( [], [], lambda obj, attributes: dict( itertools.chain( attributes.iteritems(), { "_repo": obj._repo }.iteritems() ) ) ),
ElementGetable( "comment", lambda repo, id: { "_repo": repo, "id": id } ),
ElementCreatable( "comment", [ "body" ], [], lambda obj, attributes: dict( itertools.chain( attributes.iteritems(), { "_repo": obj._repo }.iteritems() ) ) ),
),
)
__modifyAttributesForObjectsReferingRepo = lambda obj, attributes: dict( itertools.chain( attributes.iteritems(), { "_repo": obj }.iteritems() ) )
Repository = GithubObject(
"Repository",
BaseUrl( lambda obj: "/repos/" + obj.owner.login + "/" + obj.name ),
@@ -135,25 +201,40 @@ Repository = GithubObject(
ListAttribute( "watchers", NamedUser, ListGetable( [], [] ) ),
Editable( [ "name" ], [ "description", "homepage", "public", "has_issues", "has_wiki", "has_downloads" ] ),
ListAttribute( "git/refs", GitRef,
ListGetable( [], [], __modifyAttributesForGitObjects ),
ListGetable( [], [], __modifyAttributesForObjectsReferingRepo ),
ElementGetable( "git_ref", lambda repo, ref: { "_repo": repo, "ref": ref } ),
ElementCreatable( "git_ref", [ "ref", "sha" ], [], __modifyAttributesForGitObjects )
ElementCreatable( "git_ref", [ "ref", "sha" ], [], __modifyAttributesForObjectsReferingRepo )
),
ListAttribute( "git/commits", GitCommit,
ElementGetable( "git_commit", lambda repo, sha: { "_repo": repo, "sha": sha } ),
ElementCreatable( "git_commit", [ "message", "tree", "parents" ], [ "author", "commiter" ], __modifyAttributesForGitObjects )
ElementCreatable( "git_commit", [ "message", "tree", "parents" ], [ "author", "commiter" ], __modifyAttributesForObjectsReferingRepo )
),
ListAttribute( "git/trees", GitTree,
ElementGetable( "git_tree", lambda repo, sha: { "_repo": repo, "sha": sha } ),
ElementCreatable( "git_tree", [ "tree" ], [], __modifyAttributesForGitObjects )
ElementCreatable( "git_tree", [ "tree" ], [], __modifyAttributesForObjectsReferingRepo )
),
ListAttribute( "git/blobs", GitBlob,
ElementGetable( "git_blob", lambda repo, sha: { "_repo": repo, "sha": sha } ),
ElementCreatable( "git_blob", [ "content", "encoding" ], [], __modifyAttributesForGitObjects )
ElementCreatable( "git_blob", [ "content", "encoding" ], [], __modifyAttributesForObjectsReferingRepo )
),
ListAttribute( "git/tags", GitTag,
ElementGetable( "git_tag", lambda repo, sha: { "_repo": repo, "sha": sha } ),
ElementCreatable( "git_tag", [ "tag", "message", "object", "type" ], [ "tagger" ], __modifyAttributesForGitObjects )
ElementCreatable( "git_tag", [ "tag", "message", "object", "type" ], [ "tagger" ], __modifyAttributesForObjectsReferingRepo )
),
ListAttribute( "labels", Label,
ListGetable( [], [], __modifyAttributesForObjectsReferingRepo ),
ElementGetable( "label", lambda repo, name: { "_repo": repo, "name": name } ),
ElementCreatable( "label", [ "name", "color" ], [], __modifyAttributesForObjectsReferingRepo ),
),
ListAttribute( "milestones", Milestone,
ListGetable( [], [ "state", "sort", "direction" ], __modifyAttributesForObjectsReferingRepo ),
ElementGetable( "milestone", lambda repo, number: { "_repo": repo, "number": number } ),
ElementCreatable( "milestone", [ "title" ], [ "state", "description", "due_on" ], __modifyAttributesForObjectsReferingRepo )
),
ListAttribute( "issues", Issue,
ListGetable( [], [ "milestone", "state", "assignee", "mentioned", "labels", "sort", "direction", "since" ], __modifyAttributesForObjectsReferingRepo ),
ElementGetable( "issue", lambda repo, number: { "_repo": repo, "number": number } ),
ElementCreatable( "issue", [ "title" ], [ "body", "assignee", "milestone", "labels", ], __modifyAttributesForObjectsReferingRepo )
),
)
Repository._addAttributePolicy( ComplexAttribute( "parent", Repository ) )
+31
View File
@@ -77,6 +77,37 @@ class ElementGetable:
def __execute( self, obj, *args, **kwds ):
return self.__type( obj._github, self.__attributes( obj, *args, **kwds ), lazy = False )
class ListAddable:
def apply( self, list, cls ):
self.__type = list.type
self.__attributeName = list.attributeName
cls._addMethod( "add_to_" + list.attributeName.replace( "/", "_" ), self.__execute )
def __execute( self, obj, *toBeAddeds ):
for toBeAdded in toBeAddeds:
assert isinstance( toBeAdded, self.__type )
obj._github._statusRequest( "POST", obj._baseUrl + "/" + self.__attributeName, None, [ toBeAdded._identity for toBeAdded in toBeAddeds ] )
class ListSetable:
def apply( self, list, cls ):
self.__type = list.type
self.__attributeName = list.attributeName
cls._addMethod( "set_" + list.attributeName.replace( "/", "_" ), self.__execute )
def __execute( self, obj, *toBeSets ):
for toBeSet in toBeSets:
assert isinstance( toBeSet, self.__type )
obj._github._statusRequest( "PUT", obj._baseUrl + "/" + self.__attributeName, None, [ toBeSet._identity for toBeSet in toBeSets ] )
class ListDeletable:
def apply( self, list, cls ):
self.__type = list.type
self.__attributeName = list.attributeName
cls._addMethod( "delete_" + list.attributeName.replace( "/", "_" ), self.__execute )
def __execute( self, obj ):
obj._github._statusRequest( "DELETE", obj._baseUrl + "/" + self.__attributeName, None, None )
class ListAttribute:
def __init__( self, attributeName, type, *capacities ):
self.attributeName = attributeName
+2
View File
@@ -1,3 +1,5 @@
### @todo Add a copyright and license notice in all files
import httplib
import json
import base64