Propan is a powerful and easy-to-use Python framework for building event-driven applications that interact with any MQ Broker
MIT License
Bot releases are visible (Hide)
Full Changelog: https://github.com/Lancetnik/Propan/compare/0.1.5.15...0.1.5.17
Published by Lancetnik about 1 year ago
Added detail exceptions traceback, fix FastAPI yield dependencies support, fix an empty RMQ message_id parsing, fix some routers' erros, add kafka publish_batch
method and some other fixes.
Also:
Full Changelog: https://github.com/Lancetnik/Propan/compare/0.1.5.0...0.1.5.15
Published by Lancetnik over 1 year ago
This update adds NATS JetStream (a persistent layer of NATS) supporting.
Now you can work with this great broker without fear of losing messages, using the acknowledgment confirmation mechanism and the built-in key-value
and object
storages.
Also, some internal classes were changed to further create a synchronous interfaces based on them.
@bodograumann @v-sopov @hbrooks @sallory, thank you, guys!
Published by Lancetnik over 1 year ago
The main change in this update is the support for the PydanticV2 beta version.
Also, this update still supports Pydantic v1, so if something with PydanticV2 breaks you can simply roll it back - the latest Propan continues to work without changes.
Be careful: if you use Propan together with FastAPI when migrating to PydanticV2, you must install the version fastapi>=0.100.0b1
, which is also compatible with both versions of Pydantic. However, if you are working on versions of FastAPI 0.9*
, the current release is compatible with them as well (but only using PydanticV1).
All test suites work correctly with all variations of the dependencies and on all supported Python versions.
Other changes:
Improved compatibility with FastAPI:
PropanRouter supports top-level dependencies
from propan.fastapi import RabbitRouter
router = RabbitRouter(dependencies=[...])
@router.event("test", dependencies=[...])
async def handler(a: str, b: int):
...
You can test router.event
using build_message
directly
import pytest, pydantic
from propan.fastapi import RabbitRouter
from propan.test.rabbit import build_message
router = RabbitRouter()
@router.event("test")
async def handler(a: str, b: int):
...
with pytest.raises(pydantic.ValidationError):
handler(build_message("Hello", "test"), reraise_exc=True)
Implemented BrokerRouter for the convenience of splitting the application code into imported submodules.
from propan import RabbitBroker, RabbitRouter
router = RabbitRouter(prefix="user/")
@router.handle("created")
async def handle_user_created_event(user_id: str):
...
broker = RabbitBroker()
broker.include_router(router)
Added documentation section about custom message serialization (using the example with Protobuf).
And also updated several other sections of the documentation, fixed several non-critical bugs, removed RabbitBroker deprecated methods, and increased test coverage of rare scenarios.
Published by Lancetnik over 1 year ago
amq.rabbitmq.reply-to
to implement RPC by @Lancetnik in https://github.com/Lancetnik/Propan/pull/72
Now you can use pydantic.Field
to describe your arguments in AsyncAPI spec
from pydantic import Field
@broker.handle(...)
async def handler(
user_id: str = Field(title="DBUserId", description="UserId at main Postgres")
): ...
Full Changelog: https://github.com/Lancetnik/Propan/compare/0.1.3.0...0.1.3.5
Published by Lancetnik over 1 year ago
The current update adds functionality that I've been working hard on for the last month:
Now Propan can automatically generate and host documentation for your application
according to the AsyncAPI specification.
You can simply provide related teams with a link to your documentation page, where they can get acquainted with all the parameters of the server used, channels, and the format of messages consumed by your service.
You can learn more about this functionality in the corresponding [documentation section] (getting_started/9_documentation.md).
Also, the ability to determine a broker and consumers level dependencies has been added.:
from propan import RabbitBroker, Depends
broker = RabbitBroker(dependencies=[Depends(...)])
@broker.handler(..., dependencies=[Depends(...)])
async def handler():
...
Full Changelog: https://github.com/Lancetnik/Propan/compare/0.1.2.17...0.1.3.0
Published by Lancetnik over 1 year ago
The current update is a sum of several changes and improvements released from the previous release.
The main change - Propan no longer obliges you to receive a message in the form of only one argument.
Your handler function can consume as many arguments as needed and also combine them with pydantic.BaseModel.
@router.handle(...)
async def handler(a: int, b: float):
...
async def handler(a: Message, b: float, c: str):
A few public methods for declaring objects RabbitMQ were added to RabbitBroker:
broker = RabbitBroker()
...
await broker.declare_exchange(RabbitExchange("test"))
await broker.declare_queue(RabbitQueue("test"))
channel: aio_pika.RobustChannel = broker.channel
To maintain the ability to send messages and initialize channels, an after_startup
hook has been added to all FastAPI PropanRouters.
router = RabbitRouter()
@router.after_startup
async def init_whatever(app: FastAPI): ...
In addition, the behavior of the __init__
and connect
methods for all brokers have been improved (now the connect
parameters have priority and override the __init__
parameters when connecting to the broker), a correct exception has been implemented when accessing an object unavailable for import, several errors have been fixed and other minor internal changes.
Published by Lancetnik over 1 year ago
Propan added support for SQS as a message broker. This functionality is full tested.
SQSBroker supports:
SQSBroker not supports RPC yet.
Also, current release include the following fixes:
Published by Lancetnik over 1 year ago
NatsBroker
is full tested now.
Also, to Nats supporting added:
TestNatsBroker
and test messages to local testingNatsRouter
for FastAPI
Published by Lancetnik over 1 year ago
Propan added support for Kafka as a message broker. This functionality is full tested.
KafkaBroker supports:
KafkaBroker not supports RPC yet.
Published by Lancetnik over 1 year ago
Propan added support for Redis Pub/Sub as a message broker. This functionality is fully tested and described in the documentation.
RedisBroker supports:
Also, Propan CLI is able to generate templates to any supported broker
propan create async [broker] [APPNAME]
Published by Lancetnik over 1 year ago
Stable and fully documented Propan release!
From the current release, no more breaking changes - use the framework safely!
At the current release, all RabbitMQ use cases are supported, tested, and described in the documentation.
Expect support for Redis (testing now), Kafka (in development), and full support for Nats (also in development) soon.
Published by Lancetnik over 1 year ago
Great news! Now Propan can be used as a full part of FastAPI!
from fastapi import FastAPI
from propan.fastapi import RabbitRouter
app = FastAPI()
router = RabbitRouter("amqp://guest:guest@localhost:5672")
@router.event("test")
async def hello(m: dict) -> dict:
return { "response": "Hello Propan!" }
app.include_router(router)
You can find a complete example in documentation
Also, added the ability to test your application without running external dependencies as a broker (for now only for RabbitMQ)!
from propan import RabbitBroker
from propan.test import TestRabbitBroker
broker = RabbitBroker()
@broker.handler("ping")
async def healthcheck(msg: str) -> str:
return "pong"
def test_publish():
async with TestRabbitBroker(broker) as test_broker:
await test_broker.start()
r = await test_broker.publish("ping", queue="ping", callback=True)
assert r == "pong"
Also added support for RPC over MQ (RabbitMQ only for now): return
of your handler function will be sent in response to a message if a response is expected.
publish_message
method has been renamed to publish
declare
argument in RabbitQueue
and RabbitExchange
- now you need to use passive
Published by Lancetnik over 1 year ago
Release is timed to accompany the release of fast-depends.
Now it's used as the Propan Dependency Injection system deep inside. Context is an fast-depends CustomField child now.
Depends
nestingContext
behaviorpropan.annotation
module to faster access to already declared context fields@use_context
was removed. Use @apply_types
to solve Context
nowAlias
was merged with the Context
fieldNow you should use the following code:
from propan import Context, apply_types
@apply_types
def func(logger = Context()): ...
# or
from propan import Context, apply_types
@apply_types
def func(l = Context("logger")): ...
# or
from propan import apply_types
from propan.annotations import Logger
@apply_types
def func(logger: Logger): ...
Published by Lancetnik over 1 year ago
Hello there! Congratulate everybody and me with the first stable Propan release!
As an experimental feature in this release was added NATS (not Jetstream) supporting.