Skip to content

Commit

Permalink
Check all pydoc strings, fix problem with invalid rendered markdown (#…
Browse files Browse the repository at this point in the history
…173)

Fixes: #169
  • Loading branch information
GNUSheep committed Jan 2, 2024
1 parent 1c75c89 commit 262181b
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 41 deletions.
73 changes: 47 additions & 26 deletions docs/result.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,20 @@ is_ok(result: 'Result[T, E]') → TypeGuard[Ok[T]]

A typeguard to check if a result is an Ok

Usage: ``` r: Result[int, str] = get_a_result()```
``` if is_ok(r):``` ``` r # r is of type Ok[int]```
``` elif is_err(r):``` ``` r # r is of type Err[str]```
Usage:

``` python
r: Result[int, str] = get_a_result()
if is_ok(r):
r # r is of type Ok[int]
elif is_err(r):
r # r is of type Err[str]
```


---

<a href="https://github.com/rustedpy/result/blob/master/src/result/result.py#L517"><img align="right" style="float:right;" src="https://img.shields.io/badge/-source-cccccc?style=flat-square"></a>
<a href="https://github.com/rustedpy/result/blob/master/src/result/result.py#L521"><img align="right" style="float:right;" src="https://img.shields.io/badge/-source-cccccc?style=flat-square"></a>

## <kbd>function</kbd> `is_err`

Expand All @@ -73,15 +78,20 @@ is_err(result: 'Result[T, E]') → TypeGuard[Err[E]]

A typeguard to check if a result is an Err

Usage: ``` r: Result[int, str] = get_a_result()```
``` if is_ok(r):``` ``` r # r is of type Ok[int]```
``` elif is_err(r):``` ``` r # r is of type Err[str]```
Usage:

``` python
r: Result[int, str] = get_a_result()
if is_ok(r):
r # r is of type Ok[int]
elif is_err(r):
r # r is of type Err[str]
```


---

<a href="https://github.com/rustedpy/result/blob/master/src/result/result.py#L530"><img align="right" style="float:right;" src="https://img.shields.io/badge/-source-cccccc?style=flat-square"></a>
<a href="https://github.com/rustedpy/result/blob/master/src/result/result.py#L538"><img align="right" style="float:right;" src="https://img.shields.io/badge/-source-cccccc?style=flat-square"></a>

## <kbd>function</kbd> `do`

Expand All @@ -93,22 +103,32 @@ Do notation for Result (syntactic sugar for sequence of `and_then()` calls).



Usage: ``` # This is similar to```
Usage:

``` rust
// This is similar to
use do_notation::m;
let final_result = m! {
x <- Ok("hello");
y <- Ok(True);
Ok(len(x) + int(y) + 0.5)
};
```

``` final_result: Result[float, int] = do(``` Ok(len(x) + int(y) + 0.5) for x in Ok("hello") for y in Ok(True) )
``` rust
final_result: Result[float, int] = do(
Ok(len(x) + int(y) + 0.5)
for x in Ok("hello")
for y in Ok(True)
)
```

NOTE: If you exclude the type annotation e.g. `Result[float, int]` your type checker might be unable to infer the return type. To avoid an error, you might need to help it with the type hint.


---

<a href="https://github.com/rustedpy/result/blob/master/src/result/result.py#L570"><img align="right" style="float:right;" src="https://img.shields.io/badge/-source-cccccc?style=flat-square"></a>
<a href="https://github.com/rustedpy/result/blob/master/src/result/result.py#L583"><img align="right" style="float:right;" src="https://img.shields.io/badge/-source-cccccc?style=flat-square"></a>

## <kbd>function</kbd> `do_async`

