Skip to main content
The Python application SDK is the varianz package (install). Its test-side counterpart, varianz-pytest, is covered in Testing → pytest.

Runtime

The SDK activates only when enabled (VARIANZ_ENABLED=true); otherwise every API is a no-op and VPoints pass through.

Defining VPoints

  • The name= keyword argument is required in practice — always set it explicitly.
  • Decorating is not enough: the function, class, or instance must be registered. A decorated-but-unregistered method raises a clear error when called, to catch the common mistake.

Registration methods

For classes, register the instance to preserve constructor state (vz.register(PricingService(config))); registering the class auto-instantiates via cls(). Don’t pass unbound methods. vz.register(...) blocks until the registry confirms the schema (up to 5 seconds), then proceeds regardless — Varianz fails open if the registry is unreachable.

Schema resolution: annotate your types

With type annotations (recommended): the schema is built at decoration time, the VPD registers eagerly, and stages work from the first request. Statically mapped types: int, float, bool, str, None, list[T], dict[K, V], Optional[T], and @dataclass types. Proto messages resolve eagerly from their DESCRIPTOR. Without annotations (lazy fallback): the schema is built from the first call’s actual values, and registration happens then instead of at startup — tests trigger the VPoint once before inserting stages (details). Runtime-introspectable types include Pydantic models, attrs classes, and anything with __annotations__, __slots__, or vars(). Prefer annotations; where you can’t, wire varianz-scan into the build.

gRPC servicer methods

Python can instrument servicer methods directly — annotate the proto types and mark the gRPC context as opaque:
opaque=["context"] passes the ServicerContext through without exposing it to CEL. Proto field names, types, and nested messages come from the descriptor — no warmup needed. CEL overrides that construct proto structs (ChargeResponse { transaction_id: "test" }) are converted back to real proto messages automatically. Use the message’s simple name in CEL, not the package-qualified one. Set up the server interceptor once so sessions reach these handlers.

Session API

Propagation is interceptor-driven; these are the primitives interceptors use:
The session lives in a contextvar, so it follows asyncio tasks automatically.

Context functions

Context functions require type annotations on every parameter and the return — they are never lazily resolved. Functions with no profile are available to all VPoints; class-scoped functions are always available to that class’s VPoints.

Platform notes

Wheels only (no sdist): CPython 3.10–3.15 and PyPy 3.11 on macOS and Linux (glibc and musl). In Docker, install inside the Linux image — or run tests from the host against the containerized service, since only the registry connection matters.