{"id":18508672,"url":"https://github.com/noteable-io/asyncapi-eventrouter","last_synced_at":"2025-04-09T03:32:08.903Z","repository":{"id":45876315,"uuid":"430118940","full_name":"noteable-io/asyncapi-eventrouter","owner":"noteable-io","description":"Python framework for AsyncAPI-documented Websocket, PubSub, and other async constructs","archived":false,"fork":false,"pushed_at":"2024-03-20T16:02:35.000Z","size":201,"stargazers_count":6,"open_issues_count":3,"forks_count":2,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-03-23T22:42:21.656Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/noteable-io.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-11-20T14:04:18.000Z","updated_at":"2023-12-18T12:01:59.000Z","dependencies_parsed_at":"2022-09-05T15:40:46.392Z","dependency_job_id":null,"html_url":"https://github.com/noteable-io/asyncapi-eventrouter","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/noteable-io%2Fasyncapi-eventrouter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/noteable-io%2Fasyncapi-eventrouter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/noteable-io%2Fasyncapi-eventrouter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/noteable-io%2Fasyncapi-eventrouter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/noteable-io","download_url":"https://codeload.github.com/noteable-io/asyncapi-eventrouter/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247973870,"owners_count":21026735,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-06T15:15:03.373Z","updated_at":"2025-04-09T03:32:08.552Z","avatar_url":"https://github.com/noteable-io.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# asyncapi-eventrouter\n\n*Work in Progress*\n\nWrite Python code for Event-Driven Architectures!  The **`asyncapi-eventrouter`** prototype library creates Websocket,\nPubSub, and other asynchronous frameworks with message validation and automatic schema documentation in the\n[AsyncAPI](https://www.asyncapi.com/) specification.  It's heavily inspired by how\n[FastAPI](https://fastapi.tiangolo.com/) documents REST endpoints in the [OpenAPI](https://swagger.io/specification/)\nspecification.\n\n## Example\n\nWhat would the [Streetlights API](https://www.asyncapi.com/docs/tutorials/streetlights#creating-the-asyncapi-file) look like in Python code with `asyncapi-eventrouter`?\n\n```python\n# asyncapi.py\nfrom pydantic import BaseModel, Field\nfrom datetime import datetime\nfrom asyncapi_eventrouter import Application\n\nasyncapi_app = Application()\n\nclass LightMeasured(BaseModel):\n    id: int = Field(..., gte=0, description=\"ID of the streetlight.\")\n    lumens: int = Field(..., gte=0, description=\"Light intensity measured in lumens.\")\n    sentAt: datetime = Field(..., description=\"Date and time when the message was sent.\")\n\n@asyncapi_app.subscribe(channel_name=\"light/measured\",\n                        event_name=\"LightMeasured\")\nasync def record_measurement(measurement: LightMeasured):\n    # record to db or take some other action\n    return {'received': datetime.now()}\n```\n\n```python\n# main.py\nfrom fastapi import FastAPI, WebSocket\nfrom asyncapi import asyncapi_app\n\napp = FastAPI()\n\n@app.websocket('/ws')\nasync def ws(websocket: Websocket):\n    await ws.accept()\n    while True:\n        content = await websocket.receive_text()\n        response = await asyncapi_app.process(content)\n        await websocket.send_json(response)\n\n@app.get('/ws-schema')\nasync def ws_schema():\n    return asyncapi_app.schema()\n```\n\n```python\n# client.py\nimport asyncio\nimport json\nfrom datetime import datetime\n\nimport websockets\n\nasync def send_measurement():\n    data = {\"id\": 123, \"lumens\": 42, \"sentAt\": datetime.now().isoformat()}\n    event = {\"channel\": \"light/measured\", \"event\": \"LightMeasured\", \"data\": data}\n    async with websockets.connect(\"ws://localhost:8000/ws\") as ws:\n        await ws.send(json.dumps(event))\n\nif __name__ == '__main__':\n    asyncio.run(send_measurement())\n```\n\nLast but not least, you can view the spec by visiting that `/ws-schema` endpoint or by importing the `asyncapi_app` and dumping the schema.\n\n```python\nfrom asyncapi import asyncapi_app\nimport yaml\n\nprint(yaml.dump(asyncapi_app.schema())\n\nasyncapi: 2.2.0\nchannels:\n  light/measured:\n    publish:\n      LightMeasured:\n        payload:\n          properties:\n            id:\n              description: ID of the streetlight.\n              gte: 0\n              title: Id\n              type: integer\n            lumens:\n              description: Light intensity measured in lumens.\n              gte: 0\n              title: Lumens\n              type: integer\n            sentAt:\n              description: Date and time when the message was sent.\n              format: date-time\n              title: Sentat\n              type: string\n          required:\n          - id\n          - lumens\n          - sentAt\n          title: LightMeasured\n          type: object\n```\n\n## Development\n\nThis project uses [poetry](https://python-poetry.org/) and [pre-commit](https://pre-commit.com/) for development.\n\n1. `poetry env use 3.9` will create a `.venv` directory in your `asyncapi-eventrouter` directory.\n2. `poetry install` will install `asyncapi-eventrouter` and all dependencies into that virtual environment.\n3. `pre-commit run --all-files` will show you what will be executed any time you `git commit`.\n\n### Skip Pre-commit\n\nIf the `pre-commit` hooks can not be easily resolved, you can still commit using `git commit --no-verify`.\n\n### Testing\n\nThis project uses [tox](https://github.com/tox-dev/tox) and [pytest](https://docs.pytest.org) for testing.  You'll need to have [installed tox](https://tox.wiki/en/latest/install.html) on your system Python.  To run tests, just execute `tox` (`tox -q` for less verbosity, `tox -p` to run in parallel).\n\nYou'll also need a system installation for each Python version you want to test with `tox` (e.g. `python3.7`, `python3.8`, `python3.9`, `python3.10`).  Installation steps may be different for each OS.  On Ubuntu 20.04, it is a matter of adding the [deadsnakes](https://launchpad.net/~deadsnakes/+archive/ubuntu/ppa) repository (`sudo add-apt-repository ppa:deadsnakes/ppa`) and installing the version you want: `sudo apt install python3.10`.\n\n\n## Inspiration and gratitude\n\nThe useful FastAPI project inspires this project. Any code snippets from FastAPI are given credit and attribution in the\nsource code. We are thankful to the FastAPI community for their work.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnoteable-io%2Fasyncapi-eventrouter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnoteable-io%2Fasyncapi-eventrouter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnoteable-io%2Fasyncapi-eventrouter/lists"}