From 9011b24c9fead5d19026013f974c9847563c8676 Mon Sep 17 00:00:00 2001 From: Yuneng Jiang Date: Fri, 17 Jul 2026 17:22:04 -0700 Subject: [PATCH] build(rust): raise pyo3 to 0.29 so the native bridge compiles on Python 3.14 pyo3 0.23.5 hard-caps the interpreter at Python 3.13, so building the native bridge against a 3.14 interpreter aborts inside pyo3-ffi's build script before anything links. This raises pyo3 and pyo3-async-runtimes to 0.29 (currently the newest line, and the range starting at 0.26 that supports 3.14) and migrates the three call sites whose APIs were renamed across that range: Python::with_gil is now Python::attach and Python::allow_threads is now Python::detach. On a GIL-enabled interpreter those are pure renames with identical semantics, so behavior on 3.10 through 3.13 is unchanged Verified by compiling the native module for cp313 and cp314 and driving it directly on both interpreters: gil_stats reports exactly one GIL release per sync OCR call and the async path completes, matching the 0.23.5 baseline. cargo fmt, clippy, and the workspace tests pass on both 3.13 and 3.14 with the lockfile locked, and the lock churn is confined to the pyo3 crates Part of #26343; addresses the pyo3 build failure reported in #33116 --- litellm-rust/Cargo.lock | 94 ++++--------------- litellm-rust/Cargo.toml | 4 +- .../crates/ai-gateway/src/python/config.rs | 2 +- litellm-rust/crates/python-bridge/src/gil.rs | 4 +- litellm-rust/crates/python-bridge/src/lib.rs | 2 +- 5 files changed, 22 insertions(+), 84 deletions(-) diff --git a/litellm-rust/Cargo.lock b/litellm-rust/Cargo.lock index 9bffe9f9ec69..f563c18ea14c 100644 --- a/litellm-rust/Cargo.lock +++ b/litellm-rust/Cargo.lock @@ -19,12 +19,6 @@ version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" -[[package]] -name = "autocfg" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" - [[package]] name = "axum" version = "0.7.9" @@ -233,21 +227,6 @@ dependencies = [ "percent-encoding", ] -[[package]] -name = "futures" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - [[package]] name = "futures-channel" version = "0.3.32" @@ -264,17 +243,6 @@ version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" -[[package]] -name = "futures-executor" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", -] - [[package]] name = "futures-io" version = "0.3.32" @@ -310,7 +278,6 @@ version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" dependencies = [ - "futures-channel", "futures-core", "futures-io", "futures-macro", @@ -608,15 +575,6 @@ dependencies = [ "hashbrown", ] -[[package]] -name = "indoc" -version = "2.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79cf5c93f93228cf8efb3ba362535fb11199ac548a09ce117c9b1adc3030d706" -dependencies = [ - "rustversion", -] - [[package]] name = "ipnet" version = "2.12.0" @@ -718,15 +676,6 @@ version = "2.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "88904434abc2901f197fe8cc55f0445e7ded921dba5911dad2e2b39b48e663c4" -[[package]] -name = "memoffset" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" -dependencies = [ - "autocfg", -] - [[package]] name = "mime" version = "0.3.17" @@ -803,29 +752,26 @@ dependencies = [ [[package]] name = "pyo3" -version = "0.23.5" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7778bffd85cf38175ac1f545509665d0b9b92a198ca7941f131f85f7a4f9a872" +checksum = "cd274650b21d4bfc26a0a47587962c1edb425f69287324355cd040c3ea66071c" dependencies = [ - "cfg-if", - "indoc", "libc", - "memoffset", "once_cell", "portable-atomic", "pyo3-build-config", "pyo3-ffi", "pyo3-macros", - "unindent", ] [[package]] name = "pyo3-async-runtimes" -version = "0.23.0" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "977dc837525cfd22919ba6a831413854beb7c99a256c03bf8624ad707e45810e" +checksum = "b3ef68daa7316a3fac65e5e18b2203f010346de1c1c53456811a2624673ab046" dependencies = [ - "futures", + "futures-channel", + "futures-util", "once_cell", "pin-project-lite", "pyo3", @@ -834,19 +780,18 @@ dependencies = [ [[package]] name = "pyo3-build-config" -version = "0.23.5" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94f6cbe86ef3bf18998d9df6e0f3fc1050a8c5efa409bf712e661a4366e010fb" +checksum = "c5e2a7d2f0d013342f295c048ad19237add5154a55b1c5a254c0ec93d4109078" dependencies = [ - "once_cell", "target-lexicon", ] [[package]] name = "pyo3-ffi" -version = "0.23.5" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9f1b4c431c0bb1c8fb0a338709859eed0d030ff6daa34368d3b152a63dfdd8d" +checksum = "ca85c467da1bbc8d866eea5deff9cf29ea5f7785054a17da36e65bda9c05845b" dependencies = [ "libc", "pyo3-build-config", @@ -854,9 +799,9 @@ dependencies = [ [[package]] name = "pyo3-macros" -version = "0.23.5" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbc2201328f63c4710f68abdf653c89d8dbc2858b88c5d88b0ff38a75288a9da" +checksum = "9ac53762fd065daa3194dd09337a38bd793a188100fd1a9304c4ab312d901771" dependencies = [ "proc-macro2", "pyo3-macros-backend", @@ -866,13 +811,12 @@ dependencies = [ [[package]] name = "pyo3-macros-backend" -version = "0.23.5" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fca6726ad0f3da9c9de093d6f116a93c1a38e417ed73bf138472cf4064f72028" +checksum = "4ca3a1557399783172dc5bf39cfca835157732532cba56b71d2292161e53b362" dependencies = [ "heck", "proc-macro2", - "pyo3-build-config", "quote", "syn", ] @@ -1321,9 +1265,9 @@ dependencies = [ [[package]] name = "target-lexicon" -version = "0.12.16" +version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" +checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca" [[package]] name = "thiserror" @@ -1559,12 +1503,6 @@ version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" -[[package]] -name = "unindent" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7264e107f553ccae879d21fbea1d6724ac785e8c3bfc762137959b5802826ef3" - [[package]] name = "untrusted" version = "0.9.0" diff --git a/litellm-rust/Cargo.toml b/litellm-rust/Cargo.toml index 5842ed5ba9bd..a3baa33e6cf8 100644 --- a/litellm-rust/Cargo.toml +++ b/litellm-rust/Cargo.toml @@ -15,8 +15,8 @@ repository = "https://github.com/BerriAI/litellm" litellm-core = { path = "crates/core" } litellm-ai-gateway = { path = "crates/ai-gateway", default-features = false } axum = "0.7" -pyo3 = "0.23.5" -pyo3-async-runtimes = { version = "0.23.0", features = ["tokio-runtime"] } +pyo3 = "0.29.0" +pyo3-async-runtimes = { version = "0.29.0", features = ["tokio-runtime"] } rand = "0.8" reqwest = { version = "0.12", default-features = false, features = ["blocking", "json", "rustls-tls", "http2", "stream"] } serde = { version = "1.0", features = ["derive"] } diff --git a/litellm-rust/crates/ai-gateway/src/python/config.rs b/litellm-rust/crates/ai-gateway/src/python/config.rs index 6ec9595469df..54b7a53bafac 100644 --- a/litellm-rust/crates/ai-gateway/src/python/config.rs +++ b/litellm-rust/crates/ai-gateway/src/python/config.rs @@ -17,7 +17,7 @@ use crate::gil; /// Load the router's `model_list` from `config_path` via the Python reader. pub fn load_router_from_config(config_path: &str) -> CoreResult { gil::record_acquisition(); - Python::with_gil(|py| { + Python::attach(|py| { let model_list = py .import("litellm.proxy.read_model_list") .and_then(|module| module.getattr("read_model_list")) diff --git a/litellm-rust/crates/python-bridge/src/gil.rs b/litellm-rust/crates/python-bridge/src/gil.rs index dc1b591735c2..e887c8ec1e3a 100644 --- a/litellm-rust/crates/python-bridge/src/gil.rs +++ b/litellm-rust/crates/python-bridge/src/gil.rs @@ -2,7 +2,7 @@ //! //! A single chokepoint for releasing the GIL around blocking work. Every //! blocking call in the bridge goes through [`release_gil`] instead of calling -//! `Python::allow_threads` directly, so the release count stays accurate and we +//! `Python::detach` directly, so the release count stays accurate and we //! have one place to extend later (timing histograms, per-call labels, etc.). use std::sync::atomic::{AtomicU64, Ordering}; @@ -23,7 +23,7 @@ where T: Send, { GIL_RELEASES.fetch_add(1, Ordering::Relaxed); - py.allow_threads(f) + py.detach(f) } /// Total GIL releases performed by the bridge so far. diff --git a/litellm-rust/crates/python-bridge/src/lib.rs b/litellm-rust/crates/python-bridge/src/lib.rs index 946a99f990c1..271864581f30 100644 --- a/litellm-rust/crates/python-bridge/src/lib.rs +++ b/litellm-rust/crates/python-bridge/src/lib.rs @@ -167,7 +167,7 @@ fn aocr( .await .map_err(core_error_to_pyerr)?; - Python::with_gil(|py| json_to_py(py, value)) + Python::attach(|py| json_to_py(py, value)) }) }