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 2 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
94 changes: 62 additions & 32 deletions docs/result.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,22 @@ 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#L523"><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 +80,22 @@ 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#L542"><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 +107,36 @@ 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#L591"><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 @@ -118,28 +146,26 @@ do_async(
) → Result[T, E]
```

Async version of do. Example:
Async version of do. Example: ```
``` 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()
)
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() )

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This rendered example doesn't look right. There's some issue with the docstring.

Tip, you can use this button to preview it in GitHub, in case you had not used it before
image

```

NOTE: Python makes generators async in a counter-intuitive way.
This is a regular generator:
async def foo(): ...
do(Ok(1) for x in await foo())

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()
)

``` python

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

```

``` 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 @@ -149,14 +175,18 @@ See `do()`.
However, for better usability, it's better for `do_async()` to also accept
regular generators, as you get in the first case:

async def foo(): ...
do(Ok(1) for x in await foo())
``` 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.

```


---
Expand Down
68 changes: 53 additions & 15 deletions src/result/result.py
Original file line number Diff line number Diff line change
Expand Up @@ -505,11 +505,17 @@ 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 +524,17 @@ 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,20 +544,29 @@ 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.
To avoid an error, you might need to help it with the type hint.
Expand All @@ -572,19 +593,30 @@ 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(
Expand All @@ -593,6 +625,8 @@ async def bar(): ...
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.
Expand All @@ -601,9 +635,13 @@ 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()`
as accepting only an async generator. This is additional motivation
Expand Down
Loading