Typed in-process request dispatch for Python 3.12+
PyMediate routes typed requests to handlers. A request declares its response type, so
Mediator.send() preserves that type for static type checkers and editors.
Installation
pip install pymediate
The core package has no required dependencies. Install the optional Dependency Injector
integration with pip install 'pymediate[di]'.
First request
import asyncio
from dataclasses import dataclass
from pymediate import Mediator, Request, RequestHandler, Services
@dataclass(frozen=True)
class OrderReceipt:
order_id: int
summary: str
@dataclass(frozen=True)
class PlaceOrder(Request[OrderReceipt]):
customer_id: int
item: str
quantity: int
class PlaceOrderHandler(RequestHandler[PlaceOrder]):
async def __call__(self, request: PlaceOrder) -> OrderReceipt:
return OrderReceipt(
order_id=42,
summary=f"{request.quantity} × {request.item}",
)
async def main() -> None:
mediator = Mediator(Services(PlaceOrderHandler()))
receipt = await mediator.send(
PlaceOrder(customer_id=7, item="tea", quantity=2),
)
print(receipt.order_id, receipt.summary)
asyncio.run(main())
The program prints:
42 2 × tea
Read the declarations as follows:
OrderReceiptis the response.PlaceOrder(Request[OrderReceipt])is a request for anOrderReceipt.PlaceOrderHandler(RequestHandler[PlaceOrder])handlesPlaceOrderrequests.
The introduction contains an interactive guide to these relationships. The quick start explains the complete dispatch flow.
API at a glance
| Need | API | Result |
|---|---|---|
| Send a request to one handler | Mediator.send() |
One response, inferred from Request[T] |
| Yield results over time | Mediator.stream() |
Typed chunks from StreamRequest[T] |
| Notify zero or more subscribers | Mediator.publish() |
No response |
| Wrap request handling | PipelineBehavior |
Shared processing around send() |
| Supply handlers and behaviors | Services or another ServiceProvider |
Resolved instances |
The top-level package is asynchronous. pymediate.sync provides corresponding blocking mediator
and handler classes. Shared message types, services, and errors are the same objects in both
namespaces.
Type checking and validation
Request[T] records the return type used by send() at static call sites. Separately, PyMediate
checks a request handler's parameter annotation, return annotation, and asynchronous or synchronous
form when Python defines the handler class.
Configuration can still fail during dispatch. For example, sending a request without a registered handler instance raises an error at that point. The type-safety guide describes which checks happen statically, at class definition, and during dispatch.
Scope and trade-offs
PyMediate provides in-process dispatch. It does not provide a task queue, choose persistence, or require CQRS or hexagonal architecture. Direct calls are often clearer when callers can depend on their collaborators without repeated wiring, and a small hand-written dispatcher can be enough.
The article Using a mediator to reduce change coupling develops the case for a mediator and covers the added indirection, registration, and runtime cost. The comparison documents the current feature set, dated dispatch benchmarks, and a runnable benchmark script.
Documentation
Development
git clone https://github.com/sina-al/pymediate.git
cd pymediate
uv sync --all-extras --group test
uv run poe test
uv run poe check:all
Run uv run poe to list the repository tasks. See
CONTRIBUTING.md for the
contribution process.
Versioning
PyMediate follows ZeroVer: the major version remains 0. A minor release
(0.X.0) can contain a breaking API change or a backward-compatible feature. A patch release
(0.X.Y) contains changes that do not alter the public API.
License
PyMediate is available under the MIT License.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pymediate-0.10.0.tar.gz.
File metadata
- Download URL: pymediate-0.10.0.tar.gz
- Upload date:
- Size: 1.4 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
93a4c11ab0b5e2673faf6f3dd016c66f836c9e9f082612e675f72e5d12d77992
|
|
| MD5 |
5b23230ff06f78b4b75805a4b615b52f
|
|
| BLAKE2b-256 |
645b23b05990656bd3041efae91ef1d1dd9bc642485c41749566ad59ff318595
|
Provenance
The following attestation bundles were made for pymediate-0.10.0.tar.gz:
Publisher:
release.yml on sina-al/pymediate
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pymediate-0.10.0.tar.gz -
Subject digest:
93a4c11ab0b5e2673faf6f3dd016c66f836c9e9f082612e675f72e5d12d77992 - Sigstore transparency entry: 2275202788
- Sigstore integration time:
-
Permalink:
sina-al/pymediate@af7e45de0597e4c5ce6b0db472ea4131fcad790a -
Branch / Tag:
refs/tags/v0.10.0 - Owner: https://github.com/sina-al
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@af7e45de0597e4c5ce6b0db472ea4131fcad790a -
Trigger Event:
push
-
Statement type:
File details
Details for the file pymediate-0.10.0-py3-none-any.whl.
File metadata
- Download URL: pymediate-0.10.0-py3-none-any.whl
- Upload date:
- Size: 51.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b8e885e49bf65e0464fd45013165a50d65a36720eab1ad644f399fa46a571b08
|
|
| MD5 |
3690805a56313fbad11550eef3129e28
|
|
| BLAKE2b-256 |
39ed60f5cfd46c024b813a1b25d8b94ca36472fdffdaddd2a6ea6f0292a58bf9
|
Provenance
The following attestation bundles were made for pymediate-0.10.0-py3-none-any.whl:
Publisher:
release.yml on sina-al/pymediate
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pymediate-0.10.0-py3-none-any.whl -
Subject digest:
b8e885e49bf65e0464fd45013165a50d65a36720eab1ad644f399fa46a571b08 - Sigstore transparency entry: 2275202907
- Sigstore integration time:
-
Permalink:
sina-al/pymediate@af7e45de0597e4c5ce6b0db472ea4131fcad790a -
Branch / Tag:
refs/tags/v0.10.0 - Owner: https://github.com/sina-al
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@af7e45de0597e4c5ce6b0db472ea4131fcad790a -
Trigger Event:
push
-
Statement type: