Skip to main content

Cross-platform file system utilities for Python

Project description

zerofilesystem

zerofilesystem

CI PyPI version Python versions License: MIT Status Typed Dependencies Code style: ruff

Cross-platform file system utilities for Python 3.12+. Zero runtime dependencies.

Problem

Reliable file handling in Python normally means stitching together os, shutil, pathlib, json, gzip, tarfile, zipfile, hashlib, fcntl/msvcrt, tempfile and secrets, then carefully wrapping each operation to make it atomic, cross-platform, and crash-safe. The pain shows up in three recurring places: writes that can be left half-finished if the process dies, multi-file operations that have no rollback when one of them fails, and platform-specific behavior — file locking, hidden attributes, executable bits, path normalization — that has to be re-derived in every project.

The cost of getting these right is rarely the headline feature, but the cost of getting them wrong is corrupted config files, partial deploys, and "works on Linux, breaks on Windows" bug reports.

Solution

zerofilesystem consolidates these primitives behind a single, flat API and makes safe behavior the default. Atomic writes are on by default (temp file plus os.replace). FileTransaction groups multiple writes/copies/deletes under a single commit-or-rollback umbrella. FileLock exposes one cross-platform locking interface backed by fcntl on Unix/macOS and msvcrt on Windows. Finder and Watcher provide fluent builder APIs for filtered search and polling-based monitoring. Archive extraction guards against zip-slip path traversal. Every public function accepts both str and pathlib.Path.

The library is built on the standard library only — no external runtime dependencies — and ships a py.typed marker for full PEP 561 typing.

What it gives you

  • Atomic text/binary/JSON writes — temp file + atomic rename, on by default. zfs.write_text("config.json", data).
  • Multi-file transactions — commit several writes/copies/deletes together, automatic rollback on error. with zfs.FileTransaction() as tx: ....
  • Cross-platform file locking — same interface on Unix and Windows, with optional timeout. with zfs.FileLock("/tmp/app.lock", timeout=5): ....
  • Fluent file finder — patterns, exclusions, size/date/permission filters, depth limits. Finder("./src").patterns("*.py").modified_last_days(7).find().
  • Polling file watcher — created/modified/deleted callbacks with debouncing and the same filter vocabulary as Finder.
  • Integrity verificationdirectory_hash, create_manifest/verify_manifest, compare_directories, snapshot_hash.
  • Archives — tar (gz/bz2/xz) and zip create/extract with filtering, base-dir control, and zip-slip protection.
  • Secure operationssecure_delete (multi-pass overwrite), private_directory (0o700), create_private_file (0o600).
  • Path utilities — normalize, expand ~/env vars, validate, posix conversion, subpath checks.
  • Permissions and metadataFileMetadata dataclass, readonly/hidden/executable toggles, octal-mode parsing.

Installation

pip install zerofilesystem
uv add zerofilesystem

Requires Python 3.12+. No runtime dependencies.

Quick start

import zerofilesystem as zfs

# Atomic JSON write
zfs.write_json("config/app.json", {"version": 2})

# Multi-file transaction with automatic rollback
with zfs.FileTransaction() as tx:
    tx.write_text("config/app.json", '{"version": 3}')
    tx.write_text("config/db.json", '{"host": "localhost"}')
    # Both files committed atomically on exit

# Cross-platform locking
with zfs.FileLock("/tmp/myapp.lock", timeout=5):
    # Critical section — held across processes
    ...

# Fluent file search
from zerofilesystem import Finder
recent_py = (
    Finder("./src")
    .patterns("*.py")
    .modified_last_days(7)
    .not_hidden()
    .exclude("__pycache__")
    .find()
)

# Integrity manifest
manifest = zfs.create_manifest("./src", algorithm="sha256")
zfs.save_manifest(manifest, "src.manifest")
result = zfs.verify_manifest("./src", manifest)
assert result.is_valid

More runnable examples in examples/.

Comparison with alternatives

The standard library provides every primitive zerofilesystem uses; the value is in combining them safely under one API. Third-party libraries cover individual slices.

Library Atomic writes Transactions Cross-platform lock Fluent finder File watcher Integrity manifest Archives Runtime deps
zerofilesystem polling tar+zip none
pathlib + shutil (stdlib) manual basic glob manual tar+zip none
filelock none
portalocker none
watchdog native FSEvents/inotify yes
send2trash varies
aiofiles yes

watchdog is the right choice when you need real-time filesystem events; zerofilesystem's Watcher is a polling implementation and trades latency for portability and zero dependencies.

Known limits and open issues

