{"id":26827758,"url":"https://github.com/raceychan/lihil","last_synced_at":"2025-04-06T13:08:58.522Z","repository":{"id":282510689,"uuid":"925936041","full_name":"raceychan/lihil","owner":"raceychan","description":"Unbelievably fast async webframework, proudly written in python, offering high-level development, low-level performance, multiplying 0.1x engineers by a factor of 100.","archived":false,"fork":false,"pushed_at":"2025-04-05T16:37:10.000Z","size":1505,"stargazers_count":94,"open_issues_count":0,"forks_count":2,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-04-05T17:30:29.621Z","etag":null,"topics":["10xengineer","ai","api","asgi","asyncio","cyberpunks","fast","framework","llm","mcp","python","web","webframewok"],"latest_commit_sha":null,"homepage":"https://lihil.cc/lihil","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/raceychan.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":"ROADMAP.md","authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-02-02T05:31:27.000Z","updated_at":"2025-04-03T17:46:59.000Z","dependencies_parsed_at":"2025-04-05T17:26:01.661Z","dependency_job_id":"a47e8cd9-22f1-4215-9934-ab5dd188d303","html_url":"https://github.com/raceychan/lihil","commit_stats":null,"previous_names":["raceychan/lihil"],"tags_count":14,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/raceychan%2Flihil","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/raceychan%2Flihil/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/raceychan%2Flihil/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/raceychan%2Flihil/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/raceychan","download_url":"https://codeload.github.com/raceychan/lihil/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247377197,"owners_count":20929283,"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":["10xengineer","ai","api","asgi","asyncio","cyberpunks","fast","framework","llm","mcp","python","web","webframewok"],"created_at":"2025-03-30T12:16:59.833Z","updated_at":"2025-04-06T13:08:58.508Z","avatar_url":"https://github.com/raceychan.png","language":"Python","readme":"![Lihil](docs/images/lihil_logo_transparent.png)\n\n# Lihil\n**Lihil** \u0026nbsp;*/ˈliːhaɪl/* — a **performant**, **productive**, and **professional** web framework with a vision:\n\n\u003e **Making Python the mainstream programming language for web development.**\n\n**lihil is *100%* test covered and *strictly* typed.**\n\n[![codecov](https://codecov.io/gh/raceychan/lihil/graph/badge.svg?token=KOK5S1IGVX)](https://codecov.io/gh/raceychan/lihil)\n[![PyPI version](https://badge.fury.io/py/lihil.svg)](https://badge.fury.io/py/lihil)\n[![License](https://img.shields.io/github/license/raceychan/lihil)](https://github.com/raceychan/lihil/blob/master/LICENSE)\n[![Downloads](https://img.shields.io/pypi/dm/lihil.svg)](https://pypistats.org/packages/lihil)\n[![Python Version](https://img.shields.io/pypi/pyversions/lihil.svg)](https://pypi.org/project/lihil/)\n\n📚 Docs: https://lihil.cc/lihil\n---\n\nLihil is\n\n- **Performant**: lihil is fast, 50%-100% faster than ASGI frameworks offering similar functionalities, even more with its own server. see [benchmarks](https://github.com/raceychan/lhl_bench)\n- **Productive**: ergonomic API with strong typing support and built-in solutions for common problems — along with beloved features like openapi docs generation — empowers users to build their apps swiftly without sacrificing extensibility.\n- **Professional**: lihil is designed for enterprise web development, deliver robust\u0026scalable solutions with best practices in microservice architecture and related patterns.\n\n## Features\n\n- **Dependency injection**: inject factories, functions, sync/async, scoped/singletons based on type hints, blazingly fast.\n\n```python\nasync def get_conn(engine: Engine):\n    async with engine.connect() as conn:\n        yield conn\n\nasync def get_users(conn: AsyncConnection):\n    return await conn.execute(text(\"SELECT * FROM users\"))\n\n@Route(\"users\").get\nasync def list_users(users: Annotated[list[User], use(get_users)], is_active: bool=True):\n    return [u for u in users if u.is_active == is_active]\n```\n\n- **OpenAPI docs \u0026 Error Response Generator**\n\nlihil creates smart \u0026 accurate openapi schemas based on your routes/endpoints, union types, `oneOf` responses, all supported.\n\nyour exception classes are also automatically transformed to a `Problem` and genrate detailed response accordingly.\n\n```python\nclass OutOfStockError(HTTPException[str]):\n    \"The order can't be placed because items are out of stock\"\n    __status__ = 422\n\n    def __init__(self, order: Order):\n        detail: str = f\"{order} can't be placed, because {order.items} is short in quantity\"\n        super().__init__(detail)\n```\n\nwhen such exception is raised from endpoint, client would receive a response like this\n\n![outofstock](/docs/images/order_out_of_stock.png)\n\n- **Problems Page**: declare exceptions using route decorator and they will be displayed as route response at openapi schemas \u0026 problem page\n\n![problem page](/docs/images/order_out_of_stock_problem_page.png)\n\n- **Data validation\u0026Param Parsing**: using `msgspec`, which is about 12x faster than pydantic v2 for valiation and 25x memory efficient than pydantic v2, see [benchmarks](https://jcristharif.com/msgspec/benchmarks.html)\n\n![msgspec_vs_others](/docs/images/msgspec_others.png)\n\n- **Message System Bulitin**: publish command/event anywhere in your app with both in-process and out-of-process event handlers. Optimized data structure for maximum efficiency, de/serialize millions events from external service within seconds.\n\n```python\nfrom lihil import Route, EventBus, Empty, Resp, status\n\n@Route(\"users\").post\nasync def create_user(data: UserCreate, service: UserService, bus: EventBus)-\u003eResp[Empty, status.Created]:\n    user_id = await service.create_user(data)\n    await bus.publish(UserCreated(**data, user_id=user_id))\n```\n\n- **Great Testability**: bulit-in `LocalClient` to easily test your endpoints, routes, middlewares, app, everything.\n\n- **Strong support for AI featuers**: lihil takes AI as a main usecase, AI related features such as SSE, remote handler will be well supported, there will also be tutorials on how to develop your own AI agent/chatbot using lihil.\n\n\n## Compatability with starlette\n\nLihil is ASGI compatible and uses starlette as ASGI toolkit, which means that:\n\n- starlette `Request`, `Response` and its subclasses, should work just fine with lihil.\n\nMeaning you can declare `Request` in your endpoint and return an instance of `Response`(or subclass of it).\n\n```python\n@users.post\nasync def create_user(req: Request):\n    return Response(...)\n```\n\n- lihil is ASGI-Compatible, ASGI middlewares that works for any ASGIApp should also work with lihil.\n\n## Quick Start\n\n```python\nfrom lihil import Lihil\n\nlhl = Lihil()\n\n@lhl.get\nasync def hello():\n    return {\"hello\": \"world!\"}\n```\n\na more realistic example would be\n\n```python\nfrom lihil import Lihil, Route, use, EventBus\n\nchat_route = Route(\"/chats/{chat_id}\")\nmessage_route = chat_route / \"messages\"\nUserToken = NewType(\"UserToken\", str)\n\n@chat_route.factory\ndef parse_access_token(\n    service: UserService, token: UserToken\n) -\u003e ParsedToken:\n    return service.decrypt_access_token(token)\n\n@message_route.post\nasync def stream(\n   service: ChatService,\n   token: ParsedToken,\n   bus: EventBus,\n   chat_id: str,\n   data: CreateMessage\n) -\u003e Annotated[Stream[GPTMessage], CustomEncoder(gpt_encoder)]:\n    chat = service.get_user_chat(token.sub)\n    chat.add_message(data)\n    answer = service.ask(chat, model=data.model)\n    buffer = []\n    async for word in answer:\n        buffer.append(word)\n        yield word\n    await bus.publish(NewMessageCreated(chat, buffer))\n```\n\n## Install\n\nlihil(currently) requires python\u003e=3.12\n\n### pip\n\n```bash\npip install lihil\n```\n\n### uv\n\nif you want to install this project with uv\n\n[uv install guide](https://docs.astral.sh/uv/getting-started/installation/#installation-methods)\n\n1. init your web project with `project_name`\n\n```bash\nuv init project_name\n```\n\n2. install lihil via uv, this will solve all dependencies for your in a dedicated venv.\n\n```bash\nuv add lihil\n```\n\n## serve your application\n\n### serve with lihil\n\n#### app.py\n\n```python\nfrom lihil import Lihil\n\n# your application code\n\nlhl = Lihil()\n\nif __name__ == \"__main__\":\n    lhl.run(__file__)\n```\n\nthen in command line\n\n```python\nuv run python -m myproject.app --server.port=8080\n```\n\nThis allows you to override configurations using command-line arguments.\n\nIf your app is deployed in a containerized environment, such as Kubernetes, providing secrets this way is usually safer than storing them in files.\n\n### serve with uvicorn\n\nlihil is ASGI compatible, you can run it with an ASGI server, such as uvicorn\nstart a server with `app.py`, default to port 8000\n\n1. create `__main__.py` under your project root.\n2. use uvicorn to run you app in your `__main__.py`\n\n```python\nimport uvicorn\n\nuvicorn.run(app)\n```\n\n## versioning\n\nlihil follows semantic versioning, where a version in x.y.z represents:\n\n- x: major, breaking change\n- y: minor, feature updates\n- z: patch, bug fixes, typing updates\n\n**v1.0.0** will be the first stable major version.\n\n## Tutorials\n\ncheck detailed tutorials at https://lihil.cc/lihil/tutorials/, covering\n\n- Core concepts, create endpoint, route, middlewares, etc.\n- Configuring your app via `pyproject.toml`, or via command line arguments.\n- Dependency Injection \u0026 Plugins\n- Testing\n- Type-Based Message System, Event listeners, atomic event handling, etc.\n- Error Handling\n- ...and much more\n\n## Contribution \u0026 RoadMap\n\nNo contribution is trivial, and every contribution is appreciated. However, our focus and goals vary at different stages of this project.\n\n### version 0.1.x: Feature Parity\n\n- Feature Parity: we should offer core functionalities of a web framework ASAP, similar to what fastapi is offering right now. Given both fastapi and lihil uses starlette, this should not take too much effort.\n\n- Correctness: We should have a preliminary understanding of lihil's capabilities—knowing what should be supported and what shouldn't. This allows us to distinguish between correct and incorrect usage by users.\n\n- Test Coverage: There's no such thing as too many tests. For every patch, we should maintain at least 99% test coverage, and 100% for the last patch of 0.1.x. For core code, 100% coverage is just the baseline—we should continuously add test cases to ensure reliability.\n\nBased on the above points, in version v0.1.x, we welcome contributions in the following areas:\n\n- Documentation: Fix and expand the documentation. Since lihil is actively evolving, features may change or extend, and we need to keep the documentation up to date.\n\n- Testing: Contribute both successful and failing test cases to improve coverage and reliability.\n\n- Feature Requests: We are open to discussions on what features lihil should have or how existing features can be improved. However, at this stage, we take a conservative approach to adding new features unless there is a significant advantage.\n\n\n### version 0.2.x Cool Stuff\n\n- Out-of-process event system (RabbitMQ, Kafka, etc.).\n- A highly performant schema-based query builder based on asyncpg\n- Local command handler(http rpc) and remote command handler (gRPC)\n- More middleware and official plugins (e.g., throttling, caching, auth).\n\n\n### version 0.3.x performance boost\n\n- rewrite starlette request form:\n    1. use multipart\n    2. rewrite starlette `Multidict`, `Formdata`, perhaps using https://github.com/aio-libs/multidict\n","funding_links":[],"categories":["📚 Projects (1974 total)"],"sub_categories":["MCP Servers"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fraceychan%2Flihil","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fraceychan%2Flihil","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fraceychan%2Flihil/lists"}