pymediate

Introduction

What PyMediate is, why it exists, and where to go next.

PyMediate is a type-safe implementation of the mediator pattern for Python 3.12+. It routes typed Request objects to their Handlers through a single Mediator, so the code that asks for something never has to know the code that does it.

response = mediator.send(CreateUser(username="alice", email="alice@example.com"))
# response is UserCreated — inferred from the request type, checked by mypy

Why PyMediate?

Most mediator implementations in Python rely on naming conventions, string registries, or decorators that erase types. PyMediate takes a different approach:

  • Type inspection, not naming conventions. A handler declares the request it handles with Handler[CreateUser] — the link is in the type system, not in a magic string.
  • The response type is declared once. A request inherits Request[UserCreated], and from then on mediator.send() returns UserCreated everywhere — inferred by mypy, no casts.
  • Validation at class-definition time. Handler signatures are checked when the class is defined. Wiring mistakes surface at import, not when a request fails in production.
  • Zero runtime dependencies. The core is pure Python 3.12+ built on PEP 695 generics. dependency-injector support is an optional extra.
  • A structural async mirror. pymediate.aio mirrors the sync API class for class — switch the import, add await, and everything else stays the same.

The moving parts

ConceptRole
Request[T]A message declaring what it wants and the response type T it expects
Handler[R]The single place where a request type R gets handled
MediatorRoutes each request to its handler; the only thing callers depend on
PipelineBehaviorOptional middleware wrapping handlers — logging, validation, transactions
Services / ServiceProviderRegistration and resolution of handlers, behaviors, and their dependencies

Where to go next

On this page