Skip to content

Commit 6091dc5

Browse files
committed
Don't use anywidget command directly
1 parent a8d267a commit 6091dc5

File tree

4 files changed

+65
-16
lines changed

4 files changed

+65
-16
lines changed

lonboard/_layer.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
Union,
2222
)
2323

24-
import anywidget
2524
import ipywidgets
2625
import traitlets
2726
from arro3.core import Table
@@ -522,27 +521,28 @@ def _handle_anywidget_dispatch(
522521
) -> None:
523522
self.called += 1
524523
print(msg)
525-
if not isinstance(msg, dict) or msg.get("kind") != "anywidget-dispatch":
524+
525+
if not isinstance(msg, dict) or msg.get("kind") != "anywidget-command":
526526
return
527527

528528
print("test")
529529
print(msg)
530+
531+
response = "helloworld from init"
532+
buffers = [b"hello world"]
530533
self.send(
531534
{
532535
"id": msg["id"],
533-
"kind": "anywidget-dispatch-response",
534-
"response": "hello world",
535-
}
536+
"kind": "anywidget-command-response",
537+
"response": response,
538+
},
539+
buffers,
536540
)
537541

538542
print("before on msg")
539543
self.on_msg(_handle_anywidget_dispatch)
540544
super().__init__(**kwargs) # type: ignore
541545

542-
@anywidget.experimental.command
543-
def helloworld(self, msg, buffers):
544-
return "hello world", buffers
545-
546546
_layer_type = traitlets.Unicode("bitmap-tile").tag(sync=True)
547547

548548
data = traitlets.Union(

lonboard/_map.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
from pathlib import Path
66
from typing import IO, TYPE_CHECKING, Optional, Sequence, TextIO, Union, overload
77

8-
import anywidget
98
import ipywidgets
109
import traitlets
1110
from ipywidgets.embed import embed_minimal_html
@@ -97,10 +96,6 @@ def __init__(
9796

9897
super().__init__(layers=layers, **kwargs)
9998

100-
@anywidget.experimental.command
101-
def helloworld(self, msg, buffers):
102-
return "hello world from top-level map component", buffers
103-
10499
_esm = bundler_output_dir / "index.js"
105100
_css = bundler_output_dir / "index.css"
106101

src/model/invoke.ts

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// Invoke is vendored from anywidget because we want to ensure we're using the
2+
// widget messages on the **specific** widget layer, not the top-level Map
3+
// layer. E.g. when the JS BitmapTileLayer is requesting tiles, we want to make
4+
// sure that the same, specific BitmapTileLayer on the Python side is receiving
5+
// the requests.
6+
//
7+
// For now, it's simplest to vendor this code and implement our own responses on
8+
// the Python side.
9+
10+
import { AnyModel } from "@anywidget/types";
11+
import { v4 } from "uuid";
12+
13+
type InvokeOptions = {
14+
buffers?: DataView[];
15+
signal?: AbortSignal;
16+
};
17+
18+
export async function invoke<T>(
19+
model: AnyModel,
20+
name: string,
21+
msg: object,
22+
options: InvokeOptions = {},
23+
): Promise<[T, DataView[]]> {
24+
// crypto.randomUUID() is not available in non-secure contexts (i.e., http://)
25+
// so we use simple (non-secure) polyfill.
26+
const id = v4();
27+
const signal = options.signal ?? AbortSignal.timeout(3000);
28+
29+
return new Promise((resolve, reject) => {
30+
if (signal.aborted) {
31+
reject(signal.reason);
32+
}
33+
signal.addEventListener("abort", () => {
34+
model.off("msg:custom", handler);
35+
reject(signal.reason);
36+
});
37+
38+
function handler(
39+
msg: { id: string; kind: "anywidget-command-response"; response: T },
40+
buffers: DataView[],
41+
) {
42+
if (!(msg.id === id)) return;
43+
resolve([msg.response, buffers]);
44+
model.off("msg:custom", handler);
45+
}
46+
model.on("msg:custom", handler);
47+
model.send(
48+
{ id, kind: "anywidget-command", name, msg },
49+
undefined,
50+
options.buffers ?? [],
51+
);
52+
});
53+
}

src/model/layer.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import { TileLayer, TileLayerProps } from "@deck.gl/geo-layers";
2929
import { isDefined } from "../util.js";
3030
import { dispatch } from "../dispatch.js";
3131
import { Experimental } from "@anywidget/types";
32+
import { invoke } from "./invoke.js";
3233

3334
/**
3435
* An abstract base class for a layer that uses an Arrow Table as the data prop.
@@ -285,11 +286,11 @@ export class BitmapTileModel extends BaseLayerModel {
285286

286287
async getTileData(tile: TileLoadProps) {
287288
console.log("in getTileData");
288-
const { invoke } = this.anywidgetExperimental;
289+
// const { invoke } = this.anywidgetExperimental;
289290

290291
console.log(invoke);
291292
console.log("calling invoke");
292-
const out = await invoke("helloworld");
293+
const out = await invoke(this.model, "helloworld", {});
293294
console.log("returned from invoke");
294295
console.log(out);
295296

0 commit comments

Comments
 (0)