Skip to main content

Python implementation of the Cap'n Web protocol

Project description

Cap'n Web Python Implementation

Python implementation of the Cap'n Web protocol, delivering both server and client with support for HTTP batch and WebSocket transports.

Status: v0.3.1-dev

โœ… Production-ready with comprehensive test coverage

  • 329 tests passing, 85% coverage
  • Fully interoperable with TypeScript reference implementation
  • Hook-based architecture (legacy code removed)
  • ~98% protocol compliance

Documentation

What's New in v0.3.1

  • ๐Ÿ—๏ธ Architecture Complete: Removed all legacy code (evaluator.py, tables.py)
  • ๐Ÿ“ˆ Test Coverage: 67% โ†’ 85% coverage (+172 tests, 329 total)
  • โœจ 8 Modules at 100% Coverage: payload, serializer, stubs, error, ids, types, init
  • ๐Ÿ“š Comprehensive Documentation: Quickstart guide, architecture guide, API reference
  • ๐Ÿ”ง Code Quality: All linting and type checks passing

What's New in v0.3.0

  • ๐ŸŽ‰ Full TypeScript Interoperability: 100% compatibility with TypeScript reference
  • ๐Ÿ”„ Promise Pipelining: Batch multiple dependent calls into one round-trip
  • ๐Ÿ“Š Interop Test Suite: Automated testing across all implementation combinations

Features

  • Capability-based security: Unforgeable object references with explicit disposal
  • Promise pipelining: Batch multiple dependent RPC calls into single round trips
  • Expression evaluation: Full support for wire expressions including remap (.map() operations)
  • Multiple transports: HTTP batch and WebSocket with pluggable transport abstraction
  • Type-safe: Full type hints with pyright/mypy compatibility
  • Async/await: Built on Python's asyncio
  • Error handling: Structured error model with security-conscious stack trace redaction
  • Reference counting: Automatic resource management with proper refcounting
  • Resume tokens: Session restoration for stateful connections
  • Bidirectional RPC: Peer-to-peer capability passing
  • 100% Interoperable: Fully compatible with TypeScript reference implementation

Installation

pip install capnweb
# or
uv add capnweb

or, from this repository:

uv sync

Quick Start

Server

import asyncio
from typing import Any
from capnweb.server import Server, ServerConfig
from capnweb.types import RpcTarget
from capnweb.error import RpcError

class Calculator(RpcTarget):
    async def call(self, method: str, args: list[Any]) -> Any:
        match method:
            case "add":
                return args[0] + args[1]
            case "subtract":
                return args[0] - args[1]
            case _:
                raise RpcError.not_found(f"Method {method} not found")

    async def get_property(self, property: str) -> Any:
        raise RpcError.not_found("Property access not implemented")

async def main() -> None:
    config = ServerConfig(host="127.0.0.1", port=8080)
    server = Server(config)

    # Register the main capability
    server.register_capability(0, Calculator())

    await server.start()
    print("Calculator server listening on http://127.0.0.1:8080/rpc/batch")

    # Keep running
    try:
        await asyncio.Event().wait()
    except KeyboardInterrupt:
        await server.stop()

if __name__ == "__main__":
    asyncio.run(main())

Client

import asyncio
from capnweb.client import Client, ClientConfig

async def main() -> None:
    config = ClientConfig(url="http://localhost:8080/rpc/batch")

    # Use async context manager for automatic cleanup
    async with Client(config) as client:
        # Make RPC calls
        result = await client.call(0, "add", [5, 3])
        print(f"5 + 3 = {result}")  # Output: 5 + 3 = 8

        result = await client.call(0, "subtract", [10, 4])
        print(f"10 - 4 = {result}")  # Output: 10 - 4 = 6

if __name__ == "__main__":
    asyncio.run(main())

Promise Pipelining

Batch multiple dependent calls into a single round trip:

import asyncio
from capnweb.client import Client, ClientConfig

async def main() -> None:
    config = ClientConfig(url="http://localhost:8080/rpc/batch")

    async with Client(config) as client:
        # Create a pipeline batch
        batch = client.pipeline()

        # Make dependent calls - they will be batched
        user = batch.call(0, "authenticate", ["token-123"])
        profile = batch.call(0, "getUserProfile", [user.id])  # Property access on promise!
        notifications = batch.call(0, "getNotifications", [user.id])

        # All three calls execute efficiently
        u, p, n = await asyncio.gather(user, profile, notifications)

        print(f"User: {u['name']}")
        print(f"Profile: {p['bio']}")
        print(f"Notifications: {len(n)} unread")

if __name__ == "__main__":
    asyncio.run(main())

Development

Setup

# Clone and install with uv
git clone https://github.com/abilian/py-capnweb.git
cd py-capnweb
uv sync

Testing

make test
# or
pytest
pytest tests/test_wire.py -v
# etc.

Linting & Type Checking

# Run linter
ruff check

# Run type checker
pyrefly check src

# Run both
make check

Project Structure

