Safe filesystem operations with SQLite-backed journaling and recovery primitives.
Project description
safe-fs-ops
Conservative filesystem mutation primitives with SQLite-backed leases, resource claims, operation journaling, checkpoints, and recovery hooks.
safe-fs-ops is for tools that need to change local files without pretending
the filesystem has real transactions. It records intent before mutation, keeps
durable proof for supported rollback paths, coordinates concurrent workers with
leases and claims, and fails closed when recovery would require guessing.
Status
This package is pre-1.0 alpha. The current public surface is ready for careful integration in tools that can tolerate explicit recovery semantics, especially workspace-scoped writes, deletes, directory creation, no-replace renames, directory capture, snapshot bundles, and tree backup artifacts.
It is not a sandbox, a general command rollback engine, or a generic rm -rf
replacement. If another tool mutates a directory after you hand it control,
safe-fs-ops can only restore state that you explicitly snapshotted, backed up,
captured, or journaled first.
Install
uv add safe-fs-ops
Python 3.12 or newer is required.
Quick Start
from pathlib import Path
from safe_fs_ops import SafeWorkspace
workspace = SafeWorkspace.open(
Path(".safe-fs-ops/state.sqlite"),
owner="worker-a",
)
settings = workspace.file("settings.toml")
with workspace.transaction(
name="update-settings",
resources={"settings": settings},
rollback="automatic",
) as tx:
tx.write_text(tx.r.settings, "enabled = true\n")
The transaction acquires a workspace lease, claims settings.toml, records a
journal batch, captures rollback proof for supported operations, performs the
write, records checkpoints, and releases claims on exit.
Common Patterns
Back up named files before invoking another tool:
root = workspace.tree(project_root)
with workspace.transaction(
name="prepare-risky-tool",
resources={"root": root},
) as tx:
backup_result = tx.backup_tree(
tx.r.root,
["pyproject.toml", "src/package/__init__.py"],
)
Capture a directory before tearing it down:
worktree = workspace.directory(".git/worktrees/topic")
quarantine = ".safe-fs-ops/quarantine/worktree-topic"
with workspace.transaction(
name="capture-worktree",
resources={"worktree": worktree},
rollback="automatic",
) as tx:
tx.capture_directory(tx.r.worktree, quarantine_path=quarantine)
Resume pending recovery work after a crash or lease handoff:
error = workspace.recover_pending_batches(run_id="run-123")
if error is not None:
raise error
Documentation
- Docs index: entry points for the documentation set.
- Public API: supported imports, workspace usage, transactions, phased operations, and advanced modules.
- Recovery model: what automatic rollback can and cannot do, and how pending recovery is resumed.
- Filesystem primitives: lower-level path, mutation, snapshot, content-addressed, backup, capture, and restore helpers.
- Development: local setup, tests, slow-test markers, build, and release notes.
- Source review: current public-interface assessment, strengths, sharp edges, and remaining risks.
- Design notes: longer-running architecture notes and historical extraction context.
Development
uv sync
uv run pytest -q
uv run mypy src
uv build
The default test run skips opt-in stress tests and slow recovery integration tests. Run the recovery-heavy tests with:
uv run pytest -q --slow-recovery -m slow_recovery
The project also defines task aliases:
mise run test
mise run test-slow
mise run test-full
mise run test-stress
License
MIT. See LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
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 safe_fs_ops-0.1.0.tar.gz.
File metadata
- Download URL: safe_fs_ops-0.1.0.tar.gz
- Upload date:
- Size: 151.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.14 {"installer":{"name":"uv","version":"0.11.14","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d6fed8784c81596d6c661758486d803029e03cd0930e4314808de4bb1285beb1
|
|
| MD5 |
f7c66e7ec8122e813cdaaed42493cb2c
|
|
| BLAKE2b-256 |
7a25713cab6445c0f22fd923ba045baac1f6b631644192b6a3678e667a5f89d3
|
File details
Details for the file safe_fs_ops-0.1.0-py3-none-any.whl.
File metadata
- Download URL: safe_fs_ops-0.1.0-py3-none-any.whl
- Upload date:
- Size: 202.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.14 {"installer":{"name":"uv","version":"0.11.14","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4f377dbab17225958a513930269921a64a8c6781dfb361826cf918d3aa6cc1d8
|
|
| MD5 |
f2bc49ac0f7cc7429e1757ef17048bec
|
|
| BLAKE2b-256 |
e8066236a641cce6559fb0643d98825c0af4d6d65226f0e1cb3f5e0fe1175d0d
|