Skip to main content
Glama
test_normalize_payload.py•4.81 kB
"""Unit tests for the payload normalization shim used by the REST API.""" from types import SimpleNamespace import pytest from tiger_rest_api_full import ( _normalize_payload, _structure_option_chain, _to_plain_dict, ) class DummyDataFrame: """Simulates a pandas DataFrame providing a to_dict(orient='records') signature.""" def __init__(self, rows): self._rows = rows def to_dict(self, orient=None): if orient != "records": raise ValueError("Expected orient='records'") return self._rows class AmbiguousRecords: """Iterable that raises on truthiness, mimicking pandas.DataFrame behaviour.""" def __init__(self, rows): self._rows = rows def __iter__(self): return iter(self._rows) def __bool__(self): raise ValueError("The truth value of a DataFrame is ambiguous") class AmbiguousDataFrame(DummyDataFrame): """DataFrame variant that surfaces ambiguous truthiness via to_dict return.""" def to_dict(self, orient=None): base = super().to_dict(orient=orient) return AmbiguousRecords(base) class DictLikeToDict: """Simulates objects that only support a zero-argument to_dict().""" def __init__(self, payload): self._payload = payload def to_dict(self): return self._payload class IterableWrapper: """Iterable object that is not a builtin list/tuple.""" def __init__(self, data): self._data = data def __iter__(self): yield from self._data def test_normalize_none_returns_empty_list(): assert _normalize_payload(None) == [] def test_normalize_list_of_dicts_wraps_into_namespace(): payload = [{"symbol": "AAPL", "price": 189.12}, {"symbol": "TSLA", "price": 196.3}] result = _normalize_payload(payload) assert len(result) == 2 assert isinstance(result[0], SimpleNamespace) assert result[0].symbol == "AAPL" assert result[1].price == pytest.approx(196.3) def test_normalize_dict_returns_single_namespace(): payload = {"symbol": "AAPL", "volume": 12345} result = _normalize_payload(payload) assert len(result) == 1 assert isinstance(result[0], SimpleNamespace) assert result[0].volume == 12345 def test_normalize_dataframe_like_object(): payload = DummyDataFrame( [ {"symbol": "AAPL", "price": 189.12}, {"symbol": "MSFT", "price": 411.29}, ] ) result = _normalize_payload(payload) assert len(result) == 2 assert result[1].symbol == "MSFT" assert result[1].price == pytest.approx(411.29) def test_normalize_dataframe_with_ambiguous_truthiness(): payload = AmbiguousDataFrame( [ {"symbol": "NVDA", "price": 118.45}, {"symbol": "AMD", "price": 31.84}, ] ) result = _normalize_payload(payload) assert [item.symbol for item in result] == ["NVDA", "AMD"] def test_normalize_to_dict_without_orient(): payload = DictLikeToDict({"symbol": "AMZN", "price": 131.52}) result = _normalize_payload(payload) assert len(result) == 1 assert isinstance(result[0], SimpleNamespace) assert result[0].symbol == "AMZN" def test_normalize_iterable_wrapper(): payload = IterableWrapper([{"symbol": "BABA"}, {"symbol": "BIDU"}]) result = _normalize_payload(payload) extracted = [item.symbol for item in result] assert extracted == ["BABA", "BIDU"] def test_normalize_scalar_value_preserves_object(): payload = 42 result = _normalize_payload(payload) assert result == [42] def test_normalize_leaves_strings_intact(): payload = "raw-token-value" result = _normalize_payload(payload) assert result == ["raw-token-value"] def test_to_plain_dict_handles_simple_namespace(): item = SimpleNamespace(strike=150, put_call="CALL") result = _to_plain_dict(item) assert result == {"strike": 150, "put_call": "CALL"} class ContractObject: def __init__(self, strike, side): self.strike = strike self.put_call = side self.last_price = 1.25 def test_to_plain_dict_handles_custom_object(): item = ContractObject(125, "PUT") result = _to_plain_dict(item) assert result["strike"] == 125 assert result["put_call"] == "PUT" assert result["last_price"] == 1.25 def test_structure_option_chain_splits_calls_puts_other(): payload = [ {"put_call": "CALL", "strike": 100}, {"put_call": "PUT", "strike": 110}, {"strike": 120}, ] structured = _structure_option_chain(payload) assert structured["total"] == 3 assert [c["strike"] for c in structured["calls"]] == [100] assert [p["strike"] for p in structured["puts"]] == [110] assert [o["strike"] for o in structured["other"]] == [120]

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/luxiaolei/tiger-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server