src/capnweb/
โ”œโ”€โ”€ __init__.py         # Public API exports
โ”œโ”€โ”€ ids.py              # ID types (ImportId, ExportId, IdAllocator)
โ”œโ”€โ”€ error.py            # Error types (RpcError, ErrorCode)
โ”œโ”€โ”€ wire.py             # Wire protocol messages and expressions
โ”œโ”€โ”€ tables.py           # Import/Export tables with refcounting
โ”œโ”€โ”€ types.py            # Core types (RpcTarget, Transport protocol)
โ”œโ”€โ”€ evaluator.py        # Expression evaluator with remap support
โ”œโ”€โ”€ transports.py       # Transport implementations (HTTP, WebSocket)
โ”œโ”€โ”€ server.py           # Server with configurable security
โ”œโ”€โ”€ client.py           # Client with automatic resource management
โ””โ”€โ”€ __main__.py         # CLI entry point (if applicable)

tests/
โ”œโ”€โ”€ test_ids.py                 # ID allocation tests
โ”œโ”€โ”€ test_wire.py                # Wire protocol tests
โ”œโ”€โ”€ test_wire_protocol.py       # Advanced protocol features
โ”œโ”€โ”€ test_tables.py              # Import/export table tests
โ”œโ”€โ”€ test_error.py               # Error handling tests
โ”œโ”€โ”€ test_evaluator.py           # Expression evaluation tests
โ”œโ”€โ”€ test_remap_evaluation.py    # Remap (.map) tests
โ”œโ”€โ”€ test_transports.py          # Transport abstraction tests
โ”œโ”€โ”€ test_improvements.py        # Recent enhancements tests
โ”œโ”€โ”€ test_integration.py         # End-to-end integration tests
โ””โ”€โ”€ test_bidirectional.py       # Peer-to-peer tests

examples/
โ”œโ”€โ”€ calculator/          # Simple RPC calculator
โ”œโ”€โ”€ batch-pipelining/    # Batching demonstration
โ””โ”€โ”€ peer_to_peer/        # Bidirectional RPC example

Protocol Compliance

This implementation follows the official Cap'n Web protocol specification and supports:

โœ… Implemented Features

  • Wire Protocol: All core message types (push, pull, resolve, reject, release, abort)
  • Wire Expressions: Error, import, export, promise, pipeline, date, remap
  • Array Escaping: Proper [[...]] literal array escaping compatible with TypeScript implementation
  • Export ID Convention: Positive export IDs matching TypeScript reference implementation
  • Release with refcount: Proper reference counting for resource management
  • Remap expressions: Full .map() operation support with captures and instructions
  • Transport abstraction: HTTP batch and WebSocket transports
  • Security: Configurable stack trace redaction
  • Error handling: Structured error model with custom error data

๐Ÿšง Planned Features

  • WebTransport support: H3-based transport for modern applications
  • IL plan execution: Complex multi-step operations
  • Recorder macros: Ergonomic client-side API generation

Interoperability Testing

Comprehensive cross-implementation testing with the TypeScript reference implementation:

cd interop
bash run_tests.sh

Test Matrix (all passing โœ…):

  • Python Server โ† Python Client
  • Python Server โ† TypeScript Client
  • TypeScript Server โ† Python Client
  • TypeScript Server โ† TypeScript Client

The interop test suite validates:

  • Basic RPC operations (echo, arithmetic, string manipulation)
  • Complex data types (arrays, objects)
  • Error handling (not_found, bad_request)
  • Concurrent batch calls
  • Property access patterns

License

Dual-licensed under MIT or Apache-2.0, at your option.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

py_capnweb-0.3.1.tar.gz (36.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

py_capnweb-0.3.1-py3-none-any.whl (45.2 kB view details)

Uploaded Python 3

File details

Details for the file py_capnweb-0.3.1.tar.gz.

File metadata

  • Download URL: py_capnweb-0.3.1.tar.gz
  • Upload date:
  • Size: 36.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.0rc1

File hashes

Hashes for py_capnweb-0.3.1.tar.gz
Algorithm Hash digest
SHA256 175541a657466c570ef71d4fa22b508e2b6755a7a88103761e1908835d609691
MD5 754fc6a14623634513508e87435c0719
BLAKE2b-256 36d849335b7252725ce15421ff11f58ede3833134f5ea55520af785e882b2298

See more details on using hashes here.

File details

Details for the file py_capnweb-0.3.1-py3-none-any.whl.

File metadata

  • Download URL: py_capnweb-0.3.1-py3-none-any.whl
  • Upload date:
  • Size: 45.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.0rc1

File hashes

Hashes for py_capnweb-0.3.1-py3-none-any.whl
Algorithm Hash digest
SHA256 e1b9669f5cba9db3e43e350d854a7fb423181ce46fe26eaf46a1f521fd0993cd
MD5 047270e878181f0d693d3712c87c09b7
BLAKE2b-256 60895b9fc650bf5939982ef4c0180299ca9e2b6dae47d7be424d917bba00210a

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page