faultlib
faultlib is the Python interface to the Rust
fault network fault-injection engine. It runs TCP
and UDP proxies inside an asyncio application, applies ordered fault chains,
and exposes typed progress, status, TCP-stream, and UDP-exchange records.
Use it when network degradation is one part of a larger Python experiment—for
example, adding database latency while restarting a pod and observing service
recovery. For shell-driven experiments, use the
fault CLI.
Python is a thin binding: validation, phase lifecycle, scheduling decisions, events, and errors remain canonical Rust behavior. The package adds typed Python mappings and dataclasses, not a second fault model.
Requirements and installation
faultlib requires Python 3.14 or newer.
python -m pip install faultlib
Start a proxy
import asyncio
from faultlib import Engine, Run
RUN: Run = {
"schema_version": 1,
"name": "slow database",
"proxies": [
{
"name": "database",
"protocol": "tcp",
"listen": "127.0.0.1:15432",
"upstream": "database.internal:5432",
}
],
"phases": [
{
"name": "degraded for thirty seconds",
"duration": "30s",
"proxies": [
{
"proxy": "database",
"faults": [
{
"type": "latency",
"flow": "both",
"distribution": {
"type": "normal",
"mean_ms": 200.0,
"stddev_ms": 20.0,
},
}
],
}
],
}
],
}
async def main() -> None:
async with Engine(RUN) as engine:
print(f"proxy listening on {engine.endpoints.tcp[0]}")
result = await engine.run()
print(f"run outcome: {result.outcome.kind}")
asyncio.run(main())
Point the application at 127.0.0.1:15432 for the duration of the experiment.
The proxy forwards the connection to database.internal:5432; no database
protocol support is required.
Run and its nested TypedDict types give type checkers the same shape as the
published schema. Runtime results and events are frozen dataclasses rather
than unstructured dictionaries.
Observe traffic
Engine.next_event() returns a completed transport record when one is
available and otherwise publishes periodic status:
from faultlib import StatusEvent, TcpStreamEvent, UdpExchangeEvent
async def observe(engine: Engine) -> None:
while engine.alive():
match event := await engine.next_event():
case StatusEvent(status):
print(
f"active={status.tcp.active} "
f"impacted={status.tcp.impacted}"
)
case TcpStreamEvent(stream):
print(stream.stream_id, stream.outcome)
case UdpExchangeEvent(exchange):
print(exchange.exchange_id, exchange.outcome)
case None:
return
Record delivery is bounded and best effort. A slow Python consumer never
stalls the Rust proxy. Aggregate status remains complete and reports omitted
records through dropped_records.
Adapt a running experiment
engine.schedule() exposes Rust-owned phase controls to Python. You can add,
modify, delete, start, or stop future phases while ordinary Python tasks
coordinate the surrounding system. A phase becomes immutable once it starts;
invalid mutations raise PhaseStateError.
The complete example in the repository demonstrates engine events, adaptive scheduling, and bounded record retention: examples/python_proxy.py.
Supported behavior
- TCP: latency, jitter, bandwidth, blackhole, connection reset
- UDP: latency, jitter, directional blackhole
- DNS over UDP: delay, timeout, truncation, refusal, SERVFAIL, NXDOMAIN, empty answers, and random A records
See the guide for realistic failure scenarios and the generated field reference for the exact wire contract.
Local development
From a checkout of the repository:
uv sync --project fault-python --python 3.14 --reinstall-package faultlib
uv run --project fault-python --python 3.14 python examples/python_proxy.py
uv run --project fault-python --python 3.14 ruff check \
fault-python/python examples
Repeat uv sync --reinstall-package faultlib after changing Rust binding code.
Licensed under the Apache License 2.0.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file faultlib-1.0.0.tar.gz.
File metadata
- Download URL: faultlib-1.0.0.tar.gz
- Upload date:
- Size: 67.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
201293b6feb6461d7a03a0a81e25a0224e4147da2ddc1bee0b12a74b4eeac7fb
|
|
| MD5 |
3ff3329d8cec4c2fd301f6c921859cc3
|
|
| BLAKE2b-256 |
627954615bc0b48cf5d822600748fe255abc3baba0f6e91ea7d8e68499d2083f
|
Provenance
The following attestation bundles were made for faultlib-1.0.0.tar.gz:
Publisher:
release.yaml on fault-project/fault
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
faultlib-1.0.0.tar.gz -
Subject digest:
201293b6feb6461d7a03a0a81e25a0224e4147da2ddc1bee0b12a74b4eeac7fb - Sigstore transparency entry: 2655209964
- Sigstore integration time:
-
Permalink:
fault-project/fault@ec288fc73dd02413dae20c4071daf7e91ccc9bca -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/fault-project
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yaml@ec288fc73dd02413dae20c4071daf7e91ccc9bca -
Trigger Event:
push
-
Statement type:
File details
Details for the file faultlib-1.0.0-cp314-abi3-win_amd64.whl.
File metadata
- Download URL: faultlib-1.0.0-cp314-abi3-win_amd64.whl
- Upload date:
- Size: 613.0 kB
- Tags: CPython 3.14+, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e5a0bbaad98c7b3453d6cc938b0b487bce5cfa9cb943e6f78381e0c067547d16
|
|
| MD5 |
103e80f329c3659ccddc78654709e1b3
|
|
| BLAKE2b-256 |
3733a8fa0a0b38f7af64c847532c2b8e4d60ffb067c8d34441ee222a87fbd189
|
Provenance
The following attestation bundles were made for faultlib-1.0.0-cp314-abi3-win_amd64.whl:
Publisher:
release.yaml on fault-project/fault
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
faultlib-1.0.0-cp314-abi3-win_amd64.whl -
Subject digest:
e5a0bbaad98c7b3453d6cc938b0b487bce5cfa9cb943e6f78381e0c067547d16 - Sigstore transparency entry: 2655209989
- Sigstore integration time:
-
Permalink:
fault-project/fault@ec288fc73dd02413dae20c4071daf7e91ccc9bca -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/fault-project
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yaml@ec288fc73dd02413dae20c4071daf7e91ccc9bca -
Trigger Event:
push
-
Statement type:
File details
Details for the file faultlib-1.0.0-cp314-abi3-manylinux_2_34_x86_64.whl.
File metadata
- Download URL: faultlib-1.0.0-cp314-abi3-manylinux_2_34_x86_64.whl
- Upload date:
- Size: 809.3 kB
- Tags: CPython 3.14+, manylinux: glibc 2.34+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b98b17f6898a126bdfd17f41bf478819ffa059f10622d651d7a4eeb84e066b66
|
|
| MD5 |
cbbd779e2ec52d8ef9a9ac17569abf26
|
|
| BLAKE2b-256 |
3acc3720013186481aea73111317aa56a3f9d04ec57ef42166d66706e554424b
|
Provenance
The following attestation bundles were made for faultlib-1.0.0-cp314-abi3-manylinux_2_34_x86_64.whl:
Publisher:
release.yaml on fault-project/fault
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
faultlib-1.0.0-cp314-abi3-manylinux_2_34_x86_64.whl -
Subject digest:
b98b17f6898a126bdfd17f41bf478819ffa059f10622d651d7a4eeb84e066b66 - Sigstore transparency entry: 2655210015
- Sigstore integration time:
-
Permalink:
fault-project/fault@ec288fc73dd02413dae20c4071daf7e91ccc9bca -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/fault-project
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yaml@ec288fc73dd02413dae20c4071daf7e91ccc9bca -
Trigger Event:
push
-
Statement type:
File details
Details for the file faultlib-1.0.0-cp314-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl.
File metadata
- Download URL: faultlib-1.0.0-cp314-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl
- Upload date:
- Size: 1.4 MB
- Tags: CPython 3.14+, macOS 10.12+ universal2 (ARM64, x86-64), macOS 10.12+ x86-64, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
84f4ca35b94bc0041c505fb5a039702cf8474c03c86d52cc3f5e1b5201da542c
|
|
| MD5 |
f3c3716298a0acb40f651ad01691dc97
|
|
| BLAKE2b-256 |
f78e6dc53fe93f56ff50205f5b2a2cadda067f8f79a4e527040ef4bd52bd7779
|
Provenance
The following attestation bundles were made for faultlib-1.0.0-cp314-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl:
Publisher:
release.yaml on fault-project/fault
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
faultlib-1.0.0-cp314-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl -
Subject digest:
84f4ca35b94bc0041c505fb5a039702cf8474c03c86d52cc3f5e1b5201da542c - Sigstore transparency entry: 2655209979
- Sigstore integration time:
-
Permalink:
fault-project/fault@ec288fc73dd02413dae20c4071daf7e91ccc9bca -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/fault-project
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yaml@ec288fc73dd02413dae20c4071daf7e91ccc9bca -
Trigger Event:
push
-
Statement type: