Bridge¶
The Python half of the native bridge: JSON
codec, per-platform transports, protocol handshake, main-queue posting,
and the single callback native uses to reach Python. App code never
calls this module directly; the
BridgeBackend,
BridgeModule, and
NativeScreenHost do.
The native bridge: one channel between Python and Swift / Kotlin.
Everything that crosses into native code goes through a
Transport (apply a transaction, run a
command, drive an animate request, or call a native module), and
everything native sends back arrives at
native_callback. The protocol
is documented in docs/concepts/bridge.md.
Under pn preview the native side is a browser page, reached through
WebTransport; the preview
installs it with set_transport
before any screen mounts. In headless tests there is no transport at
all: native modules fall back to their Python implementations, and
tests that want to exercise the bridge itself install a
FakeTransport.
Modules:
| Name | Description |
|---|---|
android |
Android transport: the |
codec |
JSON encoding for the native bridge. |
commits |
Versioned commit validation and surface ownership. |
fake |
An in-process stand-in for the native side of the bridge. |
ios |
iOS transport: C-ABI calls into |
list_store |
Revisioned list patch semantics shared by validation and headless renderers. |
web |
WebSocket transport for the browser renderer. |
Classes:
| Name | Description |
|---|---|
Transport |
The Python -> native half of the bridge. |
Functions:
| Name | Description |
|---|---|
get_transport |
Return the active transport, creating the platform one on first use. |
has_transport |
Whether a transport exists or can be created without raising. |
set_transport |
Install a transport explicitly (tests) or reset with |
handshake |
Verify the native library speaks our protocol version. |
native_callback |
Single entry point for every native -> Python message. |
Attributes:
| Name | Type | Description |
|---|---|---|
PROTOCOL_VERSION |
The bridge protocol every runtime speaks; generated native contracts carry it. |
PROTOCOL_VERSION
module-attribute
¶
The bridge protocol every runtime speaks; generated native contracts carry it.
Transport
¶
Bases: Protocol
The Python -> native half of the bridge.
Native and browser transports run Yoga beside their widgets. Only the
headless FakeTransport lays
out in Python, so it alone also answers measure and accepts frame
(f) operations.
Methods:
| Name | Description |
|---|---|
protocol_version |
Return the protocol version compiled into the native library. |
apply |
Apply one serialized transaction (a JSON array of ops). |
command |
Run an imperative command on one view; returns its JSON result or |
animate |
Handle an animation request ( |
call |
Call a native module method with a |
set_callback |
Install |
protocol_version
¶
protocol_version() -> int
Return the protocol version compiled into the native library.
command
¶
Run an imperative command on one view; returns its JSON result or None.
animate
¶
Handle an animation request (set / start / cancel) for one view.
call
¶
Call a native module method with a {"call_id", "args"} envelope.
get_transport
¶
get_transport() -> Transport
Return the active transport, creating the platform one on first use.
Raises:
| Type | Description |
|---|---|
RuntimeError
|
Off-device, where no native runtime exists. |
has_transport
¶
has_transport() -> bool
Whether a transport exists or can be created without raising.
set_transport
¶
Install a transport explicitly (tests) or reset with None.
handshake
¶
handshake() -> int
Verify the native library speaks our protocol version.
Called by the native templates right after Python starts. Returns the negotiated version.
Raises:
| Type | Description |
|---|---|
RuntimeError
|
On a version mismatch, with a hint to rebuild. |
native_callback
¶
Single entry point for every native -> Python message.
Native delivers every message asynchronously, from its events thread,
and never waits for a result. This function never raises: failures
are reported through diagnostics so nothing propagates into UIKit
or the Android looper.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
kind
|
str
|
|
required |
tag
|
int
|
View tag (events), screen id (host), otherwise |
required |
name
|
str
|
Event name, module name, or host event. |
required |
payload
|
str
|
JSON text whose shape depends on |
required |
Codec¶
JSON encoding for the native bridge.
The bridge speaks JSON in both directions (see docs/concepts/bridge.md).
Prop values coming out of the reconciler are almost, but not quite,
JSON: they may contain frozenset event-name sets, tuples, floats
that are infinite, and Python callables that native must never see.
to_jsonable normalizes a
value into something json.dumps accepts. Callbacks and declared
Python-only fields stay in the backend's sidecar; unsupported native
values raise an error.
Functions:
| Name | Description |
|---|---|
to_jsonable |
Return a JSON-serializable copy of |
split_props |
Split |
build_transaction |
Build the wire operations for a mutation batch, JSON-ready but not yet serialized. |
encode_transaction |
Encode a mutation batch as the bridge's transaction JSON. |
dumps |
Compact |
loads |
Parse a bridge payload ( |
Attributes:
| Name | Type | Description |
|---|---|---|
INF |
Wire spelling of |
|
NEG_INF |
Wire spelling of |
to_jsonable
¶
Return a JSON-serializable copy of value.
set/frozenset/tuplebecome lists (sets are sorted when their members are strings so the output is deterministic).- Infinite floats become the strings
"inf"/"-inf"; NaN becomesNone(native clamps missing geometry to zero). - Dataclass-like objects with
to_json()are converted through it.
Raises:
| Type | Description |
|---|---|
TypeError
|
When |
split_props
¶
split_props(
props: Dict[str, Any],
python_only: frozenset[str] = frozenset(),
) -> Tuple[Dict[str, Any], Dict[str, Any]]
Split props into (wire_props, python_props).
wire_props is JSON-ready; python_props holds callbacks and
fields explicitly declared Python-only. Other unsupported values
fail encoding. The backend keeps Python props in a per-tag sidecar.
(The reconciler has already published Animated.event bindings
under _pn_animated_events before props reach the codec.)
build_transaction
¶
build_transaction(
ops: Sequence[Mutation],
types: Mapping[int, str] | None = None,
) -> Tuple[List[Any], List[Tuple[int, Dict[str, Any]]]]
Build the wire operations for a mutation batch, JSON-ready but not yet serialized.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ops
|
Sequence[Mutation]
|
Ordered mutations from the reconciler. |
required |
types
|
Mapping[int, str] | None
|
Native component names for tags, used to identify Python-only props. |
None
|
Returns:
| Type | Description |
|---|---|
List[Any]
|
|
List[Tuple[int, Dict[str, Any]]]
|
transaction envelope carries under |
Tuple[List[Any], List[Tuple[int, Dict[str, Any]]]]
|
normalized by |
Tuple[List[Any], List[Tuple[int, Dict[str, Any]]]]
|
and |
Tuple[List[Any], List[Tuple[int, Dict[str, Any]]]]
|
stayed Python-side (for |
Tuple[List[Any], List[Tuple[int, Dict[str, Any]]]]
|
sidecar entries using |
Tuple[List[Any], List[Tuple[int, Dict[str, Any]]]]
|
operations. |
encode_transaction
¶
encode_transaction(
ops: Sequence[Mutation],
types: Mapping[int, str] | None = None,
) -> Tuple[str, List[Tuple[int, Dict[str, Any]]]]
Encode a mutation batch as the bridge's transaction JSON.
A convenience over build_transaction
for callers that want the serialized op list alone (tests and
tooling); the backend serializes the whole envelope itself.
Returns:
| Type | Description |
|---|---|
Tuple[str, List[Tuple[int, Dict[str, Any]]]]
|
|
Fake transport (tests)¶
An in-process stand-in for the native side of the bridge.
FakeTransport decodes the
same JSON the Swift and Kotlin runtimes receive and keeps a tiny view
tree so tests can assert on what would have reached native: created
types and props, insert order, frames, commands, animation requests,
and module calls. It also lets tests play the native side, firing
events and module results back through
native_callback.
Classes:
| Name | Description |
|---|---|
FakeNativeView |
One decoded native view: type, merged props, children, and frame. |
FakeTransport |
Decode bridge traffic into inspectable Python structures. |
ModuleHandler
module-attribute
¶
handler(method, args) -> value for a fake native module.
FakeNativeView
¶
One decoded native view: type, merged props, children, and frame.
FakeTransport
¶
FakeTransport(
*,
version: int = PROTOCOL_VERSION,
measure: Optional[Dict[str, Tuple[float, float]]] = None
)
Decode bridge traffic into inspectable Python structures.
Attributes:
| Name | Type | Description |
|---|---|---|
views |
Dict[int, FakeNativeView]
|
Live views by tag. |
transactions |
List[List[Any]]
|
Every decoded transaction (list of op lists). |
commands |
List[Tuple[int, str, Dict[str, Any]]]
|
|
animations |
List[Tuple[int, Dict[str, Any]]]
|
|
calls |
List[Tuple[str, str, Dict[str, Any]]]
|
|
Methods:
| Name | Description |
|---|---|
protocol_version |
Return the protocol version compiled into the native library. |
set_callback |
Install |
apply |
Validate a full revision before applying any native mutations. |
measure |
Return the intrinsic |
command |
Run an imperative command on one view; returns its JSON result or |
animate |
Handle an animation request ( |
call |
Call a native module method with a |
fire |
Emit a view event as native would. |
emit_module_event |
Push an unsolicited module event ( |
resolve_pending |
Settle a call that returned |
host_event |
Deliver a screen lifecycle event as the native host would. |
complete_animation |
Report a native animation as finished (or interrupted) to Python. |
find |
Every live view whose type is |
roots |
Views with no parent (the attached screen roots and detached subtrees). |
pending |
Sentinel a module handler returns to answer |
protocol_version
¶
protocol_version() -> int
Return the protocol version compiled into the native library.
set_callback
¶
Install callback as the native -> Python entry point.
apply
¶
Validate a full revision before applying any native mutations.
measure
¶
Return the intrinsic (width, height) of the view tag under the constraints.
command
¶
Run an imperative command on one view; returns its JSON result or None.
animate
¶
Handle an animation request (set / start / cancel) for one view.
call
¶
Call a native module method with a {"call_id", "args"} envelope.
emit_module_event
¶
Push an unsolicited module event (AppState change, ...) into Python.
resolve_pending
¶
Settle a call that returned pending.
host_event
¶
Deliver a screen lifecycle event as the native host would.
complete_animation
¶
Report a native animation as finished (or interrupted) to Python.
find
¶
find(type_name: str) -> List[FakeNativeView]
Every live view whose type is type_name, in creation order.
roots
¶
roots() -> List[FakeNativeView]
Views with no parent (the attached screen roots and detached subtrees).
Bootstrap¶
Entry point the native app templates run right after Python starts.
Both templates call start once the
interpreter is up, on a background thread at launch:
It connects the two halves of the bridge (installing the native -> Python
callback on iOS), verifies the protocol version, routes print() to the
console on iOS, warms the asyncio runtime, in debug builds starts the dev
client that syncs sources from pn start, and imports the entry module,
so the first screen only has to render. From then on the native runtime drives
everything through callback("host", ...); see docs/concepts/bridge.md.
Functions:
| Name | Description |
|---|---|
start |
Connect the bridge and prepare the runtime. |
status |
Return the result of the last |
start
¶
Connect the bridge and prepare the runtime.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dev
|
bool
|
Enable dev mode (RedBox, validation warnings, the dev
client). Debug templates pass |
False
|
strict
|
bool
|
Re-raise the failure after recording it. The templates
pass |
False
|
entry
|
Optional[str]
|
The app's entry module, imported last so a broken app fails here with its traceback, and so the first screen doesn't pay for the import. |
None
|
Returns:
| Type | Description |
|---|---|
Dict[str, Any]
|
A status dict ( |
Dict[str, Any]
|
template logs. Unless |
Dict[str, Any]
|
failures are printed and reported in the dict under |
Dict[str, Any]
|
|
Next steps¶
- Wire format and native contracts: The native bridge.
- Bundling native plugins: Configuration.