diff --git a/github/GithubObject.UnitTest.py b/github/GithubObject.UnitTest.py index 0a9ea27f..ef7f2e92 100644 --- a/github/GithubObject.UnitTest.py +++ b/github/GithubObject.UnitTest.py @@ -100,6 +100,10 @@ class EditableGithubObject( TestCaseWithGithubTestObject ): with self.assertRaises( TypeError ): self.o.edit() + def testEditWithoutMandatoryArgument( self ): + with self.assertRaises( TypeError ): + self.o.edit( a2 = 2, a4 = 3 ) + def testEditWithSillyArgument( self ): with self.assertRaises( TypeError ): self.o.edit( foobar = 42 ) @@ -124,6 +128,10 @@ class EditableGithubObject( TestCaseWithGithubTestObject ): self.expectDataPatch( "/test", { "a1": 11 } ).andReturn( {} ) self.o.edit( 11 ) + def testEditWithRepeatedPositionalArgument( self ): + with self.assertRaises( TypeError ): + self.o.edit( 11, a1 = 11 ) + def testEditWithTwoPositionalArguments( self ): self.expectDataPatch( "/test", { "a1": 11, "a2": 22 } ).andReturn( {} ) self.o.edit( 11, 22 ) @@ -279,12 +287,32 @@ class GithubObjectWithModifiableListOfObjects( TestCaseWithGithubTestObject ): "GithubTestObject", BaseUrl( lambda obj: "/test" ), BasicAttributes( "a1", "a2" ), - ListOfObjects( "a3s", ContainedObject, creatable = True ) + ListOfObjects( "a3s", ContainedObject, Creatable( "a3", [ "name" ], [ "p1", "p2" ] ) ) ) def testCreate( self ): self.expectDataPost( "/test/a3s", { "name": "nameCreate" } ).andReturn( { "id": "idCreate" } ) - self.assertEqual( self.o.create_a3s( name = "nameCreate" ).id, "idCreate" ) + self.assertEqual( self.o.create_a3( name = "nameCreate" ).id, "idCreate" ) + + def testCreateWithOptionalArguments( self ): + self.expectDataPost( "/test/a3s", { "name": "nameCreate", "p1": 1 } ).andReturn( { "id": "idCreate" } ) + self.assertEqual( self.o.create_a3( name = "nameCreate", p1 = 1 ).id, "idCreate" ) + self.expectDataPost( "/test/a3s", { "name": "nameCreate", "p2": 2 } ).andReturn( { "id": "idCreate" } ) + self.assertEqual( self.o.create_a3( name = "nameCreate", p2 = 2 ).id, "idCreate" ) + self.expectDataPost( "/test/a3s", { "name": "nameCreate", "p1": 1, "p2": 2 } ).andReturn( { "id": "idCreate" } ) + self.assertEqual( self.o.create_a3( name = "nameCreate", p2 = 2, p1 = 1 ).id, "idCreate" ) + + def testCreateWithPositionalArguments( self ): + self.expectDataPost( "/test/a3s", { "name": "nameCreate", "p1": 1 } ).andReturn( { "id": "idCreate" } ) + self.assertEqual( self.o.create_a3( "nameCreate", 1 ).id, "idCreate" ) + self.expectDataPost( "/test/a3s", { "name": "nameCreate", "p2": 2 } ).andReturn( { "id": "idCreate" } ) + self.assertEqual( self.o.create_a3( "nameCreate", p2 = 2 ).id, "idCreate" ) + self.expectDataPost( "/test/a3s", { "name": "nameCreate", "p1": 1, "p2": 2 } ).andReturn( { "id": "idCreate" } ) + self.assertEqual( self.o.create_a3( "nameCreate", 1, 2 ).id, "idCreate" ) + + def testCreateWithSillyArgument( self ): + with self.assertRaises( TypeError ): + self.o.create_a3( foobar = 42 ) class GithubObjectWithObjectGetter( TestCaseWithGithubTestObject ): ContainedObject = GithubObject( diff --git a/github/GithubObject.py b/github/GithubObject.py index 4ade07dd..5aa5dca4 100644 --- a/github/GithubObject.py +++ b/github/GithubObject.py @@ -129,13 +129,20 @@ class ListOfReferences: assert isinstance( toBeQueried, self.__type ) return obj._github._statusRequest( "GET", obj._baseUrl + "/" + self.__attributeName + "/" + toBeQueried._identity, None, None ) == 204 +class Creatable: + def __init__( self, singularName, mandatoryParameters, optionalParameters ): + self.singularName = singularName + self.mandatoryParameters = mandatoryParameters + self.optionalParameters = optionalParameters + class ListOfObjects: - def __init__( self, attributeName, type, creatable = False, singularName = None ): + def __init__( self, attributeName, type, creatable = None ): self.__attributeName = attributeName self.__type = type self.__getName = "get_" + attributeName if creatable: - self.__createName = "create_" + ( singularName or attributeName ) + self.__createName = "create_" + creatable.singularName + self.__createArgumentsChecker = _ArgumentsChecker( creatable.mandatoryParameters, creatable.optionalParameters ) else: self.__createName = None @@ -150,7 +157,8 @@ class ListOfObjects: for attributes in obj._github._dataRequest( "GET", obj._baseUrl + "/" + self.__attributeName, None, None ) ] - def __executeCreate( self, obj, **data ): + def __executeCreate( self, obj, *args, **kwds ): + data = self.__createArgumentsChecker.check( args, kwds ) return self.__type( obj._github, obj._github._dataRequest( "POST", obj._baseUrl + "/" + self.__attributeName, None, data ), lazy = True ) class MethodFromCallable: @@ -161,21 +169,36 @@ class MethodFromCallable: def apply( self, cls ): cls._addMethod( self.__name, self.__callable ) -class Editable( MethodFromCallable ): +class _ArgumentsChecker: def __init__( self, mandatoryParameters, optionalParameters ): - MethodFromCallable.__init__( self, "edit", self.__execute ) self.__mandatoryParameters = mandatoryParameters self.__optionalParameters = optionalParameters - def __execute( self, obj, *args, **kwds ): + def check( self, args, kwds ): + data = dict( kwds ) if len( args ) + len( kwds ) == 0: raise TypeError() for arg, argumentName in itertools.izip( args, itertools.chain( self.__mandatoryParameters, self.__optionalParameters ) ): - kwds[ argumentName ] = arg - for argumentName in kwds: + if argumentName in kwds: + raise TypeError() + else: + data[ argumentName ] = arg + for argumentName in data: if argumentName not in itertools.chain( self.__mandatoryParameters, self.__optionalParameters ): raise TypeError() - attributes = obj._github._dataRequest( "PATCH", obj._baseUrl, None, kwds ) + for argumentName in self.__mandatoryParameters: + if argumentName not in data: + raise TypeError() + return data + +class Editable( MethodFromCallable ): + def __init__( self, mandatoryParameters, optionalParameters ): + MethodFromCallable.__init__( self, "edit", self.__execute ) + self.__argumentsChecker = _ArgumentsChecker( mandatoryParameters, optionalParameters ) + + def __execute( self, obj, *args, **kwds ): + data = self.__argumentsChecker.check( args, kwds ) + attributes = obj._github._dataRequest( "PATCH", obj._baseUrl, None, data ) obj._updateAttributes( attributes ) class Deletable( MethodFromCallable ): diff --git a/github/GithubObjects.py b/github/GithubObjects.py index 61a29701..d94f4402 100644 --- a/github/GithubObjects.py +++ b/github/GithubObjects.py @@ -80,9 +80,10 @@ Repository._addAttributePolicy( ComplexAttribute( "parent", Repository ) ) Repository._addAttributePolicy( ComplexAttribute( "source", Repository ) ) Repository._addAttributePolicy( ListOfReferences( "forks", Repository ) ) -AuthenticatedUser._addAttributePolicy( ListOfObjects( "repos", Repository, creatable = True, singularName = "repo" ) ) +__repoCreatable = Creatable( "repo", [ "name" ], [ "description", "homepage", "private", "has_issues", "has_wiki", "has_downloads", "team_id", ] ) +AuthenticatedUser._addAttributePolicy( ListOfObjects( "repos", Repository, __repoCreatable ) ) NamedUser._addAttributePolicy( ListOfObjects( "repos", Repository ) ) -Organization._addAttributePolicy( ListOfObjects( "repos", Repository, creatable = True, singularName = "repo" ) ) +Organization._addAttributePolicy( ListOfObjects( "repos", Repository, __repoCreatable ) ) AuthenticatedUser._addAttributePolicy( ObjectGetter( "repo", Repository, lambda user, name: { "name": name, "owner": { "login": user.login } } ) ) NamedUser._addAttributePolicy( ObjectGetter( "repo", Repository, lambda user, name: { "name": name, "owner": { "login": user.login } } ) )