add 3.12 features, inline script metadata, argparse

- README: recommend 3.12+
- typing.md: native generic syntax [T], type statement
- uv.md: PEP 723 inline script metadata (# /// script)
- patterns.md: argparse with subparsers

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

Changed files
+70 -18
languages
+1 -1
languages/python/README.md
··· 4 4 5 5 python is dynamically typed but increasingly written with static type hints. it has first-class async support but doesn't force it on you. it has a global interpreter lock but that matters less than people think for I/O-bound work. 6 6 7 - these notes focus on modern python (3.10+) - the patterns that emerge when you take typing seriously and use async where it makes sense. 7 + these notes assume python 3.12 or later. 3.12 introduced native generic syntax and the `type` statement - the typing story finally feels complete. 8 8 9 9 ## the language 10 10
+29
languages/python/patterns.md
··· 181 181 182 182 the wrapper's signature now includes `_filter`. IDEs and schema generators see it. 183 183 184 + ## argparse for CLIs 185 + 186 + argparse is stdlib and sufficient for most CLIs. subparsers give you git-style commands: 187 + 188 + ```python 189 + import argparse 190 + 191 + def main() -> int: 192 + parser = argparse.ArgumentParser(description="my tool") 193 + subparsers = parser.add_subparsers(dest="command") 194 + 195 + list_parser = subparsers.add_parser("list", aliases=["ls"]) 196 + list_parser.add_argument("collection") 197 + list_parser.add_argument("--limit", type=int, default=50) 198 + 199 + args = parser.parse_args() 200 + 201 + match args.command: 202 + case "list" | "ls": 203 + return do_list(args.collection, args.limit) 204 + case _: 205 + parser.print_help() 206 + return 1 207 + 208 + return 0 209 + ``` 210 + 211 + the pattern: parse once at the top, dispatch based on command, return exit codes. 212 + 184 213 ## module-level singletons 185 214 186 215 instantiate once, import everywhere:
+20 -17
languages/python/typing.md
··· 1 1 # typing 2 2 3 - modern python type hints - not just for IDEs, but for thinking clearly about code. 3 + python 3.12 made typing feel native. generics have real syntax, type aliases have a keyword, and you rarely need to import from `typing` anymore. 4 4 5 - ## basics 5 + ## the basics 6 6 7 - use `|` for unions, not `Optional`: 7 + use `|` for unions: 8 8 9 9 ```python 10 - # yes 11 10 def fetch(url: str, timeout: float | None = None) -> dict[str, Any]: ... 11 + ``` 12 + 13 + `from __future__ import annotations` at the top of files lets you reference types before they're defined and avoids some runtime costs. 14 + 15 + ## type aliases 12 16 13 - # no 14 - from typing import Optional 15 - def fetch(url: str, timeout: Optional[float] = None) -> Dict[str, Any]: ... 17 + the `type` statement creates type aliases: 18 + 19 + ```python 20 + type UserId = int 21 + type Handler = Callable[[Request], Response] 22 + type Result[T] = T | Error 16 23 ``` 17 24 18 - `from __future__ import annotations` at the top of every file. this defers evaluation so you can reference types before they're defined. 25 + clearer than `TypeAlias` annotations and supports generics directly. 19 26 20 27 ## TypedDict 21 28 ··· 73 80 74 81 ## generics 75 82 76 - for functions that work with any type: 83 + 3.12 introduced native syntax for generics. no more `TypeVar`: 77 84 78 85 ```python 79 - from typing import TypeVar 80 - 81 - T = TypeVar("T") 82 - 83 - def first(items: list[T]) -> T | None: 86 + def first[T](items: list[T]) -> T | None: 84 87 return items[0] if items else None 85 88 ``` 86 89 ··· 89 92 ```python 90 93 from pydantic import BaseModel 91 94 92 - ModelT = TypeVar("ModelT", bound=BaseModel) 93 - 94 - def parse(data: dict, model: type[ModelT]) -> ModelT: 95 + def parse[M: BaseModel](data: dict, model: type[M]) -> M: 95 96 return model.model_validate(data) 96 97 ``` 98 + 99 + the `[T]` declares the type parameter inline. `[M: BaseModel]` constrains it. this is real syntax, not a workaround. 97 100 98 101 ## ParamSpec 99 102
+20
languages/python/uv.md
··· 56 56 uv run --with git+https://github.com/prefecthq/prefect.git@branch#subdirectory=src/integrations/prefect-redis repro.py 57 57 ``` 58 58 59 + ## inline script metadata 60 + 61 + PEP 723 lets you embed dependencies directly in a script: 62 + 63 + ```python 64 + # /// script 65 + # dependencies = ["httpx", "rich"] 66 + # requires-python = ">=3.12" 67 + # /// 68 + 69 + import httpx 70 + from rich import print 71 + 72 + print(httpx.get("https://httpbin.org/get").json()) 73 + ``` 74 + 75 + run with `uv run script.py` - uv reads the metadata and creates an environment with those dependencies. no pyproject.toml, no requirements.txt, just a self-contained script. 76 + 77 + this is how you share reproducible examples. put the dependencies in the file itself, and anyone with uv can run it. 78 + 59 79 ## shareable one-liners 60 80 61 81 no file needed: