|
1 | | -REQUIRES REWRITE |
| 1 | +# Exacting |
| 2 | + |
| 3 | +> *(adj.) making great demands on one's skill, attention, or other resources.* |
| 4 | +
|
| 5 | +`exacting` is a picky dataclass runtime utility collection, making sure all type annotations are followed. |
| 6 | + |
| 7 | +Essentially... **THE** go-to option for dataclasses. heh. |
| 8 | + |
| 9 | +**🔑 Key features**: |
| 10 | + |
| 11 | +- **100% static typing.** Because I hate nothing too. |
| 12 | +- Up to **10x faster** than [`pydantic`](https://pydantic.dev)! (Them: 60ms, us: 6~9ms) |
| 13 | + |
| 14 | + |
| 15 | + |
| 16 | +## Quick tour |
| 17 | + |
| 18 | +This won't take you long :) |
| 19 | + |
| 20 | +**🛍️ Get `exacting`**: |
| 21 | + |
| 22 | +```haskell |
| 23 | +pip install -U exacting |
| 24 | +``` |
| 25 | + |
| 26 | +**🔥 Define some model**: |
| 27 | + |
| 28 | +(Let's just say you're on Python 3.10+... good boy!) |
| 29 | + |
| 30 | +```python |
| 31 | +from exacting import Exact |
| 32 | + |
| 33 | +class Actor(Exact): |
| 34 | + name: str |
| 35 | + portrays: str |
| 36 | + |
| 37 | +class Show(Exact): |
| 38 | + name: str |
| 39 | + description: str | None |
| 40 | + actors: list[Actor] |
| 41 | +``` |
| 42 | + |
| 43 | +<details> |
| 44 | +<summary><b>Nawh... I'm on an older version</b></summary> |
| 45 | + |
| 46 | +Oh, it's definitely okay! We got you covered 🔥🔥 |
| 47 | + |
| 48 | +```python |
| 49 | +from typing import List, Optional |
| 50 | +from exacting import Exact |
| 51 | + |
| 52 | +class Actor(Exact): |
| 53 | + name: str |
| 54 | + portrays: str |
| 55 | + |
| 56 | +class Show(Exact): |
| 57 | + name: str |
| 58 | + description: Optional[str] |
| 59 | + actors: List[Actor] |
| 60 | +``` |
| 61 | + |
| 62 | +</details> |
| 63 | + |
| 64 | +<br /> |
| 65 | + |
| 66 | +**📦 Build 'em**: |
| 67 | + |
| 68 | +```python |
| 69 | +# (1) ✅ OK, exacting is happi |
| 70 | +Show( |
| 71 | + name="Severance", |
| 72 | + description="great show", |
| 73 | + actors=[ |
| 74 | + Actor(name="Adam Scott", portrays="Mark S."), |
| 75 | + Actor(name="Britt Lower", portrays="Helly R."), |
| 76 | + ] |
| 77 | +) |
| 78 | + |
| 79 | +# (2) ❌ Nuh-uh, exacting is angri |
| 80 | +Show( |
| 81 | + name=123, |
| 82 | + description=False, |
| 83 | + actors=[ |
| 84 | + "Walter White", |
| 85 | + "Jesse Pinkman" |
| 86 | + ] |
| 87 | +) |
| 88 | +``` |
| 89 | + |
| 90 | +<details> |
| 91 | +<summary>🔴 <b>ValidationError: During validation of…</b></summary> |
| 92 | + |
| 93 | + |
| 94 | +```python |
| 95 | +ValidationError: |
| 96 | +During validation of dataclass Show at field 'name', got: |
| 97 | + • Expected type <class 'str'>, got <class 'int'> |
| 98 | +``` |
| 99 | + |
| 100 | +</details> |
| 101 | + |
| 102 | +<br /> |
| 103 | + |
| 104 | +Normally, when you use the parameters passed in example (2) above, the Python `dataclasses` library might as well just go with it, because they only put the additional **static typing** to the model, but not at **runtime**. Exacting makes sure that at both times, types are all enforced. It even gives you a detailed error message on where this occurs! (In a cool way) |
| 105 | + |
| 106 | +It's worth noting that error generations are *lazy*, which means once Exacting finds out about a problem about a dataclass, it raises a `ValidationError`. This saves a lot of computation time if you have a larger model. |
| 107 | + |
| 108 | + |
0 commit comments