Skip to main content

wex-addon-process

Version: 1.0.4

wexample-wex-addon-process runs the treatments a board declares. A process says what to run and on which selection of files; a run is one execution of it, asked for by writing a record and picked up by a worker.

Nothing here talks to a database. A run names a process, the process names a selection and a type, the selection names files, and all four are records under the app's own .wex/data/ — which is what lets a process run on a repository that has no board at all, and what makes a demand survive a broker that falls over.

Running one by hand

wex process::run/execute --run 8020e9fb-05b8-4da7-857d-d3947449b6f7

The run record goes from pending to running to complete, gaining its dates, its counters and, at the end, whatever the type wrote in data. A run in any state but pending is left alone: a queue redelivers, and a run is done once.

Running as a worker

wex process::worker/start

Blocks, consuming the process_run queue, and rings back on process_run_event every time a run moves — on each state change, and at most once a second while it advances. This is the process a worker container runs, and there may be as many as the parallelism asked for.

The types on offer

A type is named by the family that answers for it. The whole of the filestate family is read off filestate's own options — every option that can produce an operation is a treatment a process may name:

filestate:report                    says what the selection takes, changes nothing
filestate:mode                      permissions, and ownership with them
filestate:should_exist              create when missing, delete when forbidden
filestate:name                      rename to a required form
filestate:content  filestate:text   write, trim, sort, keep unique lines
filestate:yaml     filestate:structured_keys
filestate:should_contain_lines      and its `should_not_` twin
filestate:managed_blocks            filestate:class      filestate:on_bad_format

Nothing is written per treatment: an option added to filestate is a type available here the same day, under the very name filestate gives it.

The process's options block is the configuration handed to each file, and has to carry the option the type is named after:

# a process of type filestate:mode
mode: '600'
dry_run: true

dry_run is read by the family and handed to nobody: it runs the pass without applying it, so what a treatment would do is readable before it does it.

Writing a type

A type of your own is a name and a run():

class ReviewProcessType(AbstractProcessType):
    name = "agent:review"
    label = "Review"

    def run(self, context: ProcessContext) -> dict[str, Any]:
        for path in context.files:
            context.advance()

        return {"files": len(context.files)}

What run() returns goes into the run's data. Raising is how a type says it could not go on — the failure is written down for it, so nothing in a type has to know what a failed run looks like.

A type that touches files should not be written this way: it belongs to the filestate family, where the operation, its description and its undo already exist.

Table of Contents

Installation

pip install wexample-wex-addon-process

Requires Python >=3.10.

A process and a selection are records, so a treatment can be declared without a board:

# .wex/data/selection/<uuid>.yml
title: Markdowns
patterns: "*.md\n!.wex/**"
# .wex/data/process/<uuid>.yml
title: What the Markdowns take
type: 'filestate:report'
selection_id: <the selection's uuid>
options: ''

Asking for a run is writing a third record:

# .wex/data/process_run/<uuid>.yml
process_id: <the process's uuid>
state: pending

Then:

wex process::run/execute --run <the run's uuid>

The same file is read back afterwards, holding what happened:

process_id: ...
state: complete
items_total: 3
items_done: 3
data: |
  files: 3
  bytes: 16
  by_extension:
    .md: 3

Tests

This project uses pytest for testing and pytest-cov for code coverage analysis.

Installation

First, install the required testing dependencies:

.venv/bin/python -m pip install pytest pytest-cov

Basic Usage

Run all tests with coverage:

.venv/bin/python -m pytest --cov --cov-report=html

Common Commands

# Run tests with coverage for a specific module
.venv/bin/python -m pytest --cov=your_module

# Show which lines are not covered
.venv/bin/python -m pytest --cov=your_module --cov-report=term-missing

# Generate an HTML coverage report
.venv/bin/python -m pytest --cov=your_module --cov-report=html

# Combine terminal and HTML reports
.venv/bin/python -m pytest --cov=your_module --cov-report=term-missing --cov-report=html

