mirror of
https://github.com/status-im/PyGithub.git
synced 2026-08-31 10:51:14 +00:00
dos2unix
This commit is contained in:
@@ -1,24 +1,24 @@
|
||||
Object:
|
||||
- GET-able or not: lazy on attribute reading
|
||||
- PATCH-able or not: object.edit( ... )
|
||||
- DELETE-able or not: object.delete()
|
||||
- has attributes
|
||||
- scalars (in the GET for the object)
|
||||
- lists (in a specific GET)
|
||||
|
||||
Scalar:
|
||||
- fondamental type or objet
|
||||
|
||||
List:
|
||||
- contains fondamental type or objet
|
||||
- GET-able or not
|
||||
- elements GET-able or not
|
||||
- to ask if an element is in the list
|
||||
- elements PUT-able or not
|
||||
- add an existing element to the list: parent.add_to_elements( element )
|
||||
- POST-able or not
|
||||
- create a new element and add it to the list: parent.create_element( ... )
|
||||
- elements DELETE-able or not
|
||||
- delete an element from a list can have two meanings:
|
||||
- the element's life is finished: element.delete()
|
||||
- the element is just removed from the list, but continues to live somewhere else: parent.remove_from_elements( element )
|
||||
Object:
|
||||
- GET-able or not: lazy on attribute reading
|
||||
- PATCH-able or not: object.edit( ... )
|
||||
- DELETE-able or not: object.delete()
|
||||
- has attributes
|
||||
- scalars (in the GET for the object)
|
||||
- lists (in a specific GET)
|
||||
|
||||
Scalar:
|
||||
- fondamental type or objet
|
||||
|
||||
List:
|
||||
- contains fondamental type or objet
|
||||
- GET-able or not
|
||||
- elements GET-able or not
|
||||
- to ask if an element is in the list
|
||||
- elements PUT-able or not
|
||||
- add an existing element to the list: parent.add_to_elements( element )
|
||||
- POST-able or not
|
||||
- create a new element and add it to the list: parent.create_element( ... )
|
||||
- elements DELETE-able or not
|
||||
- delete an element from a list can have two meanings:
|
||||
- the element's life is finished: element.delete()
|
||||
- the element is just removed from the list, but continues to live somewhere else: parent.remove_from_elements( element )
|
||||
|
||||
+27
-27
@@ -1,27 +1,27 @@
|
||||
Documentation
|
||||
=============
|
||||
- tutorial
|
||||
- classes for Github objects
|
||||
- how to get instances of them
|
||||
- properties
|
||||
- methods (and arguments)
|
||||
- api and how it is wrapped
|
||||
- rationale:
|
||||
- lazyness for objects returned by API, not for objects requested by user
|
||||
- naming: get_xxx() to avoid clashes with attribute xxx (User.followers for example), and to explicit api calls. One get_ <=> one api call. No get_ <=> no api call, most often, and one from time to time to complete an object.
|
||||
- lazy completion, but no caching
|
||||
- explicit edit instead of writeable attributes
|
||||
- data model (cf Design.md)
|
||||
|
||||
Functional improvements
|
||||
=======================
|
||||
- implement the full API
|
||||
- add a full example creating your github graph (listing followers, following, co-contributors, watched repositories, organization co-members, etc.)
|
||||
|
||||
Technical improvements
|
||||
======================
|
||||
- Anything.edit shall read the response data and update the object's attributes
|
||||
- improve rawRequest
|
||||
- pagination
|
||||
- http status
|
||||
- privatize private methods/hide them behind facade/do something
|
||||
Documentation
|
||||
=============
|
||||
- tutorial
|
||||
- classes for Github objects
|
||||
- how to get instances of them
|
||||
- properties
|
||||
- methods (and arguments)
|
||||
- api and how it is wrapped
|
||||
- rationale:
|
||||
- lazyness for objects returned by API, not for objects requested by user
|
||||
- naming: get_xxx() to avoid clashes with attribute xxx (User.followers for example), and to explicit api calls. One get_ <=> one api call. No get_ <=> no api call, most often, and one from time to time to complete an object.
|
||||
- lazy completion, but no caching
|
||||
- explicit edit instead of writeable attributes
|
||||
- data model (cf Design.md)
|
||||
|
||||
Functional improvements
|
||||
=======================
|
||||
- implement the full API
|
||||
- add a full example creating your github graph (listing followers, following, co-contributors, watched repositories, organization co-members, etc.)
|
||||
|
||||
Technical improvements
|
||||
======================
|
||||
- Anything.edit shall read the response data and update the object's attributes
|
||||
- improve rawRequest
|
||||
- pagination
|
||||
- http status
|
||||
- privatize private methods/hide them behind facade/do something
|
||||
|
||||
+240
-240
@@ -1,240 +1,240 @@
|
||||
import unittest
|
||||
import MockMockMock
|
||||
|
||||
from GithubObject import *
|
||||
|
||||
class GithubObjectTestCase( unittest.TestCase ):
|
||||
def testDuplicatedAttributeInOnePolicy( self ):
|
||||
with self.assertRaises( BadGithubObjectException ):
|
||||
GithubObject( "", BasicAttributes( "a", "a" ) )
|
||||
|
||||
def testDuplicatedAttributeInTwoPolicies( self ):
|
||||
with self.assertRaises( BadGithubObjectException ):
|
||||
GithubObject( "", BasicAttributes( "a" ), BasicAttributes( "a" ) )
|
||||
|
||||
class TestCaseWithGithubTestObject( unittest.TestCase ):
|
||||
def setUp( self ):
|
||||
unittest.TestCase.setUp( self )
|
||||
self.g = MockMockMock.Mock( "github" )
|
||||
self.o = self.GithubTestObject( self.g.object, { "a1": 1, "a2": 2 }, lazy = True )
|
||||
|
||||
def tearDown( self ):
|
||||
self.g.tearDown()
|
||||
unittest.TestCase.tearDown( self )
|
||||
|
||||
def expectDataGet( self, url ):
|
||||
return self.g.expect._dataRequest( "GET", url )
|
||||
|
||||
def expectStatusPut( self, url ):
|
||||
return self.g.expect._statusRequest( "PUT", url )
|
||||
|
||||
def expectStatusGet( self, url ):
|
||||
return self.g.expect._statusRequest( "GET", url )
|
||||
|
||||
def expectDataPatch( self, url, data ):
|
||||
return self.g.expect._dataRequest( "PATCH", url, data )
|
||||
|
||||
def expectStatusDelete( self, url ):
|
||||
return self.g.expect._statusRequest( "DELETE", url )
|
||||
|
||||
class GithubObjectWithOnlyBasicAttributes( TestCaseWithGithubTestObject ):
|
||||
GithubTestObject = GithubObject(
|
||||
"GithubTestObject",
|
||||
BaseUrl( lambda obj: "/test" ),
|
||||
BasicAttributes( "a1", "a2", "a3", "a4" )
|
||||
)
|
||||
|
||||
def testInterface( self ):
|
||||
self.assertEqual( [ e for e in dir( self.o ) if not e.startswith( "_" ) ], [ "a1", "a2", "a3", "a4" ] )
|
||||
|
||||
def testCompletion( self ):
|
||||
# A GithubObject:
|
||||
# - knows the attributes given to its constructor
|
||||
self.assertEqual( self.o.a1, 1 )
|
||||
self.assertEqual( self.o.a2, 2 )
|
||||
# - is completed the first time any unknown attribute is requested
|
||||
self.expectDataGet( "/test" ).andReturn( { "a2": 22, "a3": 3 } )
|
||||
self.assertEqual( self.o.a3, 3 )
|
||||
# - remembers the attributes that were not updated
|
||||
self.assertEqual( self.o.a1, 1 )
|
||||
# - acknowledges updates of attributes
|
||||
self.assertEqual( self.o.a2, 22 )
|
||||
# - remembers that some attributes are absent even after an update
|
||||
self.assertEqual( self.o.a4, None )
|
||||
|
||||
def testUnknownAttribute( self ):
|
||||
self.assertRaises( AttributeError, lambda: self.o.foobar )
|
||||
|
||||
def testNonLazyConstruction( self ):
|
||||
self.expectDataGet( "/test" ).andReturn( { "a2": 2, "a3": 3 } )
|
||||
o = self.GithubTestObject( self.g.object, {}, lazy = False )
|
||||
self.g.tearDown()
|
||||
self.assertEqual( o.a1, None )
|
||||
self.assertEqual( o.a2, 2 )
|
||||
self.assertEqual( o.a3, 3 )
|
||||
self.assertEqual( o.a4, None )
|
||||
|
||||
class GithubObjectWithOtherBaseUrl( TestCaseWithGithubTestObject ):
|
||||
GithubTestObject = GithubObject(
|
||||
"GithubTestObject",
|
||||
BaseUrl( lambda obj: "/other/" + str( obj.a1 ) ),
|
||||
BasicAttributes( "a1", "a2", "a3", "a4" )
|
||||
)
|
||||
|
||||
def testCompletion( self ):
|
||||
self.expectDataGet( "/other/1" ).andReturn( { "a2": 22, "a3": 3 } )
|
||||
self.assertEqual( self.o.a3, 3 )
|
||||
|
||||
class EditableGithubObject( TestCaseWithGithubTestObject ):
|
||||
GithubTestObject = GithubObject(
|
||||
"GithubTestObject",
|
||||
BaseUrl( lambda obj: "/test" ),
|
||||
BasicAttributes( "a1", "a2", "a3", "a4" ),
|
||||
Editable( [ "a1" ], [ "a2", "a4" ] ),
|
||||
)
|
||||
|
||||
def testEditWithoutArgument( self ):
|
||||
with self.assertRaises( TypeError ):
|
||||
self.o.edit()
|
||||
|
||||
def testEditWithSillyArgument( self ):
|
||||
with self.assertRaises( TypeError ):
|
||||
self.o.edit( foobar = 42 )
|
||||
|
||||
def testEditWithOneKeywordArgument( self ):
|
||||
self.expectDataPatch( "/test", { "a1": 11 } ).andReturn( {} )
|
||||
self.o.edit( a1 = 11 )
|
||||
|
||||
def testEditWithTwoKeywordArguments( self ):
|
||||
self.expectDataPatch( "/test", { "a1": 11, "a2": 22 } ).andReturn( {} )
|
||||
self.o.edit( a1 = 11, a2 = 22 )
|
||||
|
||||
def testEditWithTwoKeywordArgumentsSkipingFirstOptionalArgument( self ):
|
||||
self.expectDataPatch( "/test", { "a1": 11, "a4": 44 } ).andReturn( {} )
|
||||
self.o.edit( a1 = 11, a4 = 44 )
|
||||
|
||||
def testEditWithThreeKeywordArguments( self ):
|
||||
self.expectDataPatch( "/test", { "a1": 11, "a2": 22, "a4": 44 } ).andReturn( {} )
|
||||
self.o.edit( a1 = 11, a4 = 44, a2 = 22 )
|
||||
|
||||
def testEditWithOnePositionalArgument( self ):
|
||||
self.expectDataPatch( "/test", { "a1": 11 } ).andReturn( {} )
|
||||
self.o.edit( 11 )
|
||||
|
||||
def testEditWithTwoPositionalArguments( self ):
|
||||
self.expectDataPatch( "/test", { "a1": 11, "a2": 22 } ).andReturn( {} )
|
||||
self.o.edit( 11, 22 )
|
||||
|
||||
def testEditWithThreePositionalArguments( self ):
|
||||
self.expectDataPatch( "/test", { "a1": 11, "a2": 22, "a4": 44 } ).andReturn( {} )
|
||||
self.o.edit( 11, 22, 44 )
|
||||
|
||||
def testEditWithMixedArguments_1( self ):
|
||||
self.expectDataPatch( "/test", { "a1": 11, "a2": 22 } ).andReturn( {} )
|
||||
self.o.edit( 11, a2 = 22 )
|
||||
|
||||
def testEditWithMixedArguments_2( self ):
|
||||
self.expectDataPatch( "/test", { "a1": 11, "a2": 22, "a4": 44 } ).andReturn( {} )
|
||||
self.o.edit( 11, a2 = 22, a4 = 44 )
|
||||
|
||||
def testEditWithMixedArguments_3( self ):
|
||||
self.expectDataPatch( "/test", { "a1": 11, "a2": 22, "a4": 44 } ).andReturn( {} )
|
||||
self.o.edit( 11, 22, a4 = 44 )
|
||||
|
||||
def testAcknoledgeUpdatesOfAttributes( self ):
|
||||
self.expectDataPatch( "/test", { "a1": 11 } ).andReturn( { "a2": 22, "a3": 3 } )
|
||||
self.o.edit( a1 = 11 )
|
||||
self.assertEqual( self.o.a1, 1 )
|
||||
self.assertEqual( self.o.a2, 22 )
|
||||
self.assertEqual( self.o.a3, 3 )
|
||||
self.expectDataGet( "/test" ).andReturn( {} )
|
||||
self.assertEqual( self.o.a4, None )
|
||||
|
||||
class DeletableGithubObject( TestCaseWithGithubTestObject ):
|
||||
GithubTestObject = GithubObject(
|
||||
"GithubTestObject",
|
||||
BaseUrl( lambda obj: "/test" ),
|
||||
BasicAttributes( "a1", "a2", "a3", "a4" ),
|
||||
Deletable(),
|
||||
)
|
||||
|
||||
def testDelete( self ):
|
||||
self.expectStatusDelete( "/test" ).andReturn( 204 )
|
||||
self.o.delete()
|
||||
|
||||
class GithubObjectWithComplexAttribute( TestCaseWithGithubTestObject ):
|
||||
ContainedObject = GithubObject(
|
||||
"ContainedObject",
|
||||
BaseUrl( lambda obj: "/test/a3s/" + obj.id ),
|
||||
BasicAttributes( "id", "name", "desc" )
|
||||
)
|
||||
|
||||
GithubTestObject = GithubObject(
|
||||
"GithubTestObject",
|
||||
BaseUrl( lambda obj: "/test" ),
|
||||
BasicAttributes( "a1", "a2" ),
|
||||
ComplexAttribute( "a3", ContainedObject )
|
||||
)
|
||||
|
||||
def testCompletion( self ):
|
||||
self.expectDataGet( "/test" ).andReturn( { "a3": { "id": "id1", "name": "name1" } } )
|
||||
self.assertEqual( self.o.a3.id, "id1" )
|
||||
self.assertEqual( self.o.a3.name, "name1" )
|
||||
self.expectDataGet( "/test/a3s/id1" ).andReturn( { "desc": "desc1" } )
|
||||
self.assertEqual( self.o.a3.desc, "desc1" )
|
||||
|
||||
class GithubObjectWithListOfReferences( TestCaseWithGithubTestObject ):
|
||||
ContainedObject = GithubObject(
|
||||
"ContainedObject",
|
||||
BaseUrl( lambda obj: "/test/a3s/" + obj.id ),
|
||||
BasicAttributes( "id", "name" )
|
||||
)
|
||||
|
||||
GithubTestObject = GithubObject(
|
||||
"GithubTestObject",
|
||||
BaseUrl( lambda obj: "/test" ),
|
||||
BasicAttributes( "a1", "a2" ),
|
||||
ListOfReferences( "a3s", ContainedObject )
|
||||
)
|
||||
|
||||
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.expectDataGet( "/test/a3s/id1" ).andReturn( { "name": "name1" } )
|
||||
self.assertEqual( a3s[ 0 ].name, "name1" )
|
||||
|
||||
class GithubObjectWithModifiableListOfReferences( 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" ),
|
||||
ListOfReferences( "a3s", ContainedObject, addable = True, removable = True, hasable = True )
|
||||
)
|
||||
|
||||
def testAddToList( self ):
|
||||
a3ToAdd = self.ContainedObject( self.g.object, { "id": "idAdd", "name": "nameAdd" }, lazy = True )
|
||||
self.expectStatusPut( "/test/a3s/idAdd" ).andReturn( 204 )
|
||||
self.o.add_to_a3s( a3ToAdd )
|
||||
|
||||
def testRemoveFromList( self ):
|
||||
a3ToRemove = self.ContainedObject( self.g.object, { "id": "idRemove", "name": "nameRemove" }, lazy = True )
|
||||
self.expectStatusDelete( "/test/a3s/idRemove" ).andReturn( 204 )
|
||||
self.o.remove_from_a3s( a3ToRemove )
|
||||
|
||||
def testHasInList( self ):
|
||||
a3ToQuery = self.ContainedObject( self.g.object, { "id": "idQuery", "name": "nameQuery" }, lazy = True )
|
||||
self.expectStatusGet( "/test/a3s/idQuery" ).andReturn( 204 )
|
||||
self.assertTrue( self.o.has_in_a3s( a3ToQuery ) )
|
||||
self.expectStatusGet( "/test/a3s/idQuery" ).andReturn( 404 )
|
||||
self.assertFalse( self.o.has_in_a3s( a3ToQuery ) )
|
||||
|
||||
unittest.main()
|
||||
import unittest
|
||||
import MockMockMock
|
||||
|
||||
from GithubObject import *
|
||||
|
||||
class GithubObjectTestCase( unittest.TestCase ):
|
||||
def testDuplicatedAttributeInOnePolicy( self ):
|
||||
with self.assertRaises( BadGithubObjectException ):
|
||||
GithubObject( "", BasicAttributes( "a", "a" ) )
|
||||
|
||||
def testDuplicatedAttributeInTwoPolicies( self ):
|
||||
with self.assertRaises( BadGithubObjectException ):
|
||||
GithubObject( "", BasicAttributes( "a" ), BasicAttributes( "a" ) )
|
||||
|
||||
class TestCaseWithGithubTestObject( unittest.TestCase ):
|
||||
def setUp( self ):
|
||||
unittest.TestCase.setUp( self )
|
||||
self.g = MockMockMock.Mock( "github" )
|
||||
self.o = self.GithubTestObject( self.g.object, { "a1": 1, "a2": 2 }, lazy = True )
|
||||
|
||||
def tearDown( self ):
|
||||
self.g.tearDown()
|
||||
unittest.TestCase.tearDown( self )
|
||||
|
||||
def expectDataGet( self, url ):
|
||||
return self.g.expect._dataRequest( "GET", url )
|
||||
|
||||
def expectStatusPut( self, url ):
|
||||
return self.g.expect._statusRequest( "PUT", url )
|
||||
|
||||
def expectStatusGet( self, url ):
|
||||
return self.g.expect._statusRequest( "GET", url )
|
||||
|
||||
def expectDataPatch( self, url, data ):
|
||||
return self.g.expect._dataRequest( "PATCH", url, data )
|
||||
|
||||
def expectStatusDelete( self, url ):
|
||||
return self.g.expect._statusRequest( "DELETE", url )
|
||||
|
||||
class GithubObjectWithOnlyBasicAttributes( TestCaseWithGithubTestObject ):
|
||||
GithubTestObject = GithubObject(
|
||||
"GithubTestObject",
|
||||
BaseUrl( lambda obj: "/test" ),
|
||||
BasicAttributes( "a1", "a2", "a3", "a4" )
|
||||
)
|
||||
|
||||
def testInterface( self ):
|
||||
self.assertEqual( [ e for e in dir( self.o ) if not e.startswith( "_" ) ], [ "a1", "a2", "a3", "a4" ] )
|
||||
|
||||
def testCompletion( self ):
|
||||
# A GithubObject:
|
||||
# - knows the attributes given to its constructor
|
||||
self.assertEqual( self.o.a1, 1 )
|
||||
self.assertEqual( self.o.a2, 2 )
|
||||
# - is completed the first time any unknown attribute is requested
|
||||
self.expectDataGet( "/test" ).andReturn( { "a2": 22, "a3": 3 } )
|
||||
self.assertEqual( self.o.a3, 3 )
|
||||
# - remembers the attributes that were not updated
|
||||
self.assertEqual( self.o.a1, 1 )
|
||||
# - acknowledges updates of attributes
|
||||
self.assertEqual( self.o.a2, 22 )
|
||||
# - remembers that some attributes are absent even after an update
|
||||
self.assertEqual( self.o.a4, None )
|
||||
|
||||
def testUnknownAttribute( self ):
|
||||
self.assertRaises( AttributeError, lambda: self.o.foobar )
|
||||
|
||||
def testNonLazyConstruction( self ):
|
||||
self.expectDataGet( "/test" ).andReturn( { "a2": 2, "a3": 3 } )
|
||||
o = self.GithubTestObject( self.g.object, {}, lazy = False )
|
||||
self.g.tearDown()
|
||||
self.assertEqual( o.a1, None )
|
||||
self.assertEqual( o.a2, 2 )
|
||||
self.assertEqual( o.a3, 3 )
|
||||
self.assertEqual( o.a4, None )
|
||||
|
||||
class GithubObjectWithOtherBaseUrl( TestCaseWithGithubTestObject ):
|
||||
GithubTestObject = GithubObject(
|
||||
"GithubTestObject",
|
||||
BaseUrl( lambda obj: "/other/" + str( obj.a1 ) ),
|
||||
BasicAttributes( "a1", "a2", "a3", "a4" )
|
||||
)
|
||||
|
||||
def testCompletion( self ):
|
||||
self.expectDataGet( "/other/1" ).andReturn( { "a2": 22, "a3": 3 } )
|
||||
self.assertEqual( self.o.a3, 3 )
|
||||
|
||||
class EditableGithubObject( TestCaseWithGithubTestObject ):
|
||||
GithubTestObject = GithubObject(
|
||||
"GithubTestObject",
|
||||
BaseUrl( lambda obj: "/test" ),
|
||||
BasicAttributes( "a1", "a2", "a3", "a4" ),
|
||||
Editable( [ "a1" ], [ "a2", "a4" ] ),
|
||||
)
|
||||
|
||||
def testEditWithoutArgument( self ):
|
||||
with self.assertRaises( TypeError ):
|
||||
self.o.edit()
|
||||
|
||||
def testEditWithSillyArgument( self ):
|
||||
with self.assertRaises( TypeError ):
|
||||
self.o.edit( foobar = 42 )
|
||||
|
||||
def testEditWithOneKeywordArgument( self ):
|
||||
self.expectDataPatch( "/test", { "a1": 11 } ).andReturn( {} )
|
||||
self.o.edit( a1 = 11 )
|
||||
|
||||
def testEditWithTwoKeywordArguments( self ):
|
||||
self.expectDataPatch( "/test", { "a1": 11, "a2": 22 } ).andReturn( {} )
|
||||
self.o.edit( a1 = 11, a2 = 22 )
|
||||
|
||||
def testEditWithTwoKeywordArgumentsSkipingFirstOptionalArgument( self ):
|
||||
self.expectDataPatch( "/test", { "a1": 11, "a4": 44 } ).andReturn( {} )
|
||||
self.o.edit( a1 = 11, a4 = 44 )
|
||||
|
||||
def testEditWithThreeKeywordArguments( self ):
|
||||
self.expectDataPatch( "/test", { "a1": 11, "a2": 22, "a4": 44 } ).andReturn( {} )
|
||||
self.o.edit( a1 = 11, a4 = 44, a2 = 22 )
|
||||
|
||||
def testEditWithOnePositionalArgument( self ):
|
||||
self.expectDataPatch( "/test", { "a1": 11 } ).andReturn( {} )
|
||||
self.o.edit( 11 )
|
||||
|
||||
def testEditWithTwoPositionalArguments( self ):
|
||||
self.expectDataPatch( "/test", { "a1": 11, "a2": 22 } ).andReturn( {} )
|
||||
self.o.edit( 11, 22 )
|
||||
|
||||
def testEditWithThreePositionalArguments( self ):
|
||||
self.expectDataPatch( "/test", { "a1": 11, "a2": 22, "a4": 44 } ).andReturn( {} )
|
||||
self.o.edit( 11, 22, 44 )
|
||||
|
||||
def testEditWithMixedArguments_1( self ):
|
||||
self.expectDataPatch( "/test", { "a1": 11, "a2": 22 } ).andReturn( {} )
|
||||
self.o.edit( 11, a2 = 22 )
|
||||
|
||||
def testEditWithMixedArguments_2( self ):
|
||||
self.expectDataPatch( "/test", { "a1": 11, "a2": 22, "a4": 44 } ).andReturn( {} )
|
||||
self.o.edit( 11, a2 = 22, a4 = 44 )
|
||||
|
||||
def testEditWithMixedArguments_3( self ):
|
||||
self.expectDataPatch( "/test", { "a1": 11, "a2": 22, "a4": 44 } ).andReturn( {} )
|
||||
self.o.edit( 11, 22, a4 = 44 )
|
||||
|
||||
def testAcknoledgeUpdatesOfAttributes( self ):
|
||||
self.expectDataPatch( "/test", { "a1": 11 } ).andReturn( { "a2": 22, "a3": 3 } )
|
||||
self.o.edit( a1 = 11 )
|
||||
self.assertEqual( self.o.a1, 1 )
|
||||
self.assertEqual( self.o.a2, 22 )
|
||||
self.assertEqual( self.o.a3, 3 )
|
||||
self.expectDataGet( "/test" ).andReturn( {} )
|
||||
self.assertEqual( self.o.a4, None )
|
||||
|
||||
class DeletableGithubObject( TestCaseWithGithubTestObject ):
|
||||
GithubTestObject = GithubObject(
|
||||
"GithubTestObject",
|
||||
BaseUrl( lambda obj: "/test" ),
|
||||
BasicAttributes( "a1", "a2", "a3", "a4" ),
|
||||
Deletable(),
|
||||
)
|
||||
|
||||
def testDelete( self ):
|
||||
self.expectStatusDelete( "/test" ).andReturn( 204 )
|
||||
self.o.delete()
|
||||
|
||||
class GithubObjectWithComplexAttribute( TestCaseWithGithubTestObject ):
|
||||
ContainedObject = GithubObject(
|
||||
"ContainedObject",
|
||||
BaseUrl( lambda obj: "/test/a3s/" + obj.id ),
|
||||
BasicAttributes( "id", "name", "desc" )
|
||||
)
|
||||
|
||||
GithubTestObject = GithubObject(
|
||||
"GithubTestObject",
|
||||
BaseUrl( lambda obj: "/test" ),
|
||||
BasicAttributes( "a1", "a2" ),
|
||||
ComplexAttribute( "a3", ContainedObject )
|
||||
)
|
||||
|
||||
def testCompletion( self ):
|
||||
self.expectDataGet( "/test" ).andReturn( { "a3": { "id": "id1", "name": "name1" } } )
|
||||
self.assertEqual( self.o.a3.id, "id1" )
|
||||
self.assertEqual( self.o.a3.name, "name1" )
|
||||
self.expectDataGet( "/test/a3s/id1" ).andReturn( { "desc": "desc1" } )
|
||||
self.assertEqual( self.o.a3.desc, "desc1" )
|
||||
|
||||
class GithubObjectWithListOfReferences( TestCaseWithGithubTestObject ):
|
||||
ContainedObject = GithubObject(
|
||||
"ContainedObject",
|
||||
BaseUrl( lambda obj: "/test/a3s/" + obj.id ),
|
||||
BasicAttributes( "id", "name" )
|
||||
)
|
||||
|
||||
GithubTestObject = GithubObject(
|
||||
"GithubTestObject",
|
||||
BaseUrl( lambda obj: "/test" ),
|
||||
BasicAttributes( "a1", "a2" ),
|
||||
ListOfReferences( "a3s", ContainedObject )
|
||||
)
|
||||
|
||||
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.expectDataGet( "/test/a3s/id1" ).andReturn( { "name": "name1" } )
|
||||
self.assertEqual( a3s[ 0 ].name, "name1" )
|
||||
|
||||
class GithubObjectWithModifiableListOfReferences( 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" ),
|
||||
ListOfReferences( "a3s", ContainedObject, addable = True, removable = True, hasable = True )
|
||||
)
|
||||
|
||||
def testAddToList( self ):
|
||||
a3ToAdd = self.ContainedObject( self.g.object, { "id": "idAdd", "name": "nameAdd" }, lazy = True )
|
||||
self.expectStatusPut( "/test/a3s/idAdd" ).andReturn( 204 )
|
||||
self.o.add_to_a3s( a3ToAdd )
|
||||
|
||||
def testRemoveFromList( self ):
|
||||
a3ToRemove = self.ContainedObject( self.g.object, { "id": "idRemove", "name": "nameRemove" }, lazy = True )
|
||||
self.expectStatusDelete( "/test/a3s/idRemove" ).andReturn( 204 )
|
||||
self.o.remove_from_a3s( a3ToRemove )
|
||||
|
||||
def testHasInList( self ):
|
||||
a3ToQuery = self.ContainedObject( self.g.object, { "id": "idQuery", "name": "nameQuery" }, lazy = True )
|
||||
self.expectStatusGet( "/test/a3s/idQuery" ).andReturn( 204 )
|
||||
self.assertTrue( self.o.has_in_a3s( a3ToQuery ) )
|
||||
self.expectStatusGet( "/test/a3s/idQuery" ).andReturn( 404 )
|
||||
self.assertFalse( self.o.has_in_a3s( a3ToQuery ) )
|
||||
|
||||
unittest.main()
|
||||
|
||||
+225
-225
@@ -1,225 +1,225 @@
|
||||
import itertools
|
||||
|
||||
class BadGithubObjectException( Exception ):
|
||||
pass
|
||||
|
||||
class BasicAttributes:
|
||||
class AttributeDefinition:
|
||||
def __init__( self, attributeNames ):
|
||||
self.__attributeNames = attributeNames
|
||||
|
||||
def getValueFromRawValue( self, obj, rawValue ):
|
||||
# if isinstance( rawValue, dict ):
|
||||
# print rawValue, "is a dict, you may want to use an extended attribute for it"
|
||||
return rawValue
|
||||
|
||||
def updateAttributes( self, obj ):
|
||||
attributes = obj._github._dataRequest( "GET", obj._baseUrl )
|
||||
for attributeName in self.__attributeNames:
|
||||
if attributeName not in attributes:
|
||||
attributes[ attributeName ] = None
|
||||
obj._updateAttributes( attributes )
|
||||
|
||||
def __init__( self, *attributeNames ):
|
||||
self.__attributeNames = attributeNames
|
||||
|
||||
def apply( self, cls ):
|
||||
commonDefinition = BasicAttributes.AttributeDefinition( self.__attributeNames )
|
||||
for attributeName in self.__attributeNames:
|
||||
cls._addAttribute( attributeName, commonDefinition )
|
||||
|
||||
class ListOfReferences:
|
||||
def __init__( self, attributeName, type, addable = False, removable = False, hasable = False ):
|
||||
self.__attributeName = attributeName
|
||||
self.__type = type
|
||||
self.__getName = "get_" + attributeName
|
||||
if addable:
|
||||
self.__addName = "add_to_" + attributeName
|
||||
else:
|
||||
self.__addName = None
|
||||
if removable:
|
||||
self.__removeName = "remove_from_" + attributeName
|
||||
else:
|
||||
self.__removeName = None
|
||||
if hasable:
|
||||
self.__hasName = "has_in_" + attributeName
|
||||
else:
|
||||
self.__hasName = None
|
||||
|
||||
def apply( self, cls ):
|
||||
cls._addMethod( self.__getName, self.__executeGet )
|
||||
if self.__addName is not None:
|
||||
cls._addMethod( self.__addName, self.__executeAdd )
|
||||
if self.__removeName is not None:
|
||||
cls._addMethod( self.__removeName, self.__executeRemove )
|
||||
if self.__hasName is not None:
|
||||
cls._addMethod( self.__hasName, self.__executeHas )
|
||||
|
||||
def __executeAdd( self, obj, toBeAdded ):
|
||||
assert( isinstance( toBeAdded, self.__type ) )
|
||||
obj._github._statusRequest( "PUT", obj._baseUrl + "/" + self.__attributeName + "/" + toBeAdded._identity )
|
||||
|
||||
def __executeRemove( self, obj, toBeDeleted ):
|
||||
assert( isinstance( toBeDeleted, self.__type ) )
|
||||
obj._github._statusRequest( "DELETE", obj._baseUrl + "/" + self.__attributeName + "/" + toBeDeleted._identity )
|
||||
|
||||
def __executeHas( self, obj, toBeQueried ):
|
||||
assert( isinstance( toBeQueried, self.__type ) )
|
||||
return obj._github._statusRequest( "GET", obj._baseUrl + "/" + self.__attributeName + "/" + toBeQueried._identity ) == 204
|
||||
|
||||
def __executeGet( self, obj ):
|
||||
return [
|
||||
self.__type( obj._github, attributes, lazy = True )
|
||||
for attributes in obj._github._dataRequest( "GET", obj._baseUrl + "/" + self.__attributeName )
|
||||
]
|
||||
|
||||
class ComplexAttribute:
|
||||
class AttributeDefinition:
|
||||
def __init__( self, attributeName, type ):
|
||||
self.__attributeName = attributeName
|
||||
self.__type = type
|
||||
|
||||
def getValueFromRawValue( self, obj, rawValue ):
|
||||
return self.__type( obj._github, rawValue, lazy = True )
|
||||
|
||||
def updateAttributes( self, obj ):
|
||||
attributes = obj._github._dataRequest( "GET", obj._baseUrl )
|
||||
# for attributeName in self.__attributeNames:
|
||||
# if attributeName not in attributes:
|
||||
# attributes[ attributeName ] = None
|
||||
obj._updateAttributes( attributes )
|
||||
|
||||
def __init__( self, attributeName, type ):
|
||||
self.__attributeName = attributeName
|
||||
self.__type = type
|
||||
|
||||
def apply( self, cls ):
|
||||
cls._addAttribute( self.__attributeName, ComplexAttribute.AttributeDefinition( self.__attributeName, self.__type ) )
|
||||
|
||||
class Editable:
|
||||
def __init__( self, mandatoryParameters, optionalParameters ):
|
||||
self.__mandatoryParameters = mandatoryParameters
|
||||
self.__optionalParameters = optionalParameters
|
||||
|
||||
def apply( self, cls ):
|
||||
cls._addMethod( "edit", self.__execute )
|
||||
|
||||
def __execute( self, obj, *args, **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 not in itertools.chain( self.__mandatoryParameters, self.__optionalParameters ):
|
||||
raise TypeError()
|
||||
attributes = obj._github._dataRequest( "PATCH", obj._baseUrl, kwds )
|
||||
obj._updateAttributes( attributes )
|
||||
|
||||
class Deletable:
|
||||
def apply( self, cls ):
|
||||
cls._addMethod( "delete", self.__execute )
|
||||
|
||||
def __execute( self, obj, *args, **kwds ):
|
||||
obj._github._statusRequest( "DELETE", obj._baseUrl )
|
||||
|
||||
class BaseUrl:
|
||||
class AttributeDefinition:
|
||||
def __init__( self, baseUrl ):
|
||||
self.__baseUrl = baseUrl
|
||||
|
||||
def getValueFromRawValue( self, obj, rawValue ):
|
||||
return rawValue
|
||||
|
||||
def updateAttributes( self, obj ):
|
||||
obj._updateAttributes( { "_baseUrl": self.__baseUrl( obj ) } )
|
||||
|
||||
def __init__( self, baseUrl ):
|
||||
self.__baseUrl = baseUrl
|
||||
|
||||
def apply( self, cls ):
|
||||
cls._addAttribute( "_baseUrl", BaseUrl.AttributeDefinition( self.__baseUrl ) )
|
||||
|
||||
class Identity:
|
||||
class AttributeDefinition:
|
||||
def __init__( self, identity ):
|
||||
self.__identity = identity
|
||||
|
||||
def getValueFromRawValue( self, obj, rawValue ):
|
||||
return rawValue
|
||||
|
||||
def updateAttributes( self, obj ):
|
||||
obj._updateAttributes( { "_identity": self.__identity( obj ) } )
|
||||
|
||||
def __init__( self, identity ):
|
||||
self.__identity = identity
|
||||
|
||||
def apply( self, cls ):
|
||||
cls._addAttribute( "_identity", Identity.AttributeDefinition( self.__identity ) )
|
||||
|
||||
def GithubObject( className, *attributePolicies ):
|
||||
class GithubObject:
|
||||
__attributeDefinitions = dict()
|
||||
__methodDefinitions = dict()
|
||||
|
||||
@staticmethod
|
||||
def _addAttributePolicies( attributePolicies ):
|
||||
for attributePolicy in attributePolicies:
|
||||
GithubObject._addAttributePolicy( attributePolicy )
|
||||
|
||||
@staticmethod
|
||||
def _addAttributePolicy( attributePolicy ):
|
||||
attributePolicy.apply( GithubObject )
|
||||
|
||||
@staticmethod
|
||||
def _addAttribute( attributeName, attributeDefinition ):
|
||||
if attributeName in GithubObject.__attributeDefinitions:
|
||||
raise BadGithubObjectException( "Same attribute defined by two policies" )
|
||||
else:
|
||||
GithubObject.__attributeDefinitions[ attributeName ] = attributeDefinition
|
||||
|
||||
@staticmethod
|
||||
def _addMethod( methodName, methodDefinition ):
|
||||
if methodName in GithubObject.__methodDefinitions:
|
||||
raise BadGithubObjectException( "Same method defined by two policies" )
|
||||
else:
|
||||
GithubObject.__methodDefinitions[ methodName ] = methodDefinition
|
||||
|
||||
def __init__( self, github, attributes, lazy ):
|
||||
self._github = github
|
||||
self.__attributes = dict()
|
||||
self._updateAttributes( attributes )
|
||||
if not lazy:
|
||||
for attributeName in GithubObject.__attributeDefinitions:
|
||||
if attributeName not in self.__attributes:
|
||||
self.__fetchAttribute( attributeName )
|
||||
|
||||
def __getattr__( self, attributeName ):
|
||||
if attributeName in GithubObject.__methodDefinitions:
|
||||
return lambda *args, **kwds: GithubObject.__methodDefinitions[ attributeName ]( self, *args, **kwds )
|
||||
elif attributeName in GithubObject.__attributeDefinitions:
|
||||
if attributeName not in self.__attributes:
|
||||
self.__fetchAttribute( attributeName )
|
||||
return self.__attributes[ attributeName ]
|
||||
else:
|
||||
raise AttributeError( attributeName )
|
||||
|
||||
def _updateAttributes( self, attributes ):
|
||||
for attributeName, attributeValue in attributes.iteritems():
|
||||
attributeDefinition = GithubObject.__attributeDefinitions[ attributeName ]
|
||||
if attributeValue is None:
|
||||
if attributeName not in self.__attributes:
|
||||
self.__attributes[ attributeName ] = None
|
||||
else:
|
||||
self.__attributes[ attributeName ] = attributeDefinition.getValueFromRawValue( self, attributeValue )
|
||||
|
||||
def __dir__( self ):
|
||||
return GithubObject.__attributeDefinitions.keys()
|
||||
|
||||
def __fetchAttribute( self, attributeName ):
|
||||
attributeDefinition = GithubObject.__attributeDefinitions[ attributeName ]
|
||||
attributeDefinition.updateAttributes( self )
|
||||
|
||||
GithubObject.__name__ = className
|
||||
GithubObject._addAttributePolicies( attributePolicies )
|
||||
|
||||
return GithubObject
|
||||
import itertools
|
||||
|
||||
class BadGithubObjectException( Exception ):
|
||||
pass
|
||||
|
||||
class BasicAttributes:
|
||||
class AttributeDefinition:
|
||||
def __init__( self, attributeNames ):
|
||||
self.__attributeNames = attributeNames
|
||||
|
||||
def getValueFromRawValue( self, obj, rawValue ):
|
||||
# if isinstance( rawValue, dict ):
|
||||
# print rawValue, "is a dict, you may want to use an extended attribute for it"
|
||||
return rawValue
|
||||
|
||||
def updateAttributes( self, obj ):
|
||||
attributes = obj._github._dataRequest( "GET", obj._baseUrl )
|
||||
for attributeName in self.__attributeNames:
|
||||
if attributeName not in attributes:
|
||||
attributes[ attributeName ] = None
|
||||
obj._updateAttributes( attributes )
|
||||
|
||||
def __init__( self, *attributeNames ):
|
||||
self.__attributeNames = attributeNames
|
||||
|
||||
def apply( self, cls ):
|
||||
commonDefinition = BasicAttributes.AttributeDefinition( self.__attributeNames )
|
||||
for attributeName in self.__attributeNames:
|
||||
cls._addAttribute( attributeName, commonDefinition )
|
||||
|
||||
class ListOfReferences:
|
||||
def __init__( self, attributeName, type, addable = False, removable = False, hasable = False ):
|
||||
self.__attributeName = attributeName
|
||||
self.__type = type
|
||||
self.__getName = "get_" + attributeName
|
||||
if addable:
|
||||
self.__addName = "add_to_" + attributeName
|
||||
else:
|
||||
self.__addName = None
|
||||
if removable:
|
||||
self.__removeName = "remove_from_" + attributeName
|
||||
else:
|
||||
self.__removeName = None
|
||||
if hasable:
|
||||
self.__hasName = "has_in_" + attributeName
|
||||
else:
|
||||
self.__hasName = None
|
||||
|
||||
def apply( self, cls ):
|
||||
cls._addMethod( self.__getName, self.__executeGet )
|
||||
if self.__addName is not None:
|
||||
cls._addMethod( self.__addName, self.__executeAdd )
|
||||
if self.__removeName is not None:
|
||||
cls._addMethod( self.__removeName, self.__executeRemove )
|
||||
if self.__hasName is not None:
|
||||
cls._addMethod( self.__hasName, self.__executeHas )
|
||||
|
||||
def __executeAdd( self, obj, toBeAdded ):
|
||||
assert( isinstance( toBeAdded, self.__type ) )
|
||||
obj._github._statusRequest( "PUT", obj._baseUrl + "/" + self.__attributeName + "/" + toBeAdded._identity )
|
||||
|
||||
def __executeRemove( self, obj, toBeDeleted ):
|
||||
assert( isinstance( toBeDeleted, self.__type ) )
|
||||
obj._github._statusRequest( "DELETE", obj._baseUrl + "/" + self.__attributeName + "/" + toBeDeleted._identity )
|
||||
|
||||
def __executeHas( self, obj, toBeQueried ):
|
||||
assert( isinstance( toBeQueried, self.__type ) )
|
||||
return obj._github._statusRequest( "GET", obj._baseUrl + "/" + self.__attributeName + "/" + toBeQueried._identity ) == 204
|
||||
|
||||
def __executeGet( self, obj ):
|
||||
return [
|
||||
self.__type( obj._github, attributes, lazy = True )
|
||||
for attributes in obj._github._dataRequest( "GET", obj._baseUrl + "/" + self.__attributeName )
|
||||
]
|
||||
|
||||
class ComplexAttribute:
|
||||
class AttributeDefinition:
|
||||
def __init__( self, attributeName, type ):
|
||||
self.__attributeName = attributeName
|
||||
self.__type = type
|
||||
|
||||
def getValueFromRawValue( self, obj, rawValue ):
|
||||
return self.__type( obj._github, rawValue, lazy = True )
|
||||
|
||||
def updateAttributes( self, obj ):
|
||||
attributes = obj._github._dataRequest( "GET", obj._baseUrl )
|
||||
# for attributeName in self.__attributeNames:
|
||||
# if attributeName not in attributes:
|
||||
# attributes[ attributeName ] = None
|
||||
obj._updateAttributes( attributes )
|
||||
|
||||
def __init__( self, attributeName, type ):
|
||||
self.__attributeName = attributeName
|
||||
self.__type = type
|
||||
|
||||
def apply( self, cls ):
|
||||
cls._addAttribute( self.__attributeName, ComplexAttribute.AttributeDefinition( self.__attributeName, self.__type ) )
|
||||
|
||||
class Editable:
|
||||
def __init__( self, mandatoryParameters, optionalParameters ):
|
||||
self.__mandatoryParameters = mandatoryParameters
|
||||
self.__optionalParameters = optionalParameters
|
||||
|
||||
def apply( self, cls ):
|
||||
cls._addMethod( "edit", self.__execute )
|
||||
|
||||
def __execute( self, obj, *args, **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 not in itertools.chain( self.__mandatoryParameters, self.__optionalParameters ):
|
||||
raise TypeError()
|
||||
attributes = obj._github._dataRequest( "PATCH", obj._baseUrl, kwds )
|
||||
obj._updateAttributes( attributes )
|
||||
|
||||
class Deletable:
|
||||
def apply( self, cls ):
|
||||
cls._addMethod( "delete", self.__execute )
|
||||
|
||||
def __execute( self, obj, *args, **kwds ):
|
||||
obj._github._statusRequest( "DELETE", obj._baseUrl )
|
||||
|
||||
class BaseUrl:
|
||||
class AttributeDefinition:
|
||||
def __init__( self, baseUrl ):
|
||||
self.__baseUrl = baseUrl
|
||||
|
||||
def getValueFromRawValue( self, obj, rawValue ):
|
||||
return rawValue
|
||||
|
||||
def updateAttributes( self, obj ):
|
||||
obj._updateAttributes( { "_baseUrl": self.__baseUrl( obj ) } )
|
||||
|
||||
def __init__( self, baseUrl ):
|
||||
self.__baseUrl = baseUrl
|
||||
|
||||
def apply( self, cls ):
|
||||
cls._addAttribute( "_baseUrl", BaseUrl.AttributeDefinition( self.__baseUrl ) )
|
||||
|
||||
class Identity:
|
||||
class AttributeDefinition:
|
||||
def __init__( self, identity ):
|
||||
self.__identity = identity
|
||||
|
||||
def getValueFromRawValue( self, obj, rawValue ):
|
||||
return rawValue
|
||||
|
||||
def updateAttributes( self, obj ):
|
||||
obj._updateAttributes( { "_identity": self.__identity( obj ) } )
|
||||
|
||||
def __init__( self, identity ):
|
||||
self.__identity = identity
|
||||
|
||||
def apply( self, cls ):
|
||||
cls._addAttribute( "_identity", Identity.AttributeDefinition( self.__identity ) )
|
||||
|
||||
def GithubObject( className, *attributePolicies ):
|
||||
class GithubObject:
|
||||
__attributeDefinitions = dict()
|
||||
__methodDefinitions = dict()
|
||||
|
||||
@staticmethod
|
||||
def _addAttributePolicies( attributePolicies ):
|
||||
for attributePolicy in attributePolicies:
|
||||
GithubObject._addAttributePolicy( attributePolicy )
|
||||
|
||||
@staticmethod
|
||||
def _addAttributePolicy( attributePolicy ):
|
||||
attributePolicy.apply( GithubObject )
|
||||
|
||||
@staticmethod
|
||||
def _addAttribute( attributeName, attributeDefinition ):
|
||||
if attributeName in GithubObject.__attributeDefinitions:
|
||||
raise BadGithubObjectException( "Same attribute defined by two policies" )
|
||||
else:
|
||||
GithubObject.__attributeDefinitions[ attributeName ] = attributeDefinition
|
||||
|
||||
@staticmethod
|
||||
def _addMethod( methodName, methodDefinition ):
|
||||
if methodName in GithubObject.__methodDefinitions:
|
||||
raise BadGithubObjectException( "Same method defined by two policies" )
|
||||
else:
|
||||
GithubObject.__methodDefinitions[ methodName ] = methodDefinition
|
||||
|
||||
def __init__( self, github, attributes, lazy ):
|
||||
self._github = github
|
||||
self.__attributes = dict()
|
||||
self._updateAttributes( attributes )
|
||||
if not lazy:
|
||||
for attributeName in GithubObject.__attributeDefinitions:
|
||||
if attributeName not in self.__attributes:
|
||||
self.__fetchAttribute( attributeName )
|
||||
|
||||
def __getattr__( self, attributeName ):
|
||||
if attributeName in GithubObject.__methodDefinitions:
|
||||
return lambda *args, **kwds: GithubObject.__methodDefinitions[ attributeName ]( self, *args, **kwds )
|
||||
elif attributeName in GithubObject.__attributeDefinitions:
|
||||
if attributeName not in self.__attributes:
|
||||
self.__fetchAttribute( attributeName )
|
||||
return self.__attributes[ attributeName ]
|
||||
else:
|
||||
raise AttributeError( attributeName )
|
||||
|
||||
def _updateAttributes( self, attributes ):
|
||||
for attributeName, attributeValue in attributes.iteritems():
|
||||
attributeDefinition = GithubObject.__attributeDefinitions[ attributeName ]
|
||||
if attributeValue is None:
|
||||
if attributeName not in self.__attributes:
|
||||
self.__attributes[ attributeName ] = None
|
||||
else:
|
||||
self.__attributes[ attributeName ] = attributeDefinition.getValueFromRawValue( self, attributeValue )
|
||||
|
||||
def __dir__( self ):
|
||||
return GithubObject.__attributeDefinitions.keys()
|
||||
|
||||
def __fetchAttribute( self, attributeName ):
|
||||
attributeDefinition = GithubObject.__attributeDefinitions[ attributeName ]
|
||||
attributeDefinition.updateAttributes( self )
|
||||
|
||||
GithubObject.__name__ = className
|
||||
GithubObject._addAttributePolicies( attributePolicies )
|
||||
|
||||
return GithubObject
|
||||
|
||||
Reference in New Issue
Block a user