py-better-result 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,277 @@
1
+ Metadata-Version: 2.3
2
+ Name: py-better-result
3
+ Version: 1.0.0
4
+ Summary: A narrow, typed Result API for Python
5
+ Author: Tomperez98
6
+ Author-email: Tomperez98 <tomasperezalvarez@gmail.com>
7
+ Requires-Dist: typing-extensions>=4.10,<5
8
+ Requires-Python: >=3.12
9
+ Description-Content-Type: text/markdown
10
+
11
+ # py-better-result
12
+
13
+ > Credits: [better-result.dev](https://better-result.dev)
14
+
15
+ A typed `Result[T, E]` for Python: return `Ok(value)` or `Err(error)`, compose workflows without exception-driven control flow, and keep expected failures visible to the type checker.
16
+
17
+ ```python
18
+ from dataclasses import dataclass
19
+
20
+ from better_result import Err, Ok, Result
21
+
22
+
23
+ @dataclass(frozen=True)
24
+ class User:
25
+ name: str
26
+
27
+
28
+ def parse_user_id(raw: str) -> Result[int, str]:
29
+ if not raw.isdecimal():
30
+ return Err("invalid user id")
31
+ return Ok(int(raw))
32
+
33
+
34
+ def load_user(user_id: int) -> Result[User, str]:
35
+ if user_id == 42:
36
+ return Ok(User("Ada"))
37
+ return Err("user not found")
38
+
39
+
40
+ result = parse_user_id("42").and_then(load_user).map(lambda user: user.name)
41
+
42
+ match result:
43
+ case Ok(name):
44
+ print(name)
45
+ case Err(message):
46
+ print(f"error: {message}")
47
+ ```
48
+
49
+ ```text
50
+ Ada
51
+ ```
52
+
53
+ ## Install
54
+
55
+ Using [uv](https://docs.astral.sh/uv/):
56
+
57
+ ```bash
58
+ uv add py-better-result
59
+ ```
60
+
61
+ With pip:
62
+
63
+ ```bash
64
+ pip install py-better-result
65
+ ```
66
+
67
+ `py-better-result` requires Python 3.12 or newer. The runtime dependency is `typing-extensions`.
68
+
69
+ ## Why use a Result?
70
+
71
+ Use a `Result` when failure is an expected part of an operation—validation, a missing record, a rejected request, or a downstream service error. The error stays in the return type instead of being hidden in a broad `try`/`except` or collapsed into `None`.
72
+
73
+ - `Ok[T]` contains a successful value.
74
+ - `Err[E]` contains an expected error value.
75
+ - `Result[T, E]` is the common type for either branch.
76
+ - `and_then` and `map` short-circuit on the first `Err`.
77
+ - Exceptions raised by callbacks are not silently converted into `Err`; unexpected defects propagate.
78
+ - `Ok` and `Err` are frozen, unhashable dataclasses and support structural pattern matching.
79
+
80
+ ## Core API
81
+
82
+ ```python
83
+ from better_result import Err, Ok, Result, is_err, is_ok
84
+
85
+ result: Result[int, str] = Ok(2)
86
+
87
+ result.map(lambda value: value * 10) # Ok(20)
88
+ result.and_then(lambda value: Ok(str(value))) # Ok("2")
89
+ result.map_err(str.upper) # unchanged Ok(2)
90
+ result.unwrap_or(0) # 2
91
+ result.match(ok=str, err=lambda error: error) # "2"
92
+
93
+ failure: Result[int, str] = Err("offline")
94
+ failure.map(lambda value: value * 10) # unchanged Err("offline")
95
+ failure.map_err(str.upper) # Err("OFFLINE")
96
+ failure.unwrap_or(0) # 0
97
+ failure.unwrap_or_else(lambda error: len(error)) # 7
98
+ ```
99
+
100
+ The branch-specific values are available as `ok_value` and `err_value`. Use `isinstance`, `is_ok`, or `is_err` to narrow a `Result`:
101
+
102
+ ```python
103
+ if is_ok(result):
104
+ print(result.ok_value) # int
105
+ elif is_err(result):
106
+ print(result.err_value) # str
107
+ ```
108
+
109
+ ### Choosing a combinator
110
+
111
+ | Operation | Runs when | Returns |
112
+ | --- | --- | --- |
113
+ | `map(fn)` | the result is `Ok` | a new `Result` with the mapped success value |
114
+ | `map_err(fn)` | the result is `Err` | a new `Result` with the mapped error |
115
+ | `and_then(fn)` | the result is `Ok` | the `Result` returned by the next operation |
116
+ | `or_else(fn)` | the result is `Err` | the `Result` returned by the recovery operation |
117
+ | `map_or(default, fn)` | either branch | a plain value |
118
+ | `map_or_else(default_fn, fn)` | either branch | a plain value |
119
+ | `match(ok=..., err=...)` | exactly one branch | the handler's return value |
120
+ | `inspect(fn)` / `inspect_err(fn)` | only the selected branch | the original `Result`, for side effects |
121
+
122
+ `unwrap()` and `expect(message)` return the success value but raise `UnwrapError` on `Err`. Their counterparts `unwrap_err()` and `expect_err()` select the error branch. Prefer `unwrap_or`, `unwrap_or_else`, or explicit matching when failure is expected.
123
+
124
+ ## Async workflows
125
+
126
+ The core combinators have async forms: `map_async`, `and_then_async`, `or_else_async`, `inspect_async`, `inspect_err_async`, and `inspect_both_async`.
127
+
128
+ ```python
129
+ import asyncio
130
+
131
+ from better_result import Ok
132
+
133
+
134
+ async def fetch_name(user_id: int) -> Ok[str]:
135
+ return Ok(f"user-{user_id}")
136
+
137
+
138
+ async def main() -> None:
139
+ result = await Ok(2).and_then_async(fetch_name)
140
+ print(result)
141
+
142
+
143
+ asyncio.run(main())
144
+ ```
145
+
146
+ ```text
147
+ Ok(value='user-2')
148
+ ```
149
+
150
+ Async callbacks are only awaited for the active branch. A failed `Result` therefore skips downstream success callbacks just like the synchronous API.
151
+
152
+ ## Capture exceptions and retry operations
153
+
154
+ Use `try_result` or `try_async` at a boundary where an exception is an expected failure mode. Without a mapper, the exception itself becomes the error value; `catch` can convert it into a domain error.
155
+
156
+ ```python
157
+ from better_result import Err, TryContext, try_result
158
+
159
+
160
+ def read_port(context: TryContext) -> int:
161
+ return int("not-a-port")
162
+
163
+
164
+ result = try_result(read_port, catch=lambda exc: {"message": str(exc)})
165
+ assert result == Err(
166
+ {"message": "invalid literal for int() with base 10: 'not-a-port'"}
167
+ )
168
+ ```
169
+
170
+ `try_result` accepts `retry=<number>` for immediate synchronous retries. For asynchronous operations, `RetryPolicy` supports bounded retries, constant/linear/exponential backoff, jitter, a `should_retry` predicate, and cooperative cancellation:
171
+
172
+ ```python
173
+ import asyncio
174
+
175
+ from better_result import Ok, RetryPolicy, TryContext, try_async
176
+
177
+
178
+ async def fetch(context: TryContext) -> str:
179
+ if context.attempt < 2:
180
+ raise TimeoutError("temporary timeout")
181
+ return "response body"
182
+
183
+
184
+ async def main() -> None:
185
+ result = await try_async(
186
+ fetch,
187
+ catch=str,
188
+ retry=RetryPolicy(
189
+ times=3, # retries after the first attempt
190
+ delay=0,
191
+ backoff="exponential",
192
+ should_retry=lambda error, _: "timeout" in error.lower(),
193
+ ),
194
+ )
195
+ print(result)
196
+
197
+
198
+ asyncio.run(main())
199
+ ```
200
+
201
+ ```text
202
+ Ok(value='response body')
203
+ ```
204
+
205
+ `TryContext.attempt` starts at `1`. `CancellationToken` can stop a retry wait and is passed to each async attempt through `TryContext.cancel_token`. Cancellation exceptions themselves are not swallowed.
206
+
207
+ ## Collect or partition Results
208
+
209
+ ```python
210
+ from better_result import Err, Ok, all_results, partition_results
211
+
212
+
213
+ all_results([Ok(1), Ok(2)])
214
+ # Ok(value=(1, 2))
215
+
216
+ all_results([Ok(1), Err("database unavailable"), Ok(3)])
217
+ # Err(value="database unavailable")
218
+
219
+ partition_results([Ok(1), Err("bad input"), Ok(2)])
220
+ # ([1, 2], ["bad input"])
221
+ ```
222
+
223
+ - `all_results` returns every success in a tuple, or the first error in input order.
224
+ - `partition_results` returns `(success_values, error_values)` while preserving the relative order of each list.
225
+ - `flatten_result` turns `Result[Result[T, E], F]` into `Result[T, E | F]`.
226
+ - `all_results_async` and `partition_results_async` accept `Result` values or awaitables, await them concurrently, and preserve input order.
227
+
228
+ ## Encode and decode at boundaries
229
+
230
+ `codec` and `async_codec` turn a `Result` into a typed envelope suitable for JSON or another wire format. Each schema returns either the converted value or `SchemaFailure` with structured issues.
231
+
232
+ ```python
233
+ from better_result import Err, Ok, codec
234
+
235
+
236
+ result_codec = codec(
237
+ serialize_ok=lambda user: {"id": user["id"]},
238
+ serialize_err=lambda error: {"code": error},
239
+ deserialize_ok=lambda value: value["id"],
240
+ deserialize_err=lambda value: value["code"],
241
+ )
242
+
243
+ encoded = result_codec.serialize(Ok({"id": 42}))
244
+ assert encoded == Ok({"status": "ok", "value": {"id": 42}})
245
+
246
+ encoded_error = result_codec.serialize(Err("not_found"))
247
+ assert encoded_error == Ok({"status": "error", "error": {"code": "not_found"}})
248
+
249
+ decoded = result_codec.deserialize({"status": "ok", "value": {"id": 42}})
250
+ assert decoded == Ok(42)
251
+ ```
252
+
253
+ A decoded wire-level error is returned as `Err` with the decoded error value. Malformed envelopes and schema rejections are returned as `Err(ResultDeserializationError)`, so the deserialization error type is `ErrOutput | ResultDeserializationError`. Serialization schema rejections are returned as `Err(ResultSerializationError)`.
254
+
255
+ Use `async_codec` when schemas are asynchronous. The `serialize_unsafe` and `deserialize_unsafe` methods unwrap codec failures and raise `UnwrapError`; they are useful only when the boundary failure is already handled elsewhere.
256
+
257
+ ## Public API
258
+
259
+ The package exports:
260
+
261
+ - Core types: `Result`, `Ok`, `Err`, `UnwrapError`, `is_ok`, `is_err`
262
+ - Async and sync operations: `try_result`, `try_async`, `RetryPolicy`, `TryContext`, `CancellationToken`
263
+ - Collection operations: `all_results`, `all_results_async`, `partition_results`, `partition_results_async`, `flatten_result`
264
+ - Codecs: `codec`, `async_codec`, `ResultCodec`, `AsyncResultCodec`
265
+ - Codec types: `SchemaFailure`, `CodecIssue`, `SerializedOk`, `SerializedErr`, `SerializedResult`, `SyncSchema`, `AsyncSchema`, `ResultSerializationError`, `ResultDeserializationError`
266
+
267
+ ## Development
268
+
269
+ ```bash
270
+ uv sync
271
+ uv run pytest
272
+ uv run pytest --cov
273
+ uv run ruff check .
274
+ uv run ty check
275
+ ```
276
+
277
+ The test suite includes runtime behavior and static type contracts.
@@ -0,0 +1,267 @@
1
+ # py-better-result
2
+
3
+ > Credits: [better-result.dev](https://better-result.dev)
4
+
5
+ A typed `Result[T, E]` for Python: return `Ok(value)` or `Err(error)`, compose workflows without exception-driven control flow, and keep expected failures visible to the type checker.
6
+
7
+ ```python
8
+ from dataclasses import dataclass
9
+
10
+ from better_result import Err, Ok, Result
11
+
12
+
13
+ @dataclass(frozen=True)
14
+ class User:
15
+ name: str
16
+
17
+
18
+ def parse_user_id(raw: str) -> Result[int, str]:
19
+ if not raw.isdecimal():
20
+ return Err("invalid user id")
21
+ return Ok(int(raw))
22
+
23
+
24
+ def load_user(user_id: int) -> Result[User, str]:
25
+ if user_id == 42:
26
+ return Ok(User("Ada"))
27
+ return Err("user not found")
28
+
29
+
30
+ result = parse_user_id("42").and_then(load_user).map(lambda user: user.name)
31
+
32
+ match result:
33
+ case Ok(name):
34
+ print(name)
35
+ case Err(message):
36
+ print(f"error: {message}")
37
+ ```
38
+
39
+ ```text
40
+ Ada
41
+ ```
42
+
43
+ ## Install
44
+
45
+ Using [uv](https://docs.astral.sh/uv/):
46
+
47
+ ```bash
48
+ uv add py-better-result
49
+ ```
50
+
51
+ With pip:
52
+
53
+ ```bash
54
+ pip install py-better-result
55
+ ```
56
+
57
+ `py-better-result` requires Python 3.12 or newer. The runtime dependency is `typing-extensions`.
58
+
59
+ ## Why use a Result?
60
+
61
+ Use a `Result` when failure is an expected part of an operation—validation, a missing record, a rejected request, or a downstream service error. The error stays in the return type instead of being hidden in a broad `try`/`except` or collapsed into `None`.
62
+
63
+ - `Ok[T]` contains a successful value.
64
+ - `Err[E]` contains an expected error value.
65
+ - `Result[T, E]` is the common type for either branch.
66
+ - `and_then` and `map` short-circuit on the first `Err`.
67
+ - Exceptions raised by callbacks are not silently converted into `Err`; unexpected defects propagate.
68
+ - `Ok` and `Err` are frozen, unhashable dataclasses and support structural pattern matching.
69
+
70
+ ## Core API
71
+
72
+ ```python
73
+ from better_result import Err, Ok, Result, is_err, is_ok
74
+
75
+ result: Result[int, str] = Ok(2)
76
+
77
+ result.map(lambda value: value * 10) # Ok(20)
78
+ result.and_then(lambda value: Ok(str(value))) # Ok("2")
79
+ result.map_err(str.upper) # unchanged Ok(2)
80
+ result.unwrap_or(0) # 2
81
+ result.match(ok=str, err=lambda error: error) # "2"
82
+
83
+ failure: Result[int, str] = Err("offline")
84
+ failure.map(lambda value: value * 10) # unchanged Err("offline")
85
+ failure.map_err(str.upper) # Err("OFFLINE")
86
+ failure.unwrap_or(0) # 0
87
+ failure.unwrap_or_else(lambda error: len(error)) # 7
88
+ ```
89
+
90
+ The branch-specific values are available as `ok_value` and `err_value`. Use `isinstance`, `is_ok`, or `is_err` to narrow a `Result`:
91
+
92
+ ```python
93
+ if is_ok(result):
94
+ print(result.ok_value) # int
95
+ elif is_err(result):
96
+ print(result.err_value) # str
97
+ ```
98
+
99
+ ### Choosing a combinator
100
+
101
+ | Operation | Runs when | Returns |
102
+ | --- | --- | --- |
103
+ | `map(fn)` | the result is `Ok` | a new `Result` with the mapped success value |
104
+ | `map_err(fn)` | the result is `Err` | a new `Result` with the mapped error |
105
+ | `and_then(fn)` | the result is `Ok` | the `Result` returned by the next operation |
106
+ | `or_else(fn)` | the result is `Err` | the `Result` returned by the recovery operation |
107
+ | `map_or(default, fn)` | either branch | a plain value |
108
+ | `map_or_else(default_fn, fn)` | either branch | a plain value |
109
+ | `match(ok=..., err=...)` | exactly one branch | the handler's return value |
110
+ | `inspect(fn)` / `inspect_err(fn)` | only the selected branch | the original `Result`, for side effects |
111
+
112
+ `unwrap()` and `expect(message)` return the success value but raise `UnwrapError` on `Err`. Their counterparts `unwrap_err()` and `expect_err()` select the error branch. Prefer `unwrap_or`, `unwrap_or_else`, or explicit matching when failure is expected.
113
+
114
+ ## Async workflows
115
+
116
+ The core combinators have async forms: `map_async`, `and_then_async`, `or_else_async`, `inspect_async`, `inspect_err_async`, and `inspect_both_async`.
117
+
118
+ ```python
119
+ import asyncio
120
+
121
+ from better_result import Ok
122
+
123
+
124
+ async def fetch_name(user_id: int) -> Ok[str]:
125
+ return Ok(f"user-{user_id}")
126
+
127
+
128
+ async def main() -> None:
129
+ result = await Ok(2).and_then_async(fetch_name)
130
+ print(result)
131
+
132
+
133
+ asyncio.run(main())
134
+ ```
135
+
136
+ ```text
137
+ Ok(value='user-2')
138
+ ```
139
+
140
+ Async callbacks are only awaited for the active branch. A failed `Result` therefore skips downstream success callbacks just like the synchronous API.
141
+
142
+ ## Capture exceptions and retry operations
143
+
144
+ Use `try_result` or `try_async` at a boundary where an exception is an expected failure mode. Without a mapper, the exception itself becomes the error value; `catch` can convert it into a domain error.
145
+
146
+ ```python
147
+ from better_result import Err, TryContext, try_result
148
+
149
+
150
+ def read_port(context: TryContext) -> int:
151
+ return int("not-a-port")
152
+
153
+
154
+ result = try_result(read_port, catch=lambda exc: {"message": str(exc)})
155
+ assert result == Err(
156
+ {"message": "invalid literal for int() with base 10: 'not-a-port'"}
157
+ )
158
+ ```
159
+
160
+ `try_result` accepts `retry=<number>` for immediate synchronous retries. For asynchronous operations, `RetryPolicy` supports bounded retries, constant/linear/exponential backoff, jitter, a `should_retry` predicate, and cooperative cancellation:
161
+
162
+ ```python
163
+ import asyncio
164
+
165
+ from better_result import Ok, RetryPolicy, TryContext, try_async
166
+
167
+
168
+ async def fetch(context: TryContext) -> str:
169
+ if context.attempt < 2:
170
+ raise TimeoutError("temporary timeout")
171
+ return "response body"
172
+
173
+
174
+ async def main() -> None:
175
+ result = await try_async(
176
+ fetch,
177
+ catch=str,
178
+ retry=RetryPolicy(
179
+ times=3, # retries after the first attempt
180
+ delay=0,
181
+ backoff="exponential",
182
+ should_retry=lambda error, _: "timeout" in error.lower(),
183
+ ),
184
+ )
185
+ print(result)
186
+
187
+
188
+ asyncio.run(main())
189
+ ```
190
+
191
+ ```text
192
+ Ok(value='response body')
193
+ ```
194
+
195
+ `TryContext.attempt` starts at `1`. `CancellationToken` can stop a retry wait and is passed to each async attempt through `TryContext.cancel_token`. Cancellation exceptions themselves are not swallowed.
196
+
197
+ ## Collect or partition Results
198
+
199
+ ```python
200
+ from better_result import Err, Ok, all_results, partition_results
201
+
202
+
203
+ all_results([Ok(1), Ok(2)])
204
+ # Ok(value=(1, 2))
205
+
206
+ all_results([Ok(1), Err("database unavailable"), Ok(3)])
207
+ # Err(value="database unavailable")
208
+
209
+ partition_results([Ok(1), Err("bad input"), Ok(2)])
210
+ # ([1, 2], ["bad input"])
211
+ ```
212
+
213
+ - `all_results` returns every success in a tuple, or the first error in input order.
214
+ - `partition_results` returns `(success_values, error_values)` while preserving the relative order of each list.
215
+ - `flatten_result` turns `Result[Result[T, E], F]` into `Result[T, E | F]`.
216
+ - `all_results_async` and `partition_results_async` accept `Result` values or awaitables, await them concurrently, and preserve input order.
217
+
218
+ ## Encode and decode at boundaries
219
+
220
+ `codec` and `async_codec` turn a `Result` into a typed envelope suitable for JSON or another wire format. Each schema returns either the converted value or `SchemaFailure` with structured issues.
221
+
222
+ ```python
223
+ from better_result import Err, Ok, codec
224
+
225
+
226
+ result_codec = codec(
227
+ serialize_ok=lambda user: {"id": user["id"]},
228
+ serialize_err=lambda error: {"code": error},
229
+ deserialize_ok=lambda value: value["id"],
230
+ deserialize_err=lambda value: value["code"],
231
+ )
232
+
233
+ encoded = result_codec.serialize(Ok({"id": 42}))
234
+ assert encoded == Ok({"status": "ok", "value": {"id": 42}})
235
+
236
+ encoded_error = result_codec.serialize(Err("not_found"))
237
+ assert encoded_error == Ok({"status": "error", "error": {"code": "not_found"}})
238
+
239
+ decoded = result_codec.deserialize({"status": "ok", "value": {"id": 42}})
240
+ assert decoded == Ok(42)
241
+ ```
242
+
243
+ A decoded wire-level error is returned as `Err` with the decoded error value. Malformed envelopes and schema rejections are returned as `Err(ResultDeserializationError)`, so the deserialization error type is `ErrOutput | ResultDeserializationError`. Serialization schema rejections are returned as `Err(ResultSerializationError)`.
244
+
245
+ Use `async_codec` when schemas are asynchronous. The `serialize_unsafe` and `deserialize_unsafe` methods unwrap codec failures and raise `UnwrapError`; they are useful only when the boundary failure is already handled elsewhere.
246
+
247
+ ## Public API
248
+
249
+ The package exports:
250
+
251
+ - Core types: `Result`, `Ok`, `Err`, `UnwrapError`, `is_ok`, `is_err`
252
+ - Async and sync operations: `try_result`, `try_async`, `RetryPolicy`, `TryContext`, `CancellationToken`
253
+ - Collection operations: `all_results`, `all_results_async`, `partition_results`, `partition_results_async`, `flatten_result`
254
+ - Codecs: `codec`, `async_codec`, `ResultCodec`, `AsyncResultCodec`
255
+ - Codec types: `SchemaFailure`, `CodecIssue`, `SerializedOk`, `SerializedErr`, `SerializedResult`, `SyncSchema`, `AsyncSchema`, `ResultSerializationError`, `ResultDeserializationError`
256
+
257
+ ## Development
258
+
259
+ ```bash
260
+ uv sync
261
+ uv run pytest
262
+ uv run pytest --cov
263
+ uv run ruff check .
264
+ uv run ty check
265
+ ```
266
+
267
+ The test suite includes runtime behavior and static type contracts.
@@ -0,0 +1,41 @@
1
+ [project]
2
+ name = "py-better-result"
3
+ version = "1.0.0"
4
+ description = "A narrow, typed Result API for Python"
5
+ readme = "README.md"
6
+ authors = [{ name = "Tomperez98", email = "tomasperezalvarez@gmail.com" }]
7
+ requires-python = ">=3.12"
8
+ dependencies = ["typing-extensions>=4.10,<5"]
9
+
10
+ [build-system]
11
+ requires = ["uv_build>=0.11.21,<0.12.0"]
12
+ build-backend = "uv_build"
13
+
14
+ # Module name differs from the project name (py-better-result vs better_result)
15
+ [tool.uv.build-backend]
16
+ module-name = "better_result"
17
+
18
+ [dependency-groups]
19
+ dev = [
20
+ "pytest>=9.1.1,<10",
21
+ "pytest-asyncio>=1.4.0,<2",
22
+ "pytest-cov>=7.0.0,<8",
23
+ "ruff>=0.16.6,<0.17",
24
+ "ty>=0.0.78,<0.1",
25
+ ]
26
+
27
+ [tool.ty]
28
+
29
+ [tool.ty.rules]
30
+ all = "error"
31
+
32
+ [tool.pytest.ini_options]
33
+ asyncio_mode = "auto"
34
+
35
+ [tool.coverage.run]
36
+ branch = true
37
+ source = ["src/better_result"]
38
+
39
+ [tool.coverage.report]
40
+ show_missing = true
41
+ fail_under = 100
@@ -0,0 +1,64 @@
1
+ """A small, typed Result type with boundary codecs."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from ._codec import (
6
+ AsyncResultCodec,
7
+ AsyncSchema,
8
+ CodecIssue,
9
+ ResultCodec,
10
+ ResultDeserializationError,
11
+ ResultSerializationError,
12
+ SchemaFailure,
13
+ SerializedErr,
14
+ SerializedOk,
15
+ SerializedResult,
16
+ SyncSchema,
17
+ async_codec,
18
+ codec,
19
+ )
20
+ from ._core import Err, Ok, Result, UnwrapError, is_err, is_ok
21
+ from ._operations import (
22
+ CancellationToken,
23
+ RetryPolicy,
24
+ TryContext,
25
+ all_results,
26
+ all_results_async,
27
+ flatten_result,
28
+ partition_results,
29
+ partition_results_async,
30
+ try_async,
31
+ try_result,
32
+ )
33
+
34
+ __all__ = [
35
+ "AsyncResultCodec",
36
+ "AsyncSchema",
37
+ "CancellationToken",
38
+ "CodecIssue",
39
+ "Err",
40
+ "Ok",
41
+ "Result",
42
+ "ResultCodec",
43
+ "ResultDeserializationError",
44
+ "ResultSerializationError",
45
+ "RetryPolicy",
46
+ "SchemaFailure",
47
+ "SerializedErr",
48
+ "SerializedOk",
49
+ "SerializedResult",
50
+ "SyncSchema",
51
+ "TryContext",
52
+ "UnwrapError",
53
+ "all_results",
54
+ "all_results_async",
55
+ "async_codec",
56
+ "codec",
57
+ "flatten_result",
58
+ "is_err",
59
+ "is_ok",
60
+ "partition_results",
61
+ "partition_results_async",
62
+ "try_async",
63
+ "try_result",
64
+ ]