# research: beartype runtime type checking **date**: 2025-12-19 **question**: investigate beartype for runtime type checking, determine how to integrate into plyr.fm ## summary beartype is a runtime type checker that validates Python type hints at execution time with O(1) worst-case performance. it's already a transitive dependency via `py-key-value-aio`. FastMCP does **not** use beartype. integration would require adding `beartype_this_package()` to `backend/src/backend/__init__.py`. ## findings ### what beartype does - validates type hints at runtime when functions are called - O(1) non-amortized worst-case time (constant time regardless of data structure size) - zero runtime dependencies, pure Python - MIT license ### key integration patterns **package-wide (recommended)**: ```python # At the very top of backend/src/backend/__init__.py from beartype.claw import beartype_this_package beartype_this_package() # enables type-checking for all submodules ``` **per-function**: ```python from beartype import beartype @beartype def my_function(x: int) -> str: return str(x) ``` ### configuration options (`BeartypeConf`) key parameters: - `violation_type` - exception class to raise (default: `BeartypeCallHintViolation`) - `violation_param_type` - exception for parameter violations - `violation_return_type` - exception for return type violations - `strategy` - checking strategy (default: `O1` for O(1) time) - `is_debug` - enable debugging output - `claw_skip_package_names` - packages to exclude from type checking **example with warnings for third-party code**: ```python from beartype import BeartypeConf from beartype.claw import beartype_all, beartype_this_package beartype_this_package() # strict for our code beartype_all(conf=BeartypeConf(violation_type=UserWarning)) # warn for third-party ``` ### current state in plyr.fm beartype is already installed as a transitive dependency: - `backend/uv.lock:477-482` - beartype 0.22.8 present - pulled in by `py-key-value-aio` and `py-key-value-shared` ### FastMCP status FastMCP does **not** use beartype: - not in FastMCP's dependencies - FastMCP uses type hints for schema generation/documentation, not runtime validation ### integration approach for plyr.fm 1. **add explicit dependency** (optional but good for clarity): ```toml # pyproject.toml dependencies = [ "beartype>=0.22.0", # ... existing deps ] ``` 2. **enable in `__init__.py`**: ```python # backend/src/backend/__init__.py from beartype.claw import beartype_this_package beartype_this_package() def hello() -> str: return "Hello from backend!" ``` 3. **considerations**: - must be called before importing any submodules - main.py currently imports warnings before filtering, then imports submodules - beartype should be activated in `__init__.py`, not `main.py` ### potential concerns 1. **performance**: O(1) guarantees should be fine, but worth benchmarking 2. **third-party compatibility**: some libraries may have inaccurate type hints; use `claw_skip_package_names` or warn mode 3. **FastAPI**: pydantic already validates request/response types; beartype adds internal function validation ## code references - `backend/uv.lock:477-482` - beartype 0.22.8 in lockfile - `backend/uv.lock:2240` - py-key-value-aio depends on beartype - `backend/uv.lock:2261` - py-key-value-shared depends on beartype - `backend/src/backend/__init__.py:1-2` - current init (needs modification) - `backend/src/backend/main.py:1-50` - app initialization (imports after warnings filter) ## open questions - should we enable strict mode (exceptions) or warning mode initially? - which third-party packages might have problematic type hints to skip? - should we benchmark API response times before/after enabling?