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)