decayfmt-py
A file format where decay is a first-class property: every open permanently corrupts the file.
This is the Python binding for the decayfmt format. Install it with pip install decayfmt-py; the module you import is decayfmt. Encode a clean file once, then let it decay one open at a time. Each open replaces a random slice of the payload with noise and writes it back to disk. A corrupted file cannot be restored from its own contents. The header is immutable; only the payload decays.
The binding wraps the same Rust library the CLI uses, so behavior, statistics, and errors are identical.
Install
pip install decayfmt-py
Requires Python 3.11+. Wheels are built from Rust via PyO3 (abi3), so no Rust toolchain is needed at install time.
Quickstart
import decayfmt
# Encode a clean text file. The extension carries the type and the decay rate:
# `tdcy<x>` = text, `idcy<x>` = image, x = instability (higher decays faster).
decayfmt.encode_file("notes.txt", "notes.tdcy5")
# Open it five times. Each open permanently corrupts the file on disk.
for _ in range(5):
kind, dims, data = decayfmt.decay_file("notes.tdcy5")
print(data[16:].decode("utf-8", errors="replace"))
# Work purely in memory instead: each call decays a fresh copy of the bytes.
data = b"the quick brown fox jumps over the lazy dog"
for _ in range(8):
data = decayfmt.corrupt_bytes(data, 1.0, "text")
print(data.decode("utf-8", errors="replace"))
# Zero-copy decay of a mutable buffer:
buf = bytearray(b"some text that will decay")
decayfmt.corrupt_in_place(buf, 10.0, "text")
Corruption probability per eligible byte is p = 1 - exp(-x / 10): x = 1 corrupts roughly 9.5% per open, x = 10 roughly 63%. Image corruption touches only the R, G, and B channels, so transparency (alpha) is never damaged. Text corruption replaces bytes with printable ASCII, so at high x it can break UTF-8 sequences.
API
| Function | Returns | Notes |
|---|---|---|
corrupt_bytes(data, x, kind) -> bytes |
corrupted copy | kind is "image" or "text"; immutable bytes are copied once |
corrupt_in_place(buffer, x, kind) -> None |
— | mutates a bytearray in place, no copy; for a memoryview use bytearray(mv) |
encode_file(source_path, output_path) -> None |
— | same as the CLI encode; output name decides type and x |
encode_bytes(source, output_path) -> None |
— | encodes in-memory bytes (image formats decoded, text validated as UTF-8) |
decay_file(path) -> (kind, dims, bytes) |
type label, (w, h) or None, full file bytes |
permanently corrupts the file on disk, no display |
parse_filename(name) -> (kind, x) |
— | "photo.idcy3" → ("image", 3.0) |
read_header(data) -> (kind, dims) |
— | reads the 16-byte header |
write_header(kind, width, height) -> bytes |
16-byte header | image requires width and height |
decayfmt.__version__ |
version string | — |
x is not clamped: x <= 0 corrupts nothing, and large x approaches corrupting every byte. The CLI reads x from filenames as a positive integer; the API accepts any float.
Errors
Failures raise built-in exceptions with the exact message the CLI would print:
OSErrorfor filesystem read/write failures (includes the OS error string).PermissionErrorfor a read-only target, where the corrupted payload cannot be written back.ValueErrorfor everything else: wrong magic bytes, unknown version, bad filename convention, invalid UTF-8 at encode, undecodable image, and so on.
Threading
The GIL is released while corruption, encoding, and file operations run, and large payloads (≥ 1 MiB) are corrupted in parallel across cores. Corruption is drawn from generators seeded by operating system entropy, so the corruption sequence cannot be replayed.
Image formats
encode_file / encode_bytes accept whatever the underlying Rust image library decodes: PNG, JPEG, GIF, WebP, TIFF, QOI, BMP, DDS, EXR, HDR, ICO, PNM, TGA, and farbfeld. Images are stored as raw RGBA, so any format the library can decode becomes a decaying image.
License
MIT. Same license as the decayfmt project.
Metadata
Release files for decayfmt-py 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Built distributions (wheels)
| File | Reset | |||
|---|---|---|---|---|
| decayfmt_py-0.2.0-cp311-abi3-win_amd64.whl | CPython 3.11 | abi3 | Windows x86-64 | Details |
| decayfmt_py-0.2.0-cp311-abi3-manylinux_2_34_x86_64.whl | CPython 3.11 | abi3 | Linux glibc 2.34+ x86-64 | Details |
| decayfmt_py-0.2.0-cp311-abi3-manylinux_2_34_aarch64.whl | CPython 3.11 | abi3 | Linux glibc 2.34+ ARM64 | Details |
| decayfmt_py-0.2.0-cp311-abi3-macosx_11_0_arm64.whl | CPython 3.11 | abi3 | macOS 11.0+ ARM64 | Details |
Total release size: 5.3 MB
Release files / decayfmt_py-0.2.0-cp311-abi3-win_amd64.whl
| Download URL | decayfmt_py-0.2.0-cp311-abi3-win_amd64.whl |
|---|---|
| Size | 1.3 MB |
| Tags | CPython 3.11 Windows x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
bc0f18a9cc134ca2307e1a8e0185abbb9be44ee5cd6a05810eafe39b4235bba4
|
|
BLAKE2b-256 checksum How to use checksums |
530fb890999ce31a2997ea6ddb4c08a68ba7edef86d564146901c9a5b112cd2d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
maturin/1.15.0
|
Release files / decayfmt_py-0.2.0-cp311-abi3-manylinux_2_34_x86_64.whl
| Download URL | decayfmt_py-0.2.0-cp311-abi3-manylinux_2_34_x86_64.whl |
|---|---|
| Size | 1.4 MB |
| Tags | CPython 3.11 Linux glibc 2.34+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
54665b75598fde7061af917a7bcbf14023cbcfe79ec648c076a1a2ded881831b
|
|
BLAKE2b-256 checksum How to use checksums |
9da61165072ca3c30de28a6cad3190f6e86f352cc06d198a54dd19d0bc497582
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
maturin/1.15.0
|
Release files / decayfmt_py-0.2.0-cp311-abi3-manylinux_2_34_aarch64.whl
| Download URL | decayfmt_py-0.2.0-cp311-abi3-manylinux_2_34_aarch64.whl |
|---|---|
| Size | 1.3 MB |
| Tags | CPython 3.11 Linux glibc 2.34+ ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
d9e6439a2debc22dcfd5ae531ee72a7ddf511150796d296a6e8ae7e894d0e6f6
|
|
BLAKE2b-256 checksum How to use checksums |
cc2c5624df904c41fddbd67c4725732ba5e42e19d794108bd1dfe3b774973902
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
maturin/1.15.0
|
Release files / decayfmt_py-0.2.0-cp311-abi3-macosx_11_0_arm64.whl
| Download URL | decayfmt_py-0.2.0-cp311-abi3-macosx_11_0_arm64.whl |
|---|---|
| Size | 1.3 MB |
| Tags | CPython 3.11 abi3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
712213859651ed96417cfe5c45d3cbcfdded32e111f4e65cb6819c6547d7091c
|
|
BLAKE2b-256 checksum How to use checksums |
bef5bd6f691ec299090839a3c786b6f8f870299a38df57331c33dd8c91a509df
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
maturin/1.15.0
|