Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Asyncapi #60

Merged
merged 24 commits into from
Jun 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/documentation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,6 @@ jobs:
with:
key: ${{ github.ref }}
path: .cache
- run: pip install mkdocs-material mkdocs-static-i18n mdx-include mkdocs-macros-plugin
- run: pip install mkdocs-material mkdocs-static-i18n mdx-include mkdocs-macros-plugin mkdocs-glightbox
- working-directory: ./docs
run: mkdocs gh-deploy --force
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ It is a modern, high-level framework on top of popular specific Python brokers l
* framework-independent way to manage the project environment
* application code *hot reload*
* robust application templates
* [**Documentation**](#project-documentation): **Propan** automatically generates and presents an interactive <a href="https://www.asyncapi.com/" target="_blank">**AsyncAPI**</a> documentation for your project
* <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
Expand Down Expand Up @@ -238,6 +239,16 @@ async def base_handler(body: dict,

---

## Project Documentation

**Propan** automatically generates documentation for your project according to the <a href="https://www.asyncapi.com/" target="_blank">**AsyncAPI**</a> specification. You can work with both generated artifacts and place a Web view of your documentation on resources available to related teams.

The availability of such documentation significantly simplifies the integration of services: you can immediately see what channels and message format the application works with. And most importantly, it doesn't cost you anything - **Propan** has already done everything for you!

![HTML-page](../../assets/img/docs-html-short.png)

---

## CLI power

**Propan** has its own CLI tool that provided the following features:
Expand Down
Binary file added docs/docs/assets/img/docs-html-short.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/docs/assets/img/docs-html.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
24 changes: 24 additions & 0 deletions docs/docs/en/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,29 @@
# CHANGELOG

## 2023-06-14 **0.1.3.0** AsyncAPI

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**]({{ urls.asyncapi }}){.external-link target="_blank"} 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.

![HTML-page](../../assets/img/docs-html-short.png)

You can learn more about this functionality in the corresponding [documentation section] (getting_started/9_documentation.md).

Also, the ability to determine the dependencies of the broker level and consumers has been added.:

```python
from propan import RabbitBroker, Depends

broker = RabbitBroker(dependencies=[Depends(...)])

@broker.handler(..., dependencies=[Depends(...)])
async def handler():
...
```

## 2023-06-13 **0.1.2.17**

The current update is a sum of several changes and improvements released from the previous release.
Expand Down
10 changes: 1 addition & 9 deletions docs/docs/en/contributing/1_todo.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,7 @@ To participate in the development of documentation, go to the following [section

## Code

If you want to work a little with the code, then you have even more opportunities to prove yourself. At the moment, the priority of the project is the following tasks:

* `PushBackWatcher` should store information about the number of message processing in the header:
this will allow you to keep a common counter for all consumers.
* Merge the arguments of the methods `__init__` and `connect` brokers for more flexible management of default values
* Coverage with `NatsBroker` tests
* Implementation of `NatsJSBroker`
* Implementation of the synchronous version of the application and brokers
* Broker implementation for `Apache Kafka' and other brokers from [plan](../../#supported-mq-brokers)
All actual tasks you can find at project [Issues](https://github.com/Lancetnik/Propan/issues){.external-link target="_blank"}.

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

Expand Down
10 changes: 10 additions & 0 deletions docs/docs/en/getting_started/1_quick-start.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,16 @@ and [more](../5_dependency/1_di-index).

---

## Project Documentation

**Propan** automatically generates documentation for your project according to the [**AsyncAPI**]({{ urls.asyncapi }}){ target="_blank"} specification. You can work with both generated artifacts and place a Web view of your documentation on resources available to related teams.

The availability of such documentation significantly simplifies the integration of services: you can immediately see what channels and message format the application works with. And most importantly, it doesn't cost you anything - **Propan** has already done everything for you!

![HTML-page](../../assets/img/docs-html-short.png)

---

## Project template

Also, **Propan CLI** is able to generate a production-ready application template:
Expand Down
35 changes: 28 additions & 7 deletions docs/docs/en/getting_started/4_broker/3_type-casting.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@

The first argument of the function decorated by `@broker.hanle` is the decrypted body of the incoming message.

It can be of three types:
Incoming message body can be of three types:

* `str` - if the message has the header `content-type: text/plain`
* `dict` - if the message has the header `content-type: application/json`
* `bytes` - if the message has any other header

All incoming messages will be automatically brought to this view.
Either these types can be used as an annotation, or any primitive types to which **pydantic** can cast incoming arguments (for example, `str -> float`).

A few examples:

Expand All @@ -19,7 +19,7 @@ A few examples:
async def base_handler(body: str):
'''
We are expecting a text/plain message
Messages of a different kind will trigger an error
Messages of a different kind will raise an error
'''

```
Expand All @@ -31,7 +31,7 @@ async def base_handler(body: str):
async def base_handler(body: dict):
'''
We are expecting an application/json message
Messages of a different kind will trigger an error
Messages of a different kind will raise an error
'''
```

Expand All @@ -42,7 +42,7 @@ async def base_handler(body: dict):
async def base_handler(body: bytes):
'''
We are expecting a 'raw' message
Messages of a different kind will trigger an error
Messages of a different kind will raise an error
'''
```

Expand All @@ -62,6 +62,27 @@ async def base_handler(body: Message):
'''
We are expecting an application/json message
Type { key: 1.0 }
Messages of a different kind will trigger an error
Messages of a different kind will raise an error
'''
```
```

### Multiple arguments

When annotating multiple incoming arguments, the result will be equivalent to using a similar `pydantic' model.

```python
from pydantic import BaseModel

class Message(BaseModel):
a: int
b: float

@broker.handle("test")
async def base_handler(a: int, b: float):
# async def base_handler(body: Message): - the same
'''
We are expecting an application/json message
Type { a: 1, b: 1.0 }
Messages of a different kind will raise an error
'''
```
22 changes: 22 additions & 0 deletions docs/docs/en/getting_started/5_dependency/1_di-index.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,28 @@ It's easy, isn't it?
In the code above, we didn't use this decorator for our dependencies. However, it still applies
to all functions used as dependencies. Keep this in your mind.

## Top-level dependencies

If you don't need a dependency result you can use the following code:

```python
@broker.handle("test")
def method(_ = Depends(...)): ...
```

But, using a special `handle` parameter is more suitable:

```python
@broker.handle("test", dependencies=[Depends(...)])
def method(): ...
```

Also, you are able to declare broker-level dependencies: they will be applied to all brokers' handlers.

```python
broker = RabbitBroker(dependencies=[Depends(...)])
```

## Nested dependencies

Dependencies can also contain other dependencies. This works in a very predictable way: just declare
Expand Down
2 changes: 2 additions & 0 deletions docs/docs/en/getting_started/6_lifespans.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,3 +112,5 @@ Command line arguments are available in all `@app.on_startup` hooks. To use them
### Broker initialization

The `@app.on_startup` hooks are called **BEFORE** the broker is launched by the application. The `@app.after_shutdown` hooks are triggered **AFTER** stopping the broker.

If you want to perform some actions **AFTER** initializing the broker: send messages, initialize objects, etc., you should use the `@app.after_startup` hook.
94 changes: 94 additions & 0 deletions docs/docs/en/getting_started/9_documentation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
---
hide:
- toc
---

# Documenting

**Propan** allows you not to think about the documentation of your project - it is already generated automatically in accordance with the [**AsyncAPI**]({{ urls.asyncapi }}){.external-link target="_blank"} specification !

!!! note ""
To work with a documentation you should install an extra requirements:

```console
pip install "propan[doc]"
```

## Example

Let's look at an example.

To begin with, we will write a small application with the following content:

```python linenums='1'
{!> docs_src/quickstart/documentation/example.py !}
```

## YAML schema

To generate the **AsyncAPI** specification of your project in the `.yaml` format use the following command:

<div class="termy">
```console
$ propan docs gen example:app

Your project AsyncAPI scheme was placed to `./asyncapi.yaml`
```
</div>

Now you have a scheme of your project: you can use it to generate various clients in any language using an [**AsyncAPI** tools]({{ urls.asyncapi }}/tools/generator){.external-link target="_blank"}.

???- example "Asyncapi.yaml"
```yaml
{!> docs_src/quickstart/documentation/example.yaml !}
```

## Online documentation

Also, **Propan** allows you to host HTML representation of your documentation with the following command

!!! warning ""
The online representation of documentation does not work without an internet connection, since **CDN** dependencies are used to display it.

<div class="termy">
```console
$ propan docs serve example:app
```
</div>

This way you can provide all external consumers with access to your project documentation without additional development costs.

???- example "HTML page"
![HTML-page](../../assets/img/docs-html.png)

!!! tip
**Propan** can also host `asyncapi.yaml` files.

```console
propan docs serve asyncapi.yaml
```

This can be useful if you want to extend the automatically generated **AsyncAPI** documentation: you just generate a file, modify and host it!

When using online documentation, you can also download it using the following paths:

* `/asyncapi.json` - **JSON** schema (available when hosting an application)
* `/asyncapi.yaml` - **YAML** schema (available for an application and a file both)

### FastAPI Plugin

When using **Propan** as a router for **FastAPI**, the framework automatically registers endpoints for hosting **AsyncAPI** documentation in your application with the following default values:

```python linenums='1'
{!> docs_src/quickstart/documentation/fastapi.py !}
```

## Own hosting

For hosting documentation **Propan** uses **FastAPI** + **uvicorn**.
You may want to implement the logic of displaying documentation yourself: restrict access rights, customize content regardless of access rights, embed documentation in your frontend application, and so on.
To do this, you can generate a `json`/`yaml`/`html` document yourself and use it in your own service.

```python linenums='1' hl_lines="9-12"
{!> docs_src/quickstart/documentation/custom_schema.py !}
```
1 change: 1 addition & 0 deletions docs/docs/en/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ It is a modern, high-level framework on top of popular Python libraries for vari
* framework-independent way to manage the project environment
* application code *hot reload*
* robust application templates
* [**Documentation**](getting_started/9_documentation/): **Propan** automatically generates and presents an interactive [**AsyncAPI**]({{ urls.asyncapi }}){target="_blank"} documentation for your project
* [**Testability**](getting_started/7_testing): **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!

---
Expand Down
24 changes: 23 additions & 1 deletion docs/docs/en/integrations/2_fastapi-plugin.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# **FastAPI** Plugin

## Handle messages

**Propan** can be used as a part of **FastAPI**.

Just import a **PropanRouter** you need and declare the message handler
Expand All @@ -19,7 +21,7 @@ in any way convenient for you. The message header is placed in `headers`.
Also, this router can be fully used as an `HttpRouter` (of which it is the inheritor). So you can
use it to declare any `get`, `post`, `put` and other HTTP methods. For example, this is done at **19** line.

### Sending messages
## Sending messages

Inside each router there is a broker. You can easily access it if you need to send a message to MQ.

Expand All @@ -28,3 +30,23 @@ Inside each router there is a broker. You can easily access it if you need to se
You can use the following `Depends` to access the broker if you want to use it at different parts of your program.

{! includes/integrations/fastapi/fastapi_plugin_depends.md !}

Or you can access broker from a **FastAPI** application state

```python
{! docs_src/integrations/fastapi/request.py !}
```

## @after_startup

The `PropanApp` application has the `after_startup` hook, which allows you to perform operations with your message broker after the connection is established. This can be extremely convenient for managing your brokers' objects and/or sending messages. This hook is also available for your **FastAPI PropanRouter**

{! includes/integrations/fastapi/after_startup.md !}

## Documentation

When using **Propan** as a router for **FastAPI**, the framework automatically registers endpoints for hosting **AsyncAPI** documentation into your application with the following default values:

```python linenums='1'
{!> docs_src/quickstart/documentation/fastapi.py !}
```
23 changes: 0 additions & 23 deletions docs/docs/en/nats/direct.py

This file was deleted.

23 changes: 0 additions & 23 deletions docs/docs/en/nats/pattern.py

This file was deleted.

Loading