litellm/litellm-rust/crates/callbacks-legacy-python/src/lib.rs
devin-ai-integration[bot] 4eb340abe0
fix(callbacks-legacy-python): traverse and release the retained headers dict (#43274)
* fix(callbacks-legacy-python): traverse and release the retained headers dict

LegacyLogging keeps the headers dict it hands to pre_call and post_call, but
its traverse never reported that edge to the collector and close never dropped
it. A cycle a callback builds through that dict could not be collected, and a
closed call kept the dict alive until the driver dropped the whole adapter.
Visit and clear headers like body, with regression tests for both

* refactor(callbacks-legacy-python): move the test support module into its own file

---------

Co-authored-by: Yujong Lee <yujong@berri.ai>
2026-09-25 20:24:58 -07:00

26 lines
1.1 KiB
Rust

//! The legacy `@client` wrapper as the native call sees it: litellm's `Logging` object, the
//! sync and async callback registries it fans out to, the deployment hooks and the deferred
//! proxy release. All of it sits behind one
//! [`PythonLifecycle`](litellm_host_python::PythonLifecycle), so the driver, the routes and
//! core never learn which Python object is on the other end. The SDK's own request policy
//! (credential inheritance, the budget and retry limits) is the driver's preflight, not this
//! crate's.
//!
//! Legacy callbacks receive the caller's own objects and may mutate them. [`PublicCall`]
//! is where those objects live, and [`run_legacy_call`] is how a route hands them over
//! without keeping a copy.
mod adapter;
mod call;
mod callbacks;
mod deferred;
mod logger;
mod python;
pub(crate) use adapter::LegacyLogging;
pub use adapter::{LegacySurface, PassThroughStream};
pub use call::{PublicCall, run_legacy_call};
pub(crate) use callbacks::{LegacyCallbacks, is_internal_call};
pub(crate) use logger::{DeploymentHooks, PythonLogger, finalize, setup};
#[cfg(test)]
mod test_support;