varianz package (install). Its test-side counterpart, varianz-pytest, is covered in Testing → pytest.
Runtime
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:contextvar, so it follows asyncio tasks automatically.
