Skip to main content

No project description provided

Project description

Daggery

This mini-library exposes a set of types designed for executing directed, acyclic graphs (DAGs) of operations. It supports generating synchronous and asynchronous DAGs, allows custom operations, and provides wrappers for things like logging and timing.

Getting Started (Installation)

Daggery is available on PyPi. Install with your tool of choice (pip, poetry, uv, etc). Commands below assume uv.

For checking out the docs locally:

$ uv run mkdocs serve

For running tests:

$ uv run pytest

Exposed types

The two types currently exposed are:

  • FunctionDAG
  • AsyncFunctionDAG

A FunctionDAG represents a DAG of functions, while an AsyncFunctionDAG represents a DAG of async functions (wow!). Both can take in a string encoding a linear sequence of operations, using the following format in the example below:

# Note that frozen=True is used for all nodes - and is required by Daggery.
class Foo(Node, frozen=True):
    def evaluate(self, value: int) -> int: return value * value

class Bar(Node, frozen=True):
    def evaluate(self, value: int) -> int: return value + 10

class Baz(Node, frozen=True):
    def evaluate(self, value: int) -> int: return value - 5

custom_op_node_map = {"foo": Foo, "bar": Bar, "baz": Baz}

# The below sequence can be thought of as a function composition.
# i.e. combined = foo . bar . baz, or baz(bar(foo(x)))
sequence = "foo >> bar >> baz"
dag = FunctionDAG.from_string(sequence, custom_op_node_map)
if isinstance(dag, InvalidDAG):
    do_something_with_invalid_dag(dag)
result = dag.evaluate(42)
result
# 1769

More generally both accept a DAG description, using a topologically-sorted sequence of desired operations and a sequence of argument mappings for operations with multiple inputs:

class AddNode(Node, frozen=True):
    def evaluate(self, value: float) -> float:
        return value + 1

class MultiplyNode(Node, frozen=True):
    def evaluate(self, value: float) -> float:
        return value * 2

class ExpNode(Node, frozen=True):
    def evaluate(self, base: float, exponent: float) -> float:
        return base**exponent

mock_op_node_map = {
    "add": AddNode,
    "mul": MultiplyNode,
    "exp": ExpNode,
}

ops = OperationSequence(
    ops=(
        Operation(
            name="add0", op_name="add", children=("add1", "mul0")
        ),
        Operation(
            name="add1", op_name="add", children=("exp0",)
        ),
        Operation(
            name="mul0", op_name="mul", children=("exp0",)
        ),
        Operation(
            name="exp0", op_name="exp"
        ),
    )
)
# Only need to provide mappings when arguments are ambiguous (i.e. >1 input).
# In this example, the first argument comes from `add1`, the second from `mul0`.
mapping = ArgumentMapping(op_name="exp0", inputs=("add1", "mul0"))

dag = FunctionDAG.from_dag_description(
    DAGDescription(operations=ops, argument_mappings=(mapping,)),
    custom_op_node_map,
)
if isinstance(dag, InvalidDAG):
    do_something_with_invalid_dag(dag)
result = dag.evaluate(1)
# 81

The Daggery Philosophy

This library adheres to the following mantras:

Latest and greatest developer tools used (correctly) wherever possible

uv, mypy, and ruff are all examples. Warnings are fixed immediately.

Everything is a value, including errors - code should be exception-free

Daggery code aims to never raise Exceptions, and provides utilities for user-defined Nodes to avoid doing so.

Immutability is first-class.

This encourages many things like local reasoning, safety, efficiency, and testability. Additionally it also encourages state to be decoupled and encoded explicitly, further aiding these aims.

Leverage structure and validated types - the earlier this is done, the greater the benefits.

Structure (such as sortedness and uniqueness) gives leverage and constraints provide freedom to optimise for subsequent code. Immutability is also structure and is treated accordingly.

Interfaces should be simple and composable. Avoid hacky gimmicks and unmaintainable approaches like multiple inheritance.

Simple code is unlikely to go wrong. Composable abstractions are scalable.


TODO:

  • Add HTTP client decorator to Node.evaluate.
  • Confirm graph substitution works with nested DAGs inside Operations.
  • Add examples.
  • Add unit tests for the above.
  • Add nullable_[async_]dag and throwable_[async_]dag wrappers.
  • Migrate to uv.
  • Add docstrings/doc pages
  • Tidy up/standardise terminology.
  • Showcase to others.
  • Add docstrings to public types, functions, and methods.
  • ???
  • Profit!

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

daggery-0.2.6.tar.gz (20.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

daggery-0.2.6-py3-none-any.whl (17.1 kB view details)

Uploaded Python 3

File details

Details for the file daggery-0.2.6.tar.gz.

File metadata

  • Download URL: daggery-0.2.6.tar.gz
  • Upload date:
  • Size: 20.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.5.29

File hashes

Hashes for daggery-0.2.6.tar.gz
Algorithm Hash digest
SHA256 d3137abd59c847d55f096d3221d6f9711d19ae7e302ecfcc702de702ed324d7e
MD5 e016b38481b9b36e018196680feb4759
BLAKE2b-256 dfb5d7c07a727621bce5a49232b66dff1d0b104c4ff3730fc5dce79383b6964f

See more details on using hashes here.

File details

Details for the file daggery-0.2.6-py3-none-any.whl.

File metadata

  • Download URL: daggery-0.2.6-py3-none-any.whl
  • Upload date:
  • Size: 17.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.5.29

File hashes

Hashes for daggery-0.2.6-py3-none-any.whl
Algorithm Hash digest
SHA256 da97d86470896ebf1cbb77cc1759a51b78f09966a487d628f810ec6dff851306
MD5 0f1be7c91a60d6a27534442cf4031f03
BLAKE2b-256 77404b9f1d381ce2b1abca6cbf09251b4b407417172a0d64556353ecec785e70

See more details on using hashes here.

Supported by

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