Skip to main content

chrisjen

Version PyPI Latest Release GitHub Latest Release
Status Build Status Development Status Project Stability
Documentation Hosted By
Tools Documentation Linter Dependency Manager Pre-commit CI Editor Settings Repository Template Dependency Maintainer
Compatibility Compatible Python Versions Linux MacOS Windows
Stats PyPI Download Rate (per month) GitHub Stars GitHub Contributors GitHub Issues GitHub Forks

What is chrisjen?

Named after Earth's unflappable leader in The Expanse, who knew how to get things done, chrisjen builds and runs project workflows from a plain settings file (or a Python dict). You list the parts of your project and the techniques that each part uses. chrisjen connects them into a workflow, applies it to your data, and, if you ask it to, compares alternatives and picks the best.

import dataclasses

import chrisjen


@dataclasses.dataclass
class DropNegatives(chrisjen.Technique):
    def implement(self, item, **kwargs):
        return [x for x in item if x >= 0]


@dataclasses.dataclass
class Double(chrisjen.Technique):
    def implement(self, item, **kwargs):
        return [x * 2 for x in item]


@dataclasses.dataclass
class Total(chrisjen.Technique):
    def implement(self, item, **kwargs):
        return sum(item)


settings = {
    "report_project": {"report_workers": "prepare, summarize"},
    "prepare": {"techniques": "drop_negatives, double"},
    "summarize": {"techniques": "total"},
}

project = chrisjen.Project.create(settings, item = [3, -1, 4, -1, 5])
print(project.result)
# 24

Why use chrisjen?

Intuitive

A chrisjen project is made of techniques, the actual actions, which are grouped into workers, the parts of a project (for example, "prepare" and "summarize"). A worker can also have steps, each with techniques of its own.

You describe them in an ini, toml, json, yaml, xml, or Python file (or a dict), and a Project does the rest. The same example as a file:

[report_project]
report_workers = prepare, summarize

[prepare]
techniques = drop_negatives, double

[summarize]
techniques = total
project = chrisjen.Project.create("report.ini", item = [3, -1, 4, -1, 5])
print(project.result)
# 24

chrisjen has no scripting language to learn. The settings file only names things. What those things do is plain Python.

Powerful

Each worker (and the project itself) has a design that decides how its parts are applied:

Design What it does
flow Applies its parts one after another. This is the default.
benchmark Repeats its parts until a criterion is met.
contest Tries every combination of alternatives and keeps the best result.
survey Tries every combination of alternatives and averages the results.

For example, to try three ways of scaling and keep whichever has the smallest spread, make the project a contest and name a criterion:

@dataclasses.dataclass
class Halve(chrisjen.Technique):
    def implement(self, item, **kwargs):
        return [x / 2 for x in item]


@dataclasses.dataclass
class SmallestSpread(chrisjen.Criteria):
    def score(self, item):
        return -(max(item) - min(item))


settings = {
    "compare_project": {
        "design": "contest",
        "criterion": "smallest_spread",
        "techniques": "double, halve, none",
    },
}
project = chrisjen.Project.create(settings, item = [1, 2, 3])
print(project.result)
# [0.5, 1.0, 1.5]
print(project.workflow.winner)
# halve

none is a built-in technique that does nothing, which is useful for testing whether a technique helps at all.

Flexible

chrisjen is built from small libraries that each do one job, and you can use any of them on its own:

Library What chrisjen uses it for
bobbie Loading settings from files and dict types.
holden The graph data structure of a workflow, including exports to Graphviz and mermaid.
nagata Loading and saving a project's files.
camina Small helpers, such as naming each run of a project.

A technique is an object that wraps any callable (or the import path of one), so a single interface can drive tools from many packages. Every class you define (techniques, designs, criteria, and reports) is added to a library under its snake case name as soon as it is defined, so it can be used in settings right away.

Getting started

Requirements

chrisjen requires Python 3.11 or later. It runs on Linux, macOS, and Windows. Its dependencies are installed automatically. If you want to load yaml or xml settings or use pandas file formats, also install the optional dependencies of those packages (for example, pip install pyyaml xmltodict pandas).

Installation

To install chrisjen, use pip:

pip install chrisjen

Usage

Techniques

A technique is a subclass of chrisjen.Technique. Either write an implement method, or set contents to the tool that the technique wraps: a callable, or its import path (which is only imported when the technique is used). The item is passed to the tool along with any keyword parameters that the tool accepts. Parameters come from a {name}_parameters section of your settings:

@dataclasses.dataclass
class Mean(chrisjen.Technique):
    contents: str = "statistics.fmean"


@dataclasses.dataclass
class Rounded(chrisjen.Technique):
    contents: object = round


settings = {
    "average_project": {"techniques": "mean, rounded"},
    "rounded_parameters": {"ndigits": 1},
}
print(chrisjen.Project.create(settings, item = [1, 2, 4]).result)
# 2.3

Workers and steps

A worker lists its techniques or its steps, and each step lists its techniques. In the default flow design, they are applied in order. In a contest or a survey, the techniques of each step are alternatives, and every combination of one technique from each step is tried:

settings = {
    "numbers_project": {"numbers_workers": "prepare"},
    "prepare": {
        "steps": "clean, resize",
        "clean_techniques": "drop_negatives",
        "resize_techniques": "double, halve",
    },
}
project = chrisjen.Project.create(settings, item = [1, -2, 3])
print(project.result)
# [1.0, 3.0]

Running a project

Project.create reads the settings, builds the workflow, and (unless automatic = False) applies it to item. The result is stored in result, and a report summarizes the run. apply runs the project again, on a new item if you pass one. Each run has an id, which is the name of the project and the date and time unless you pass one:

project = chrisjen.Project.create(
    "report.ini", id = "first_run", automatic = False)
print(project.apply([3, -1, 4]))
# 14
print(project.report.contents)
# project: report
# id: first_run
# paths: prepare > summarize
# result: 14

Files

Every project has a clerk, a nagata.FileManager. Pass the folder for the project's files as clerk (or pass a FileManager of your own):

import pathlib
import tempfile

root = pathlib.Path(tempfile.mkdtemp())
project = chrisjen.Project.create("report.ini", item = [1, 2], clerk = root)
project.clerk.save(project.result, file_name = "total", file_format = "pickle")
print(project.clerk.load(file_name = "total", file_format = "pickle"))
# 6

Export a workflow

Project.to_dot and Project.to_mermaid describe the workflow in Graphviz or mermaid text. Both are made by holden.

print(project.to_mermaid())
# ---
# title: report
# ---
# flowchart LR
#     prepare(prepare) --> summarize(summarize)

There is more to chrisjen, including criteria, custom designs, building workflows in code, and how the pieces fit together. See the documentation, especially the tutorial and the advanced user guide.

Contributing

Contributors are always welcome. Feel free to grab an issue to work on or make a suggested improvement. If you wish to contribute, please read the Contribution Guide and Code of Conduct.

Similar Projects

  • airflow: Apache's workflow tool that is likely the market leader. It requires substantial overhead and has a learning curve but offers the greatest extensibility for non-Python workflow components and support for continuous, always-on workflows.
  • jetstream: similar DAG workflow structures in pure Python with a greater emphasis on loading workflows from disk.
  • luigi: Spotify's workflow tool with much greater overhead and support for controlling workflow nodes outside of Python.
  • pathos: supports parallel workflow construction with heterogenuous computing framework. Among other features, it includes drop-in replacements for Python's pickle and multiprocess, called dill and multiprocessing, respectively.

License

Use of this repository is authorized under the Apache Software License 2.0.

Metadata

Release files for chrisjen 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for chrisjen 0.2.0
File Size Uploaded
chrisjen-0.2.0.tar.gz 146.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for chrisjen 0.2.0
File Interpreter ABI Platform
chrisjen-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 177.2 kB

Release files / chrisjen-0.2.0.tar.gz

Download URL chrisjen-0.2.0.tar.gz
Size 146.9 kB
Tags Source
SHA-256 checksum
How to use checksums
afe20dafcd84f8385c255a3138aa524d4e6c95e144cc9e765eac578faca1b9d6
BLAKE2b-256 checksum
How to use checksums
3a7854fd890b2803f06f32b2ad5fc73bcab0d2333b62629334fc1fb88d4a8c59
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.23 {"installer":{"name":"uv","version":"0.12.23","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / chrisjen-0.2.0-py3-none-any.whl

Download URL chrisjen-0.2.0-py3-none-any.whl
Size 30.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
8957f432ea7615bdb210f79ace132e73f5402915106eb1e1d3093c17d903af1e
BLAKE2b-256 checksum
How to use checksums
732ec9f49e6ae58e5fb1421ee057cd1c3188cf24cae818d33510a3343950c131
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.23 {"installer":{"name":"uv","version":"0.12.23","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files

0.1.3

2 release files

0.1.2

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page