{"id":33285203,"url":"https://github.com/distantmagic/aloni","last_synced_at":"2026-03-07T08:30:55.998Z","repository":{"id":244177841,"uuid":"810937252","full_name":"distantmagic/aloni","owner":"distantmagic","description":"Async Python framework optimized for IO-heavy applications.","archived":false,"fork":false,"pushed_at":"2024-06-29T15:12:05.000Z","size":220,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-12-09T23:35:56.392Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","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/distantmagic.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","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}},"created_at":"2024-06-05T16:24:06.000Z","updated_at":"2025-06-10T20:37:49.000Z","dependencies_parsed_at":"2024-06-18T22:48:12.336Z","dependency_job_id":"5aff0e17-098b-4f2d-83ad-23117a36aeb1","html_url":"https://github.com/distantmagic/aloni","commit_stats":null,"previous_names":["distantmagic/intention","distantmagic/aloni"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/distantmagic/aloni","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/distantmagic%2Faloni","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/distantmagic%2Faloni/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/distantmagic%2Faloni/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/distantmagic%2Faloni/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/distantmagic","download_url":"https://codeload.github.com/distantmagic/aloni/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/distantmagic%2Faloni/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30209934,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-07T05:23:27.321Z","status":"ssl_error","status_checked_at":"2026-03-07T05:00:17.256Z","response_time":53,"last_error":"SSL_read: 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":[],"created_at":"2025-11-17T15:06:23.972Z","updated_at":"2026-03-07T08:30:55.972Z","avatar_url":"https://github.com/distantmagic.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Aloni\n\nAloni is a Python framework designed to increase productivity when developing applications. Simplicity, productivity, and great developer experience are our primary goals.\n\nIt is based on an innovative Role-Based Services approach. (more info below).\n\nIt is async and thus performs well with IO-bound services (for example, anything that makes a lot of long-running HTTP calls to large language models or uses a lot of microservices and third-party services)—but not just those.\n\n## Try it out\n\nAloni will take only a few minutes to set up, and it might amaze you and change how you develop apps. :)\n\n## Key Features\n\n- **Effortlessly split your project into multiple files**: Aloni automatically combines your project files based on the roles you assign them, making it easy to manage large projects.\n- **Dependency Injection**: Manage your application's dependencies effortlessly with a container that holds one instance of each service, ensuring efficient resource management.\n- **Async-First**: Aloni is optimized for asynchronous programming, making it perfect for IO-bound tasks.\n- **Minial boilerplate**: Aloni adds no redundant boilerplate code. Keep your project as simple as possible.\n\n## Getting Started\n\n### Installation\n\n#### Requirements\n\nLinux or MacOS (should work on all Unix systems). It does not work on Windows because Aloni requires the `fork` multiprocessing method (which Windows does not have).\n\nThat might change in the future (see also: https://github.com/emmett-framework/granian/issues/330).\n\n#### Steps\n\nAloni works best with [Poetry](https://python-poetry.org/). Install [Poetry](https://python-poetry.org/) first and follow the steps:\n\n1. Create a new Poetry project, then install Aloni:  \n    ```shell\n    poetry add aloni\n    ```\n2. Create your application's module:  \n    ```shell\n    mkdir my_app\n    ```\n    ```shell\n    touch my_app/__init__.py\n    ```\n3. Create the `app.py` (primary application file). That is the entire boilerplate code that Aloni needs to work:  \n    ```py\n    import my_app\n    import aloni\n\n    aloni.start(my_app).exit_after_finishing()\n    ```\n\nInvoking `poetry run python ./app.py` should display something like:\n\n```shell\nusage: app.py [-h] {hello,serve} ...\n\nAloni CLI\n\npositional arguments:\n  {serve}\n    serve        Start the app in HTTP server mode\n\noptions:\n  -h, --help     show this help message and exit\n```\n\nCongratulations! You have installed the Aloni project. You can continue with the next steps.\n\n### Usage\n\nCheck the [demo project](/examples/demo-app) for basic usage.\n\nAloni will scan your module (in this case, `my_app`) for services with a role decorator and start your CLI application. That's it!\n\nAdd a new CLI command if you want to start developing something new. Use `responds_to_cli` role. Add a new file in `my_app/hello_command.py` (file name can be anything; it's just an example - file names and directory structure do not matter for Aloni):\n\n```py\nfrom aloni.cli_foundation import Command\nfrom aloni.role import responds_to_cli\n\n\n@responds_to_cli(\n    name=\"hello\",\n    description=\"Say hello!\",\n)\nclass Hello(Command):\n    async def respond(self) -\u003e int:\n        print(\"Hello, World!\")\n\n        return 0\n```\n\nYou can then run it with:\n\n```shell\npython ./app.py hello\n```\n\nYou should see:\n\n```\nHello, World!\n```\n\n## Quick Tutorials\n\n### Responding to HTTP Requests\n\nCreate a responder in your application's module. Filename and location do not matter:\n\n```py\nfrom aloni.http import Responder, TextResponse\nfrom aloni.role import responds_to_http\n\n\n@responds_to_http(pattern='/ping')\nclass Ping(Responder):\n    async def respond(self) -\u003e TextResponse:\n        return TextResponse(\"pong\")\n```\n\n### Responding with Jinja2 Templates\n\nPlace a template inside your application's `templates` directory. Name it `hello.j2`:\n\n```html\n\u003cp\u003eHello, world!\u003c/p\u003e\n```\n\n```py\nfrom aloni.http import Responder, JinjaResponse\nfrom aloni.role import responds_to_http\n\n\n@responds_to_http(pattern='/hello')\nclass Hello(Responder):\n    async def respond(self) -\u003e JinjaResponse:\n        return JinjaResponse('hello.j2')\n```\n\n### Injecting Services\n\nCreate a service in your application's module. Filename and location do not matter:\n\n```py\nfrom aloni.role import service\n\n\n@service\nclass MyService:\n    pass\n```\n\nUse it in your other services:\n\n```py\nfrom aloni.role import service\n\nfrom .my_service import MyService\n\n\n@service\nclass OtherService:\n    def __init__(self, my_service: MyService) -\u003e None:\n        self.my_service = my_service\n```\n\n### Creating Service Providers\n\nCreate a base service class in your application's module. Do not add `@service` role to that class:\n\n```py\nclass MyService:\n    def __init__(self, foo: str) -\u003e None:\n        self.foo = foo\n```\n\nCreate service provider (again, location and filename do not matter as long as it's in your application's module):\n\n```py\nfrom aloni.application_state import ApplicationState\nfrom aloni.role import service_provider\nfrom aloni.service_provider import ServiceProvider\n\nfrom .my_service import MyService\n\n\n@service_provider(provides=MyService)\nclass MyServiceProvider(ServiceProvider[MyService]):\n    def provide(self) -\u003e MyService:\n        return MyService(foo=\"bar\")\n```\n\nUse it in your other services:\n\n```py\nfrom aloni.role import service\n\nfrom .my_service import MyService\n\n\n@service\nclass OtherService:\n    def __init__(self, my_service: MyService) -\u003e None:\n        self.my_service = my_service\n```\n\n### Registering Jinja Functions\n\nCustom Jinja functions have their constructor (`__init__`) arguments injected by the dependency injection container.\n\nArguments passed to the `__call__` method are passed from a template.\n\n```py\nfrom aloni.jinja_function import JinjaFunction\nfrom aloni.role.jinja_function import jinja_function\n\n\n@jinja_function(name=\"say_hello\")\nclass UrlFor(JinjaFunction):\n    def __call__(self) -\u003e str:\n        return \"Hello, world!\"\n```\n\nThen use it in a template:\n\n```j2\n{{ say_hello() }}\n```\n\n## API Reference\n\n### HTTP Responses\n\nAll the available roles are accessible from `aloni.http` module. \n\nFor example:\n\n```py\nfrom aloni.http import AssetResponse\n```\n\n| Response | Description |\n| ------------- | ------------- |\n| [AssetResponse](aloni/http/asset_response.py) | Returns an asset file if it is present inside your application's `assets` directory |\n| [JinjaResponse](aloni/http/jinja_response.py) | Returns a parsed Jinja2 template if it is present inside your application's `templates` directory |\n| [TextResponse](aloni/http/text_response.py) | Returns a plain text response |\n\n### Available Roles\n\nAll the available roles are accessible from `aloni.role` module. \n\nFor example:\n\n```py\nfrom aloni.role import responds_to_http\n```\n\n| Role | Description |\n| ------------- | ------------- |\n| [intercepts_http_response](aloni/role/intercepts_http_response.py) | Allows to intercept any response returned by your http responder and convert it into a renderable response. It acts kind of like inversed middleware - instead of intercepting a request, it intercepts and modifies a response. |\n| [responds_to_cli](aloni/role/responds_to_cli.py) | Responds to CLI command |\n| [responds_to_http](aloni/role/responds_to_http.py) | Responds to HTTP request |\n| [service](aloni/role/service.py) | Marks the current class as a service. Its constructor arguments will be injected from the dependency injection container |\n| [service_provider](aloni/role/service_provider.py) | Registers a service provider for dependency injection. Use it to create a class that provides an instance of a different class to the dependency injection container. |\n\n## Special Thanks\n\n- [Granian](https://github.com/emmett-framework/granian) for creating an awesome HTTP Python runner with excellent performance\n\n## License\n\nThis project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdistantmagic%2Faloni","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdistantmagic%2Faloni","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdistantmagic%2Faloni/lists"}