Metadata-Version: 2.3
Name: bifurcate
Version: 2.0.0
Summary: Emergent parallelism and execution branching from inside your functions
Keywords: parallelism,branching,concurrency,decorator,execution
Author: Wannes Vantorre
Author-email: Wannes Vantorre <vantorrewannes@gmail.com>
License: MIT
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Utilities
Requires-Python: >=3.14
Project-URL: Homepage, https://codeberg.org/ProductionCode/bifurcate
Project-URL: Repository, https://codeberg.org/ProductionCode/bifurcate
Project-URL: Issues, https://codeberg.org/ProductionCode/bifurcate/issues
Description-Content-Type: text/markdown

# bifurcate

**Emergent parallelism and execution branching from inside your functions.**

Standard patterns force you to extract your logic and wrap it in `for` loops or complex task graphs just to run variations of a pipeline. `bifurcate` lets you branch the execution graph dynamically from _inside_ the function itself.

Write your logic sequentially, as if it only runs once. Let the system magically map the permutations.

## Usage

```python
import bifurcate

@bifurcate.collect
def calculate_pricing(user_id):
    base_price = database.get_price(user_id)

    # BRANCH POINT:
    # The system transparently forks the execution universe here.
    discount = bifurcate.branch([0.0, 0.10, 0.20])

    final_price = base_price * (1 - discount)

    # You own the traceability. Return a dict to map paths to results.
    return {"discount": discount, "price": final_price}

# The decorator automatically aggregates the permutations
results = calculate_pricing("user_123")
# Output:[{'discount': 0.0, 'price': 100}, {'discount': 0.1, 'price': 90}, ...]
```

## Features

- **In-line Branching:** No more `for` loops polluting your caller logic. Keep your domain functions completely isolated and focused on single-item math.
- **Zero-Boilerplate Permutations:** Perfect for A/B testing, ML hyperparameter sweeps, or fallback strategies.
- **The List Monad for Python:** Achieves mathematically pure map/flatMap operations using standard, highly-readable imperative Python syntax.

## Core Mechanics

- **Bytecode Identity:** The system doesn't track sequence order. It uses Python's bytecode instruction pointer (`f_lasti`) to identify branches. This means you can safely place `branch()` inside unpredictable `if` statements or unordered `set()` iterations. The execution topology can be completely dynamic.
- **Primitive Composition:** Because `bifurcate` simply re-evaluates the function using native mechanics, it composes flawlessly with pure caching tools. Heavy setup steps before the fork can be memoized seamlessly without DAG configuration.

## Installation

```bash
uv add bifurcate
# or
pip install bifurcate
```
