|
| 1 | +# CLAUDE.md |
| 2 | + |
| 3 | +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. |
| 4 | + |
| 5 | +## Project overview |
| 6 | + |
| 7 | +django-modern-rpc is a Python/Django library that provides an embedded XML-RPC and JSON-RPC 2.0 server. It lets developers expose Python functions as RPC endpoints within a Django project. Key capabilities: pluggable serialization backends (orjson, rapidjson, lxml, etc.), authentication via predicates, async support, batch requests (JSON-RPC), and built-in introspection (system.listMethods, system.methodHelp, etc.). |
| 8 | + |
| 9 | +## Common commands |
| 10 | + |
| 11 | +### Setup |
| 12 | +```bash |
| 13 | +uv sync # Install runtime + dev + tests dependencies |
| 14 | +``` |
| 15 | + |
| 16 | +### Tests |
| 17 | +```bash |
| 18 | +uv run pytest -n auto # Full test suite (parallelized) |
| 19 | +uv run pytest -n auto -k "jsonrpc" # Filter by keyword |
| 20 | +uv run pytest tests/test_e2e.py::TestXmlRpc::test_xml_rpc_standard_call # Single test |
| 21 | +uv run pytest -n auto --cov --cov-report=term-missing # With coverage |
| 22 | +``` |
| 23 | + |
| 24 | +### Matrix testing (Python × Django combinations via nox) |
| 25 | +```bash |
| 26 | +uvx nox -l # List available sessions |
| 27 | +uvx nox -s tests -t py312 -t dj52 # Specific Python/Django combo |
| 28 | +uvx nox -s tests:coverage -- term-missing # Coverage report |
| 29 | +``` |
| 30 | + |
| 31 | +### Linting and formatting |
| 32 | +```bash |
| 33 | +uv run ruff check . # Lint |
| 34 | +uv run ruff check . --fix # Lint with auto-fix |
| 35 | +uv run ruff format . # Format |
| 36 | +uv run ruff format . --check # Check formatting |
| 37 | +``` |
| 38 | + |
| 39 | +### Type checking |
| 40 | +```bash |
| 41 | +uvx nox -s mypy # mypy (excludes tests/ and docs/) |
| 42 | +uvx nox -s ty # ty (faster alternative) |
| 43 | +``` |
| 44 | + |
| 45 | +### Benchmarks |
| 46 | +```bash |
| 47 | +uv run pytest tests/benchmarks --benchmark-enable # Current venv |
| 48 | +uvx nox -s benchmarks # All Python versions |
| 49 | +``` |
| 50 | +Note: benchmarks must not use `-n auto` (no xdist parallelization). |
| 51 | + |
| 52 | +### Documentation |
| 53 | +```bash |
| 54 | +uvx nox -s docs:build # Build to dist/docs |
| 55 | +uvx nox -s docs:serve # Live-reload at localhost:8001 |
| 56 | +``` |
| 57 | + |
| 58 | +## Architecture |
| 59 | + |
| 60 | +### Core flow |
| 61 | + |
| 62 | +``` |
| 63 | +Django URL route → RpcServer → RpcHandler (JSON-RPC or XML-RPC) → ProcedureWrapper → user function |
| 64 | +``` |
| 65 | + |
| 66 | +1. **RpcServer** (`modernrpc/server.py`) — Central orchestrator. Maintains a procedure registry, validates HTTP requests, selects the appropriate handler based on Content-Type, and exposes `.view` (sync) and `.async_view` (async) properties for Django URL routing. |
| 67 | + |
| 68 | +2. **RegistryMixin** / **RpcNamespace** (`modernrpc/server.py`) — Shared registration logic. `RpcNamespace` groups related procedures under a dotted prefix (e.g., `math.add`). Both `RpcServer` and `RpcNamespace` inherit from `RegistryMixin`. |
| 69 | + |
| 70 | +3. **RpcHandler** (`modernrpc/handler.py`) — Abstract base class for protocol handlers. Defines `can_handle()`, `process_request()` / `aprocess_request()`, and response builders. |
| 71 | + - **JsonRpcHandler** (`modernrpc/jsonrpc/handler.py`) — JSON-RPC 2.0: named params, batch requests, notifications. |
| 72 | + - **XmlRpcHandler** (`modernrpc/xmlrpc/handler.py`) — XML-RPC: single calls, system multicall. |
| 73 | + |
| 74 | +4. **ProcedureWrapper** (`modernrpc/core.py`) — Wraps a callable/coroutine for RPC execution. Stores auth predicates, protocol restriction, and an optional `context_target` argument name for injecting `RpcRequestContext`. |
| 75 | + |
| 76 | +5. **Backend system** — Pluggable serialization/deserialization per protocol: |
| 77 | + - JSON: `modernrpc/jsonrpc/backends/` (json, orjson, rapidjson, simplejson) |
| 78 | + - XML: `modernrpc/xmlrpc/backends/` (xmlrpc, lxml, etree, xmltodict) |
| 79 | + - Selected via `MODERNRPC_*_SERIALIZER` / `MODERNRPC_*_DESERIALIZER` Django settings. |
| 80 | + |
| 81 | +6. **System procedures** (`modernrpc/system_procedures.py`) — Auto-registered under `system.*` namespace: `listMethods`, `methodSignature`, `methodHelp`, `multicall`. |
| 82 | + |
| 83 | +### Exception hierarchy (`modernrpc/exceptions.py`) |
| 84 | + |
| 85 | +`RPCException` (base) → `RPCParseError` (-32700), `RPCInvalidRequest` (-32600), `RPCMethodNotFound` (-32601), `RPCInvalidParams` (-32602), `RPCInternalError` (-32603), `AuthenticationError`, etc. |
| 86 | + |
| 87 | +### Test infrastructure |
| 88 | + |
| 89 | +- Django test project: `tests/project/` (settings, urls, rpc procedures) |
| 90 | + - `/rpc` → sync view, `/async_rpc` → async view |
| 91 | + - Procedures defined in `tests/project/rpc.py` |
| 92 | +- Fixtures in `tests/conftest.py`: `all_*_serializers` / `all_*_deserializers` parametrize backends; `xmlrpc_rf`, `jsonrpc_rf`, `jsonrpc_batch_rf` build POST requests with correct payloads. |
| 93 | +- pytest-asyncio in auto mode (session-scoped loop). Async tests use the `/async_rpc` endpoint. |
| 94 | +- Parallelization on by default (`-n auto`). Tests that aren't parallel-safe should use `-n 0`. |
| 95 | + |
| 96 | +## Code style |
| 97 | + |
| 98 | +- Line length: 120 characters |
| 99 | +- Formatter/linter: ruff (extensive rule set, see `pyproject.toml [tool.ruff.lint]`) |
| 100 | +- Bandit (S) rules disabled in `tests/` |
| 101 | +- Double quotes, LF line endings |
0 commit comments