Instanciating Clients¶
After registering 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")
result = await api.item.collection_get()
if result.is_ok():
for item in result.unwrap():
print(item)
else:
print(result.unwrap_err())
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,
get, patch, delete, to name a few to consume registered api routes.
This section will be covered in the next section.
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 result import Result
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: Result[CollectionIterator[PartialItem]] = await api.item.collection_get()
for item in items.unwrap():
full_item: Item = (await api.item.get({"name": item.name})).unwrap()
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.
Changed in version 2.0: Since blacksmith 2.0, responses are wrapped using the result library.
The collection class return a result.Result object, and the non collection,
return a blacksmith.ResponseBox that have the same mimic of the
result.Result. of the result library.
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 result import Result
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: Result[CollectionIterator[PartialItem]] = api.item.collection_get()
for item in items.unwrap():
full_item: Item = (api.item.get({"name": item.name})).unwrap()
print(full_item)