@@ -73,6 +73,67 @@ This helps a lot when separating pure and impure
73
73
FutureResult
74
74
------------
75
75
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
+
76
137
77
138
Aliases
78
139
-------
0 commit comments