Skip to content

Commit 740fe24

Browse files
committed
Adds FutureResult docs
1 parent 3bfe708 commit 740fe24

File tree

1 file changed

+61
-0
lines changed

1 file changed

+61
-0
lines changed

docs/pages/future.rst

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,67 @@ This helps a lot when separating pure and impure
7373
FutureResult
7474
------------
7575

76+
This container becomes very useful when working
77+
with ``async`` function that can fail.
78+
79+
It works the similar way regular ``Result`` does.
80+
And is literally a wrapper around ``Future[Result[_V, _E]]`` type.
81+
82+
Let's see how it can be used in a real program:
83+
84+
.. code:: python
85+
86+
from typing import Sequence
87+
88+
import anyio
89+
import httpx
90+
from typing_extensions import Final, TypedDict
91+
from returns.future import FutureResultE, future_safe
92+
93+
_URL: Final = 'https://jsonplaceholder.typicode.com/posts/{0}'
94+
_Post = TypedDict('_Post', {
95+
'id': int,
96+
'userId': int,
97+
'title': str,
98+
'body': str,
99+
})
100+
_TitleOnly = TypedDict('_TitleOnly', {'title': str})
101+
102+
@future_safe
103+
async def _fetch_post(post_id: int) -> _Post:
104+
# Ideally, we can use `ReaderFutureResult` to provide `client` from deps.
105+
async with httpx.AsyncClient(timeout=5) as client:
106+
response = await client.get(_URL.format(post_id))
107+
response.raise_for_status()
108+
return response.json()
109+
110+
def show_titles(number_of_posts: int) -> FutureResultE[Sequence[_TitleOnly]]:
111+
return FutureResultE.from_iterable([
112+
# Notice how easily we compose async and sync functions:
113+
_fetch_post(post_id).map(lambda post: post['title'])
114+
# TODO: try `for post_id in {2, 1, 0}:` to see how errors work
115+
for post_id in range(1, number_of_posts + 1)
116+
])
117+
118+
if __name__ == '__main__':
119+
# Let's fetch 3 titles of posts asynchronously:
120+
print(anyio.run(show_titles(3).awaitable))
121+
# <IOResult: <Success: (
122+
# 'sunt aut facere repellat provident occaecati ...',
123+
# 'qui est esse',
124+
# 'ea molestias quasi exercitationem repellat qui ipsa sit aut',
125+
# )>>
126+
127+
What is different?
128+
129+
1. We can now easily make ``show_titles`` sync,
130+
we can also make ``_fetch_post`` sync,
131+
but we would need to use ``ReaderFutureResult`` container
132+
with proper dependencies in this case
133+
2. We now don't care about errors at all.
134+
In this example any error will cancel the whole pipeline
135+
3. We now have ``.map`` method to easily compose sync and async functions
136+
76137

77138
Aliases
78139
-------

0 commit comments

Comments
 (0)