Skip to main content

flow-res

Rust 言語の Result 型に範を仰いだ、Python 向けの高機能かつ型安全なエラーハンドリングライブラリです。

従来の例外駆動型(Exception-driven)から、Result 駆動型(Result-driven)へのパラダイムシフトを強力に支援します。明示的なエラーハンドリングを導入することで、コードの堅牢性と可読性を飛躍的に向上させることが可能です。

主要な特徴

  • 厳密な型安全性: ジェネリクスを活用し、成功値とエラー値の双方に対して静的解析(mypy, pyright 等)を適用可能です。
  • 鉄道指向プログラミング(ROP): map や and_then によるメソッドチェーンにより、宣言的なエラーハンドリングを実現します。
  • 非同期処理のネイティブサポート: @async_result デコレータを通じて、非同期処理を AwaitableResult として透過的にチェーン可能です。
  • メタプログラミングによる統合: @safe デコレータを用いることで、既存の例外送出型関数を容易に Result 型へ変換できます。
  • 高度な結果集約: combine(早期失敗)および combine_all(全エラー集約)により、複数の処理結果を合理的に統合します。
  • 軽量設計(ゼロ依存): 外部ライブラリへの依存はなく、プロジェクトへの導入障壁が極めて低く抑えられています。

インストール

pip install flow_res

※ Python 3.13 以上が必要です。

実装ガイド

1. 基本的な定義とハンドリング

関数の戻り値に Result を指定することで、呼び出し側に対してエラー処理の検討を強制(明示)させます。Python 3.10 以降の構造的パターンマッチングを利用することで、エレガントに結果を処理できます。

from flow_res import Result, Ok, Err

def divide(a: int, b: int) -> Result[float, ValueError]:
    """2つの数値の除算を行い、結果を Result 型で返却する"""
    if b == 0:
        return Err(ValueError("Division by zero"))
    return Ok(a / b)

result = divide(10, 2)
match result:
    case Ok(value):
        print(f"Success: {value}")
    case Err(error):
        print(f"Failure: {error}")

2. 関数型インターフェースによる連鎖処理 (Railroad-Oriented Programming)

map や and_then を用いることで、命令的な条件分岐を排除し、処理のパイプラインを構築できます。

from flow_res import Err, Ok, Result

def validate_positive(x: int) -> Result[int, ValueError]:
    if x < 0:
        return Err(ValueError("Must be positive"))
    return Ok(x)

# 依存関係のある処理の連結
result = (
    Ok(5)
    .and_then(validate_positive)
    .map(lambda x: x * 2)
    .map(lambda x: x + 3)
)
print(result.unwrap())  # 13

3. @safe デコレータによる例外のラップ

既存の例外を発生させる可能性のある関数を、低コストで Result 駆動型へ移行させます。

from flow_res import safe

@safe
def parse_int(s: str) -> int:
    return int(s)

# 例外は送出されず、Err として返却される
result = parse_int("not_a_number")
print(result)  # Err(error=ValueError("invalid literal for int() with base 10: 'not_a_number'"))

4. 非同期処理の統合 (@async_result)

@async_result デコレータを使用することで、非同期関数の実行結果に対しても await 前にメソッドチェーンを適用できます。 AwaitableResult は内部のコルーチンを一つだけ保持する単一消費型です。同じインスタンスを複数回 await したり、複数のチェーンへ分岐させたりせず、一つのチェーンで消費してください。

import asyncio
from flow_res import Err, Ok, Result, async_result

@async_result
async def fetch_user(user_id: int) -> Result[dict, ValueError]:
    await asyncio.sleep(0.1)
    if user_id < 0:
        return Err(ValueError("Invalid user ID"))
    return Ok({"id": user_id, "name": f"User{user_id}"})

async def main():
    # 処理を連結した後に一括で await
    result = await (
        fetch_user(1)
        .map(lambda u: u["name"])
        .map(str.upper)
    )
    print(result.unwrap())  # USER1

asyncio.run(main())

5. 複数結果の集約ロジック (combine / combine_all)

バリデーションなど、複数の検証結果を一括で扱うためのインターフェースを提供します。

  • combine: 最初に遭遇した Err を返却する(短絡評価・早期失敗)
  • combine_all: すべての Err を集約して複数の例外を保持する Err を返却する(全件チェック)
from flow_res import Result, combine, combine_all, Ok, Err

results = (
    Ok(1),
    Err(ValueError("error1")),
    Err(RuntimeError("error2")),
)

# 最初のエラー (error1) のみを返す
print(combine(results)) 

# すべてのエラーを集約して返す
match combine_all(results):
    case Err(error):
        for e in error.exceptions:
            print(f"Error: {e}")

動作環境

  • Python バージョン: 3.13 以上
  • 型ヒント: 完全対応(Static Type Checking を推奨)

ライセンス

本プロジェクトは MIT License の下に公開されています。

協力・貢献

不具合報告や機能拡張の提案は、GitHub Issues にて承っております。

Metadata

Release files for flow-res 0.1.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for flow-res 0.1.2
File Size Uploaded
flow_res-0.1.2.tar.gz 42.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for flow-res 0.1.2
File Interpreter ABI Platform
flow_res-0.1.2-py3-none-any.whl Python 3 none any Details

Total release size: 53.8 kB

Release files / flow_res-0.1.2.tar.gz

Download URL flow_res-0.1.2.tar.gz
Size 42.7 kB
Tags Source
SHA-256 checksum
How to use checksums
0c2014ce9e1cde74472c2f323e389c4ad2992ed4f0c7c8738a98e1586a9fb337
BLAKE2b-256 checksum
How to use checksums
3c1e56031bb443755bee9e913c036bbf3987a4b1c989da4d96a3ec5f6a35f07b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 28, 2026.

Transparency log

Release files / flow_res-0.1.2-py3-none-any.whl

Download URL flow_res-0.1.2-py3-none-any.whl
Size 11.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
203c313cbf65bc746500ca13c664431fd217fa5b5e45f5626058a2db14865c92
BLAKE2b-256 checksum
How to use checksums
ac399dc4f8f85aa412bf4226a03d46c829b735b918b298bf4e5f58f3b36fc8c3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 28, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.2 This release

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page