Package: genericclient-aiohttp
A generic client for RESTful APIs based onaiohttp. Python 3.5+ only.Installation$ pip install genericclient-aiohttpQuickstartimportasynciofromgenericclient_aiohttpimportGenericClientasyncdefmain():myclient=GenericClient(api_url)myresource=awaitmyclient.resources.get(id=1)actives=awaitmyclient.posts.filter(active=True)# or you can make multiple HTTP sharing the same sessionasyncwithmyclientassession:myresource=awaitsession.resources.get(id=1)actives=awaitsession.posts.filter(active=True)loop=asyncio.get_event_loop()loop.run_until_complete(main(loop))UsageInstantiationmyclient=GenericClient(url,auth=None,session=None,trailing_slash=False,retries=3,autopaginate=None)Arguments:url: The root URL of your APIauth: The auth for your API. You can pass anything thataiohttp.ClientSessioncan accept as auth.session: Pass a session instance to haveaiohttpuse that session. IfNone(the default), it will instantiate an instance ofaiohttp.ClientSessionfor you.trailing_slash: You can set this toTrueif your API’s URLs end with a/retries: How many times should the client retry the http call after aClientConnectionErrorautopaginate: You can set this to a coroutine to fetch all pages resulting from a request. Currently, the only coroutine included isgenericclient_aiohttp.pagination.link_header, which supports [RFC5988](https://tools.ietf.org/html/rfc5988).EndpointsEndpoints are available as properties or items on the main instance:awaitmyclient.posts.all()# GET /posts/awaitmyclient["active-users"].all()# GET /active-users/.all()Retrieves all resources (essentially a simpleGETon the endpoint):awaitmyclient.posts.all()# GET /posts/.filter().filter(**kwargs)calls aGETwithkwargsas querystring values:awaitmyclient.posts.filter(blog=12,status=1)# GET /posts/?blog=12&status=1.get(**kwargs)A special case of.filter().Ifkwargscontainsid,pk,slugorusername, that value will
be used in the URL path, in that order.Otherwise, it calls aGETwithkwargsas querystring values.If the returned list is empty, will raiseResourceNotFound.If the returned list contains more than 1 resource, will raiseMultipleResourcesFoundNote that.get()will return aResource, not a list ofResourcesawaitmyclient.posts.filter(blog=12,status=1)# GET /posts/?blog=12&status=1awaitmyclient.posts.filter(id=12)# GET /posts/12/awaitmyclient.posts.filter(slug='12-ways-clickbait')# GET /posts/12-ways-clickbait/.create(payload)Will result in aPOST, withpayload(adict) as the request’s body,
returning a newResource:post=awaitmyclient.posts.create({'blog':12,'status':1})# POST /posts/.get_or_create(defaults, **kwargs)Issues a GET to fetch the resource. If the resource is not found, issues a POST
to create the resource:# Assuming it doesn't existpost=awaitmyclient.posts.get_or_update(slug='my-post',defaults={'status':1})# GET /posts/my-post/, then POST /posts/.create_or_update(payload)Ifpayloadcontains a key called'id', will issue aPUT. If the
server returns a400error, aPATCHrequest will be re-issued.
Ifpayload`does not contains'id', it will issue aPOST:post=awaitmyclient.posts.create_or_update({'status':1})# POST /posts/post=awaitmyclient.posts.create_or_update({'id':1234,'status':1})# PUT /posts/1234/post=awaitmyclient.posts.create_or_update({'id':1234})# PUT /posts/1234/# <- server returns 400# -> PATCH /posts/1234/.delete(pk)Will issue aDELETE, and will usepkas part of the URL:awaitmyclient.posts.delete(24)# DELETE /posts/24/ResourcesAll endpoints methods (with the exception of.delete()) return either aResourceor a list ofResources.AResourceis just a wrapping class for adict, where keys can be accessed
as properties.Additionally,Resources have a special property called.payload, which
contains the original payload received from the server.Resources have the following methods:Resource.delete()will result in aDELETE, withResource.idas
par of the URL:blog=awaitmyclient.posts.create({'blog':12,'status':1})# POST /posts/awaitblog.delete()# DELETE /blog/345/ -- the ID 345 was returned by the server in the previous responseResource.save()will result in aPUT, withResource.idas
par of the URL. If the
server returns a400error, aPATCHrequest will be re-issued:post=awaitmyclient.posts.create({'blog':12,'status':1})# POST /posts/post.status=2awaitpost.save()# PUT /posts/345/post=Resource(id=345,status=1)awaitpost.save()# PUT /posts/345/# <- server returns 400# -> PATCH /posts/345/ResourceSetsWhenever a method returns a list of Resources, they list will be wrapped in aResultSet.A ResultSet is a just alistobject, with the addition of a.responsecontaining the original response from the server.Customizing Endpoints and ResourcesResources can be customized by subclassinggenericclient_aiohttp.Resource.The most common reason is specifying the name of the primary key:fromgenericclient_aiohttpimportResourceclassPostResource(Resource):pk_name='slug'Endpoints can be customized by subclassinggenericclient_aiohttp.Endpoint:formgenericclient_aiohttpimportEndpointclassPostEndpoint(Endpoint):resource_class=PostResourceYou can then subclassgenericclient_aiohttp.GenericClientto tell the client which endpoint classes to use on each endpoint:fromgenericclient_aiohttpimportGenericClientclassClient(GenericClient):endpoint_classes={'posts':PostEndpoint,}RoutesIf your API has some non-RESTful calls within the main endpoints (sometimes referred asdetail_routeandlist_route), you can usegenericclientto call them:awaitmyclient.posts(id=123).publish(date=tomorrow)awaitmyclient.blogs().ping()Routes http calls usePOSTby default, but you can specify something else by using the_methodargument:awaitmyclient.posts(_method='get',id=123).pingbacks()awaitmyclient.blogs(_method='get').visits()Note that this calls will return an instance ofgenericclient.ParsedResponse, instead of instances ofgenericclient.Resource,LicenseLicensed under the MIT License.