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 apply(self, item, **kwargs):
        return [x for x in item if x >= 0]


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


@dataclasses.dataclass
class Total(chrisjen.Technique):
    def apply(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 apply(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 apply 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.3.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.3.0
File Size Uploaded Provenance Actions
chrisjen-0.3.0.tar.gz 148.4 kB Without provenance Details for chrisjen-0.3.0.tar.gz

Built distribution (wheel)

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

Total release size: 179.4 kB

Release files / chrisjen-0.3.0.tar.gz

Download URL chrisjen-0.3.0.tar.gz
Size 148.4 kB
Tags Source
SHA-256 checksum
How to use checksums
49f9427687d239f1ab287d25e297d5d94d7e5d371782ed725c68d23b1730f441
BLAKE2b-256 checksum
How to use checksums
48639e05d28d912b6d5f15b3f9d793b9757c3b7a4c031524a419d38d207a3646
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.4 {"installer":{"name":"uv","version":"0.13.4","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.3.0-py3-none-any.whl

Download URL chrisjen-0.3.0-py3-none-any.whl
Size 31.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
3ba5e1123ba79a1c7552788978c9a87db3dbd58268c4cc3c22da7d228c327a40
BLAKE2b-256 checksum
How to use checksums
abd44d3289a41d196975270305c8ebc36de1e1c3a39ac70dc8ae9792f6b21b2e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.4 {"installer":{"name":"uv","version":"0.13.4","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}

Security for chrisjen 0.3.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

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