# Run specific test file with coverage
.venv/bin/python -m pytest tests/test_file.py --cov=your_module --cov-report=term-missing

Viewing HTML Reports

After generating an HTML report, open htmlcov/index.html in your browser to view detailed line-by-line coverage information.

Coverage Threshold

To enforce a minimum coverage percentage:

.venv/bin/python -m pytest --cov=your_module --cov-fail-under=80

This will cause the test suite to fail if coverage drops below 80%.

Architecture

The addon is one runner, a few types, and two ways to reach it.

The runner

src/wexample_wex_addon_process/runner/process_runner.py is where a run is taken from pending to complete or to failed. It reads the run, the process it names, the selection that process names, resolves the type, walks the files, and writes back at every state change.

Three decisions are worth reading. A run in any state but pending is left where it is, because a queue redelivers and a run is done once. The record is written on every file dealt with, being local and being the truth, while the ring is throttled to once a second — ten thousand files must not be ten thousand messages saying the same thing. And the type never sees the run: it is handed a src/wexample_wex_addon_process/process_type/process_context.py holding the files, the options and a way to say how far it has got, so what a run is in is decided in one place.

Reading a selection

src/wexample_wex_addon_process/process_type/selection.py holds no list of files: a selection is a rule, and what it takes is read from disk each time it is asked for. The rule is PathMatcher from wexample-file, a line-for-line port of the PHP one the board uses; the walking is filestate's, the matcher being handed to a ChildrenFilterOption as its filter.

Going through filestate to enumerate and not only to change is deliberate: a type that reads the files and a type that rewrites them are then handed the very same tree, and there is one answer to what a selection takes rather than two.

The two implementations are kept honest against each other: three hundred random pattern sets, sixty paths and fifty directories were run through both and compared, with no difference.

Types, and the families that declare them

src/wexample_wex_addon_process/process_type/abstract_process_type.py is deliberately an ordinary class — no kernel, no attrs, no state. A type contributed from a bundle should be readable by whoever wrote the bundle rather than by whoever wrote wex.

A type's name carries its family: filestate:mode, agent:review. The prefix is not a branch taken at run time — src/wexample_wex_addon_process/process_type/process_type_registry.py asks each family for its names once, and what a record names is found in that map or is an error. A family declares names; it decides nothing.

src/wexample_wex_addon_process/process_type/family/file_state_process_type_family.py declares none of its types by hand. It walks filestate's DefaultOptionsProvider and keeps the options that override create_required_operation — the precise line between a treatment and a piece of structure, asked of the option itself rather than listed here. mode is a treatment, children is not. Thirteen types come out of it, and an option added to filestate is a fourteenth the same day.

Each of those is a src/wexample_wex_addon_process/process_type/filestate/file_state_option_process_type.py, which holds no logic either: the process's options become the configuration asked of every selected file, and filestate turns the difference with the disk into operations that can be described, applied and undone. dry_run in the options runs the pass without applying it.

src/wexample_wex_addon_process/process_type/filestate/file_state_report_process_type.py is in that family and yet emits no operation, on filestate's own rule: a scope names something observable on disk, and a report changes nothing observable. An operation with no scope would be an operation nothing could ever run.

The two entry points

src/wexample_wex_addon_process/commands/run/execute.py runs one run, here and now, with no queue in sight. src/wexample_wex_addon_process/service/process_run_service.py is the same runner behind a wexample-queue service: it consumes process_run, and rings back on process_run_event with the same shape of message it received — kind, id, workdir. The runner is rebuilt for each message so that the workdir a ring names is the one the message came with: one worker serves every app.

The message carries no work at all, only a pointer. A worker starting after the message was published, or reading a run somebody has since edited, sees what is true now rather than what was true when the button was pressed.

What a record is called

src/wexample_wex_addon_process/const/process.py spells every key once. The board writes these very names into the same files, so one changed here has to be changed there — this file and ProcessRunHydrator on the PHP side are two halves of one contract.

