Instanciating Clients
After registrating resources in blacksmith, to consume API, a client must be instanciated. To create a client, service has to be discoverable using a service discovery strategy, then resources can be consumed.
Note
The service discovery part will be covered later in the document, this chapter is about consuming resources.
To create a client, a blacksmith.AsyncClientFactory
object must be
configured, instanciated, then will be responsible to build client for every
registrated resources.
Synchronous code will use the blacksmith.SyncClientFactory
instead.
from blacksmith import AsyncClientFactory, AsyncStaticDiscovery
async def main():
sd = AsyncStaticDiscovery({("api", None): "http://srv:8000/"})
cli = AsyncClientFactory(sd)
api = await cli("api")
items = await api.item.collection_get()
print(items)
In the example above, we consume the previously registered resource item
,
from the service api
at version None
.
The api.item
property has methods collection_get, collection_post,
collection_put, collection_patch, collection_delete,
collection_options, and get, post, put, patch,
delete, options in order to consume api routes.
Important
Only registered routes works, consuming an unregistered route in the contract will raise error at the runtime. See Register Resources.
Type Hint
For a better development experience, type hints can be added, like the example bellow:
from blacksmith import AsyncClientFactory, AsyncStaticDiscovery, CollectionIterator
from .resources import Item, PartialItem
async def main():
sd = AsyncStaticDiscovery({("api", None): "http://srv:8000/"})
cli = AsyncClientFactory(sd)
api = await cli("api")
items: CollectionIterator[PartialItem] = await api.item.collection_get()
for item in items:
full_item: Item = (await api.item.get({"name": item.name})).response
print(full_item)
Note
methods that consume API such as .get(param)
in the exemple above,
accept both form get({"id": item.id})
and get(GetItem(id))
where GetItem
is the Request Schema of the GET
contract.
The method accept a dict version of the request schema.
Synchronous API
Resource registration does not change for the sync/async version, but,
all the runtime components differ. A prefix Async
identified the
asynchronous version and the prefix Sync
define the synchronous version.
Lastly, here is the same example, using the synchronous API.
from blacksmith import CollectionIterator, SyncClientFactory, SyncStaticDiscovery
from .resources import Item, PartialItem
def main():
sd = SyncStaticDiscovery({("api", None): "http://srv:8000/"})
cli = SyncClientFactory(sd)
api = cli("api")
items: CollectionIterator[PartialItem] = api.item.collection_get()
for item in items:
full_item: Item = (api.item.get({"name": item.name})).response
print(full_item)