fix(webhook): handle raw dict input in mode='before' validator (#282)#3
fix(webhook): handle raw dict input in mode='before' validator (#282)#3z23 wants to merge 1 commit into
Conversation
…attlove#282) `Webhook.validate_webhook` is decorated with `@model_validator(mode="before")`, which means it runs prior to model construction and receives the raw input dict from `Webhook(**query)`. The implementation accessed it as if it were a model instance — `model.source` and `model.network = {}` — which raised `AttributeError: 'dict' object has no attribute 'source'` and silently broke all HTTP webhook delivery (Slack, MS Teams, generic). Treat the input as a dict, guard with isinstance, and use `.get()` so an absent `source` key doesn't raise either. Source defaults to `"Unknown"` on the model anyway, so a missing key correctly falls through to the model default. Refs: thatmattlove#282 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Fixes webhook delivery failures caused by a @model_validator(mode="before") assuming it receives a constructed Webhook instance instead of the raw input mapping, which prevented Slack/MS Teams/generic webhook payloads from being built and sent.
Changes:
- Update
Webhook.validate_webhookto safely handle raw-dict input in amode="before"validator and resetnetworkfor localhost sources. - Add regression tests covering validator behavior and Slack/MS Teams payload rendering.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
hyperglass/models/webhook.py |
Corrects the mode="before" validator to operate on raw input data and avoid AttributeError during webhook construction. |
hyperglass/models/tests/test_webhook.py |
Adds regression tests to ensure webhook model construction and payload rendering work for common providers. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if model.source in ("127.0.0.1", "::1"): | ||
| model.network = {} | ||
| return model | ||
| @classmethod |
There was a problem hiding this comment.
@model_validator methods elsewhere in this codebase are defined as plain methods (no @classmethod). Adding @classmethod here is inconsistent and can be brittle depending on how Pydantic wraps validators; consider dropping @classmethod and keeping the same (cls, data) signature so it matches the established pattern (e.g., DnsOverHttps.validate_dns, FRRPath.validate_path).
| @classmethod |
Summary
Fixes upstream issue thatmattlove/hyperglass#282: all HTTP webhook delivery (Slack, MS Teams, generic) silently fails with:
Webhook.validate_webhookis decorated with@model_validator(mode='before'), which runs prior to model construction and receives the raw input passed to `Webhook(**query)` — a dict. The current code treats it as an instance:```python
@model_validator(mode="before")
def validate_webhook(cls, model: "Webhook") -> "Webhook":
if model.source in ("127.0.0.1", "::1"): # AttributeError on dict
model.network = {}
return model
```
Both lines raise on a dict, so the validator always fails and the webhook is never sent.
Fix
Treat the input as a dict, guard with `isinstance`, and use `.get()` so a missing `source` key falls through to the model's default rather than raising:
```python
@model_validator(mode="before")
@classmethod
def validate_webhook(cls, data: t.Any) -> t.Any:
if isinstance(data, dict) and data.get("source") in ("127.0.0.1", "::1"):
data["network"] = {}
return data
```
Test plan
🤖 Generated with Claude Code