dry-python / dry-python/returns

feat request/suggestion: fuse results from multiple results into the args of one target function

オープン
#2,045 コメント 2 件 リアクション 0 件 担当者 0 名 GitHub で見る
主要言語
Python
スター
4.4k
フォーク
155
平均マージ
2時間 27分
マージ済み PR(30日)
22

説明

A way to join the results from multiple stages to a single function fusing the results into the positional args of the target function.

Thinking something like this could work, let me know if you think it's worth cleaning up/documenting and writing all the tests for:

```python
from typing import Iterable, Callable
import inspect
from returns.result import Success, Failure, Result

def fuse(results: Iterable[Result], target: Callable) -> Result:
"""Fuse the results from multiple containers into the args for a target function.

Args:
results (Iterable[Result]): The results from multiple container functions.
target (Callable): The target function that receives the arguments.
"""
successes, failures, invalid = [], [], []

for res in results:
match res:
case Success(value):
successes.append(value)
case Failure(error):
failures.append(error)
case _:
invalid.append(res)

if invalid:
return Failure(ValueError(f"Input args are not all Result types: {invalid}"))

if failures:
return Failure(ValueError(f"Not all results are Success: {failures}"))

expected_args = len(inspect.signature(target).parameters)

if len(successes) != expected_args:
return Failure(
ValueError(
f"Expected {expected_args} args for `{target.__name__}`, but got {len(successes)}"
)
)
try:
return target(*successes)
except Exception as e:
return Failure(e)
```

Using this basic case function here:
```python
def add(a, b) -> Result[int, str]:
if a > 0:
return Success(a + b)
return Failure(f"Err: expected `a` > 0. Got `a`= {a}.")

```

# Usage:
### Happy path all args are expected
```python
fuse([Success(1), Success(3)], add)
```
output:
```

```

### Returns failure if some exist
```python
fuse([Success(3), Failure("Err: expected `a` > 0. Got `a`= -2.")], add)
```
output:
```
0. Got `a`= -2.']>
```

### Catch all the failures and report them all (avoiding solving one issue then finding another)
```python
fuse([Failure("Err: expected `a` > 0. Got `a`= -2."), Failure("Err: expected `a` > 0. Got `a`= -2.")], add)
```
output:
```
0. Got `a`= -2.', 'Err: expected `a` > 0. Got `a`= -2.']>
```

### Catch when someone is passing in a non Result type:
```python
fuse([1, Failure("Err: expected `a` > 0. Got `a`= -2.")], add)
```
output:
```

```

### catch if not given the right number of args:
```python
fuse([Success(1)], add)
```
output:
```

```

### catch overall exceptions just in case:
```python
fuse([Success(1), Success("1")], add)
```

output
```

```

コントリビューションガイド

コントリビューションガイドを開く

評価

この issue はまだ評価されていません。

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。