From 24d4e5bc60bf54156f7d72ed3b31932e2efddcb7 Mon Sep 17 00:00:00 2001 From: Harshit28j Date: Wed, 11 Mar 2026 19:28:27 +0530 Subject: [PATCH] Deregister VantageLogger on delete and add Decimal cast test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - DELETE /vantage/delete now removes the in-memory VantageLogger from litellm.callbacks via remove_callbacks_by_type, preventing the scheduler from continuing to fire exports with stale credentials - Add test_should_cast_decimal_columns_to_float covering the Decimal→Float64 cast in FocusCsvSerializer Co-Authored-By: Claude Opus 4.6 --- litellm/proxy/spend_tracking/vantage_endpoints.py | 7 +++++++ .../integrations/focus/test_csv_serializer.py | 13 +++++++++++++ 2 files changed, 20 insertions(+) diff --git a/litellm/proxy/spend_tracking/vantage_endpoints.py b/litellm/proxy/spend_tracking/vantage_endpoints.py index 4a11bb0e9d..19859bfb83 100644 --- a/litellm/proxy/spend_tracking/vantage_endpoints.py +++ b/litellm/proxy/spend_tracking/vantage_endpoints.py @@ -547,6 +547,13 @@ async def delete_vantage_settings( where={"param_name": VANTAGE_SETTINGS_PARAM_NAME} ) + # Deregister in-memory VantageLogger so the scheduler stops firing + from litellm.integrations.vantage.vantage_logger import VantageLogger + + litellm.logging_callback_manager.remove_callbacks_by_type( + litellm.callbacks, VantageLogger + ) + verbose_proxy_logger.info("Vantage settings deleted successfully") return VantageInitResponse( diff --git a/tests/test_litellm/integrations/focus/test_csv_serializer.py b/tests/test_litellm/integrations/focus/test_csv_serializer.py index f527a9dceb..f3256808e4 100644 --- a/tests/test_litellm/integrations/focus/test_csv_serializer.py +++ b/tests/test_litellm/integrations/focus/test_csv_serializer.py @@ -30,5 +30,18 @@ def test_should_return_header_only_for_empty_frame(): assert len(lines) == 1 # header only +def test_should_cast_decimal_columns_to_float(): + frame = pl.DataFrame( + {"BilledCost": [1, 2], "ServiceName": ["openai", "anthropic"]} + ).cast({"BilledCost": pl.Decimal(18, 6)}) + serializer = FocusCsvSerializer() + result = serializer.serialize(frame) + + lines = result.decode("utf-8").strip().split("\n") + # Should use floating-point notation (e.g. "1.0") not fixed-point ("1.000000") + assert "1.000000" not in lines[1] + assert lines[1].startswith("1.0,") + + def test_extension_should_be_csv(): assert FocusCsvSerializer.extension == "csv"