Integration in the Suite

This package is part of the Wexample Suite — a collection of high-quality, modular tools designed to work seamlessly together across multiple languages and environments.

The suite includes packages for configuration management, file handling, prompts, and more. Each package can be used independently or as part of the integrated suite.

Visit the Wexample Suite documentation for the complete package ecosystem.

Dependencies

  • wexample-file: >=9.1.6
  • wexample-queue: >=1.0.1
  • wexample-wex-addon-app: >=31.0.0

Versioning & Compatibility Policy

Wexample packages follow Semantic Versioning (SemVer):

  • MAJOR: Breaking changes
  • MINOR: New features, backward compatible
  • PATCH: Bug fixes, backward compatible

We maintain backward compatibility within major versions and provide clear migration guides for breaking changes.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Free to use in both personal and commercial projects.

About us

Wexample stands as a cornerstone of the digital ecosystem — a collective of seasoned engineers, researchers, and creators driven by a relentless pursuit of technological excellence. More than a media platform, it has grown into a vibrant community where innovation meets craftsmanship, and where every line of code reflects a commitment to clarity, durability, and shared intelligence.

This packages suite embodies this spirit. Trusted by professionals and enthusiasts alike, it delivers a consistent, high-quality foundation for modern development — open, elegant, and battle-tested. Its reputation is built on years of collaboration, refinement, and rigorous attention to detail, making it a natural choice for those who demand both robustness and beauty in their tools.

Wexample cultivates a culture of mastery. Each package, each contribution carries the mark of a community that values precision, ethics, and innovation — a community proud to shape the future of digital craftsmanship.

Known Limitations & Roadmap

Current limitations and planned features are tracked in the GitHub issues.

See the project roadmap for upcoming features and improvements.

Status & Compatibility

Maturity: Production-ready

Python Support: >=3.10

OS Support: Linux, macOS, Windows

Status: Actively maintained

Migration Notes

When upgrading between major versions, refer to the migration guides in the documentation.

Breaking changes are clearly documented with upgrade paths and examples.

Metadata

Release files for wexample-wex-addon-process 1.0.4

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

Source distribution (sdist)

Source distribution for wexample-wex-addon-process 1.0.4
File Size Uploaded
wexample_wex_addon_process-1.0.4.tar.gz 21.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for wexample-wex-addon-process 1.0.4
File Interpreter ABI Platform
wexample_wex_addon_process-1.0.4-py3-none-any.whl Python 3 none any Details

Total release size: 45.7 kB

Release files / wexample_wex_addon_process-1.0.4.tar.gz

Download URL wexample_wex_addon_process-1.0.4.tar.gz
Size 21.0 kB
Tags Source
SHA-256 checksum
How to use checksums
fff9a40c80e604c9b50a2432f971cebcad9d1a92435c50e450f78a6f860e1276
BLAKE2b-256 checksum
How to use checksums
41d01d28ceb2365f4e53db5235d667a1ccab53c01fb0e47b2842cd75c7cb5a4e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via pdm/2.25.9 CPython/3.12.3 Linux/6.8.0-139-generic

Release files / wexample_wex_addon_process-1.0.4-py3-none-any.whl

Download URL wexample_wex_addon_process-1.0.4-py3-none-any.whl
Size 24.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
788d9da5373eed9e00dd582828c20dc0f24809db7926dc5f1960066206190499
BLAKE2b-256 checksum
How to use checksums
3dd2c8682107a2bbda7aca9698560186bb968920a90dd9a03f8904d85c6225d3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via pdm/2.25.9 CPython/3.12.3 Linux/6.8.0-139-generic

Release history Release notifications | RSS feed

4.1.3

2 release files

4.1.2

2 release files

4.1.1

2 release files

4.1.0

2 release files

4.0.1

2 release files

4.0.0

2 release files

3.0.1

2 release files

3.0.0

2 release files

2.1.0

2 release files

2.0.0

2 release files

This release

1.0.4 This release

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