Skip to content

Commit

Permalink
0.1.1 Release
Browse files Browse the repository at this point in the history
* redis draft

* update readme blank links

* correct docs with redis examples

* correct rabbit template

* specify `propan create` command

* add create redis app subcommand

* correct tests

* add create nats app subcommand

* add redis examples

* add redis examples

* add redis ru docs

* redis docs complete

* release redis version

* python3.7 comaptible annotation
  • Loading branch information
Lancetnik committed May 18, 2023
1 parent 9ba2317 commit 2e6d64a
Show file tree
Hide file tree
Showing 194 changed files with 3,518 additions and 745 deletions.
2 changes: 0 additions & 2 deletions .github/workflows/documentation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ on:
- main
paths:
- docs/**
pull_request:
types: [opened, synchronize]

permissions:
contents: write
Expand Down
5 changes: 5 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ jobs:
image: rabbitmq
ports:
- 5672:5672

redis:
image: redis
ports:
- 6379:6379

steps:
- uses: actions/checkout@v3
Expand Down
57 changes: 31 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,11 @@

# Propan

**Propan** - just *~~an another one HTTP~~* a **declarative Python MQ framework**. It's following by [*fastapi*](https://fastapi.tiangolo.com/ru/),
simplify Message Brokers around code writing and provides a helpful development toolkit, which existed only in HTTP-frameworks world until now.
**Propan** - just *~~an another one HTTP~~* a **declarative Python MQ framework**. It's following by <a href="https://fastapi.tiangolo.com/ru/" target="_blank">*fastapi*</a>, simplify Message Brokers around code writing and provides a helpful development toolkit, which existed only in HTTP-frameworks world until now.

It's designed to create reactive microservices around <a href="https://microservices.io/patterns/communication-style/messaging.html" target="_blank">Messaging Architecture</a>.

It is a modern, high-level framework on top of popular specific Python brokers libraries, based on [*pydantic*](https://docs.pydantic.dev/) and [*fastapi*](https://fastapi.tiangolo.com/ru/), [*pytest*](https://docs.pytest.org/en/7.3.x/) concepts.
It is a modern, high-level framework on top of popular specific Python brokers libraries, based on <a href="https://docs.pydantic.dev/" target="_blank">*pydantic*</a> and <a href="https://fastapi.tiangolo.com/ru/" target="_blank">*fastapi*</a>, <a href="https://docs.pytest.org/en/7.3.x/" target="_blank">*pytest*</a> concepts.

---

Expand All @@ -43,30 +42,34 @@ It is a modern, high-level framework on top of popular specific Python brokers l

### The key features are

* **Easy**: Designed to be easy to use and learn.
* **Simple**: Designed to be easy to use and learn.
* **Intuitive**: Great editor support. Autocompletion everywhere.
* [**Dependencies management**](#dependencies): Minimize code duplication. Multiple features from each argument and parameter declaration.
* [**Integrations**](#http-frameworks-integrations): **Propan** is ready to use in pair with [any HTTP framework](https://lancetnik.github.io/Propan/5_integrations/1_integrations-index/) you want
* [**Dependencies management**](#dependencies): Minimization of code duplication. Access to dependencies at any level of the call stack.
* [**Integrations**](#http-frameworks-integrations): **Propan** is fully compatible with <a href="https://lancetnik.github.io/Propan/integrations/1_integrations-index/" target="_blank">any HTTP framework</a> you want
* **MQ independent**: Single interface to popular MQ:
* **NATS** (based on [nats-py](https://github.com/nats-io/nats.py))
* **RabbitMQ** (based on [aio-pika](https://aio-pika.readthedocs.io/en/latest/))
* [**RPC**](https://lancetnik.github.io/Propan/2_getting_started/4_broker/5_rpc/): The framework supports RPC requests over MQ, which will allow performing long operations on remote services asynchronously.
* **Redis** (based on <a href="https://redis.readthedocs.io/en/stable/index.html" target="_blank">redis-py</a>)
* **RabbitMQ** (based on <a href="https://aio-pika.readthedocs.io/en/latest/" target="_blank">aio-pika</a>)
* **NATS** (based on <a href="https://github.com/nats-io/nats.py" target="_blank">nats-py</a>)
* <a href="https://lancetnik.github.io/Propan/getting_started/4_broker/5_rpc/" target="_blank">**RPC**</a>: The framework supports RPC requests over MQ, which will allow performing long operations on remote services asynchronously.
* [**Greate to develop**](#cli-power): CLI tool provides great development experience:
* framework-independent way to rule application environment
* application code hot reloading
* [**Testability**](https://lancetnik.github.io/Propan/2_getting_started/7_testing): **Propan** allows you to test your app without external dependencies: you shouldn't suit up a Message Broker, use a virtual one!
* framework-independent way to manage the project environment
* application code *hot reload*
* robust application templates
* <a href="https://lancetnik.github.io/Propan/getting_started/7_testing" target="_blank">**Testability**</a>: **Propan** allows you to test your app without external dependencies: you do not have to set up a Message Broker, you can use a virtual one!

### Supported MQ brokers
| | async | sync |
|--------------|:-------------------------------------------------------:|:--------------------:|
| **RabbitMQ** | :heavy_check_mark: **stable** :heavy_check_mark: | :mag: planning :mag: |
| **Nats** | :warning: **beta** :warning: | :mag: planning :mag: |
| **NatsJS** | :hammer_and_wrench: **in progress** :hammer_and_wrench: | :mag: planning :mag: |
| **MQTT** | :mag: planning :mag: | :mag: planning :mag: |
| **REDIS** | :mag: planning :mag: | :mag: planning :mag: |
| **Kafka** | :mag: planning :mag: | :mag: planning :mag: |
| **SQS** | :mag: planning :mag: | :mag: planning :mag: |

| | async | sync |
|-------------------|:-------------------------------------------------------:|:--------------------:|
| **RabbitMQ** | :heavy_check_mark: **stable** :heavy_check_mark: | :mag: planning :mag: |
| **Redis** | :heavy_check_mark: **stable** :heavy_check_mark: | :mag: planning :mag: |
| **Nats** | :warning: **beta** :warning: | :mag: planning :mag: |
| **NatsJS** | :hammer_and_wrench: **in progress** :hammer_and_wrench: | :mag: planning :mag: |
| **MQTT** | :mag: planning :mag: | :mag: planning :mag: |
| **Kafka** | :mag: planning :mag: | :mag: planning :mag: |
| **Redis Streams** | :mag: planning :mag: | :mag: planning :mag: |
| **Pulsar** | :mag: planning :mag: | :mag: planning :mag: |
| **SQS** | :mag: planning :mag: | :mag: planning :mag: |

### Community

Expand All @@ -78,9 +81,9 @@ If you have any questions or ideas about features to implement, welcome to [disc

## Declarative?

With declarative tools you should define **what you need to get**. With traditional imperative tools you should write **what you need to do**.
With declarative tools you can define **what you need to get**. With traditional imperative tools you must write **what you need to do**.

Take a look at classic imperative tools, such as [aio-pika](https://aio-pika.readthedocs.io/en/latest/), [pika](https://pika.readthedocs.io/en/stable/), [nats-py](https://github.com/nats-io/nats.py), etc.
Take a look at classic imperative tools, such as <a href="https://aio-pika.readthedocs.io/en/latest/" target="_blank">aio-pika</a>, <a href="https://pika.readthedocs.io/en/stable/" target="_blank">pika</a>, <a href="https://redis.readthedocs.io/en/stable/index.html" target="_blank">redis-py</a>, <a href="https://github.com/nats-io/nats.py" target="_blank">nats-py</a>, etc.

This is the **Quickstart** with the *aio-pika*:

Expand Down Expand Up @@ -108,9 +111,9 @@ async def main():
asyncio.run(main())
```

**aio-pika** is a really great tool with a really easy learning curve. But it's still imperative. You need to *connect*, declare *channel*, *queues*, *exchanges* by yourself. Also, you need to manage *connection*, *message*, *queue* context to avoid any troubles.
**aio-pika** is a great tool with a really easy learning curve. But it's still imperative. You need to *connect*, declare *channel*, *queues*, *exchanges* by yourself. Also, you need to manage *connection*, *message*, *queue* context to avoid any troubles.

It is not a bad way, but it can be easy.
It is not a bad way, but it can be much easier.

```python
from propan import PropanApp, RabbitBroker
Expand Down Expand Up @@ -145,10 +148,12 @@ Create an application with the following code at `serve.py`:
```python
from propan import PropanApp
from propan import RabbitBroker
# from propan import RedisBroker
# from propan import NatsBroker

broker = RabbitBroker("amqp://guest:guest@localhost:5672/")
# broker = NatsBroker("nats://localhost:4222")
# broker = RedisBroker("redis://localhost:6379")

app = PropanApp(broker)

Expand Down Expand Up @@ -261,7 +266,7 @@ async def setup(env: str, context: ContextRepo):
Also, **Propan CLI** is able to generate a production-ready application template:

```bash
propan create [projectname]
propan create async rabbit [projectname]
```

*Notice: project template require* `pydantic[dotenv]` *installation.*
Expand Down
15 changes: 8 additions & 7 deletions docs/docs.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import subprocess

from yaml import load

try:
from yaml import CLoader as Loader
except ImportError:
Expand All @@ -21,16 +22,17 @@
BASE_DIR = Path(__file__).resolve().parent
CONFIG = BASE_DIR / "mkdocs.yml"
DOCS_DIR = BASE_DIR / "docs"
LANGUAGES_DIRS = tuple(filter(
lambda f: f.is_dir() and f.name not in IGNORE_DIRS, DOCS_DIR.iterdir()
))
LANGUAGES_DIRS = tuple(
filter(lambda f: f.is_dir() and f.name not in IGNORE_DIRS, DOCS_DIR.iterdir())
)
BUILD_DIR = BASE_DIR / "site"

with CONFIG.open("r") as f:
config = load(f, Loader)

DEV_SERVER = config.get("dev_addr", "0.0.0.0:8000")


def get_missing_translation(lng: str) -> str:
return str(Path(DOCS_DIR.name) / lng / "helpful" / "missing-translation.md")

Expand All @@ -43,7 +45,7 @@ def get_in_progress(lng: str) -> str:


def get_default_title(file: Path) -> str:
title = file.stem.upper().replace('-', ' ')
title = file.stem.upper().replace("-", " ")
if title == "INDEX":
title = get_default_title(file.parent)
return title
Expand Down Expand Up @@ -92,7 +94,7 @@ def build():


@app.command()
def add(path = typer.Argument(...)):
def add(path=typer.Argument(...)):
title = ""

exists = []
Expand Down Expand Up @@ -156,10 +158,9 @@ def mv(path: str = typer.Argument(...), new_path: str = typer.Argument(...)):
typer.echo(f"{i / new_path} moved")




def _build():
subprocess.run(["mkdocs", "build", "--site-dir", BUILD_DIR], check=True)


if __name__ == "__main__":
app()
2 changes: 0 additions & 2 deletions docs/docs/en/4_nats/1_nats-index.md

This file was deleted.

2 changes: 0 additions & 2 deletions docs/docs/en/4_nats/2_routing.md

This file was deleted.

2 changes: 0 additions & 2 deletions docs/docs/en/4_nats/3_publishing.md

This file was deleted.

23 changes: 20 additions & 3 deletions docs/docs/en/9_CHANGELOG.md → docs/docs/en/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,22 @@
# CHANGELOG

## 2023-05-18 **0.1.1.0** REDIS

**Propan** added support for *Redis Pub/Sub* as a message broker. This functionality is fully tested and described in the documentation.

*RedisBroker* supports:

* message delivery by key or pattern
* test client, without the need to run *Redis*
* **RPC** requests over *Redis Pub/Sub*
* *FastAPI* Plugin

Also, **Propan CLI** is able to generate templates to any supported broker

```bash
propan create async [broker] [APPNAME]
```

## 2023-05-15 **0.1.0.0** STABLE

Stable and fully documented **Propan** release!
Expand Down Expand Up @@ -28,9 +45,9 @@ async def hello(m: dict) -> dict:
app.include_router(router)
```

You can find a complete example in [documentation](../5_integrations/2_fastapi-plugin)
You can find a complete example in [documentation](../integrations/2_fastapi-plugin)

Also, added the ability to [test](../2_getting_started/7_testing) your application without running external dependencies as a broker (for now only for RabbitMQ)!
Also, added the ability to [test](../getting_started/7_testing) your application without running external dependencies as a broker (for now only for RabbitMQ)!

```python
from propan import RabbitBroker
Expand All @@ -49,7 +66,7 @@ def test_publish():
assert r == "pong"
```

Also added support for [RPC over MQ](../2_getting_started/4_broker/5_rpc) (RabbitMQ only for now): `return` of your handler function will be sent in response to a message if a response is expected.
Also added support for [RPC over MQ](../getting_started/4_broker/5_rpc) (RabbitMQ only for now): `return` of your handler function will be sent in response to a message if a response is expected.

<h3>Breaking changes:</h3>

Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,4 @@ this will allow you to keep a common counter for all consumers.

To start developing the project, go to the following [section](../2_contributing-index/).

If you want to develop your own adapter for any broker, you will find a lot of useful information in [this](../4_adapters/) section.
If you want to develop your own adapter for any broker, you will find a lot of useful information in [this](../4_adapters/) section.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,7 +1,20 @@
# QUICK START
# QUICK START

Install using `pip`:

=== "Redis"
<div class="termy">
```console
$ pip install "propan[async-redis]"
---> 100%
```
</div>
!!! tip
To working with project start a test broker container
```bash
docker run -d --rm -p 6379:6379 --name test-mq redis
```

=== "RabbitMQ"
<div class="termy">
```console
Expand Down Expand Up @@ -32,6 +45,11 @@ Install using `pip`:

Create an application with the following code at `serve.py`:

=== "Redis"
```python linenums="1"
{!> docs_src/index/01_redis_base.py!}
```

=== "RabbitMQ"
```python linenums="1"
{!> docs_src/index/01_rabbit_base.py!}
Expand Down Expand Up @@ -60,6 +78,11 @@ $ propan run serve:app

Propan uses `pydantic` to cast incoming function arguments to types according to their annotation.

=== "Redis"
```python linenums="1" hl_lines="12"
{!> docs_src/index/02_redis_type_casting.py!}
```

=== "RabbitMQ"
```python linenums="1" hl_lines="12"
{!> docs_src/index/02_rabbit_type_casting.py!}
Expand All @@ -83,6 +106,10 @@ If you call a non-existent field, raises *pydantic.error_wrappers.ValidationErro
But you can specify your own dependencies, call dependencies functions (like `Fastapi Depends`)
and [more](../5_dependency/1_di-index).

=== "Redis"
```python linenums="1" hl_lines="11-12"
{!> docs_src/index/03_redis_dependencies.py!}
```

=== "RabbitMQ"
```python linenums="1" hl_lines="11-12"
Expand All @@ -102,7 +129,7 @@ Also, **Propan CLI** is able to generate a production-ready application template

<div class="termy">
```console
$ propan create [projectname]
$ propan create async rabbit [projectname]
Create Propan project template at: /home/user/projectname
```
</div>
Expand Down Expand Up @@ -138,6 +165,11 @@ Now you can enjoy a new development experience!
You can use **Propan** `MQBrokers` without `PropanApp`.
Just *start* and *stop* them according to your application lifespan.

=== "Redis"
```python linenums="1" hl_lines="5 11-13 16-17"
{!> docs_src/index/05_redis_http_example.py!}
```

=== "RabbitMQ"
```python linenums="1" hl_lines="5 11-13 16-17"
{!> docs_src/index/05_rabbit_http_example.py!}
Expand All @@ -159,12 +191,18 @@ using the `@event` decorator. This decorator is similar to the decorator `@handl
When used this way, **Propan** does not utilize its own dependency system, but integrates into **FastAPI**.
That is, you can use `Depends`, `Background Tasks` and other tools **Facet API** as if it were a regular HTTP endpoint.

```python linenums="1" hl_lines="7 15 19"
{!> docs_src/index/06_rabbit_native_fastapi.py!}
```
=== "Redis"
```python linenums="1" hl_lines="7 15 19"
{!> docs_src/index/06_redis_native_fastapi.py!}
```

=== "RabbitMQ"
```python linenums="1" hl_lines="7 15 19"
{!> docs_src/index/06_rabbit_native_fastapi.py!}
```

!!! note
More integration examples you can find [here](../../5_integrations/1_integrations-index/)
More integration examples you can find [here](../../integrations/1_integrations-index/)

??? tip "Don't forget to stop test broker container"
```bash
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ To start a new project not from scratch, you can use the standard template **Pro

<div class="termy">
```console
$ propan create app
$ propan create async rabbit app

Create Propan project template at: ./app
```
Expand Down Expand Up @@ -79,6 +79,11 @@ $ propan run serve:app --env=.env.dev
```
</div>

=== "Redis"
```python linenums="1" hl_lines="3 14-15"
{!> docs_src/index/04_redis_context.py!}
```

=== "RabbitMQ"
```python linenums="1" hl_lines="3 14-15"
{!> docs_src/index/04_rabbit_context.py!}
Expand Down
Loading

0 comments on commit 2e6d64a

Please sign in to comment.