Some batteries Python didn't come with - a pipe operator, d language style ranges, and more

piping, pipeline, pipe, functional, ranges, python
pip install coppertop==v0.1.6



The coppertop package has two key features, a piping opertor and D language style ranges. I have found these useful for writing code in a piping style (i.e. in a smalltalk / kdb / functional manner).

The quickest and most effective way of gaining an understanding of the codebase is to start up your favourite debugger (e.g. PyCharm) and dive straight into the following:

follow the overview test in coppertop/tests/


  1. coppertop/examples/ and coppertop/examples/tests/ solve the jsp problem described in

  2. coppertop/examples/ and coppertop/examples/tests/ solve the calendar printing problem described in


The Pipeable decorator extends functions with the >> and << operators with the effect of adding pipeline like behaviour (e.g. similar to |> in F#).

x >> f and f >> x both answer f(x)
x << f calls f(x) and answers x
f << x calls f(x) and answers f

or equivalently,
lhs >> rhs answers f(x)
lhs << rhs calls f(x) and answers the lhs


from coppertop import Pipeable

def Each(xs, f):
    return [f(x) for x in xs]

def Chain(seed, xs, f):
    prior = seed
    for x in xs:
        prior = f(prior, x)
    return prior

def SquareIt(x):
    return x * x

def Add(x, y):
    return x + y

actual = [1,2,3] >> Each >> SquareIt >> Chain(seed=0) >> Add
expected = 14
assert actual == expected

Addtionally functions that are decorated with Pipeable can easily be made partial by providing some of the arguments, for example Chain(seed=0) in the code above.


Using D style ranges is similar to programming with a non-reactive pull style DAG. Debugging an apparently simple sequence such as

def test_checkNumberOfDaysInEachMonth():
    2020 >> DatesInYear \
        >> MonthChunks \
        >> Materialise >> Each >> Len \
        >> AssertEqual >> [31,29,31,30,31,30,31,31,30,31,30,31]

is similar to DAG debugging in that you need to have breakpoints in many places and code can be hard to step through.

However the the range implementation in D has a key redeeming feature.

The input and output types are not fixed as in typical DAG implementations so each range is easier to test and reason about in isolation. Thus they can be composed more easily in longer pipelines and with a higher degree of confidence.