/
/
1 """Todo API client — Python example.""" 2
3 import requests 4 from dataclasses import dataclass 5 from typing import Optional 6
7 API_BASE = "http://localhost:8080/api/v1" 8
9 # @gitian 10 # --group=clients 11 # Todo dataclass — mirrors the Go struct. Python's dataclass 12 # decorator provides __init__, __repr__, and __eq__ for free. 13 @dataclass 14 class Todo: 15 id: str 16 text: str 17 completed: bool 18 created_at: str 19 priority: str = "medium" 20
21 # @gitian 22 # --group=clients 23 # TodoClient wraps the REST API with typed methods. 24 # Uses requests sessions for connection pooling. 25 class TodoClient: 26 def __init__(self, base_url: str = API_BASE): 27 self.session = requests.Session() 28 self.base_url = base_url 29
30 # @gitian:security Validate SSL in production — session.verify defaults 31 # to True but can be overridden. Never disable in prod. 32
33 # @gitian List all todos, optionally filtered by status. 34 def list(self, status: Optional[str] = None) -> list[Todo]: 35 params = {"status": status} if status else {} 36 # @gitian:todo Add pagination support (offset/limit params) 37 resp = self.session.get(f"{self.base_url}/todos", params=params) 38 resp.raise_for_status() 39 return [Todo(**t) for t in resp.json()] 40
41 # @gitian Create a new todo and return the server response. 42 def create(self, text: str, priority: str = "medium") -> Todo: 43 resp = self.session.post( 44 f"{self.base_url}/todos", 45 json={"text": text, "priority": priority}, 46 ) 47 resp.raise_for_status() 48 return Todo(**resp.json()) 49
50 # @gitian:warning Delete is permanent — no soft-delete or undo. 51 def delete(self, todo_id: str) -> None: 52 resp = self.session.delete(f"{self.base_url}/todos/{todo_id}") 53 resp.raise_for_status() 54
55
56 if __name__ == "__main__": 57 client = TodoClient() 58 todo = client.create("Buy groceries", "high") 59 print(f"Created: {todo}") 60
61 todos = client.list(status="active") 62 print(f"Active: {len(todos)} todos") 63