Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Check all pydoc strings, fix problem with invalid rendered markdown #173

Merged
merged 3 commits into from
Jan 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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]
```
francium marked this conversation as resolved.
Show resolved Hide resolved

"""
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
Loading