{"id":35203388,"url":"https://github.com/waku-py/waku","last_synced_at":"2026-04-02T00:56:43.381Z","repository":{"id":268742868,"uuid":"898429013","full_name":"waku-py/waku","owner":"waku-py","description":"A Python framework for building modular and loosely coupled applications","archived":false,"fork":false,"pushed_at":"2026-03-01T14:10:03.000Z","size":6918,"stargazers_count":15,"open_issues_count":8,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-03-01T17:56:59.752Z","etag":null,"topics":["architecture","cqrs","dependency-injection","dishka","eventsourcing","eventstore","framework","mediatr","microservices","python","waku"],"latest_commit_sha":null,"homepage":"https://waku-py.github.io/waku/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/waku-py.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-12-04T11:30:21.000Z","updated_at":"2026-03-01T14:09:11.000Z","dependencies_parsed_at":"2026-03-06T09:01:13.338Z","dependency_job_id":null,"html_url":"https://github.com/waku-py/waku","commit_stats":null,"previous_names":["waku-py/waku"],"tags_count":89,"template":false,"template_full_name":null,"purl":"pkg:github/waku-py/waku","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/waku-py%2Fwaku","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/waku-py%2Fwaku/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/waku-py%2Fwaku/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/waku-py%2Fwaku/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/waku-py","download_url":"https://codeload.github.com/waku-py/waku/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/waku-py%2Fwaku/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30168598,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-06T07:56:45.623Z","status":"ssl_error","status_checked_at":"2026-03-06T07:55:55.621Z","response_time":250,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["architecture","cqrs","dependency-injection","dishka","eventsourcing","eventstore","framework","mediatr","microservices","python","waku"],"created_at":"2025-12-29T12:44:00.746Z","updated_at":"2026-04-02T00:56:43.358Z","avatar_url":"https://github.com/waku-py.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n    \u003cimg src=\"docs/assets/logo.png\" alt=\"waku logo\" width=\"480\"\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\" markdown=\"1\"\u003e\n    \u003csup\u003e\u003ci\u003ewaku\u003c/i\u003e [\u003cb\u003e枠\u003c/b\u003e or \u003cb\u003eわく\u003c/b\u003e] \u003ci\u003emeans framework in Japanese.\u003c/i\u003e\u003c/sup\u003e\n    \u003cbr/\u003e\n\u003c/p\u003e\n\n-----\n\n\u003cdiv align=\"center\" markdown=\"1\"\u003e\n\n\u003c!-- Project Status --\u003e\n[![CI/CD](https://img.shields.io/github/actions/workflow/status/waku-py/waku/release.yml?branch=master\u0026logo=github\u0026label=CI/CD)](https://github.com/waku-py/waku/actions?query=event%3Apush+branch%3Amaster+workflow%3ACI/CD)\n[![codecov](https://codecov.io/gh/waku-py/waku/graph/badge.svg?token=3M64SAF38A)](https://codecov.io/gh/waku-py/waku)\n[![GitHub issues](https://img.shields.io/github/issues/waku-py/waku)](https://github.com/waku-py/waku/issues)\n[![GitHub contributors](https://img.shields.io/github/contributors/waku-py/waku)](https://github.com/waku-py/waku/graphs/contributors)\n[![GitHub commit activity](https://img.shields.io/github/commit-activity/m/waku-py/waku)](https://github.com/waku-py/waku/graphs/commit-activity)\n[![GitHub license](https://img.shields.io/github/license/waku-py/waku)](https://github.com/waku-py/waku/blob/master/LICENSE)\n\n\u003c!-- Package Info --\u003e\n[![PyPI](https://img.shields.io/pypi/v/waku?label=PyPI\u0026logo=pypi)](https://pypi.python.org/pypi/waku)\n[![Python version](https://img.shields.io/pypi/pyversions/waku.svg?label=Python)](https://www.python.org/downloads/)\n[![Downloads](https://static.pepy.tech/badge/waku/month)](https://pepy.tech/projects/waku)\n\n\u003c!-- Tools --\u003e\n[![uv](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/uv/main/assets/badge/v0.json)](https://github.com/astral-sh/uv)\n[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff/)\n[![ty](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ty/main/assets/badge/v0.json)](https://github.com/astral-sh/ty)\n[![pyrefly](https://img.shields.io/endpoint?url=https://pyrefly.org/badge.json)](https://github.com/facebook/pyrefly)\n[![mypy - checked](https://www.mypy-lang.org/static/mypy_badge.svg)](https://mypy-lang.org/)\n\n\u003c!-- Social --\u003e\n[![Telegram](https://img.shields.io/badge/-telegram-black?color=blue\u0026logo=telegram\u0026label=RU)](https://t.me/wakupy)\n[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/waku-py/waku)\n\n\u003c/div\u003e\n\n-----\n\n\u003e **Python makes it easy to build a backend. waku makes it easy to keep growing one.**\n\u003e\n\u003e As your project scales, problems creep in: services import each other freely,\n\u003e swapping a database means editing dozens of files, and nobody can tell which module\n\u003e depends on what. waku gives you modules with explicit boundaries, type-safe DI\n\u003e powered by [dishka](https://github.com/reagento/dishka/), and integrated CQRS\n\u003e and event sourcing — so your codebase stays manageable as it scales.\n\n\u003e [!TIP]\n\u003e Check out the full [**documentation**](https://docs.wakupy.dev/) and our [**examples**](https://github.com/waku-py/waku/tree/master/examples) to get started.\n\n## The Problem\n\nPython has no built-in way to enforce component boundaries. Packages don't control visibility, imports aren't validated, and nothing stops module A from reaching into the internals of module B. As a project grows, what started as clean separation quietly becomes a web of implicit dependencies — where testing requires the whole system, onboarding means reading everything, and changing one module risks breaking three others.\n\n## What waku gives you\n\n### Structure\n\n- 🧩 [**Package by component**](https://docs.wakupy.dev/fundamentals/modules/):\n  Each module is a self-contained unit with its own providers.\n  Explicit imports and exports control what crosses boundaries —\n  validated at startup, not discovered in production.\n- 💉 [**Dependency inversion**](https://docs.wakupy.dev/fundamentals/providers/):\n  Define interfaces in your application core, bind adapters in infrastructure modules.\n  Swap a database, a cache, or an API client by changing one provider —\n  powered by [dishka](https://github.com/reagento/dishka/).\n- 🔌 [**One core, any entrypoint**](https://docs.wakupy.dev/fundamentals/integrations/):\n  Build your module tree once with `WakuFactory`.\n  Plug it into FastAPI, Litestar, FastStream, Aiogram, CLI, or workers —\n  same logic everywhere.\n\n### Capabilities\n\n- 📨 [**Messaging**](https://docs.wakupy.dev/features/messaging/):\n  DI alone doesn't decouple components — you need events.\n  The message bus dispatches commands, queries, and events so components\n  never reference each other directly. Pipeline behaviors handle cross-cutting concerns.\n- 📜 [**Event sourcing**](https://docs.wakupy.dev/features/eventsourcing/):\n  Aggregates, projections, snapshots, upcasting, and the decider pattern\n  with built-in SQLAlchemy adapters.\n- 🧪 [**Testing**](https://docs.wakupy.dev/fundamentals/testing/):\n  Override any provider in tests with `override()`,\n  or spin up a minimal app with `create_test_app()`.\n- 🧰 [**Lifecycle \u0026 extensions**](https://docs.wakupy.dev/advanced/extensions/):\n  Hook into startup, shutdown, and module initialization.\n  Add validation, logging, or custom behaviors —\n  decoupled from your business logic.\n\n## Quick Start\n\n### Installation\n\n```sh\nuv add waku\n```\n\n### Minimal Example\n\nDefine a service, register it in a module, and resolve it from the container:\n\n```python\nimport asyncio\n\nfrom waku import WakuFactory, module\nfrom waku.di import scoped\n\n\nclass GreetingService:\n    async def greet(self, name: str) -\u003e str:\n        return f'Hello, {name}!'\n\n\n@module(providers=[scoped(GreetingService)])\nclass GreetingModule:\n    pass\n\n\n@module(imports=[GreetingModule])\nclass AppModule:\n    pass\n\n\nasync def main() -\u003e None:\n    app = WakuFactory(AppModule).create()\n\n    async with app, app.container() as c:\n        svc = await c.get(GreetingService)\n        print(await svc.greet('waku'))\n\n\nif __name__ == '__main__':\n    asyncio.run(main())\n\n```\n\n### Module Boundaries in Action\n\nModules control visibility. `InfrastructureModule` exports `ILogger` — `UserModule` imports it. Dependencies are explicit, not implicit:\n\n```python\nimport asyncio\nfrom typing import Protocol\n\nfrom waku import WakuFactory, module\nfrom waku.di import scoped, singleton\n\n\nclass ILogger(Protocol):\n    async def log(self, message: str) -\u003e None: ...\n\n\nclass ConsoleLogger(ILogger):\n    async def log(self, message: str) -\u003e None:\n        print(f'[LOG] {message}')\n\n\nclass UserService:\n    def __init__(self, logger: ILogger) -\u003e None:\n        self.logger = logger\n\n    async def create_user(self, username: str) -\u003e str:\n        user_id = f'user_{username}'\n        await self.logger.log(f'Created user: {username}')\n        return user_id\n\n\n@module(\n    providers=[singleton(ILogger, ConsoleLogger)],\n    exports=[ILogger],\n)\nclass InfrastructureModule:\n    pass\n\n\n@module(\n    imports=[InfrastructureModule],\n    providers=[scoped(UserService)],\n)\nclass UserModule:\n    pass\n\n\n@module(imports=[UserModule])\nclass AppModule:\n    pass\n\n\nasync def main() -\u003e None:\n    app = WakuFactory(AppModule).create()\n\n    async with app, app.container() as c:\n        user_service = await c.get(UserService)\n        user_id = await user_service.create_user('alice')\n        print(f'Created user with ID: {user_id}')\n\n\nif __name__ == '__main__':\n    asyncio.run(main())\n\n```\n\n### Next steps\n\n- Learn about [module imports and exports](https://docs.wakupy.dev/fundamentals/modules/)\n- Try different [provider scopes](https://docs.wakupy.dev/fundamentals/providers/)\n- Add [Messaging](https://docs.wakupy.dev/features/messaging/) for clean command handling\n- Connect with your [favorite framework](https://docs.wakupy.dev/fundamentals/integrations/)\n- Browse the [examples directory](https://github.com/waku-py/waku/tree/master/examples) for inspiration\n\n## Documentation\n\n- [Getting Started](https://docs.wakupy.dev/getting-started/)\n- [Module System](https://docs.wakupy.dev/fundamentals/modules/)\n- [Providers](https://docs.wakupy.dev/fundamentals/providers/)\n- [Extensions](https://docs.wakupy.dev/advanced/extensions/)\n- [Messaging](https://docs.wakupy.dev/features/messaging/)\n- [Event Sourcing](https://docs.wakupy.dev/features/eventsourcing/)\n- [API Reference](https://docs.wakupy.dev/reference/)\n- [dishka Documentation](https://dishka.readthedocs.io/en/stable/index.html)\n- [DeepWiki](https://deepwiki.com/waku-py/waku)\n\n## Contributing\n\n- [Contributing Guide](https://docs.wakupy.dev/contributing/contributing/)\n- [Development Setup](https://docs.wakupy.dev/contributing/contributing/#development-setup)\n\n### Top contributors\n\n\u003ca href=\"https://github.com/waku-py/waku/graphs/contributors\"\u003e\n  \u003cimg src=\"https://contrib.rocks/image?repo=waku-py/waku\" alt=\"contrib.rocks image\" /\u003e\n\u003c/a\u003e\n\n## Roadmap\n\n- [x] Create logo\n- [x] Improve inner architecture\n- [x] Improve documentation\n- [x] Add new and improve existing validation rules\n- [ ] Provide example projects for common architectures\n\n## Support\n\n- [RU Telegram group](https://t.me/wakupy)\n- [GitHub Issues](https://github.com/waku-py/waku/issues)\n- [Discussions](https://github.com/waku-py/waku/discussions)\n\n## License\n\nThis project is licensed under the terms of the [MIT License](https://github.com/waku-py/waku/blob/master/LICENSE).\n\n## Acknowledgements\n\n- [dishka](https://github.com/reagento/dishka/) – Dependency Injection framework powering `waku` IoC container.\n- [NestJS](https://nestjs.com/) – Inspiration for modular architecture and design patterns.\n- [Wolverine (C#)](https://wolverine.netlify.app/) – Inspiration for messaging, transport model, and pipeline architecture.\n- [Marten (C#)](https://martendb.io/) – Inspiration for event sourcing, projections, and document store design.\n- [Emmett](https://event-driven-io.github.io/emmett/) – Functional-first event sourcing patterns.\n- [Eventuous](https://eventuous.dev/) – Event store interface design.\n- [Jérémie Chassaing](https://thinkbeforecoding.com/post/2021/12/17/functional-event-sourcing-decider) – Decider pattern formalization.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwaku-py%2Fwaku","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwaku-py%2Fwaku","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwaku-py%2Fwaku/lists"}