Brian Bjarke JensenandCursor 34fc046868
Code Quality Pipeline / code-quality (pull_request) Successful in 31s
PR Title Check / check-title (pull_request) Successful in 6s
Test Python Package / test (pull_request) Successful in 58s
Sync uv.lock with pyproject.toml version 0.3.2.
Co-authored-by: Cursor <[email protected]>
2026-07-05 15:38:49 +02:00
2025-08-31 17:50:04 +02:00
2026-06-30 14:12:18 +00:00

python-repositories

Unified repository interfaces and technology-specific adapters for Python projects.

Subclass an adapter in your own repository to add domain-specific methods while reusing connection management and CRUD operations.

Architecture

Layer Responsibility
Interfaces Abstract contracts for connection, context, and CRUD
Adapters Technology-specific base classes (RedisAdapter, MinioAdapter)
Your project Subclass an adapter and add domain methods

Connection adapters expose connect(), disconnect(), and is_connected(). The latter verifies backend reachability with a cached health probe (default TTL: 1 second). Subclasses may override health_check_ttl_seconds.

Optional dependencies

Repository interfaces import with the base package. Adapters require the matching extra; importing an adapter without its extra raises ImportError with install instructions.

Install with the extras you need:

uv add python-repositories[redis]
uv add python-repositories[minio]
uv add python-repositories[redis,minio]

Redis (JsonRepositoryInterface)

Requires Redis with the RedisJSON module (e.g. redis-stack).

Environment variable Description
REDIS_URI Redis connection URL (e.g. redis://localhost:6379)

MinIO (ObjectRepositoryInterface)

Environment variable Description
MINIO_ENDPOINT MinIO server endpoint
MINIO_ACCESS_KEY Access key
MINIO_SECRET_KEY Secret key
MINIO_BUCKET Bucket name (created on connect if missing)

Quick start

JSON documents with Redis

from python_repositories.examples.user_json_repository import UserJsonRepository

with UserJsonRepository() as repo:
    repo.save_user("alice", {"name": "Alice", "email": "[email protected]"})
    user = repo.get_user("alice")
    repo.delete_user("alice")

Binary objects with MinIO

from io import BytesIO

from python_repositories.examples.artifact_object_repository import (
    ArtifactObjectRepository,
)

with ArtifactObjectRepository() as repo:
    repo.store_artifact("report-1", BytesIO(b"pdf bytes here"))
    data = repo.get_artifact("report-1")

Subclassing in your own project

from python_repositories import RedisAdapter

class UserRepository(RedisAdapter):
    def _key(self, user_id: str) -> str:
        return f"user:{user_id}"

    def get_user(self, user_id: str) -> dict | None:
        return self.get(self._key(user_id))

    def save_user(self, user_id: str, user: dict) -> None:
        self.set(self._key(user_id), user)

Public API

from python_repositories import (
    ConnectionAwareInterface,
    ContextAwareInterface,
    JsonRepositoryInterface,
    ObjectRepositoryInterface,
    RedisAdapter,
    MinioAdapter,
)

Development

uv sync --all-extras
uv run pre-commit install   # once per clone — runs hooks on git commit
uv run pytest tests/integration/ -v

pre-commit is included in the dev dependency group. uv sync installs the CLI, but git does not run hooks until you install them with pre-commit install (one time per clone). After that, commits run the checks defined in .pre-commit-config.yaml (ruff, mypy, pyupgrade, prettier, and general file hygiene).

To run all hooks manually without committing:

uv run pre-commit run --all-files

Integration tests require Docker (testcontainers).

Releases

Releases are automated when a pull request is merged to main. CI reads the merged PR title to decide whether and how to bump the version.

How it works

  1. Open a PR targeting main (see .gitea/PULL_REQUEST_TEMPLATE.md).
  2. If the PR changes files under python_repositories/, the title must start with a version bump prefix (enforced by CI).
  3. On merge, release.yml bumps pyproject.toml, commits, tags vX.Y.Z, creates a Gitea release with auto-generated notes, and pushes the tag.
  4. publish.yml builds and publishes the package to the Gitea Package Registry.

Docs-, CI-, and test-only PRs do not need a prefix and will not trigger a release.

PR title prefixes

Prefix Bump Example
[patch] or [fix] patch 0.3.10.3.2
[minor] or [feat] minor 0.3.10.4.0
[major] or [breaking] major 0.3.11.0.0
(none) no release docs / CI / deps only

Example titles:

  • [minor] Add public repository interfaces and subclassable adapter CRUD API
  • [patch] Fix mypy context manager typing for adapter subclasses

Release notes

Release notes are generated from commits since the previous tag (see scripts/ci/generate-release-notes.sh).

Manual release

You can still push a v*.*.* tag manually; publish.yml will build and publish. The current baseline version is 0.3.1.

S
Description
Various python repository interfaces exposed as a python package.
Readme MIT
2.5 MiB
Languages
Python 92.5%
Shell 7.1%
Dockerfile 0.4%