feat(mcp): add quarterly pyramid distribution lookup
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
"""Verify distribution through MCP authorization, validation and audit boundaries."""
|
||||
|
||||
import httpx
|
||||
import pytest
|
||||
|
||||
from app.worldquant import WqClient
|
||||
from tests.test_mcp import credentials, invoke
|
||||
from tests.test_mcp import mcp_app as mcp_app
|
||||
|
||||
|
||||
def row(name, count, region="USA", delay=1):
|
||||
return {"category": {"id": name, "name": name}, "alphaCount": count,
|
||||
"region": region, "delay": delay}
|
||||
|
||||
|
||||
async def test_distribution(mcp_app):
|
||||
calls = []
|
||||
|
||||
def platform(request):
|
||||
calls.append(request)
|
||||
assert request.method == "GET"
|
||||
assert request.url.path == "/users/self/activities/pyramid-alphas"
|
||||
return httpx.Response(200, json={"pyramids": [row("zero", 0), row("one", 1),
|
||||
row("two", 2), row("three", 3), row("four", 4), row("other", 5, "GLB"),
|
||||
row("delay_zero", 5, delay=0)]})
|
||||
|
||||
client = WqClient(mcp_app.state.settings, transport=httpx.MockTransport(platform))
|
||||
client.credentials, client.authenticated = ("test", "test"), True
|
||||
original = mcp_app.state.runner.client
|
||||
mcp_app.state.runner.client = client
|
||||
try:
|
||||
reader, _ = await credentials(mcp_app, {"research:read"})
|
||||
result = await invoke(mcp_app, reader, "get_pyramid_distribution", {"region": "USA", "delay": 1, "current_date": "2026-09-13"})
|
||||
assert [r["alpha_count"] for r in result["lit"]] == [4, 3]
|
||||
assert [r["remaining"] for r in result["in_progress"]] == [2, 1]
|
||||
assert result["unlit"][0]["category"]["id"] == "zero"
|
||||
assert dict(calls[0].url.params) == {"startDate": "2026-07-01", "endDate": "2026-09-30"}
|
||||
assert result["period"] == {"quarter": "2026-Q3", "start_date": "2026-07-01", "end_date": "2026-09-30"}
|
||||
for args in ({"region": "USA", "delay": 2}, {"region": "USA", "delay": True},
|
||||
{"region": "../", "delay": 1}):
|
||||
response = await mcp_app.state.mcp.invoke(reader, "get_pyramid_distribution", args | {"current_date": "2026-09-13"})
|
||||
assert response.structured_content["error"]["code"] == "INVALID_INPUT"
|
||||
assert len(calls) == 1
|
||||
client.credentials, client.authenticated = None, False
|
||||
response = await mcp_app.state.mcp.invoke(reader, "get_pyramid_distribution", {"region": "USA", "delay": 1, "current_date": "2026-09-13"})
|
||||
assert response.structured_content["error"]["code"] == "DISCONNECTED"
|
||||
finally:
|
||||
mcp_app.state.runner.client = original
|
||||
await client.close()
|
||||
|
||||
|
||||
@pytest.mark.parametrize("rows", [[], [row("x", None)], [row("x", -1)],
|
||||
[row("x", True)], [row("x", 1), row("x", 2)]])
|
||||
def test_missing_evidence_is_not_zero(rows):
|
||||
from app.research_access.pyramids import distribution
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
distribution({"pyramids": rows}, "USA", 1)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(('value', 'quarter', 'start', 'end'), [
|
||||
('2026-01-01', '2026-Q1', '2026-01-01', '2026-03-31'),
|
||||
('2026-03-31', '2026-Q1', '2026-01-01', '2026-03-31'),
|
||||
('2026-04-01', '2026-Q2', '2026-04-01', '2026-06-30'),
|
||||
('2026-06-30', '2026-Q2', '2026-04-01', '2026-06-30'),
|
||||
('2026-07-01', '2026-Q3', '2026-07-01', '2026-09-30'),
|
||||
('2026-09-30', '2026-Q3', '2026-07-01', '2026-09-30'),
|
||||
('2026-10-01', '2026-Q4', '2026-10-01', '2026-12-31'),
|
||||
('2026-12-31', '2026-Q4', '2026-10-01', '2026-12-31'),
|
||||
('2027-01-01', '2027-Q1', '2027-01-01', '2027-03-31'),
|
||||
('2024-02-29', '2024-Q1', '2024-01-01', '2024-03-31'),
|
||||
])
|
||||
def test_quarter_boundaries(value, quarter, start, end):
|
||||
from datetime import date
|
||||
|
||||
from app.research_access.pyramids import quarter_period
|
||||
|
||||
assert quarter_period(date.fromisoformat(value)) == {
|
||||
'quarter': quarter, 'start_date': start, 'end_date': end}
|
||||
|
||||
|
||||
@pytest.mark.parametrize('value', [None, '2026-02-30', 'not-a-date'])
|
||||
def test_date_required_and_valid(value):
|
||||
from pydantic import ValidationError
|
||||
|
||||
from app.research_access.contracts import PyramidQuery
|
||||
|
||||
args = {'region': 'USA', 'delay': 1}
|
||||
if value is not None:
|
||||
args['current_date'] = value
|
||||
with pytest.raises(ValidationError):
|
||||
PyramidQuery.model_validate(args)
|
||||
Reference in New Issue
Block a user