/ duper-python / README.md
README.md
1 <p align="center"> 2 <img src="https://duper.dev.br/logos/duper-400.png" alt="The Duper logo, with a confident spectacled mole wearing a flailing blue cape." /> <br> 3 </p> 4 <h1 align="center">duper-python</h1> 5 6 <p align="center"> 7 <a href="https://pypi.org/project/duper-python"><img alt="PyPI version" src="https://img.shields.io/pypi/v/duper-python?style=flat&logo=python&logoColor=white&label=duper-python"></a> 8 <a href="https://github.com/EpicEric/duper"><img alt="GitHub license" src="https://img.shields.io/github/license/EpicEric/duper"></a> 9 </p> 10 11 Duper support for Python. 12 13 [Check out the official website for Duper.](https://duper.dev.br) 14 15 ## Installation 16 17 ```bash 18 uv add duper-python 19 # -- or -- 20 pip install duper-python 21 ``` 22 23 ## Examples 24 25 The basic `json`/`pickle`-like interface: 26 27 ```python 28 import duper 29 30 DUPER_DATA = """ 31 APIResponse({ 32 status: 200, 33 headers: { 34 content_type: "application/duper", 35 cache_control: "max-age=3600", 36 }, 37 body: { 38 users: [ 39 User({ 40 id: Uuid("7039311b-02d2-4849-a6de-900d4dbe9acb"), 41 name: "Alice", 42 email: Email("alice@example.com"), 43 roles: ["admin", "user"], 44 metadata: { 45 last_login: DateTime("2024-01-15T10:30:00Z"), 46 ip: IPV4("173.255.230.79"), 47 }, 48 }), 49 ], 50 }, 51 }) 52 """ 53 54 python_dict = duper.loads(DUPER_DATA) # Actually a Pydantic BaseModel! 55 56 with open("out.duper", "w") as f: 57 duper.dump(DUPER_DATA) 58 ``` 59 60 --- 61 62 Using [Pydantic](https://pypi.org/project/pydantic/): 63 64 ```python 65 from datetime import datetime 66 import re 67 import uuid 68 69 from duper import BaseModel 70 71 72 class RegisteredRegex(BaseModel): 73 regex_id: uuid.UUID 74 created_at: datetime 75 pattern: re.Pattern 76 matches: list[str] | None = None 77 78 data = RegisteredRegex( 79 regex_id=uuid.uuid4(), 80 created_at=datetime.now(), 81 pattern=re.compile(r"^Hello w.rld!$"), 82 ) 83 84 data_str = data.model_dump(mode="duper") 85 print(data_str) 86 87 reconstituted_data = RegisteredRegex.model_validate_duper(data_str) 88 assert data == reconstituted_data 89 ``` 90 91 --- 92 93 Using [FastAPI](https://pypi.org/project/fastapi/): 94 95 ```python 96 from typing import Annotated 97 from duper.fastapi import DuperBody, DuperResponse 98 from duper import BaseModel 99 from fastapi import FastAPI 100 101 class DuplicatableData(BaseModel): 102 tup: tuple[str, bytes] 103 value: int 104 105 app = FastAPI() 106 107 @app.post("/double", response_class=DuperResponse) 108 async def double_the_data( 109 body: Annotated[DuplicatableData, DuperBody(DuplicatableData)], 110 ) -> DuperResponse: 111 return DuperResponse( 112 DuplicatableData( 113 tup=(body.tup[0] + body.tup[0], body.tup[1] + body.tup[1]), 114 value=2 * body.value, 115 ) 116 ) 117 ```