Brian Bjarke JensenandCursor 30a1de32e8
Test Python Package / test (pull_request) Successful in 48s
Code Quality Pipeline / code-quality (pull_request) Successful in 31s
PR Title Check / check-title (pull_request) Successful in 5s
Fix PR coverage comment posting in CI.
Build the Gitea API payload with json.dumps so multiline coverage output is valid JSON, and fail the step when the API rejects the request.

Co-authored-by: Cursor <[email protected]>
2026-06-28 23:46:49 +02:00
2025-08-31 17:33:17 +02:00
2025-08-31 17:50:04 +02:00
2025-08-31 17:33:17 +02: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

Optional dependencies

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%