These are derived from the code and are not blockers for normal use; pick the library only if they fit your scenario.

  • limit: Watcher and FileWatcher poll the filesystem (time.sleep(poll_interval)) — there is no inotify/FSEvents/ReadDirectoryChangesW backend, so events are bounded by the configured poll interval (default 1.0s).
  • limit: secure_delete is best-effort — modern SSDs with wear leveling, journaling filesystems, and OS-level page cache may retain copies. The docstring says so explicitly. Use full-disk encryption for true confidentiality.
  • limit: move_if_absent is documented as non-atomic — there is a race window between the exists() check and shutil.move(). Use FileLock if you need cross-process exclusivity.
  • limit: copy_if_newer uses a 1-second epsilon on st_mtime to tolerate filesystem timestamp granularity, so sub-second updates can be missed.
  • limit: FilePermissions.set_hidden() raises NotImplementedError on Unix — hiding a file there requires renaming with a leading dot.
  • limit: archive extraction silently skips members that would escape the destination (path traversal protection) instead of raising — call list_archive first if you need to verify contents.
  • open: CHANGELOG.md currently stops at 0.1.1 while src/zerofilesystem/__init__.py declares __version__ = "0.1.3" — release-please should reconcile this on the next release.
  • design: no async/await variants — every operation is blocking. Wrap in a thread executor if you need to drive I/O from an event loop.

A deeper, per-component breakdown lives outside the public docs.

Anti-patterns — how NOT to use this project

A short list of misuses that the library does not protect you from.

  • Do not use FileLock to coordinate threads inside one process — it is a process-level OS lock; use threading.Lock for intra-process synchronization.
  • Do not call secure_delete and assume the data is unrecoverable on SSD or any journaling filesystem — see Known limits.
  • Do not rely on move_if_absent(on_conflict="skip") for atomic "move only if missing" — combine it with FileLock if more than one process can race.
  • Do not share one FileTransaction instance between threads or call commit() more than once — a committed/rolled-back transaction refuses further operations.
  • Do not start a Watcher and forget about it — it spawns a daemon thread; call .stop() or use the with block.
  • Do not use Finder/Watcher with poll_fast() (0.1s) on a tree of tens of thousands of files — every tick re-walks the tree and re-stats every match.
  • Do not pass mismatched algorithms to verify_manifest — the manifest stores its algorithm; pass the value returned by load_manifest instead of hardcoding.
  • Do not extract an archive into a directory that contains files you care about — extraction overwrites colliding paths without prompting.

Running tests

uv sync
uv run pytest

The suite collects over 500 tests across every public module — archives, finder, watcher, file locks, transactions, JSON, path utils, basic I/O, directory ops, integrity, secure ops, permissions — and is pinned at 100% coverage in pyproject.toml.

Running examples

Each script under examples/ is self-contained and runnable:

uv run python examples/01_basic_io.py
uv run python examples/09_finder.py
uv run python examples/10_watcher.py

See examples/ for the full list (basic I/O, JSON, discovery, locking, transactions, archives, directory ops, finder, watcher).

Development

Contributor setup, lint/type/test commands, pre-commit hooks, commit conventions, and the release process are documented in docs/DEVELOPMENT.md.

Documentation map

User documentation:

Developer documentation:

Contributing

This repository is maintained as a personal portfolio project. Pull requests are generally not accepted, but exceptional contributions may be considered.

For bug reports and feature requests, please use GitHub Issues.

License

MIT License — Copyright (c) 2025 Francesco Favi.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

zerofilesystem-0.1.4.tar.gz (331.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

zerofilesystem-0.1.4-py3-none-any.whl (56.4 kB view details)

Uploaded Python 3

File details

Details for the file zerofilesystem-0.1.4.tar.gz.

File metadata

  • Download URL: zerofilesystem-0.1.4.tar.gz
  • Upload date:
  • Size: 331.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for zerofilesystem-0.1.4.tar.gz
Algorithm Hash digest
SHA256 ce92dc42a6036361d5791391ba6fa581b4551820895ee8c0d2d9e53d7f24a31c
MD5 fadafdc6ff87023da8abd55d9d5999a2
BLAKE2b-256 70c368d2a8ad51eef37dbb87e9d4b9c4a17d923fc02e36d5c31393e831f223f8

See more details on using hashes here.

Provenance

The following attestation bundles were made for zerofilesystem-0.1.4.tar.gz:

Publisher: publish.yml on francescofavi/zerofilesystem

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file zerofilesystem-0.1.4-py3-none-any.whl.

File metadata

  • Download URL: zerofilesystem-0.1.4-py3-none-any.whl
  • Upload date:
  • Size: 56.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for zerofilesystem-0.1.4-py3-none-any.whl
Algorithm Hash digest
SHA256 2c2e7da9363b3c034bbf2bf8bb4b3c1b91a339a22f3f32a14b74541585614b94
MD5 30d97cbfa7ebf75b91a7bded3f77fa0f
BLAKE2b-256 c3ebd6e15d61ffb4b32f185e14248e34790197e7993109fca80f8bea0cc471b3

See more details on using hashes here.

Provenance

The following attestation bundles were made for zerofilesystem-0.1.4-py3-none-any.whl:

Publisher: publish.yml on francescofavi/zerofilesystem

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page