Skip to content

Commit 2a46c32

Browse files
V2 webhook updates (#14)
- Bumped benchling-sdk to v1.13.0 for updated webhook models - Updated handler.py to use V2 webhooks ahead of V0 deprecation (docs.benchling.com/changelog/explicit-webhook-subscriptions-and-webhook-version-update)
1 parent 4ba13f9 commit 2a46c32

9 files changed

Lines changed: 20 additions & 16 deletions

File tree

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@
88
**/.client_secret
99
**/.pytest_cache
1010
.mypy_cache
11-
.ruff_cache
11+
.ruff_cache

examples/chem-sync-local-flask/local_app/benchling_app/canvas_interaction.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from benchling_sdk.apps.framework import App
77
from benchling_sdk.apps.status.errors import AppUserFacingError
88
from benchling_sdk.models import AppCanvasUpdate, Molecule
9-
from benchling_sdk.models.webhooks.v0 import CanvasInteractionWebhookV0
9+
from benchling_sdk.models.webhooks.v0 import CanvasInteractionWebhookV2
1010

1111
from local_app.benchling_app.molecules import create_molecule
1212
from local_app.benchling_app.views.canvas_initialize import input_blocks
@@ -29,7 +29,7 @@ class UnsupportedButtonError(Exception):
2929
pass
3030

3131

32-
def route_interaction_webhook(app: App, canvas_interaction: CanvasInteractionWebhookV0) -> None:
32+
def route_interaction_webhook(app: App, canvas_interaction: CanvasInteractionWebhookV2) -> None:
3333
canvas_id = canvas_interaction.canvas_id
3434
if canvas_interaction.button_id == SEARCH_BUTTON_ID:
3535
with app.create_session_context("Search Chemicals", timeout_seconds=20) as session:

examples/chem-sync-local-flask/local_app/benchling_app/handler.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33
from benchling_sdk.apps.status.errors import AppUserFacingError
44
from benchling_sdk.models.webhooks.v0 import (
5-
CanvasInitializeWebhookV0,
6-
CanvasInteractionWebhookV0,
5+
CanvasInitializeWebhookV2,
6+
CanvasInteractionWebhookV2,
77
WebhookEnvelopeV0,
88
)
99

@@ -27,9 +27,9 @@ def handle_webhook(webhook_dict: dict[str, Any]) -> None:
2727
# Note: if your manifest specifies more than one item in `features`,
2828
# then `webhook.message.feature_id` may also need to be part of your routing logic
2929
try:
30-
if isinstance(webhook.message, CanvasInitializeWebhookV0):
30+
if isinstance(webhook.message, CanvasInitializeWebhookV2):
3131
render_search_canvas(app, webhook.message)
32-
elif isinstance(webhook.message, CanvasInteractionWebhookV0):
32+
elif isinstance(webhook.message, CanvasInteractionWebhookV2):
3333
route_interaction_webhook(app, webhook.message)
3434
else:
3535
# Should only happen if the app's manifest requests webhooks that aren't handled in its code paths

examples/chem-sync-local-flask/local_app/benchling_app/views/canvas_initialize.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@
99
TextInputUiBlock,
1010
TextInputUiBlockType,
1111
)
12-
from benchling_sdk.models.webhooks.v0 import CanvasInitializeWebhookV0
12+
from benchling_sdk.models.webhooks.v0 import CanvasInitializeWebhookV2
1313

1414
from local_app.benchling_app.views.constants import SEARCH_BUTTON_ID, SEARCH_TEXT_ID
1515

1616

17-
def render_search_canvas(app: App, canvas_initialized: CanvasInitializeWebhookV0) -> None:
17+
def render_search_canvas(app: App, canvas_initialized: CanvasInitializeWebhookV2) -> None:
1818
with app.create_session_context("Show Sync Search", timeout_seconds=20):
1919
canvas_builder = CanvasBuilder(
2020
app_id=app.id,

examples/chem-sync-local-flask/manifest.yaml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@ features:
77
- name: Sync Step
88
id: sync_step
99
type: ASSAY_RUN
10-
10+
subscriptions:
11+
deliveryMethod: WEBHOOK
12+
messages:
13+
- type: v2.canvas.initialized
14+
- type: v2.canvas.userInteracted
1115
configuration:
1216
- name: Sync Folder
1317
type: folder
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
flask~=3.0.2
22
# Cryptography extra needed for webhook verification
3-
benchling-sdk[cryptography]==1.12.0
3+
benchling-sdk[cryptography]==1.13.0

examples/chem-sync-local-flask/tests/files/webhooks/canvas_initialize_webhook.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
"message": {
1414
"featureId": "feat_1234",
1515
"resourceId": "assayrun_1234",
16-
"type": "v0.canvas.initialized",
16+
"type": "v2.canvas.initialized",
1717
"deprecated": false,
1818
"excludedProperties": []
1919
}

examples/chem-sync-local-flask/tests/files/webhooks/canvas_interaction_webhook.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
},
1212
"channel": "app_signals",
1313
"message": {
14-
"type": "v0.canvas.userInteracted",
14+
"type": "v2.canvas.userInteracted",
1515
"buttonId": "button_1",
1616
"canvasId": "cnvs_1234",
1717
"deprecated": false,

examples/chem-sync-local-flask/tests/unit/local_app/benchling_app/test_canvas_interaction.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from benchling_sdk.apps.status.framework import SessionContextManager
1212
from benchling_sdk.apps.types import JsonType
1313
from benchling_sdk.models import AppCanvas, AppCanvasUpdate, Molecule, TextInputUiBlock
14-
from benchling_sdk.models.webhooks.v0 import CanvasInteractionWebhookV0
14+
from benchling_sdk.models.webhooks.v0 import CanvasInteractionWebhookV2
1515

1616
from local_app.benchling_app.canvas_interaction import UnsupportedButtonError, route_interaction_webhook
1717
from local_app.benchling_app.views.canvas_initialize import input_blocks
@@ -191,8 +191,8 @@ def _mock_canvas(blocks: list[UiBlock] | None = None, data: JsonType | None = No
191191
return mock_canvas
192192

193193

194-
def _mock_interaction_webhook(canvas_id: str, button_id: str) -> CanvasInteractionWebhookV0:
195-
interaction_webhook = MagicMock(CanvasInteractionWebhookV0)
194+
def _mock_interaction_webhook(canvas_id: str, button_id: str) -> CanvasInteractionWebhookV2:
195+
interaction_webhook = MagicMock(CanvasInteractionWebhookV2)
196196
interaction_webhook.button_id = button_id
197197
interaction_webhook.canvas_id = canvas_id
198198
return interaction_webhook

0 commit comments

Comments
 (0)