feat: normalize filter values to array format for Grist API

The Grist API requires all filter values to be arrays. This change adds
automatic normalization of filter values in get_records, wrapping single
values in lists before sending to the API.

This fixes 400 errors when filtering on Ref columns with single integer IDs.

Changes:
- Add filters.py module with normalize_filter function
- Update get_records to normalize filters before API call
- Add Orders table with Ref column to mock Grist server
- Add filter validation to mock server (rejects non-array values)
- Fix shell script shebangs for portability (#!/usr/bin/env bash)
This commit is contained in:
2026-01-14 17:56:18 -05:00
parent c868e8a7fa
commit a97930848b
8 changed files with 244 additions and 5 deletions

View File

@@ -75,6 +75,45 @@ async def test_get_records(agent, auth, mock_client):
assert result == {"records": [{"id": 1, "Name": "Alice"}]}
@pytest.mark.asyncio
async def test_get_records_normalizes_filter(agent, auth, mock_client):
"""Test that filter values are normalized to array format for Grist API."""
mock_client.get_records.return_value = [{"id": 1, "Customer": 5}]
await get_records(
agent, auth, "budget", "Orders",
filter={"Customer": 5, "Status": "active"},
client=mock_client,
)
# Verify filter was normalized: single values wrapped in lists
mock_client.get_records.assert_called_once_with(
"Orders",
filter={"Customer": [5], "Status": ["active"]},
sort=None,
limit=None,
)
@pytest.mark.asyncio
async def test_get_records_preserves_list_filter(agent, auth, mock_client):
"""Test that filter values already in list format are preserved."""
mock_client.get_records.return_value = []
await get_records(
agent, auth, "budget", "Orders",
filter={"Customer": [5, 6, 7]},
client=mock_client,
)
mock_client.get_records.assert_called_once_with(
"Orders",
filter={"Customer": [5, 6, 7]},
sort=None,
limit=None,
)
@pytest.mark.asyncio
async def test_sql_query(agent, auth, mock_client):
result = await sql_query(agent, auth, "budget", "SELECT * FROM Table1", client=mock_client)