Skip to main content

PyMediate logo

A type-safe request mediator for Python 3.12+

PyPI version Python versions MIT License Documentation
Tests Coverage Checked with mypy (strict) OpenSSF Scorecard


Features

  • Type safe. Full runtime validation with mypy support.
  • Async/await support. First-class async handlers and mediators via pymediate.aio.
  • DI ready. Built-in dependency-injector integration.
  • Well tested. Comprehensive test suite.

Wondering how this stacks up against other Python mediator libraries — and what send() costs over a direct call? See How it compares, a source-level survey of the ecosystem plus a reproducible micro-benchmark you can run against the latest release with uv run https://pymediate.sina-al.uk/benchmark.py (read it first, as with any script from the network).

Quick example

from dataclasses import dataclass
from pymediate import Request, Handler, Mediator, Services

# Define response and request as pure dataclasses
@dataclass
class UserCreated:
    user_id: int
    username: str

@dataclass
class CreateUser(Request[UserCreated]):
    username: str
    email: str

# Handler automatically linked by type
class CreateUserHandler(Handler[CreateUser]):
    def __call__(self, req: CreateUser) -> UserCreated:
        return UserCreated(user_id=1, username=req.username)

# Set up and use
services = Services()
services.add(CreateUserHandler())
provider = services.provider()
mediator = Mediator(provider)

response = mediator.send(CreateUser(username="alice", email="alice@example.com"))
print(f"User {response.username} created with ID {response.user_id}")

Async support

PyMediate provides first-class async/await support through the pymediate.aio package:

import asyncio
from dataclasses import dataclass
from pymediate import Request, Services
from pymediate.aio import Handler, Mediator

@dataclass
class UserCreated:
    user_id: int
    username: str

@dataclass
class CreateUser(Request[UserCreated]):
    username: str
    email: str

class CreateUserHandler(Handler[CreateUser]):
    async def __call__(self, req: CreateUser) -> UserCreated:
        # Perform async operations
        await asyncio.sleep(0.1)  # Simulate async database call
        return UserCreated(user_id=1, username=req.username)

async def main():
    services = Services()
    services.add(CreateUserHandler())
    provider = services.provider()
    mediator = Mediator(provider)

    response = await mediator.send(CreateUser(username="alice", email="alice@example.com"))
    print(f"User {response.username} created with ID {response.user_id}")

asyncio.run(main())

Key differences for async:

  • Import from pymediate.aio instead of pymediate.
  • The handler's __call__ method must be async def.
  • Use await mediator.send(...) instead of mediator.send(...).
  • Supports concurrent request handling with asyncio.gather().

Pipeline behaviors

PyMediate supports pipeline behaviors (middleware) that automatically wrap request processing for cross-cutting concerns like logging, validation, caching, and more:

from pymediate import Request, PipelineBehavior

# Universal behavior - applies to all requests
class LoggingBehavior(PipelineBehavior[Request]):
    def __call__(self, request, next):
        print(f"Handling: {type(request).__name__}")
        response = next()
        print(f"Completed: {type(request).__name__}")
        return response

# Selective behavior - only applies to CreateUser requests
class ValidationBehavior(PipelineBehavior[CreateUser]):
    def __call__(self, request, next):
        # Validate before processing
        if not request.username:
            raise ValueError("Username is required")
        return next()

# Register behaviors and handlers
services = Services()
services.add(LoggingBehavior())       # Applied to all requests
services.add(ValidationBehavior())    # Only applied to CreateUser
services.add(CreateUserHandler())

mediator = Mediator(services.provider())

# Behaviors automatically wrap matching requests
response = mediator.send(CreateUser(username="alice", email="alice@example.com"))
# Output:
# Handling: CreateUser
# Completed: CreateUser

Behaviors can be universal (PipelineBehavior[Request]) or selective (PipelineBehavior[SpecificRequest]), applying only to matching request types or mixins. They're resolved per request and work with any dependency-injector provider lifetime — Factory, Singleton, or a scoped variant like ContextLocalSingleton. See the Pipeline behaviors guide for more examples.

Installation

# Core package
pip install pymediate

# With dependency injection support
pip install pymediate[di]

Documentation

📚 Full documentation

Development

Quick start

# Clone and install
git clone https://github.com/sina-al/pymediate.git
cd pymediate
uv sync --all-extras --group test

# Run tests
poe test

# Run all checks
poe check:all

# See all available tasks
poe

Available commands

PyMediate uses Poe the Poet for task running. Run poe to see all commands, or check tasks.toml.

Note: uv sync alone only installs the default dev dependency group (ruff, mypy, poethepoet). Test dependencies (pytest and friends) live in the separate test group and won't be installed unless you pass --group test (or --all-groups) — otherwise poe test fails with Failed to spawn: pytest.

Requirements

  • Python 3.12+.
  • Optional: dependency-injector>=4.41.0 for DI support.

Versioning

PyMediate follows ZeroVer — the major version stays at 0 indefinitely, with no planned 1.0. Expect the public API to keep evolving: a minor release (0.X.0) can include breaking changes, while a patch release (0.1.X) is backward-compatible.

Contributing

Contributions are welcome. See CONTRIBUTING.md for guidelines.

License

MIT License — see LICENSE for details.

Download files

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

Source Distribution

pymediate-0.3.1.tar.gz (1.1 MB view details)

Uploaded Source

Built Distribution

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

pymediate-0.3.1-py3-none-any.whl (45.6 kB view details)

Uploaded Python 3

File details

Details for the file pymediate-0.3.1.tar.gz.

File metadata

  • Download URL: pymediate-0.3.1.tar.gz
  • Upload date:
  • Size: 1.1 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for pymediate-0.3.1.tar.gz
Algorithm Hash digest
SHA256 93593201d59018f9f4ad0b1e69ee0cc4b7865476e62d52a3e4b75fdda3959bcb
MD5 5e7fbea0796c123e05771de665c4bbf9
BLAKE2b-256 b588eac75fcd9da802ae173b61854ef5aa1d6c50b826982b46e4ce417a86d587

See more details on using hashes here.

Provenance

The following attestation bundles were made for pymediate-0.3.1.tar.gz:

Publisher: release.yml on sina-al/pymediate

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

File details

Details for the file pymediate-0.3.1-py3-none-any.whl.

File metadata

  • Download URL: pymediate-0.3.1-py3-none-any.whl
  • Upload date:
  • Size: 45.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for pymediate-0.3.1-py3-none-any.whl
Algorithm Hash digest
SHA256 5a3af2d106b0d98d4a10b8d7617e3d0159162cb10b88774ad476e5c047b4a34a
MD5 917428d1cba6bf8a0a75670a2e3c082b
BLAKE2b-256 32dfac95dd1e900e83d49cefb9008a92f18610a2f58d550f35f3260d8001a5be

See more details on using hashes here.

Provenance

The following attestation bundles were made for pymediate-0.3.1-py3-none-any.whl:

Publisher: release.yml on sina-al/pymediate

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

Release history Release notifications | RSS feed

0.10.0

2 files

0.9.0

2 files

0.8.0

2 files

0.7.1

2 files

0.6.0

2 files

0.5.0

2 files

0.4.0

2 files

This release

0.3.1 This release

2 files

0.3.0

2 files

0.2.0

2 files

0.1.5

2 files

0.1.4

2 files

0.1.3

2 files

0.1.2

2 files

0.1.1

2 files

0.1.0

2 files

Supported by

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