chainlet - blocks for processing chains

Build Status Code Health Test Coverage Documentation Status

The chainlet library lets you quickly build iterative processing sequences. At its heart, it is built for chaining generators/coroutines, but supports arbitrary objects. It offers an easy, readable way to link elements using a concise mini language:

data_chain = read('data.txt') >> filterlet(preserve=bool) >> convert(apply=ast.literal_eval)
for element in chain:
    print(element)

The same interface can be used to create chains that push data from the start downwards, or to pull from the end upwards.

push_chain = uppercase >> encode_r13 >> mark_of_insanity >> printer
push_chain.send('uryyb jbeyq')  # outputs 'Hello World!!!'

pull_chain = word_maker >> cleanup >> encode_r13 >> lowercase
print(next(pull_chain))  # outputs 'uryyb jbeyq'

Creating new elements is intuitive and simple, as chainlet handles all the gluing and binding for you. Most functionality can be created from regular functions, generators and coroutines:

@chainlet.genlet
def moving_average(window_size=8):
    buffer = collections.deque([(yield)], maxlen=window_size)
    while True:
        new_value = yield(sum(buffer)/len(buffer))
        buffer.append(new_value)

Quick Overview

To just plug together existing chainlets, have a look at the Chainlet Mini Language. To port existing imperative code, the chainlet.protolink module provides simple helpers and equivalents of builtins.

Writing new chainlets is easily done writing generators, coroutines and functions, decorated with chainlet.genlet() or chainlet.funclet(). A chainlet.genlet() is best when state must be preserved between calls. A chainlet.funclet() allows resuming even after exceptions.

Advanced chainlets are best implemented as a subclass of chainlet.ChainLink. Overwrite instantiation and chainlet_send() to change their behaviour [1]. In order to change binding semantics, overwrite the __rshift__ and __lshift__ operators.

Contributing and Feedback

The project is hosted on github. If you have issues or suggestion, check the issue tracker: Open Issues For direct contributions, feel free to fork the development branch and open a pull request.

Indices and tables


[1]Both chainlet.genlet() and chainlet.funclet() implement instantiation and chainlet_send() for the most common use case. They simply bind their callables on instantitation, then call them on chainlet_send().

Documentation built from chainlet 1.3.1 at Jun 12, 2018.