### Lihil Quick Start Example (Python) Source: https://github.com/raceychan/lihil/blob/master/README.md A quick start example demonstrating how to set up a GPT endpoint using Lihil. It utilizes OpenAI's client to stream chat completions and formats the output as Server-Sent Events (SSE). This example showcases dependency injection, asynchronous operations, and streaming responses. ```python from lihil import Lihil, Route, EventStream, SSE from openai import OpenAI from openai.types.chat import ChatCompletionChunk as Chunk from openai.types.chat import ChatCompletionUserMessageParam as MessageIn gpt = Route("/gpt", deps=[OpenAI]) def chunk_to_str(chunk: Chunk) -> str: if not chunk.choices: return "" return chunk.choices[0].delta.content or "" @gpt.sub("/messages").post async def add_new_message( client: OpenAPI, question: MessageIn, model: str ) -> Stream[Chunk]: yield SSE(event="open") chat_iter = client.responses.create(messages=[question], model=model, stream=True) async for chunk in chat_iter: yield SSE(event="token", data={"text": chunk_to_str(chunk)}) yield SSE(event="close") ``` -------------------------------- ### Python: Complete Lihil API Example Source: https://github.com/raceychan/lihil/blob/master/LIHIL_COPILOT.md A comprehensive example demonstrating the setup of a Lihil application, including defining root and health check endpoints, API routes with subroutes, request body validation using Payload, path parameters, and including routes. ```python from lihil import Lihil, Route, Payload from typing import Annotated from lihil import Param # App setup app = Lihil() # Root endpoint @app.sub("/").get async def root(): return {"message": "Welcome to Lihil API"} # Health check @app.sub("/health").get async def health(): return {"status": "healthy"} # API routes api_route = Route("/api/v1") # Users endpoints users_route = api_route.sub("/users") class UserCreate(Payload): name: str email: str age: int @users_route.get async def list_users(page: int = 1, limit: int = 10): return {"users": [], "page": page, "limit": limit} @users_route.post async def create_user(user: UserCreate): return {"id": 1, **user.dict()} # User detail endpoints user_detail = users_route.sub("/{user_id}") @user_detail.get async def get_user(user_id: str): return {"id": user_id, "name": "John", "email": "john@example.com"} @user_detail.put async def update_user(user_id: str, user: UserCreate): return {"id": user_id, **user.dict()} @user_detail.delete async def delete_user(user_id: str): return {"deleted": user_id} # Include routes app.include_routes(api_route) # Run with: uvicorn main:app --reload ``` -------------------------------- ### Lihil Application Setup Source: https://github.com/raceychan/lihil/blob/master/AGENTS.MD Provides examples of how to initialize and configure a Lihil application. This includes creating a basic app instance, initializing it with predefined routes, and applying global middleware. ```python from lihil import Lihil # Basic app app = Lihil() # App with routes app = Lihil(users_route, posts_route) # App with middleware app = Lihil(middlewares=[middleware1, middleware2]) ``` -------------------------------- ### Complete Lihil API Example Source: https://github.com/raceychan/lihil/blob/master/AGENTS.MD Presents a comprehensive example of a Lihil application setup, including route creation, defining endpoints for root, API v1 users list, user creation, and individual user retrieval, demonstrating nested subroutes and route inclusion. ```python from lihil import Lihil from lihil.routing import Route # Create app app = Lihil() # Root endpoint @app.get async def root(): return {"message": "API"} # API routes api_route = Route("/api/v1") users_route = api_route.sub("users") @users_route.get async def list_users(): return {"users": []} @users_route.post async def create_user(name: str, age: int): return {"id": 1, "name": name, "age": age} # User detail route user_route = users_route.sub("{user_id}") @user_route.get async def get_user(user_id: str): return {"id": user_id} # Include routes app.include_routes(api_route) ``` -------------------------------- ### Middleware & Plugins Source: https://github.com/raceychan/lihil/blob/master/LIHIL_COPILOT.md This section explains how to apply middleware at the application level and plugins at the route level, providing examples for CORS and authentication. ```APIDOC ## Middleware and Plugins ### Description Shows how to integrate middleware for application-wide concerns (like CORS) and plugins for route-specific functionality (like authentication). ### Method N/A (Middleware/Plugin Pattern) ### Endpoint N/A (Middleware/Plugin Pattern) ### Parameters None ### Request Example ```python from lihil.middleware import CORSMiddleware # App-level middleware example app = Lihil(middlewares=[CORSMiddleware]) # Route-level plugin example # Assuming 'auth_plugin' is a defined plugin # @app.sub("/protected").get(plugins=[auth_plugin]) # async def protected_endpoint(): # return {"message": "Protected"} ``` ### Response N/A (Middleware/Plugin Pattern) ``` -------------------------------- ### Complete Example Source: https://github.com/raceychan/lihil/blob/master/AGENTS.MD A comprehensive example demonstrating the integration of routes, HTTP methods, and parameter handling in a Lihil application. ```APIDOC ## Complete Example ### Description A comprehensive example demonstrating the integration of routes, HTTP methods, and parameter handling in a Lihil application. ### Code Example ```python from lihil import Lihil from lihil.routing import Route # Create app app = Lihil() # Root endpoint @app.get async def root(): return {"message": "API"} # API routes api_route = Route("/api/v1") users_route = api_route.sub("users") @users_route.get async def list_users(): return {"users": []} @users_route.post async def create_user(name: str, age: int): return {"id": 1, "name": name, "age": age} # User detail route user_route = users_route.sub("{user_id}") @user_route.get async def get_user(user_id: str): return {"id": user_id} # Include routes app.include_routes(api_route) ``` ``` -------------------------------- ### Testing Patterns Source: https://github.com/raceychan/lihil/blob/master/LIHIL_COPILOT.md This section demonstrates how to test Lihil endpoints using the TestClient, covering GET, POST, and path parameter validation. ```APIDOC ## Testing Lihil Endpoints ### Description Provides examples of how to use the `TestClient` to test various aspects of your Lihil API, including different HTTP methods and path parameters. ### Method N/A (Testing Pattern) ### Endpoint N/A (Testing Pattern) ### Parameters None ### Request Example ```python from lihil.testing import TestClient # Assuming 'app' is your Lihil application instance client = TestClient(app) # Test GET request response_get = client.get("/api/v1/users") assert response_get.status_code == 200 # Test POST request user_data = {"name": "Test User", "email": "test@example.com", "age": 25} response_post = client.post("/api/v1/users", json=user_data) assert response_post.status_code == 200 # Test path parameter response_path = client.get("/api/v1/users/123") assert response_path.status_code == 200 assert response_path.json()["id"] == "123" ``` ### Response N/A (Testing Pattern) ``` -------------------------------- ### Application Setup Source: https://github.com/raceychan/lihil/blob/master/AGENTS.MD Shows how to set up the main Lihil application, with and without routes and middleware. ```APIDOC ## Application Setup ### Description Shows how to set up the main Lihil application, with and without routes and middleware. ### Code Examples **Basic App:** ```python from lihil import Lihil app = Lihil() ``` **App with Routes:** ```python app = Lihil(users_route, posts_route) ``` **App with Middleware:** ```python app = Lihil(middlewares=[middleware1, middleware2]) ``` ``` -------------------------------- ### Install Lihil with pip (Python) Source: https://github.com/raceychan/lihil/blob/master/README.md This command installs the Lihil web framework using pip. The '[standard]' extra includes the uvicorn server, which is commonly used for running ASGI applications. Ensure you have Python 3.10 or higher installed. ```bash pip install "lihil[standard]" ``` -------------------------------- ### Python: Testing Lihil Endpoints with TestClient Source: https://github.com/raceychan/lihil/blob/master/LIHIL_COPILOT.md Shows how to write tests for Lihil API endpoints using the `TestClient`. It covers testing GET and POST requests, as well as verifying path parameters in the response. ```python from lihil.testing import TestClient def test_users_endpoint(): client = TestClient(app) # Test GET response = client.get("/api/v1/users") assert response.status_code == 200 # Test POST user_data = {"name": "John", "email": "john@example.com", "age": 30} response = client.post("/api/v1/users", json=user_data) assert response.status_code == 200 # Test path parameters response = client.get("/api/v1/users/123") assert response.status_code == 200 assert response.json()["id"] == "123" ``` -------------------------------- ### User Authentication API Source: https://github.com/raceychan/lihil/blob/master/LIHIL_COPILOT.md This section covers the basic setup for a Lihil application, including defining root and health check endpoints, and setting up API routes for user management. ```APIDOC ## Lihil Application Setup ### Description Demonstrates the basic structure of a Lihil application, including root endpoint, health check, and API route setup for user management. ### Method N/A (Application Setup) ### Endpoint N/A (Application Setup) ### Parameters None ### Request Example None ### Response None --- ## GET /api/v1/users ### Description Retrieves a list of users, with support for pagination. ### Method GET ### Endpoint `/api/v1/users` ### Parameters #### Query Parameters - **page** (int) - Optional - The page number for pagination. - **limit** (int) - Optional - The number of users to return per page. ### Request Example None (GET request) ### Response #### Success Response (200) - **users** (list) - A list of user objects. - **page** (int) - The current page number. - **limit** (int) - The limit of users per page. #### Response Example ```json { "users": [], "page": 1, "limit": 10 } ``` --- ## POST /api/v1/users ### Description Creates a new user. ### Method POST ### Endpoint `/api/v1/users` ### Parameters #### Request Body - **user** (UserCreate) - Required - The payload for creating a user. - **name** (str) - Required - The name of the user. - **email** (str) - Required - The email address of the user. - **age** (int) - Required - The age of the user. ### Request Example ```json { "name": "John", "email": "john@example.com", "age": 30 } ``` ### Response #### Success Response (200) - **id** (int) - The ID of the newly created user. - (user fields) - The fields of the created user. #### Response Example ```json { "id": 1, "name": "John", "email": "john@example.com", "age": 30 } ``` --- ## GET /api/v1/users/{user_id} ### Description Retrieves details for a specific user. ### Method GET ### Endpoint `/api/v1/users/{user_id}` ### Parameters #### Path Parameters - **user_id** (str) - Required - The ID of the user to retrieve. ### Request Example None (GET request) ### Response #### Success Response (200) - **id** (str) - The ID of the user. - **name** (str) - The name of the user. - **email** (str) - The email address of the user. #### Response Example ```json { "id": "123", "name": "John", "email": "john@example.com" } ``` --- ## PUT /api/v1/users/{user_id} ### Description Updates an existing user. ### Method PUT ### Endpoint `/api/v1/users/{user_id}` ### Parameters #### Path Parameters - **user_id** (str) - Required - The ID of the user to update. #### Request Body - **user** (UserCreate) - Required - The updated user data. - **name** (str) - Required - The name of the user. - **email** (str) - Required - The email address of the user. - **age** (int) - Required - The age of the user. ### Request Example ```json { "name": "Jane", "email": "jane@example.com", "age": 31 } ``` ### Response #### Success Response (200) - **id** (str) - The ID of the updated user. - (user fields) - The updated fields of the user. #### Response Example ```json { "id": "123", "name": "Jane", "email": "jane@example.com", "age": 31 } ``` --- ## DELETE /api/v1/users/{user_id} ### Description Deletes a user. ### Method DELETE ### Endpoint `/api/v1/users/{user_id}` ### Parameters #### Path Parameters - **user_id** (str) - Required - The ID of the user to delete. ### Request Example None (DELETE request) ### Response #### Success Response (200) - **deleted** (str) - The ID of the deleted user. #### Response Example ```json { "deleted": "123" } ``` ``` -------------------------------- ### Lihil Plugin Application Example Source: https://github.com/raceychan/lihil/blob/master/README.md Demonstrates how to apply multiple plugins to an endpoint in Lihil. The order of application in the decorator determines the execution order, with the first applied plugin executing outermost during runtime. ```python @app.sub("/api").get(plugins=[ plugin.timeout(5), # Applied 1st → Executes Outermost plugin.retry(max_attempts=3), # Applied 2nd → Executes Middle plugin.cache(expire_s=60), # Applied 3rd → Executes Innermost ]) ``` -------------------------------- ### Basic Lihil Application Setup with Routes Source: https://context7.com/raceychan/lihil/llms.txt Demonstrates how to set up a basic Lihil application with routes and endpoints. It includes creating routes, defining endpoints with type validation for parameters, and running the application using uvicorn. This snippet requires the 'lihil' and 'uvicorn' libraries. ```python from lihil import Lihil, Route from typing import Literal # Create routes root = Route() # Define endpoint with type validation UserNames = Literal["alice", "bob", "charlie"] @root.sub("/user").get async def get_user(user_name: UserNames | None): if user_name: return {"user": user_name} return {"message": "No user specified"} # Create application instance app = Lihil(root) # Run the application if __name__ == "__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=8000) ``` -------------------------------- ### Create and Use Plugins for Endpoint Decoration in Lihil Source: https://context7.com/raceychan/lihil/llms.txt Illustrates how to create custom plugins to decorate endpoint functionality in Lihil. This example shows a LoggingPlugin that logs the start, completion, or failure of requests to a specified route. ```python from lihil import Lihil, Route from lihil.plugins.interface import IPlugin, IEndpointInfo from lihil.interface import IAsyncFunc, P, R from typing import Callable, Awaitable import time import logging # Create custom plugin for logging class LoggingPlugin: def __init__(self, logger: logging.Logger): self.logger = logger def decorate(self, ep_info: IEndpointInfo[P, R]) -> Callable[P, Awaitable[R]]: original_func = ep_info.func route_path = ep_info.sig.route_path async def wrapper(*args: P.args, **kwargs: P.kwargs) -> R: start_time = time.time() self.logger.info(f"Starting request to {route_path}") try: result = await original_func(*args, **kwargs) duration = time.time() - start_time self.logger.info(f"Completed {route_path} in {duration:.2f}s") return result except Exception as e: duration = time.time() - start_time self.logger.error(f"Failed {route_path} after {duration:.2f}s: {e}") raise return wrapper ``` -------------------------------- ### Override `__json_example__` for OpenAPI Documentation (Python) Source: https://github.com/raceychan/lihil/blob/master/README.md Illustrates how to override the `__json_example__` class method to provide custom JSON examples for exceptions in OpenAPI documentation. This ensures that API consumers see realistic and informative error examples. It requires defining a `ProblemDetail` object. ```python from lihil.interface.problem import ProblemDetail from lihil.exceptions import HTTPException class UserNotFound(HTTPException[str]): """The user you are looking for does not exist""" __status__ = 404 @classmethod def __json_example__(cls) -> ProblemDetail[str]: return ProblemDetail( type_="user-not-found", title="User Not Found", status=404, detail="User with ID 'user123' was not found in the system", instance="/api/v1/users/user123" ) ``` -------------------------------- ### Including Routes in Lihil Applications Source: https://github.com/raceychan/lihil/blob/master/LIHIL_COPILOT.md Demonstrates how to organize routes into separate modules and include them in the main Lihil application, either dynamically using `include_routes` or by passing them directly to the `Lihil` constructor. This promotes modularity in larger applications. ```python # Create separate route modules users_route = Route("/users") @users_route.get async def list_users(): return {"users": []} posts_route = Route("/posts") @posts_route.get async def list_posts(): return {"posts": []} # Include in app app = Lihil() app.include_routes(users_route, posts_route) # Or pass routes to constructor app = Lihil(users_route, posts_route) ``` -------------------------------- ### Python: Middleware and Plugins in Lihil Source: https://github.com/raceychan/lihil/blob/master/LIHIL_COPILOT.md Illustrates how to apply middleware and plugins in Lihil applications. It shows adding app-level middleware like `CORSMiddleware` and route-level plugins like `auth_plugin`. ```python from lihil.middleware import CORSMiddleware # App-level middleware app = Lihil(middlewares=[CORSMiddleware]) # Route-level plugins @app.sub("/protected").get(plugins=[auth_plugin]) async def protected_endpoint(): return {"message": "Protected"} ``` -------------------------------- ### Plugin Execution Flow in Lihil Source: https://github.com/raceychan/lihil/blob/master/README.md Illustrates the setup-time plugin application and runtime request execution flow for Lihil plugins. Plugins are applied from left to right during setup and execute in a nested (onion) pattern during runtime, allowing for pre- and post-processing of requests. ```text Plugin Application (Setup Time - Left to Right) ┌─────────────────────────────────────────────────────────────┐ │ original_func → plugin1(ep_info) → plugin2(ep_info) │ │ │ │ Result: plugin2(plugin1(original_func)) │ └─────────────────────────────────────────────────────────────┘ Request Execution (Runtime - Nested/Onion Pattern) ┌────────────────────────────────────────────────────────────┐ │ │ │ Request │ │ │ │ │ ▼ │ │ ┌─────────────────────────────────────────────────────┐ │ │ │ Plugin2 (Outermost) │ │ │ │ ┌─────────────────────────────────────────────────┐ │ │ │ │ │ Plugin1 (Middle) │ │ │ │ │ │ ┌─────────────────────────────────────────────┐ │ │ │ │ │ │ │ Original Function (Core) │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ async def get_data(): │ │ │ │ │ │ │ │ return {"data": "value"} │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─────────────────────────────────────────────┘ │ │ │ │ │ └─────────────────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────┘ │ │ │ │ │ ▼ │ │ Response │ │ │ └────────────────────────────────────────────────────────────┘ ``` -------------------------------- ### Lihil Dependency Injection with Graph Source: https://context7.com/raceychan/lihil/llms.txt Demonstrates how to use Lihil's dependency injection system with a Graph. This example shows defining dependencies like database configuration and services, and then injecting them into request handlers. It requires 'lihil' and 'dataclasses'. ```python from lihil import Lihil, Route, Graph, DependentNode, Request from dataclasses import dataclass # Define dependencies @dataclass class DatabaseConfig: host: str = "localhost" port: int = 5432 database: str = "myapp" class DatabaseConnection: def __init__(self, config: DatabaseConfig): self.config = config self.connection_string = f"{config.host}:{config.port}/{config.database}" async def query(self, sql: str) -> list[dict]: # Simulate database query return [{"result": "data"}] class UserService: def __init__(self, db: DatabaseConnection): self.db = db async def get_user_by_id(self, user_id: int) -> dict: result = await self.db.query(f"SELECT * FROM users WHERE id = {user_id}") return result[0] if result else {} # Create dependency graph graph = Graph() graph.node(DatabaseConfig, scope="app") graph.node(DatabaseConnection, scope="app") graph.node(UserService, scope="request") # Create route with dependencies route = Route("/api", graph=graph) @route.sub("/users/{user_id}").get async def get_user_endpoint(user_id: int, service: UserService, request: Request): user = await service.get_user_by_id(user_id) return { "user": user, "request_path": request.url.path } app = Lihil(route, graph=graph) ``` -------------------------------- ### Python: Understanding Lihil Route Structure Source: https://github.com/raceychan/lihil/blob/master/LIHIL_COPILOT.md Illustrates the correct way to structure Lihil routes, emphasizing clarity and avoiding unnecessary route creation. It shows proper use of `@app.sub` and `Route` objects for defining endpoints. ```python # Wrong - Creating new routes unnecessarily @app.get("/") # Invalid syntax async def root(): return {} @Route("/users").get("/") # Confusing path structure async def users(): return {} # Correct - Clear route structure @app.sub("/").get # Root endpoint async def root(): return {} users_route = Route("/users") @users_route.get # /users endpoint async def get_users(): return {} @users_route.sub("/{user_id}").get # /users/{user_id} endpoint async def get_user(user_id: str): return {} ``` -------------------------------- ### HTTP Method Decorators Source: https://github.com/raceychan/lihil/blob/master/AGENTS.MD Illustrates how to use HTTP method decorators like GET, POST, PUT, and DELETE on routes in Lihil. ```APIDOC ## HTTP Method Decorators ### Description Illustrates how to use HTTP method decorators like GET, POST, PUT, and DELETE on routes in Lihil. ### Code Examples ```python route = Route("/api") @route.get async def get_handler(): return {"method": "GET"} @route.post async def post_handler(data: dict): return {"method": "POST", "data": data} @route.put async def put_handler(): return {"method": "PUT"} @route.delete async def delete_handler(): return {"method": "DELETE"} ``` ``` -------------------------------- ### Lihil Dependency Injection Source: https://github.com/raceychan/lihil/blob/master/LIHIL_COPILOT.md Explains Lihil's dependency injection system, showing how to declare dependencies in route constructors or using the `Depends` function for function-level dependencies. This facilitates managing services and context within request handlers. ```python from lihil import Route # Dependencies in route constructor route = Route("/api", deps=[DatabaseService, AuthService]) @route.get async def get_data(db: DatabaseService, auth: AuthService): # db and auth are automatically injected return db.get_all() # Function dependencies async def get_current_user() -> User: return User(id=1, name="test") @app.sub("/profile").get async def get_profile(user: User = Depends(get_current_user)): return {"user": user} ``` -------------------------------- ### Python: Correct Route Path Specification Source: https://github.com/raceychan/lihil/blob/master/LIHIL_COPILOT.md Demonstrates the correct way to specify paths in Lihil routes, avoiding duplication between the Route object and the decorator. It also shows how to use subroutes for nested paths. ```python # Wrong - Path specified in both places route = Route("/users") @route.get("/profile") # Don't add path here! async def get_profile(): return {} # Correct - Path only in Route route = Route("/users") @route.get async def get_profile(): return {} # Or use subroutes for nested paths users_route = Route("/users") @users_route.sub("/profile").get async def get_profile(): return {} ``` -------------------------------- ### Define FastAPI-like Routes (Invalid in Lihil) Source: https://github.com/raceychan/lihil/blob/master/LIHIL_COPILOT.md Demonstrates invalid route definitions that mimic FastAPI syntax. These patterns will not work with the Lihil web framework and should be avoided. ```python # These patterns DO NOT work in Lihil: @app.get("/users") # INVALID @app.post("/users/{id}") # INVALID @app.put("/api/data") # INVALID @app.delete("/items") # INVALID ``` -------------------------------- ### Python: Custom Error Handling with HTTPException Source: https://github.com/raceychan/lihil/blob/master/LIHIL_COPILOT.md Demonstrates how to implement custom error handling in Lihil using `HTTPException`. It defines a custom exception `UserNotFound` and raises it when a user is not found. ```python from lihil import HTTPException class UserNotFound(HTTPException[str]): """The user you are looking for does not exist""" __status__ = 404 @app.sub("/users/{user_id}").get async def get_user(user_id: str): if not user_exists(user_id): raise UserNotFound(f"User {user_id} not found") return get_user_data(user_id) ``` -------------------------------- ### Define Lihil Routes with Subroutes Source: https://github.com/raceychan/lihil/blob/master/LIHIL_COPILOT.md Shows the correct way to define routes in Lihil using the `sub` method for path definition followed by HTTP method decorators. This is the standard approach for creating endpoints in Lihil. ```python # Use subroutes for paths: @app.sub("/users").get # CORRECT @app.sub("/users/{id}").post # CORRECT @app.sub("/api/data").put # CORRECT @app.sub("/items").delete # CORRECT ``` -------------------------------- ### Error Handling with HTTPException Source: https://github.com/raceychan/lihil/blob/master/LIHIL_COPILOT.md This section details how to implement custom error handling in Lihil using HTTPException for specific error scenarios like 'User Not Found'. ```APIDOC ## Custom Error Handling ### Description Illustrates how to define and raise custom exceptions inheriting from `HTTPException` to handle specific error conditions in your Lihil application, such as a user not being found. ### Method N/A (Error Handling Pattern) ### Endpoint N/A (Error Handling Pattern) ### Parameters None ### Request Example ```python from lihil import HTTPException class UserNotFound(HTTPException[str]): """The user you are looking for does not exist""" __status__ = 404 # Example usage within an endpoint: # @app.sub("/users/{user_id}").get # async def get_user(user_id: str): # if not user_exists(user_id): # Assume user_exists is a defined function # raise UserNotFound(f"User {user_id} not found") # return get_user_data(user_id) # Assume get_user_data is a defined function ``` ### Response #### Error Response (404) - **detail** (str) - A descriptive error message (e.g., "User {user_id} not found"). #### Response Example ```json { "detail": "User 123 not found" } ``` ``` -------------------------------- ### Implement Server-Sent Events (SSE) Streaming in Lihil Source: https://context7.com/raceychan/lihil/llms.txt Demonstrates how to implement Server-Sent Events (SSE) for real-time data streaming to clients using Lihil. Includes examples for streaming current time, simulating chat responses, and tracking task progress. ```python from lihil import Lihil, Route, SSE, Stream, EventStream from typing import AsyncGenerator import asyncio route = Route("/api") # Simple SSE endpoint @route.sub("/stream/time").get async def stream_time() -> Stream[str]: yield SSE(event="open", data="Stream started") for i in range(10): await asyncio.sleep(1) current_time = asyncio.get_event_loop().time() yield SSE(event="time", data={"timestamp": current_time, "count": i}) yield SSE(event="close", data="Stream ended") # Chat streaming example with OpenAI @route.sub("/chat/stream").post async def chat_stream(message: str, model: str = "gpt-4") -> Stream[dict]: yield SSE(event="start") # Simulate streaming response (replace with actual OpenAI call) response_text = f"Response to: {message}" for word in response_text.split(): await asyncio.sleep(0.1) yield SSE(event="token", data={"text": word}) yield SSE(event="end") # Progress tracking endpoint @route.sub("/process/{task_id}").get async def track_process(task_id: str) -> Stream[dict]: yield SSE(event="started", data={"task_id": task_id}) stages = ["Initializing", "Processing", "Finalizing", "Complete"] for i, stage in enumerate(stages): await asyncio.sleep(2) progress = int((i + 1) / len(stages) * 100) yield SSE( event="progress", data={"stage": stage, "progress": progress, "task_id": task_id} ) yield SSE(event="completed", data={"task_id": task_id, "result": "success"}) app = Lihil(route) ``` -------------------------------- ### Core Lihil Route Creation Patterns Source: https://github.com/raceychan/lihil/blob/master/LIHIL_COPILOT.md Demonstrates three primary ways to create routes in Lihil: creating a route object first, using app subroutes directly, and utilizing nested subroutes for hierarchical path structures. These patterns are fundamental for building Lihil applications. ```python from lihil import Lihil, Route # Pattern 1: Create route object first route = Route("/api/users") @route.get async def list_users(): return {"users": []} @route.post async def create_user(name: str): return {"id": 1, "name": name} # Pattern 2: Use app subroutes app = Lihil() @app.sub("/health").get async def health_check(): return {"status": "ok"} # Pattern 3: Nested subroutes api = app.sub("/api") users = api.sub("/users") @users.get async def get_users(): return {"users": []} user_detail = users.sub("/{user_id}") @user_detail.get async def get_user(user_id: str): return {"id": user_id} ``` -------------------------------- ### Define Lihil Routes by Creating Route Objects Source: https://github.com/raceychan/lihil/blob/master/LIHIL_COPILOT.md Illustrates an alternative method for defining Lihil routes by first creating a `Route` object with a path and then applying HTTP method decorators to functions associated with that route. This pattern offers flexibility in route organization. ```python # Or create routes first: users_route = Route("/users") @users_route.get # CORRECT @users_route.post # CORRECT ``` -------------------------------- ### Lihil Request Body, Query, Header, and Form Parameters Source: https://github.com/raceychan/lihil/blob/master/LIHIL_COPILOT.md Demonstrates how to handle different types of request data in Lihil, including JSON payloads using `Payload` classes, query parameters, header parameters using `Param`, and form data using `Form`. This covers common API input patterns. ```python from typing import Annotated from lihil import Param, Form, Payload # Payload for JSON body class UserData(Payload): name: str age: int email: str @app.sub("/users").post async def create_user(user: UserData): return {"created": user} # Query parameters (automatically detected) @app.sub("/search").get async def search(q: str = "", page: int = 1, limit: int = 10): return {"query": q, "page": page, "limit": limit} # Header parameters @app.sub("/protected").get async def protected_endpoint( auth: Annotated[str, Param("header", alias="Authorization")] ): return {"auth": auth} # Form data @app.sub("/upload").post async def upload_file( file: Annotated[bytes, Form()], filename: Annotated[str, Form()] ): return {"uploaded": filename} ``` -------------------------------- ### Correct Lihil Route Syntax vs. FastAPI Mistake Source: https://github.com/raceychan/lihil/blob/master/LIHIL_COPILOT.md Highlights a common mistake where AI agents try to use FastAPI's direct decorator syntax (`@app.get`) for defining routes in Lihil. It contrasts this with the correct Lihil approach using `@app.sub('/path').get`. ```python # Wrong - AI agents often try this @app.get("/users") async def get_users(): return [] # Correct - Use subroutes @app.sub("/users").get async def get_users(): return [] ``` -------------------------------- ### Server-Sent Events (SSE) Format (Text) Source: https://github.com/raceychan/lihil/blob/master/README.md This illustrates the expected format of Server-Sent Events (SSE) that a frontend client would receive from the Lihil GPT endpoint example. It shows different event types like 'open', 'token' (with data), and 'close' for managing the streaming communication. ```text event: open event: token data: {"text":"Hello"} event: token data: {"text":" world"} event: token data: {"text":"!"} event: close ``` -------------------------------- ### GET /api/events - Get Events with Datetime Decoding Source: https://context7.com/raceychan/lihil/llms.txt Retrieves events within a specified date range. Supports custom ISO datetime decoding for start and end dates and session retrieval from cookies. ```APIDOC ## GET /api/events ### Description Retrieves a list of events within a given time period. Uses custom datetime decoding for query parameters and retrieves session information from cookies. ### Method GET ### Endpoint `/api/events` ### Parameters #### Query Parameters - **start_date** (datetime) - Required - The start date and time for fetching events in ISO format (e.g., YYYY-MM-DDTHH:MM:SS). - **end_date** (datetime) - Required - The end date and time for fetching events in ISO format (e.g., YYYY-MM-DDTHH:MM:SS). #### Cookie Parameters - **session_id** (str) - Optional - The session identifier. (Alias: session) ### Request Example ``` GET /api/events?start_date=2024-01-01T00:00:00&end_date=2024-12-31T23:59:59 HTTP/1.1 Host: example.com Cookie: session=abc123 ``` ### Response #### Success Response (200) - **events** (list) - A list of event objects (currently an empty list). - **period** (dict) - The specified time period. - **start** (str) - The start date and time in ISO format. - **end** (str) - The end date and time in ISO format. - **session** (str) - The retrieved session ID. #### Response Example ```json { "events": [], "period": { "start": "2024-01-01T00:00:00", "end": "2024-12-31T23:59:59" }, "session": "abc123" } ``` ``` -------------------------------- ### Python: Manage Application Lifespan with Context Managers Source: https://context7.com/raceychan/lihil/llms.txt This snippet illustrates how to manage the application's startup and shutdown sequences using an asynchronous context manager in lihil. It covers initializing resources like database connections and background tasks during startup, and cleaning them up during shutdown, ensuring graceful termination. ```python from lihil import Lihil, Route from contextlib import asynccontextmanager import asyncio # Shared state class AppState: def __init__(self): self.db_connection = None self.cache = {} self.background_task = None app_state = AppState() @asynccontextmanager async def app_lifespan(app: Lihil): # Startup logic print("Application starting...") # Initialize database connection app_state.db_connection = "Connected to database" print(f"Database: {app_state.db_connection}") # Start background task async def background_worker(): while True: await asyncio.sleep(60) print("Background task running...") app_state.cache.clear() # Clear cache every minute app_state.background_task = asyncio.create_task(background_worker()) # Yield control to the application yield # Shutdown logic print("Application shutting down...") # Cancel background task if app_state.background_task: app_state.background_task.cancel() try: await app_state.background_task except asyncio.CancelledError: print("Background task cancelled") # Close database connection print("Database connection closed") app_state.db_connection = None # Create routes route = Route("/api") @route.sub("/status").get async def get_status(): return { "database": app_state.db_connection, "cache_size": len(app_state.cache) } @route.sub("/cache/{key}").get async def get_cache(key: str): return {"key": key, "value": app_state.cache.get(key)} @route.sub("/cache/{key}").post async def set_cache(key: str, value: str): app_state.cache[key] = value return {"key": key, "value": value, "cached": True} # Create application with lifespan app = Lihil(route, lifespan=app_lifespan) # Startup sequence: # 1. Application starting... # 2. Database: Connected to database # 3. Background task starts # 4. Application ready to serve requests # # Shutdown sequence: # 1. Application shutting down... # 2. Background task cancelled # 3. Database connection closed ``` -------------------------------- ### GET /api/data/{item_id} - Get Data with Caching Source: https://context7.com/raceychan/lihil/llms.txt Retrieves data for a specific item, utilizing a custom caching plugin to store and serve results from cache if available and not expired. Includes logging. ```APIDOC ## GET /api/data/{item_id} ### Description Retrieves data for a specific item with caching and logging. The response is cached for a duration defined by the `CachePlugin`'s TTL. ### Method GET ### Endpoint `/api/data/{item_id}` ### Parameters #### Path Parameters - **item_id** (int) - Required - The ID of the item to retrieve. ### Request Example ```json { "item_id": 123 } ``` ### Response #### Success Response (200) - **item_id** (int) - The ID of the requested item. - **data** (str) - The computed data for the item. #### Response Example ```json { "item_id": 123, "data": "expensive computation result" } ``` ``` -------------------------------- ### Route Creation Source: https://github.com/raceychan/lihil/blob/master/AGENTS.MD Demonstrates different ways to create routes in the Lihil framework, including basic routes, routes with path parameters, middleware, and dependencies. ```APIDOC ## Route Creation ### Description Demonstrates different ways to create routes in the Lihil framework, including basic routes, routes with path parameters, middleware, and dependencies. ### Code Examples **Basic Route:** ```python from lihil.routing import Route route = Route("/users") ``` **Route with Path Parameters:** ```python route = Route("/users/{user_id}") ``` **Route with Middleware:** ```python route = Route("/api", middlewares=[middleware1, middleware2]) ``` **Route with Dependencies:** ```python route = Route("/service", deps=[ServiceClass]) ``` ``` -------------------------------- ### Lihil: Implement User API Endpoints (Python) Source: https://context7.com/raceychan/lihil/llms.txt Implements RESTful API endpoints for managing users using Lihil's routing system. Includes GET for retrieving a user by ID, POST for creating a user, and GET for listing users with optional limit. ```python users_db: dict[int, User] = { 1: User(id=1, username="alice", email="alice@example.com"), 2: User(id=2, username="bob", email="bob@example.com") } route = Route("/api") @route.sub("/users/{user_id}").get async def get_user(user_id: int) -> User: if user_id not in users_db: raise UserNotFound(f"User {user_id} not found") return users_db[user_id] @route.sub("/users").post async def create_user(user: UserCreate) -> User: new_id = max(users_db.keys()) + 1 new_user = User(id=new_id, username=user.username, email=user.email) users_db[new_id] = new_user return new_user @route.sub("/users").get async def list_users(limit: int = 10) -> list[User]: return list(users_db.values())[:limit] app = Lihil(route) ``` -------------------------------- ### GET /api/cache/{key} Source: https://context7.com/raceychan/lihil/llms.txt Retrieves a value from the application cache using the provided key. ```APIDOC ## GET /api/cache/{key} ### Description Retrieves a value from the application cache using the provided key. ### Method GET ### Endpoint /api/cache/{key} #### Path Parameters - **key** (str) - Required - The key of the cache entry to retrieve. ### Response #### Success Response (200) - **key** (str) - The requested cache key. - **value** (str) - The value associated with the cache key (or null if not found). #### Response Example ```json { "key": "user_session_123", "value": "session_data_here" } ``` ``` -------------------------------- ### Python: Testing Lihil Applications with LocalClient Source: https://context7.com/raceychan/lihil/llms.txt This snippet introduces testing lihil applications using the LocalClient. It imports necessary components for creating routes, handling exceptions, and setting up tests with pytest, preparing the ground for writing comprehensive unit and integration tests for lihil applications. ```python from lihil import Lihil, Route, Struct, HTTPException from lihil.local_client import LocalClient import pytest ``` -------------------------------- ### GET /api/users/{user_id} Source: https://context7.com/raceychan/lihil/llms.txt Retrieves a specific user by their ID. If the user is not found, a 404 error is returned. ```APIDOC ## GET /api/users/{user_id} ### Description Retrieves a specific user by their ID. If the user is not found, a 404 error is returned. ### Method GET ### Endpoint /api/users/{user_id} ### Parameters #### Path Parameters - **user_id** (int) - Required - The unique identifier of the user to retrieve. ### Response #### Success Response (200) - **id** (int) - The user's unique identifier. - **username** (str) - The user's username. - **email** (str) - The user's email address. #### Error Response (404) - **type** (str) - Indicates the type of error, e.g., "user-not-found". - **detail** (str) - A message describing the error, e.g., "User {user_id} not found". ### Response Example ```json { "id": 1, "username": "alice", "email": "alice@example.com" } ``` ``` -------------------------------- ### GET /api/status Source: https://context7.com/raceychan/lihil/llms.txt Retrieves the current status of the application, including database connection status and cache size. ```APIDOC ## GET /api/status ### Description Retrieves the current status of the application, including database connection status and cache size. ### Method GET ### Endpoint /api/status ### Response #### Success Response (200) - **database** (str) - The status of the database connection (e.g., "Connected to database" or null). - **cache_size** (int) - The current number of items in the application cache. #### Response Example ```json { "database": "Connected to database", "cache_size": 150 } ``` ``` -------------------------------- ### GET /api/users Source: https://context7.com/raceychan/lihil/llms.txt Retrieves a list of users. Supports an optional limit parameter to control the number of returned users. ```APIDOC ## GET /api/users ### Description Retrieves a list of users. Supports an optional limit parameter to control the number of returned users. ### Method GET ### Endpoint /api/users ### Parameters #### Query Parameters - **limit** (int) - Optional - The maximum number of users to return. Defaults to 10. ### Response #### Success Response (200) - An array of user objects, where each object contains: - **id** (int) - The user's unique identifier. - **username** (str) - The user's username. - **email** (str) - The user's email address. ### Response Example ```json [ { "id": 1, "username": "alice", "email": "alice@example.com" }, { "id": 2, "username": "bob", "email": "bob@example.com" } ] ``` ```