insequence 5

Creator: bradpython12

Last updated:

Add to Cart

Description:

insequence 5

insequence
A small Python library for function composition and execution orchestration.
Setup
Currently, Python 3.10 or higher is required. There are no further runtime requirements.
Install via pip install insequence or uv pip install insequence.
For full type-annotation support, install insequence[typing]. This will install typing-extensions, which are required for all supported Python versions. This dependency will no longer be needed in Python 3.13 once PEP 742 is implemented.
Outline
insequence facilitates building complex transformations (referred to as Chains) by composing simpler transformations. Each transformation (referred to as an Action) takes a single argument and returns an object of the same type; Actions can be combined only if they operate on the same type.
Actions are generated by factories obtained by applying the action decorator to user-written functions. Generated Actions inherit the first parameter and return type from the decorated function; further parameters of that function become arguments to the Action factory (the process somewhat resembles function currying).
Modifiers allow altering a Chain's execution without any explicit modification of the chain. Adding new modifiers is simple using the controller decorator.
Example
To generate Fibonacci numbers, create two Action factories: one for initialization and one for adding the next number.
>>> from insequence import action
>>>
>>> @action
... def init(numbers: list[int], first: int, second: int) -> list[int]:
... numbers.extend((first, second))
... return numbers
...
>>> @action
... def add_next(numbers: list[int]) -> list[int]:
... numbers.append(numbers[-1] + numbers[-2])
... return numbers

Actions are generated by calling the factory functions and can be composed using +. The resulting Chain is callable; upon execution, the Actions are applied in sequence where each Action receives the output of its predecessor as its own argument.
>>> generate = init(0, 1) + add_next() + add_next() + add_next()
>>> generate([])
[0, 1, 1, 2, 3]

Chain execution can be stopped by raising StopIteration inside one of its Actions. The repeat modifier allows looping (with or without limit) within a Chain.
>>> @action
... def stop_at(numbers: list[int], limit: int) -> list[int]:
... if numbers[-1] > limit:
... raise StopIteration()
... return numbers
...
>>> add_number = add_next() + stop_at(limit=1000)
>>>
>>> from insequence import modifiers
>>> m = modifiers[list[int]]
>>> generate = init(0, 1) + m.repeat()(add_number)
>>> generate([])
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597]

Chain modifiers can themselves be composed. Adding some printing at the end of each iteration of the loop can be done without redefining the add_number.
>>> import time
>>>
>>> @action
... def show(numbers: list[int], sec: float) -> list[int]:
... print(numbers[-1], end="\r")
... time.sleep(sec)
... return numbers
...
>>> generate = init(0, 1) + (m.repeat() + m.append(show(0.1)))(add_number)
>>> generate([])

What's next?
The package repository contains an examples folder with more meaningful examples.

License

For personal and professional use. You cannot resell or redistribute these repositories in their original state.

Customer Reviews

There are no reviews.