feat(mcp): add quarterly pyramid distribution lookup
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
"""Read-only Pyramid endpoint probe: python -m app.probe_pyramids.
|
||||
|
||||
Uses the project's configured account and WqClient without changing stored data.
|
||||
A standalone process authenticates separately; it cannot inherit a running
|
||||
server's in-memory cookies. Authentication responses and secrets are never printed.
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import json
|
||||
|
||||
from .config import Settings
|
||||
from .db import create_database
|
||||
from .models import Account
|
||||
from .security import cipher
|
||||
from .worldquant import WqClient, WqError
|
||||
|
||||
PATHS = (
|
||||
"/users/self/activities/pyramid-alphas",
|
||||
"/users/self/pyramid/alphas",
|
||||
"/activities/pyramid-alphas",
|
||||
"/pyramid/alphas",
|
||||
)
|
||||
|
||||
|
||||
async def probe(client):
|
||||
"""Probe fixed same-origin GET paths using an authenticated WqClient.
|
||||
|
||||
Returns status and successful JSON for each path; stops on session expiry.
|
||||
Transport failures propagate to the caller without exposing request details.
|
||||
"""
|
||||
if not client.authenticated:
|
||||
raise WqError("请先连接 WorldQuant", "disconnected")
|
||||
results = []
|
||||
for path in PATHS:
|
||||
response = await client.client.get(path)
|
||||
result = {"path": path, "status": response.status_code}
|
||||
if response.status_code == 200:
|
||||
try:
|
||||
result["data"] = response.json()
|
||||
except ValueError:
|
||||
result["error"] = "invalid_json"
|
||||
results.append(result)
|
||||
if response.status_code in (401, 429):
|
||||
break
|
||||
return results
|
||||
|
||||
|
||||
async def main():
|
||||
settings = Settings()
|
||||
client = WqClient(settings)
|
||||
engine = None
|
||||
try:
|
||||
if settings.wq_email:
|
||||
email, password = settings.wq_email, settings.wq_password.get_secret_value()
|
||||
else:
|
||||
engine, sessions = create_database(settings.database_url)
|
||||
async with sessions() as db:
|
||||
account = await db.get(Account, 1)
|
||||
if not account or not account.email or not account.password_encrypted:
|
||||
raise WqError("未配置平台凭据", "disconnected")
|
||||
email = account.email
|
||||
password = cipher(settings).decrypt(account.password_encrypted.encode()).decode()
|
||||
await client.authenticate(email, password)
|
||||
print(json.dumps(await probe(client), ensure_ascii=False, indent=2))
|
||||
except WqError as exc:
|
||||
print(json.dumps({"error": exc.code}, ensure_ascii=False))
|
||||
return 1
|
||||
except Exception as exc:
|
||||
# Connection/config errors can contain credentials; print only the type.
|
||||
print(json.dumps({"error": type(exc).__name__}))
|
||||
return 1
|
||||
finally:
|
||||
await client.close()
|
||||
if engine is not None:
|
||||
await engine.dispose()
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(asyncio.run(main()))
|
||||
Reference in New Issue
Block a user