npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@signicode/verser2-guest-python

v0.4.5

Published

Python ASGI Guest package for Verser2.

Readme

@signicode/verser2-guest-python

Python package for verser2 providing Guest and Broker implementations.

This package connects outbound to an existing verser2 Host over TLS HTTP/2. It is recognized by the repository's npm workspace tooling through package.json and by Python packaging tooling through pyproject.toml.

Public API

  • VERSER2_GUEST_PYTHON_PACKAGE_NAME
  • VerserGuest / create_verser_guest — Python ASGI Guest
  • VerserBroker / create_verser_broker — Python Broker
  • VerserBrokerResponse — Broker response type

Commands

npm run build --workspace=@signicode/verser2-guest-python
npm run test --workspace=@signicode/verser2-guest-python
npm run lint --workspace=@signicode/verser2-guest-python

The package commands use uv run --project . so Python dependencies such as h2 are resolved in an isolated project environment.

Python Guest usage

The Guest serves an ASGI 3 app without opening an inbound listening port.

import asyncio
from verser2_guest_python import create_verser_guest


async def app(scope, receive, send):
    assert scope["type"] == "http"
    body = b""
    while True:
        event = await receive()
        body += event.get("body", b"")
        if not event.get("more_body", False):
            break
    await send({"type": "http.response.start", "status": 200, "headers": []})
    await send({"type": "http.response.body", "body": body})


async def main():
    guest = create_verser_guest(
        host_url="https://localhost:8443",
        guest_id="python-guest-a",
        app=app,
        routed_domains=["python-guest-a.local.test"],
        tls_ca_file="/etc/verser/ca.crt",
        # For mTLS Hosts, present a client identity as PEM:
        # tls_cert_file="/etc/verser/client.crt",
        # tls_key_file="/etc/verser/client.key",
        # Or as PFX/PKCS12:
        # tls_pfx_file="/etc/verser/client.p12",
        # tls_pfx_password="...",
    )
    await guest.connect()
    await asyncio.Event().wait()


asyncio.run(main())

Domain note: Unlike Node and Bun Guests, the Python Guest does not default the route domain to the Guest ID. You must provide routed_domains explicitly.

FastAPI-compatible apps

FastAPI and Starlette applications work because the Guest calls the standard ASGI 3 interface. FastAPI is not a core runtime dependency.

from fastapi import FastAPI
from verser2_guest_python import create_verser_guest

app = FastAPI()


@app.get("/health")
async def health():
    return {"ok": True}


guest = create_verser_guest(
    host_url="https://localhost:8443",
    guest_id="fastapi-guest",
    app=app,
    routed_domains=["fastapi-guest.local.test"],
    tls_ca_file="/etc/verser/ca.crt",
)

Python Broker usage

The Python Broker connects outbound, registers as broker, and sends requests to advertised Guest routes.

import asyncio
from verser2_guest_python import create_verser_broker


async def main():
    broker = create_verser_broker(
        host_url="https://localhost:8443",
        broker_id="broker-a",
        tls_ca_file="/etc/verser/ca.crt",
    )
    await broker.connect()
    await broker.wait_for_route("python-guest-a.local.test")

    response = await broker.get("http://python-guest-a.local.test/health")
    print(await response.text())


asyncio.run(main())

The Broker supports request, get, post, put, patch, and delete helpers. VerserBrokerResponse exposes status, headers, request_id, read(), text(), json(), and aiter_bytes(chunk_size=8192). Response bodies are one-shot.

TLS for Python Broker

broker = create_verser_broker(
    host_url="https://localhost:8443",
    broker_id="broker-a",
    tls_ca_file="/etc/verser/ca.crt",
    tls_cert_file="/etc/verser/client.crt",
    tls_key_file="/etc/verser/client.key",
    # PFX/PKCS12 also supported:
    # tls_pfx_file="/etc/verser/client.p12",
    # tls_pfx_password="...",
)

Python Guests support the same tls_ca_file, PEM client identity, and PFX/PKCS12 client identity options. PFX/PKCS12 support uses the package's cryptography dependency.

Streaming behavior

  • Guest: routed request body chunks from the Host/Broker lease stream are delivered as ASGI http.request events with more_body continuation flags.
  • Guest: ASGI http.response.start is converted to the Verser response envelope before response bytes are written.
  • Guest: ASGI http.response.body events are written back to the Host lease stream; more_body: false ends the response side of the lease.
  • Direct dispatch_routed_request(...) calls are batch-only — they buffer the ASGI response and enforce max_response_bytes before joining chunks. Use leased Host/Broker routing for streaming.
  • Guest app exceptions before response start are returned as Verser local-handler-failure error envelopes with Guest, request, and path context.
  • Broker response bodies are one-shot; read(), text(), and json() consume the body.

Avoid non-terminating async streams

Verser Python transports use async read loops and async body iteration. Any custom async stream, test double, or request-body async iterable must eventually signal completion:

  • asyncio stream readers should return b"" for EOF.
  • Async request-body iterables should stop iteration when the body is complete.
  • Test mocks should not leave reader.read() as a bare AsyncMock, because each awaited call can produce another truthy mock object forever.

Use an explicit EOF:

reader = AsyncMock()
reader.read = AsyncMock(return_value=b"")

or a finite sequence:

reader.read = AsyncMock(side_effect=[b"first-frame", b""])

Known limits

  • The first implementation focuses on Python Guest and Broker behavior.
  • Python Host, Python-side fetch helper APIs, and Python-side Agent/Dispatcher are not implemented.
  • HTTP/3, complete application authentication, public gateway policy, per-request Broker target authorization, WebSockets, upgrades, trailers, and advanced ASGI lifespan behavior are not implemented.
  • The transport is intentionally minimal: one outbound TLS HTTP/2 session with a replenished pool of one-use Guest lease streams.

Links