Metadata-Version: 2.4
Name: without-dag
Version: 0.0.1
Summary: Bounded-concurrency execution of DAG-shaped async workflows for without, liftable into a Processor.
Author: Josh Karpel
Author-email: Josh Karpel <josh.karpel@gmail.com>
License-Expression: MIT
Classifier: Development Status :: 2 - Pre-Alpha
Classifier: Framework :: AsyncIO
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Software Development :: Libraries
Classifier: Typing :: Typed
Requires-Dist: without-core==0.0.1
Requires-Python: >=3.14
Description-Content-Type: text/markdown

# without-dag

Concurrent execution of DAG-shaped async workflows, liftable into a `without`
`Processor`. A `Processor[In, Out]` is otherwise an opaque stream-to-stream
closure; this package lets the *inside* of a per-event step be a graph of async
sub-steps that run with bounded concurrency and recombine into one output. It is
the value-level fan-out/fan-in the substrate leaves room for: one input value
drives many concurrent computations.

`Graph` is the typed frontend: a builder that threads value types through the
wiring so a mismatched dependency is a mypy error and a cycle is unrepresentable.
It compiles once into a `CompiledGraph`, an async callable reused per event:

```python
from without_dag import Graph

async def fetch(request: Request) -> Fetched: ...
async def parse(fetched: Fetched) -> Parsed: ...
async def render(fetched: Fetched, parsed: Parsed) -> Report: ...

graph, (request,) = Graph.of(Request)
fetched = graph.node(fetch, request)
parsed = graph.node(parse, fetched)
report = graph.node(render, fetched, parsed)
run = graph.build(output=report, limit=4)

result: Report = await run(some_request)
```

Each node runs once (memoized, so a diamond's shared ancestor executes a single
time with no glitch), acyclicity is proven at the boundary via stdlib
`graphlib`, and a single-input graph is an async `(In) -> Out` callable, exactly
what `from_map` lifts into a `Processor`.

See the
[`without-dag` guide](https://without.help/guides/without-dag/)
(with the [API reference](https://without.help/reference/without_dag/))
for the full surface: the object-seam execution core (`Plan`, `drive`,
`evaluate`), the typed frontend, and lifting into a processor.
