Skip to main content

Chain functions easily and safely

Project description

logo FunChain

chain functions easily and safely

Tests License MIT Read the Docs Python versions PyPI version PyPI - Downloads

Introduction

FunChain is a package that provides tools and utilities to easily compose functions sequentially to create processing pipelines with minimum code and simple syntax, all while tracking, reporting and containing any crash that could occur in any step.

The library was part of another API client project and was developed to reduce boilerplate code when dealing with networking and unstructured responses, after that and due to its general purpose usage, it was separated into an independent library that could be integrated in other python projects.

FunChain is now based on another standalone library called Failures that only specialises in labeling and reporting nested errors.

NOTE This library is still in experimentation phase, if you plan to include it in your production app, make sure to test that use case to avoid any unexpected bugs.

Installation

You can include FunChain into your environment using this command

pip install funchain

Audience

Anyone working on a python project that requires processing data through multiple functions and needs to isolate each step and report errors with labels and details can benefit from the tooling offered by this library, using it may reduce boilerplate code and code repetition.

Continue reading the documentation to find out if FunChain offers tools that you need or aligns with your design pattern.

Features

Composing functions sequentially 🔗

Composing functions in a sequence to create a pipeline is the main functionality of this library, the sequence of functions (or so-called nodes) results in a single function-like objects that passes the result of one function to the next as input.

This means fun1 ➜ fun2 ➜ fun3, or programmatically speaking fun3(fun2(fun1(input)))

Iterating multiple items ⛓️

While composing functions, we might want to apply a function to each item of an iterable instead of applying it to the whole iterable, for example if fun1 returns a list like [1, 2, 3] the next one will be called like [fun2(1), fun2(2), fun2(3)] instead of fun2([1, 2, 3])

This means fun1 ⭄ fun2, or programmatically speaking [fun2(item) for item in fun1(input)]

Branching 🦑

When a returned value needs to take multiple routes at some points, we can use branching methods, and that by defining the structure of the result and (either a dict and list) filling it with the sequence of functions, and the result will have the same structure.

So for dictionaries, the model {'a': fun1, 'b': fun2} will return {'a': fun1(input), 'b': fun2(input)}

And the model [fun1, fun2] will return [fun1(input), fun2(input)].

Debug friendly 🪲

Composing multiple functions makes it hard to traceback errors and get which input caused it, especially in production where it's hard to reproduce the same crash or debug it. But thanks to the failures library, tracking and pinpointing nested errors becomes way easier; each exception gets wrapped and labeled with a qualified name indicating its location, and the exact input that caused it.

Good and minimal syntax 🎈

The syntax of this library was intentionally made easy and minimal users to compose functions, to achieve complex pipeline structures with the least amount of code, and make it more readable and intuitive to be easily maintained. It also makes it a beginner-friendly tool with a gentle learning curve.

Async support 🪄

All the previously mentioned features are available for asynchronous operations; coroutines can be composed together the same way to produce an asynchronous chain of functions, the same if a normal function is piped to an async one.

Normal and asynchronous functions can be mixed together and funchain will know what to do, and if any async function is chained, the result will automatically be an asynchronous callable.

This makes this library a good choice for processing IO intensive operations, such as performing network requests or reading files from the hard drive in a non-blocking way.

Flexibility

The structure of a function chain can be as deep and complex as needed, every component is considered a chain node, so a chain can contain a dict or list model and each can contain another chain or model and so.

Usage

Function chaining

This example illustrates how to compose functions in a sequence using chain()

>>> from funchain import chain

>>> def add_two(num: int) -> int:
...   return num + 2

>>> def double(num: int) -> int:
...   return num * 2

>>> fun = chain(add_two, double, add_two)

>>> fun(5)
16

In this example we created two simple functions add_two and double and we chained them chain(add_two, double, add_two).

This basically means that any input given to fun which is a chain, will be incremented by 2, then doubled, then incremented again by 2;

This mean: add_two(5) = 7 ⮕ double(7) = 14 ⮕ add_two(14) = 16

Predefined nodes

We can compile nodes in advance using node() and chain them later by concatenation (using + operator)

>>> from funchain import node

>>> add_two = node(lambda x: x + 2, name="add_two")

>>> double = node(lambda x: x * 2, name="double")

>>> fun = add_two | double | add_two

>>> fun(5)
16

This works the same as the first example and it's more convenient for functions that are meant to be used as components.

If we had a functions like the previous example, we can integrate compile it to a node like this

>>> from funchain import node

>>> def double(num: int) -> int:
...   return num * 2

>>> nd = node(double)

>>> fun = nd | nd

>>> fun(5)
20

... TODO

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

FunChain-0.1.0.tar.gz (12.5 kB view details)

Uploaded Source

Built Distribution

FunChain-0.1.0-py3-none-any.whl (11.6 kB view details)

Uploaded Python 3

File details

Details for the file FunChain-0.1.0.tar.gz.

File metadata

  • Download URL: FunChain-0.1.0.tar.gz
  • Upload date:
  • Size: 12.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.2 CPython/3.11.7

File hashes

Hashes for FunChain-0.1.0.tar.gz
Algorithm Hash digest
SHA256 e35dae1364c83ddb4b48b50695a98a33ac92a5b0525c488edb09befc215e086c
MD5 14f036cb4df68df285fa48564f967e1a
BLAKE2b-256 02ac0070dd2b92f6230c7b9e7baa40b2f5edfffd3b2327381e2d4e7f55887983

See more details on using hashes here.

File details

Details for the file FunChain-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: FunChain-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 11.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.2 CPython/3.11.7

File hashes

Hashes for FunChain-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 b903225fc022517824456d5889ab0c4a1134705bb567df3067e8ed436a1b176c
MD5 60a610aed7d8902866691ce757a93fee
BLAKE2b-256 ce753ed1336d40ed2d2c3912fe6242810bf6eafcbfcbb17c837d54b33a43d704

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page