feat(signals): Signals list API changes for Code inbox#51740
feat(signals): Signals list API changes for Code inbox#51740
Conversation
|
Size Change: 0 B Total Size: 110 MB ℹ️ View Unchanged
|
Prompt To Fix All With AIThis is a comment left during a code review.
Path: products/signals/backend/serializers.py
Line: 147-152
Comment:
**`AttributeError` on valid-JSON non-dict content**
`data.get("priority")` is called *outside* the `try/except` block. If `art.content` is valid JSON but not a dict (e.g. `'null'`, `'[]'`, or `'"some string"'`) then `json.loads()` succeeds, the except is not triggered, and `data.get(...)` raises `AttributeError` — resulting in a 500 for the list/retrieve endpoint.
```suggestion
try:
data = json.loads(art.content)
except (json.JSONDecodeError, TypeError, ValueError):
return None
if not isinstance(data, dict):
return None
p = data.get("priority")
return p if isinstance(p, str) else None
```
How can I resolve this? If you propose a fix, please make it concise.
---
This is a comment left during a code review.
Path: products/signals/backend/test/test_signal_report_api.py
Line: 150-176
Comment:
**Prefer parameterised tests; missing non-dict JSON case**
Per the project convention, these three standalone "priority is null" tests (`invalid_json`, `non_string_priority`, and the no-artefact test above) are good candidates for a single `@parameterized.expand`. A parameterised approach also makes it easy to add the currently-untested case of *valid* JSON that isn't a dict (e.g. `content='null'`), which would expose the `AttributeError` described in the sibling comment.
Example sketch (artefact-content cases only):
```python
@parameterized.expand(
[
("invalid_json", "not-json{"),
("json_null", "null"),
("json_array", "[]"),
("non_string_priority", json.dumps({"priority": 2})),
("missing_priority_key", json.dumps({"choice": "immediately_actionable"})),
]
)
def test_list_priority_null_for_bad_content(self, _name, content):
report = self._create_report()
SignalReportArtefact.objects.create(
team=self.team,
report=report,
type=SignalReportArtefact.ArtefactType.ACTIONABILITY_JUDGMENT,
content=content,
)
response = self.client.get(self._list_url())
assert response.status_code == status.HTTP_200_OK
row = next(r for r in response.json()["results"] if r["id"] == str(report.id))
assert row["priority"] is None
```
How can I resolve this? If you propose a fix, please make it concise.Last reviewed commit: "test(signals): add A..." |
| def test_list_priority_null_when_artefact_json_invalid(self): | ||
| report = self._create_report() | ||
| SignalReportArtefact.objects.create( | ||
| team=self.team, | ||
| report=report, | ||
| type=SignalReportArtefact.ArtefactType.ACTIONABILITY_JUDGMENT, | ||
| content="not-json{", | ||
| ) | ||
|
|
||
| response = self.client.get(self._list_url()) | ||
| assert response.status_code == status.HTTP_200_OK | ||
| row = next(r for r in response.json()["results"] if r["id"] == str(report.id)) | ||
| assert row["priority"] is None | ||
|
|
||
| def test_list_priority_null_when_priority_not_a_string(self): | ||
| report = self._create_report() | ||
| SignalReportArtefact.objects.create( | ||
| team=self.team, | ||
| report=report, | ||
| type=SignalReportArtefact.ArtefactType.ACTIONABILITY_JUDGMENT, | ||
| content=json.dumps({"priority": 2}), | ||
| ) | ||
|
|
||
| response = self.client.get(self._list_url()) | ||
| assert response.status_code == status.HTTP_200_OK | ||
| row = next(r for r in response.json()["results"] if r["id"] == str(report.id)) | ||
| assert row["priority"] is None |
There was a problem hiding this comment.
Prefer parameterised tests; missing non-dict JSON case
Per the project convention, these three standalone "priority is null" tests (invalid_json, non_string_priority, and the no-artefact test above) are good candidates for a single @parameterized.expand. A parameterised approach also makes it easy to add the currently-untested case of valid JSON that isn't a dict (e.g. content='null'), which would expose the AttributeError described in the sibling comment.
Example sketch (artefact-content cases only):
@parameterized.expand(
[
("invalid_json", "not-json{"),
("json_null", "null"),
("json_array", "[]"),
("non_string_priority", json.dumps({"priority": 2})),
("missing_priority_key", json.dumps({"choice": "immediately_actionable"})),
]
)
def test_list_priority_null_for_bad_content(self, _name, content):
report = self._create_report()
SignalReportArtefact.objects.create(
team=self.team,
report=report,
type=SignalReportArtefact.ArtefactType.ACTIONABILITY_JUDGMENT,
content=content,
)
response = self.client.get(self._list_url())
assert response.status_code == status.HTTP_200_OK
row = next(r for r in response.json()["results"] if r["id"] == str(report.id))
assert row["priority"] is NonePrompt To Fix With AI
This is a comment left during a code review.
Path: products/signals/backend/test/test_signal_report_api.py
Line: 150-176
Comment:
**Prefer parameterised tests; missing non-dict JSON case**
Per the project convention, these three standalone "priority is null" tests (`invalid_json`, `non_string_priority`, and the no-artefact test above) are good candidates for a single `@parameterized.expand`. A parameterised approach also makes it easy to add the currently-untested case of *valid* JSON that isn't a dict (e.g. `content='null'`), which would expose the `AttributeError` described in the sibling comment.
Example sketch (artefact-content cases only):
```python
@parameterized.expand(
[
("invalid_json", "not-json{"),
("json_null", "null"),
("json_array", "[]"),
("non_string_priority", json.dumps({"priority": 2})),
("missing_priority_key", json.dumps({"choice": "immediately_actionable"})),
]
)
def test_list_priority_null_for_bad_content(self, _name, content):
report = self._create_report()
SignalReportArtefact.objects.create(
team=self.team,
report=report,
type=SignalReportArtefact.ArtefactType.ACTIONABILITY_JUDGMENT,
content=content,
)
response = self.client.get(self._list_url())
assert response.status_code == status.HTTP_200_OK
row = next(r for r in response.json()["results"] if r["id"] == str(report.id))
assert row["priority"] is None
```
How can I resolve this? If you propose a fix, please make it concise.Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Problem
We're currently saving priority (P0-P4) on the actionability judgement artifact, and PostHog Code needs it on signal reports in list responses without fetching
/artefacts/per report. Code also needs to fetch the reports not just by creation, but by their status in pipeline.Changes
SignalReportSerializergets read-onlypriorityfield from the latestACTIONABILITY_JUDGMENTartefact + gets more robust ordering, now bystatus.To avoid N+1 we're doing artefact prefetching in the list endpoint.
Also, decreasing the buffer wait time from 60s to 5s, as discussed with Olly on Slack.
How did you test this code?
Some new API tests.
Publish to changelog?
do not publish to changelog