chore(V2): cleanup quality gate

- ruff: contextlib.suppress al posto di try/except/pass (client_registry, test_env_routing)
- rimozione services/ legacy (residuo da git rm)
- fix integration test fixture: rimosso sys.modules.pop che inquinava module references nei test successivi (test_audit, test_client_init_default_http)

254 test passano. Ruff: clean. Mypy: 68 warning preesistenti dal codice V1 migrato (strict=false).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
AdrianoDev
2026-04-30 19:02:55 +02:00
parent b552127479
commit b71c66917c
13 changed files with 35 additions and 34 deletions
+6 -1
View File
@@ -18,7 +18,12 @@ from cerbero_mcp.client_registry import ClientRegistry
from cerbero_mcp.common.logging import configure_root_logging from cerbero_mcp.common.logging import configure_root_logging
from cerbero_mcp.exchanges import build_client from cerbero_mcp.exchanges import build_client
from cerbero_mcp.routers import ( from cerbero_mcp.routers import (
alpaca, bybit, deribit, hyperliquid, macro, sentiment, alpaca,
bybit,
deribit,
hyperliquid,
macro,
sentiment,
) )
from cerbero_mcp.server import build_app from cerbero_mcp.server import build_app
from cerbero_mcp.settings import Settings from cerbero_mcp.settings import Settings
+2 -3
View File
@@ -2,6 +2,7 @@
from __future__ import annotations from __future__ import annotations
import asyncio import asyncio
import contextlib
from collections import defaultdict from collections import defaultdict
from collections.abc import Awaitable, Callable from collections.abc import Awaitable, Callable
from typing import Any, Literal from typing import Any, Literal
@@ -34,8 +35,6 @@ class ClientRegistry:
close = getattr(client, "aclose", None) close = getattr(client, "aclose", None)
if close is None: if close is None:
continue continue
try: with contextlib.suppress(Exception):
await close() await close()
except Exception:
pass
self._clients.clear() self._clients.clear()
+2 -1
View File
@@ -3,9 +3,10 @@ from __future__ import annotations
import asyncio import asyncio
from typing import Any from typing import Any
from pybit.unified_trading import HTTP
from cerbero_mcp.common import indicators as ind from cerbero_mcp.common import indicators as ind
from cerbero_mcp.common import microstructure as micro from cerbero_mcp.common import microstructure as micro
from pybit.unified_trading import HTTP
def _f(v: Any) -> float | None: def _f(v: Any) -> float | None:
+7 -2
View File
@@ -4,9 +4,14 @@ from datetime import UTC, datetime, timedelta
from typing import Any from typing import Any
import httpx import httpx
from cerbero_mcp.common.http import async_client
from cerbero_mcp.exchanges.macro.cot import classify_extreme, compute_percentile, parse_disagg_row, parse_tff_row from cerbero_mcp.common.http import async_client
from cerbero_mcp.exchanges.macro.cot import (
classify_extreme,
compute_percentile,
parse_disagg_row,
parse_tff_row,
)
from cerbero_mcp.exchanges.macro.cot_contracts import ( from cerbero_mcp.exchanges.macro.cot_contracts import (
ALL_DISAGG_SYMBOLS, ALL_DISAGG_SYMBOLS,
ALL_TFF_SYMBOLS, ALL_TFF_SYMBOLS,
+4 -13
View File
@@ -9,12 +9,12 @@ solo che il costruttore venga chiamato con i parametri corretti.
""" """
from __future__ import annotations from __future__ import annotations
import contextlib
import importlib import importlib
import pytest import pytest
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
# ── Fixtures ──────────────────────────────────────────────────────────────── # ── Fixtures ────────────────────────────────────────────────────────────────
@pytest.fixture @pytest.fixture
@@ -23,13 +23,6 @@ def app(monkeypatch):
for k, v in _minimal_env().items(): for k, v in _minimal_env().items():
monkeypatch.setenv(k, v) monkeypatch.setenv(k, v)
# Re-import fresco per evitare Settings cached con env vuoto
import importlib
import sys
for mod_name in list(sys.modules.keys()):
if "cerbero_mcp" in mod_name:
sys.modules.pop(mod_name, None)
from cerbero_mcp.__main__ import _make_app from cerbero_mcp.__main__ import _make_app
from cerbero_mcp.settings import Settings from cerbero_mcp.settings import Settings
return _make_app(Settings()) return _make_app(Settings())
@@ -58,12 +51,10 @@ def _spy_constructor(monkeypatch, module_path: str, cls_name: str, capture: dict
def spy_init(self, *args, **kwargs): def spy_init(self, *args, **kwargs):
capture["args"] = args capture["args"] = args
capture["kwargs"] = kwargs capture["kwargs"] = kwargs
try: # Se il costruttore fallisce (network, SDK unavailable) non importa:
# la capture è già avvenuta.
with contextlib.suppress(Exception):
real_init(self, *args, **kwargs) real_init(self, *args, **kwargs)
except Exception:
# Se il costruttore fallisce (network, SDK unavailable) non importa:
# la capture è già avvenuta.
pass
monkeypatch.setattr(real_cls, "__init__", spy_init) monkeypatch.setattr(real_cls, "__init__", spy_init)
+1 -1
View File
@@ -1,6 +1,6 @@
from __future__ import annotations from __future__ import annotations
from cerbero_mcp.common.errors import error_envelope, HTTP_CODE_MAP from cerbero_mcp.common.errors import HTTP_CODE_MAP, error_envelope
def test_envelope_minimal(): def test_envelope_minimal():
+1 -1
View File
@@ -1,8 +1,8 @@
from __future__ import annotations from __future__ import annotations
from cerbero_mcp.common.mcp_bridge import _derive_input_schemas, mount_mcp_endpoint
from fastapi import FastAPI from fastapi import FastAPI
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from cerbero_mcp.common.mcp_bridge import _derive_input_schemas, mount_mcp_endpoint
from pydantic import BaseModel from pydantic import BaseModel
VALID_TOKEN = "t" VALID_TOKEN = "t"
@@ -1,8 +1,8 @@
from __future__ import annotations from __future__ import annotations
import pytest import pytest
from fastapi import HTTPException
from cerbero_mcp.exchanges.alpaca.leverage_cap import enforce_leverage, get_max_leverage from cerbero_mcp.exchanges.alpaca.leverage_cap import enforce_leverage, get_max_leverage
from fastapi import HTTPException
def test_get_max_leverage_returns_creds_value(): def test_get_max_leverage_returns_creds_value():
@@ -1,8 +1,8 @@
from __future__ import annotations from __future__ import annotations
import pytest import pytest
from fastapi import HTTPException
from cerbero_mcp.exchanges.bybit.leverage_cap import enforce_leverage, get_max_leverage from cerbero_mcp.exchanges.bybit.leverage_cap import enforce_leverage, get_max_leverage
from fastapi import HTTPException
def test_get_max_leverage_returns_creds_value(): def test_get_max_leverage_returns_creds_value():
@@ -1,8 +1,8 @@
from __future__ import annotations from __future__ import annotations
import pytest import pytest
from fastapi import HTTPException
from cerbero_mcp.exchanges.deribit.leverage_cap import enforce_leverage, get_max_leverage from cerbero_mcp.exchanges.deribit.leverage_cap import enforce_leverage, get_max_leverage
from fastapi import HTTPException
def test_get_max_leverage_returns_creds_value(): def test_get_max_leverage_returns_creds_value():
@@ -1,8 +1,8 @@
from __future__ import annotations from __future__ import annotations
import pytest import pytest
from fastapi import HTTPException
from cerbero_mcp.exchanges.hyperliquid.leverage_cap import enforce_leverage, get_max_leverage from cerbero_mcp.exchanges.hyperliquid.leverage_cap import enforce_leverage, get_max_leverage
from fastapi import HTTPException
def test_get_max_leverage_returns_creds_value(): def test_get_max_leverage_returns_creds_value():
+1 -1
View File
@@ -1,4 +1,3 @@
import pytest
from fastapi import FastAPI, Request from fastapi import FastAPI, Request
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
@@ -92,6 +91,7 @@ def test_mainnet_token_sets_env_mainnet():
def test_uses_compare_digest(): def test_uses_compare_digest():
"""Verifica che _check_token usi secrets.compare_digest (timing-safe).""" """Verifica che _check_token usi secrets.compare_digest (timing-safe)."""
import inspect import inspect
from cerbero_mcp import auth from cerbero_mcp import auth
src = inspect.getsource(auth) src = inspect.getsource(auth)
+7 -7
View File
@@ -10,8 +10,8 @@ async def test_build_client_deribit_returns_correct_url(monkeypatch):
for k, v in _minimal_env().items(): for k, v in _minimal_env().items():
monkeypatch.setenv(k, v) monkeypatch.setenv(k, v)
from cerbero_mcp.settings import Settings
from cerbero_mcp.exchanges import build_client from cerbero_mcp.exchanges import build_client
from cerbero_mcp.settings import Settings
s = Settings() s = Settings()
c_test = await build_client(s, "deribit", "testnet") c_test = await build_client(s, "deribit", "testnet")
@@ -38,8 +38,8 @@ async def test_build_client_bybit_returns_correct_env(monkeypatch):
monkeypatch.setattr(bybit_client, "HTTP", _FakeHTTP) monkeypatch.setattr(bybit_client, "HTTP", _FakeHTTP)
from cerbero_mcp.settings import Settings
from cerbero_mcp.exchanges import build_client from cerbero_mcp.exchanges import build_client
from cerbero_mcp.settings import Settings
s = Settings() s = Settings()
c_test = await build_client(s, "bybit", "testnet") c_test = await build_client(s, "bybit", "testnet")
@@ -57,8 +57,8 @@ async def test_build_client_hyperliquid_returns_correct_env(monkeypatch):
for k, v in _minimal_env().items(): for k, v in _minimal_env().items():
monkeypatch.setenv(k, v) monkeypatch.setenv(k, v)
from cerbero_mcp.settings import Settings
from cerbero_mcp.exchanges import build_client from cerbero_mcp.exchanges import build_client
from cerbero_mcp.settings import Settings
s = Settings() s = Settings()
c_test = await build_client(s, "hyperliquid", "testnet") c_test = await build_client(s, "hyperliquid", "testnet")
@@ -90,8 +90,8 @@ async def test_build_client_alpaca_returns_correct_env(monkeypatch):
monkeypatch.setattr(alpaca_client, "CryptoHistoricalDataClient", _FakeSdk) monkeypatch.setattr(alpaca_client, "CryptoHistoricalDataClient", _FakeSdk)
monkeypatch.setattr(alpaca_client, "OptionHistoricalDataClient", _FakeSdk) monkeypatch.setattr(alpaca_client, "OptionHistoricalDataClient", _FakeSdk)
from cerbero_mcp.settings import Settings
from cerbero_mcp.exchanges import build_client from cerbero_mcp.exchanges import build_client
from cerbero_mcp.settings import Settings
s = Settings() s = Settings()
c_test = await build_client(s, "alpaca", "testnet") c_test = await build_client(s, "alpaca", "testnet")
@@ -109,9 +109,9 @@ async def test_build_client_macro_no_env_distinction(monkeypatch):
for k, v in _minimal_env().items(): for k, v in _minimal_env().items():
monkeypatch.setenv(k, v) monkeypatch.setenv(k, v)
from cerbero_mcp.settings import Settings
from cerbero_mcp.exchanges import build_client from cerbero_mcp.exchanges import build_client
from cerbero_mcp.exchanges.macro.client import MacroClient from cerbero_mcp.exchanges.macro.client import MacroClient
from cerbero_mcp.settings import Settings
s = Settings() s = Settings()
c_test = await build_client(s, "macro", "testnet") c_test = await build_client(s, "macro", "testnet")
@@ -132,9 +132,9 @@ async def test_build_client_sentiment_no_env_distinction(monkeypatch):
for k, v in _minimal_env().items(): for k, v in _minimal_env().items():
monkeypatch.setenv(k, v) monkeypatch.setenv(k, v)
from cerbero_mcp.settings import Settings
from cerbero_mcp.exchanges import build_client from cerbero_mcp.exchanges import build_client
from cerbero_mcp.exchanges.sentiment.client import SentimentClient from cerbero_mcp.exchanges.sentiment.client import SentimentClient
from cerbero_mcp.settings import Settings
s = Settings() s = Settings()
c_test = await build_client(s, "sentiment", "testnet") c_test = await build_client(s, "sentiment", "testnet")
@@ -155,8 +155,8 @@ async def test_build_client_unknown_exchange_raises(monkeypatch):
for k, v in _minimal_env().items(): for k, v in _minimal_env().items():
monkeypatch.setenv(k, v) monkeypatch.setenv(k, v)
from cerbero_mcp.settings import Settings
from cerbero_mcp.exchanges import build_client from cerbero_mcp.exchanges import build_client
from cerbero_mcp.settings import Settings
s = Settings() s = Settings()
with pytest.raises(ValueError): with pytest.raises(ValueError):