Skip to main content

Atomic-like Agnostic Object Storage Framework, the Pydantic way

CI Codacy Coverage Roadmap PyPI versions License: MIT Last Commit Codacy Grade

Documentation: 📖 Docs


FennFlow is a Python s3 framework designed to help you quickly, confidently, and painlessly manipulate files in your object storage implementing SSOT pattern and Saga compensation flow.

Why use FennFlow?

Working with aiobotocore often feels like handling raw bytes and dicts. FennFlow wraps S3 operations into a high-level Unit of Work pattern, providing:

  • SSOT — the backend is the single source of truth for your file storage. No matter what your file storage contains, the backend ensures a consistent view of what exists.
  • Saga compensation flow — if something fails mid-operation, all previous actions are automatically compensated in reverse order, leaving storage in a consistent state.
  • Clean Architecture — treat S3 as proper repositories using mixins (PutRepository, GetRepository, etc.).
  • Pydantic-powered models — work with TextContent, JsonContent, ImageContent and others instead of raw bytes.
  • Testability — swap S3ConnectorConfig for InMemoryConnectorConfig and point the backend at an in-memory SQLite database. Zero infrastructure, zero mocks.

Supported Connectors

Connector Description Documentation
AWS S3 (default) s3 compatible object storage via aiobotocore 📖 Docs
In-Memory great for and tests and development 📖 Docs

Supported Backends

FennFlow uses backend as a source of truth for your file storage. No matter what your file storage contains, backend ensures your data is consistent.

Backend Description Documentation
SQLAlchemy (default) persistent metadata backend, great for all environments 📖 Docs
In-Memory great for and tests, development 📖 Docs

Backend Comparison

Raw aiobotocore SQLAlchemy (default)
Consistency 🔴 None
No link between files and metadata
✅ High
Persistent across restarts
Compensation 🔴 None
Orphaned files on failure
✅ High
Automatic within session
Reliability 🔴 Low
Failures leave storage in unknown state
✅ High
Consistent state guaranteed across restarts
Latency ✅ Lowest
Pure S3 network overhead only
🟡 Low/middle
DB overhead
Infrastructure ✅ None ✅ None
SQLite by default
Memory usage ✅ None ✅ Minimal
Metadata persisted to disk, not held in-process

Quick Start

Here's a minimal example of FennFlow:

import asyncio

from fennflow import ConfigDict, UnitOfWork
from fennflow.backends import SqlalchemyBackendConfig
from fennflow.connectors import S3ConnectorConfig
from fennflow.files import BinaryContent, JsonContent, MediaType, TextContent
from fennflow.repositories import (
    DeleteRepository,
    GetRepository,
    ListRepository,
    PutRepository,
    S3RepoField,
    )


# 1. Define your repository with mixins
class CrudRepository(
    PutRepository,
    DeleteRepository,
    GetRepository,
    ListRepository,
    ):
    pass


# 2. Set up your Unit of Work
class UOW(UnitOfWork):
    my_files = S3RepoField(CrudRepository, bucket_name="my_files")
    config = ConfigDict(
        backend=SqlalchemyBackendConfig(),
        connector=S3ConnectorConfig(),
        )


async def main():
    text_file = TextContent.from_content("Hello, world!")
    json_file = JsonContent.from_content([1, 2, 3])

    from_path_binary_file = BinaryContent.from_local_path("my_file.txt")
    binary_file = BinaryContent(data=b"some bytes", media_type=MediaType.TEXT_PLAIN)

    async with UOW() as uow:
        await uow.my_files.at("folder1").put(
            text_file,
            json_file,
            from_path_binary_file,
            binary_file,
            )

        paths = await uow.my_files.at("folder1").list()
        print(paths)  # ListResponse[Filepath, ...]

        files = await uow.my_files.get(*paths)
        print(files)  # MediaResponse[TextContent, JsonContent, TextContent, BaseBinary]


if __name__ == "__main__":
    asyncio.run(main())

(This example is complete, it can be run “as is”, assuming you’ve installed the fennflow package)

Next Steps

To try FennFlow for yourself, clone it and follow the instructions in the examples.

Read the docs to learn more about working with FennFlow.

Read the API Reference to understand FennFlow’s interface.

Learn how to utilize llms with FennFlow.

Metadata

Release files for fennflow 0.8.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for fennflow 0.8.0
File Size Uploaded
fennflow-0.8.0.tar.gz 252.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for fennflow 0.8.0
File Interpreter ABI Platform
fennflow-0.8.0-py3-none-any.whl Python 3 none any Details

Total release size: 370.9 kB

Release files / fennflow-0.8.0.tar.gz

Download URL fennflow-0.8.0.tar.gz
Size 252.0 kB
Tags Source
SHA-256 checksum
How to use checksums
23da6cfd15afc4e5c38727a62b40c3af95e8140e99b77b5c0b25263e62ce507a
BLAKE2b-256 checksum
How to use checksums
0f1c8cbd2876ed7420ae4d6c84a21dbffcc35314b54e846f0b10d8a1952cacfc
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 13, 2026.

Transparency log

Release files / fennflow-0.8.0-py3-none-any.whl

Download URL fennflow-0.8.0-py3-none-any.whl
Size 118.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
d79d94351609ca7c8ab37065957926db876af24fee811b090b9820f2d625015c
BLAKE2b-256 checksum
How to use checksums
e24278c771a31a9bddf469bedb9980cc08e79141cb132510881223d4c2ca7c2f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 13, 2026.

Transparency log

Release history Release notifications | RSS feed

0.8.1

2 release files

This release

0.8.0 This release

2 release files

0.7.0

2 release files

0.6.0

2 release files

0.5.1

2 release files

0.5.0

2 release files

0.4.0

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page