Expand All @@ -120,43 +140,44 @@ do_async(

Async version of do. Example:

``` final_result: Result[float, int] = await do_async(```
``` python
final_result: Result[float, int] = await do_async(
Ok(len(x) + int(y) + z)
for x in await get_async_result_1()
for y in await get_async_result_2()
for z in get_sync_result_3()
)
```

NOTE: Python makes generators async in a counter-intuitive way.
This is a regular generator:
NOTE: Python makes generators async in a counter-intuitive way.

``` python
# This is a regular generator:
async def foo(): ...
do(Ok(1) for x in await foo())
```

But this is an async generator:
``` python
# But this is an async generator:
async def foo(): ...
async def bar(): ...
do(
Ok(1)
for x in await foo()
for y in await bar()
)
```

We let users try to use regular `do()`, which works in some cases
of awaiting async values. If we hit a case like above, we raise
an exception telling the user to use `do_async()` instead.
See `do()`.
We let users try to use regular `do()`, which works in some cases of awaiting async values. If we hit a case like above, we raise an exception telling the user to use `do_async()` instead. See `do()`.

However, for better usability, it's better for `do_async()` to also accept
regular generators, as you get in the first case:
However, for better usability, it's better for `do_async()` to also accept regular generators, as you get in the first case:

``` python
async def foo(): ...
do(Ok(1) for x in await foo())
```

Furthermore, neither mypy nor pyright can infer that the second case is
actually an async generator, so we cannot annotate `do_async()`
as accepting only an async generator. This is additional motivation
to accept either.

Furthermore, neither mypy nor pyright can infer that the second case is actually an async generator, so we cannot annotate `do_async()` as accepting only an async generator. This is additional motivation to accept either.


---
Expand Down
52 changes: 37 additions & 15 deletions src/result/result.py
Original file line number Diff line number Diff line change
Expand Up @@ -505,11 +505,15 @@ def is_ok(result: Result[T, E]) -> TypeGuard[Ok[T]]:
"""A typeguard to check if a result is an Ok
Usage:
>>> r: Result[int, str] = get_a_result()
>>> if is_ok(r):
>>> r # r is of type Ok[int]
>>> elif is_err(r):
>>> r # r is of type Err[str]
``` python
r: Result[int, str] = get_a_result()
if is_ok(r):
r # r is of type Ok[int]
elif is_err(r):
r # r is of type Err[str]
```
"""
return result.is_ok()

Expand All @@ -518,11 +522,15 @@ def is_err(result: Result[T, E]) -> TypeGuard[Err[E]]:
"""A typeguard to check if a result is an Err
Usage:
>>> r: Result[int, str] = get_a_result()
>>> if is_ok(r):
>>> r # r is of type Ok[int]
>>> elif is_err(r):
>>> r # r is of type Err[str]
``` python
r: Result[int, str] = get_a_result()
if is_ok(r):
r # r is of type Ok[int]
elif is_err(r):
r # r is of type Err[str]
```
"""
return result.is_err()

Expand All @@ -532,19 +540,24 @@ def do(gen: Generator[Result[T, E], None, None]) -> Result[T, E]:
Usage:
>>> # This is similar to
``` rust
// This is similar to
use do_notation::m;
let final_result = m! {
x <- Ok("hello");
y <- Ok(True);
Ok(len(x) + int(y) + 0.5)
};
```
>>> final_result: Result[float, int] = do(
``` rust
final_result: Result[float, int] = do(
Ok(len(x) + int(y) + 0.5)
for x in Ok("hello")
for y in Ok(True)
)
```
NOTE: If you exclude the type annotation e.g. `Result[float, int]`
your type checker might be unable to infer the return type.
Expand Down Expand Up @@ -572,26 +585,33 @@ async def do_async(
) -> Result[T, E]:
"""Async version of do. Example:
>>> final_result: Result[float, int] = await do_async(
``` python
final_result: Result[float, int] = await do_async(
Ok(len(x) + int(y) + z)
for x in await get_async_result_1()
for y in await get_async_result_2()
for z in get_sync_result_3()
)
```
NOTE: Python makes generators async in a counter-intuitive way.
This is a regular generator:
``` python
# This is a regular generator:
async def foo(): ...
do(Ok(1) for x in await foo())
```
But this is an async generator:
``` python
# But this is an async generator:
async def foo(): ...
async def bar(): ...
do(
Ok(1)
for x in await foo()
for y in await bar()
)
```
We let users try to use regular `do()`, which works in some cases
of awaiting async values. If we hit a case like above, we raise
Expand All @@ -601,8 +621,10 @@ async def bar(): ...
However, for better usability, it's better for `do_async()` to also accept
regular generators, as you get in the first case:
``` python
async def foo(): ...
do(Ok(1) for x in await foo())
```
Furthermore, neither mypy nor pyright can infer that the second case is
actually an async generator, so we cannot annotate `do_async()`
Expand Down

0 comments on commit 262181b

Please sign in to comment.