Metadata-Version: 2.4
Name: fusedzoo
Version: 0.1.0
Summary: A FUSE filesystem that mounts an Apache ZooKeeper tree as a local directory.
Project-URL: Documentation, https://github.com/ModdingFox/fusedzoo#README.md
Project-URL: Issues, https://github.com/ModdingFox/fusedzoo/issues
Project-URL: Source, https://github.com/ModdingFox/fusedzoo
Author-email: Tyst Marin <moddingfox@foxtek.us>
License-Expression: Apache-2.0
License-File: LICENSE.txt
Keywords: filesystem,fuse,kazoo,zookeeper
Classifier: Development Status :: 3 - Alpha
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Topic :: System :: Distributed Computing
Classifier: Topic :: System :: Filesystems
Requires-Python: >=3.12
Requires-Dist: fusepy>=3.0.1
Requires-Dist: kazoo>=2.10
Provides-Extra: docs
Requires-Dist: furo; extra == 'docs'
Requires-Dist: sphinx-autodoc-typehints; extra == 'docs'
Requires-Dist: sphinx>=7.0; extra == 'docs'
Provides-Extra: pyfuse3
Requires-Dist: pyfuse3>=3.3; extra == 'pyfuse3'
Description-Content-Type: text/markdown

# fusedzoo

A [FUSE](https://github.com/libfuse/libfuse) filesystem that mounts an Apache
[ZooKeeper](https://zookeeper.apache.org/) tree as a local directory, backed by
[kazoo](https://kazoo.readthedocs.io/).

## The dual znode model

ZooKeeper znodes are simultaneously containers (they have children) *and* data
holders (they carry a byte payload). fusedzoo exposes both facets at once:

- Every znode `/a/b/c` maps to a **directory** at the mountpoint.
- The znode's data payload is exposed through a virtual file named `.zk-data`
  inside that directory.

```text
/mnt/zk/
  my/
    favorite/          <- znode /my/favorite (ls to see children)
      .zk-data         <- read/write the node's raw byte payload
      node/            <- child znode /my/favorite/node
        .zk-data
```

| Filesystem operation              | ZooKeeper operation             |
| --------------------------------- | ------------------------------- |
| `ls /mnt/zk/a/b`                  | `get_children(/a/b)`            |
| `cat /mnt/zk/a/b/.zk-data`        | `get(/a/b)`                     |
| `echo foo > /mnt/zk/a/b/.zk-data` | `set(/a/b, b"foo")`             |
| `mkdir /mnt/zk/a/b/c`             | `create(/a/b/c, b"")`           |
| `rmdir /mnt/zk/a/b/c`             | `delete(/a/b/c)` (if childless) |

Node data is passed through as **raw bytes** with no encoding.

## Installation

```bash
pip install fusedzoo            # default: fusepy (libfuse2) backend
pip install fusedzoo[pyfuse3]   # opt-in: pyfuse3 (libfuse3, async) backend
```

The host system needs libfuse installed (`libfuse2` for the fusepy backend,
`libfuse3` for pyfuse3) and a usable `/dev/fuse` device.

## Usage

```bash
fusedzoo mount localhost:2181 /mnt/zk   # mounts in the foreground
fusedzoo umount /mnt/zk
```

See `fusedzoo mount --help` for pool sizing, backend selection, read-only, and
experimental poll options.

```bash
# Create a znode
mkdir /mnt/zk/services

# Write its payload
echo '{"host": "db1"}' > /mnt/zk/services/.zk-data

# Read it back
cat /mnt/zk/services/.zk-data

# Inspect ZooKeeper metadata as extended attributes
getfattr -d /mnt/zk/services

# Remove a childless znode
rmdir /mnt/zk/services
```

> **Note:** `df` will not show fusedzoo in plain `df -h` because ZooKeeper has
> no filesystem capacity concept and the mount reports `0/0` blocks. Use
> `df -h -a` or `df -h /mnt/zk` to see it explicitly.

## Development

```bash
hatch run release      # ruff + mypy + pytest --cov + hatch build (full gate)
hatch run dry_release  # same but non-blocking (continues on failure)
hatch run docs:build   # build Sphinx docs
```

## License

Apache 2.0
