Skip to content

Commit 37a6399

Browse files
committed
MIN Add AGENTS.md
1 parent 9ccb859 commit 37a6399

1 file changed

Lines changed: 69 additions & 0 deletions

File tree

AGENTS.md

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# AGENTS.md
2+
3+
This file provides guidance to agents when working with code in this repository.
4+
5+
## Commands
6+
7+
**Run all tests:**
8+
```bash
9+
pytest jug/tests/
10+
```
11+
12+
**Run a single test file:**
13+
```bash
14+
pytest jug/tests/test_tasks.py
15+
```
16+
17+
**Run a single test:**
18+
```bash
19+
pytest jug/tests/test_tasks.py::test_function_name
20+
```
21+
22+
**Install in development mode (with dev dependencies):**
23+
```bash
24+
pip install -e ".[dev]"
25+
```
26+
27+
**Build the package:**
28+
```bash
29+
python -m build
30+
```
31+
32+
## Architecture
33+
34+
Jug is a task-based parallelization framework where a **jugfile** (a Python script) defines tasks, and multiple `jug execute` processes run those tasks concurrently using a shared backend store for coordination and result caching.
35+
36+
### Core concepts
37+
38+
**Task** (`jug/task.py`): The central abstraction. A `Task` wraps a function call with its arguments. Tasks are identified by a content hash of their function + arguments. `task.alltasks` is a module-level list that accumulates all tasks as the jugfile is imported. Tasks are typically created via the `@TaskGenerator` decorator.
39+
40+
**Backends** (`jug/backends/`): Storage and locking layer. `base_store` (abstract) defines the interface: `dump`, `load`, `can_load`, `list`, `lock`, etc. Implementations:
41+
- `file_store` — filesystem-based (default, NFS-safe). Results stored as files named by task hash.
42+
- `dict_store` — in-memory (useful for testing).
43+
- `redis_store` — Redis-based.
44+
45+
Backends also implement **locking** to prevent duplicate execution across workers. `file_store` uses lock files; `redis_store` uses Redis locks.
46+
47+
**Hashing** (`jug/hash.py`): Task identity is determined by hashing the function (by name/module) and all arguments recursively. Objects can implement `__jug_hash__()` for custom hashing. numpy arrays and polars DataFrames have special handling in `file_store` (stored in native format for efficiency).
48+
49+
**Subcommands** (`jug/subcommands/`): Each `jug <cmd>` maps to a subcommand module: `execute`, `status`, `invalidate`, `cleanup`, `count`, `check`, `graph`, `shell`, `webstatus`, `pack`, `demo`. The `execute` subcommand runs the core execution loop.
50+
51+
**Barrier** (`jug/barrier.py`): `barrier()` raises `BarrierError` if any previously defined task isn't complete yet. This stops jugfile parsing at that point, allowing dynamic task graphs where the number of tasks depends on prior results. `bvalue(t)` is a scoped version that only checks one task.
52+
53+
**CompoundTask** (`jug/compound.py`): A task whose function itself returns a Task. Used to create dynamic sub-graphs that are only instantiated after the compound task runs.
54+
55+
**Hooks** (`jug/hooks/`): Event system for extending jug behavior (e.g., logging task execution events). Register with `register_hook(event_name, callback)`.
56+
57+
**Options** (`jug/options.py`): A chained options object where attributes fall through to the next layer. Configuration can come from CLI args, local config files, or defaults.
58+
59+
### Execution flow
60+
61+
1. `jug execute jugfile.py --jugdir jugdata/` is called
62+
2. `jug.init()` sets up the backend store and imports the jugfile, populating `task.alltasks`
63+
3. If a `barrier()` is hit before all prior tasks are done, a `BarrierError` is raised and jugfile import stops at that point (the execution loop re-imports once more tasks complete)
64+
4. The execution loop picks tasks that are ready (all dependencies loadable), acquires a lock, executes, stores result, releases lock
65+
5. Multiple workers run in parallel — coordination is entirely through the backend store
66+
67+
### Test infrastructure
68+
69+
Tests live in `jug/tests/`. The `tmp_file_store` pytest fixture (in `jug/tests/utils.py`) provides a temporary `file_store` and handles cleanup of `task.Task.store`. Test jugfiles (used as fixtures for integration tests) are in `jug/tests/jugfiles/`.

0 commit comments

Comments
 (0)