ProvenPin Install

toolz compose, curry and cytoolz-accelerated pipelines: working versions (tested 2026-10-16)

Build lazy functional pipelines with toolz.compose, curry and pipe, accelerated by cytoolz.curried map/filter/reduce, and test the lazy and curry gotchas offline.

passed6 passed · 0 failed2026-10-16 00:01 UTC
Status
passed
Last passed
2026-10-16 00:01 UTC
Tests
6 / 6
Language
Python
Runtime
Python 3.13.16
pinned versions3
toolz@1.2.0cytoolz@1.2.0pytest@9.1.1
run it
uv venv -q .venv && uv pip install -q --python .venv/bin/python -r requirements.txt
.venv/bin/python -m pytest -q
test environment
Python 3.13.16
linux 6.17.0-1022-azure
x64
runner: github-actions 38826982604

The code

Exactly the files that passed. Your agent can pull them with get_recipe("toolz-cytoolz-pipeline") (install), or see them on GitHub.

requirements.txt
toolz==1.2.0
cytoolz==1.2.0
pytest==9.1.1
pipeline.py
from toolz import compose, curry, pipe
from cytoolz import curry as ccurry
from cytoolz.curried import map as cmap, filter as cfilter, reduce as creduce


@ccurry
def scale(factor, value):
    return factor * value


@ccurry
def bump(value, by):
    return value + by


def add_one(value):
    return value + 1


def running_total(values):
    # cmap is lazy, creduce consumes it left to right
    return creduce(bump, cmap(scale(2), values), 0)


def evens_plus_one(values):
    # returns a lazy cytoolz iterator, nothing runs until consumed
    return cmap(add_one, cfilter(lambda x: x % 2 == 0, values))
tests/test_pipeline.py
import pytest
import cytoolz
import cytoolz.curried
from toolz import compose, curry, pipe
from cytoolz import curry as ccurry

from pipeline import scale, bump, add_one, running_total, evens_plus_one


def test_compose_is_right_to_left():
    assert compose(add_one, scale(2))(5) == 11
    assert pipe(5, scale(2), add_one) == 11
    assert compose(scale(2), add_one)(5) == 12


def test_cytoolz_pipeline_is_lazy():
    seen = []

    def record(x):
        seen.append(x)
        return x

    stream = compose(
        cytoolz.curried.map(record),
        cytoolz.curried.filter(lambda n: n % 2 == 0),
    )([1, 2, 3, 4])

    assert seen == []
    with pytest.raises(TypeError):
        len(stream)
    assert list(stream) == [2, 4]
    assert seen == [2, 4]


def test_lazy_iterator_is_single_use():
    stream = evens_plus_one([1, 2, 3, 4])
    assert list(stream) == [3, 5]
    assert list(stream) == []


def test_top_level_cytoolz_map_is_not_curried():
    with pytest.raises(TypeError):
        cytoolz.map(add_one)
    assert list(cytoolz.curried.map(add_one)([1, 2])) == [2, 3]


def test_curry_and_default_arguments():
    @ccurry
    def tag(prefix, value, sep="-"):
        return f"{prefix}{sep}{value}"

    assert callable(tag("x"))
    assert tag("x", "y") == "x-y"
    assert tag("x", sep=":")("y") == "x:y"


def test_toolz_and_cytoolz_curry_compose_together():
    def inc_by(value, by):
        return value + by

    t_inc = curry(inc_by)
    c_inc = ccurry(inc_by)

    assert type(t_inc) is not type(c_inc)
    pipeline = compose(scale(2), c_inc(1), t_inc(10))
    assert list(map(pipeline, [1, 2])) == [24, 26]
    assert running_total([1, 2, 3, 4]) == 20
pytest.ini
[pytest]
pythonpath = .

Connect to ProvenPin

Add the free MCP server so your agent can pull this recipe and others like it. Same setup as the docs.

terminal
claude mcp add --transport http provenpin https://mcp.provenpin.com/mcp

Any other MCP client: Streamable HTTP at https://mcp.provenpin.com/mcp. No API key, no signup.