mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-10 03:28:53 +00:00
feat(rust-bridge): expose module version and build info
This commit is contained in:
parent
df73c623b2
commit
8bfe009522
5 changed files with 98 additions and 0 deletions
1
litellm-rust/Cargo.lock
generated
1
litellm-rust/Cargo.lock
generated
|
|
@ -1456,6 +1456,7 @@ dependencies = [
|
|||
"litellm-python-interop",
|
||||
"pyo3",
|
||||
"pyo3-async-runtimes",
|
||||
"pyo3-build-config",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tokio",
|
||||
|
|
|
|||
|
|
@ -28,6 +28,9 @@ serde.workspace = true
|
|||
serde_json.workspace = true
|
||||
tokio.workspace = true
|
||||
|
||||
[build-dependencies]
|
||||
pyo3-build-config = "0.29.2"
|
||||
|
||||
[dev-dependencies]
|
||||
criterion = "0.8.2"
|
||||
tokio-tungstenite.workspace = true
|
||||
|
|
|
|||
|
|
@ -1,6 +1,34 @@
|
|||
use std::path::Path;
|
||||
|
||||
fn pyo3_version_from_lock() -> Option<String> {
|
||||
let manifest_dir = std::env::var("CARGO_MANIFEST_DIR").ok()?;
|
||||
let lockfile = Path::new(&manifest_dir).join("../../Cargo.lock");
|
||||
let contents = std::fs::read_to_string(lockfile).ok()?;
|
||||
let lines: Vec<&str> = contents.lines().collect();
|
||||
for pair in lines.windows(2) {
|
||||
if pair[0].trim() != "name = \"pyo3\"" {
|
||||
continue;
|
||||
}
|
||||
if let Some(version) = pair[1].trim().strip_prefix("version = ") {
|
||||
return Some(version.trim_matches('"').to_owned());
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn main() {
|
||||
pyo3_build_config::use_pyo3_cfgs();
|
||||
if std::env::var("CARGO_CFG_TARGET_OS").as_deref() == Ok("macos") {
|
||||
println!("cargo:rustc-cdylib-link-arg=-undefined");
|
||||
println!("cargo:rustc-cdylib-link-arg=dynamic_lookup");
|
||||
}
|
||||
println!(
|
||||
"cargo:rustc-env=LITELLM_NATIVE_PROFILE={}",
|
||||
std::env::var("PROFILE").unwrap_or_else(|_| "unknown".to_owned())
|
||||
);
|
||||
println!(
|
||||
"cargo:rustc-env=LITELLM_PYO3_VERSION={}",
|
||||
pyo3_version_from_lock().unwrap_or_else(|| "unknown".to_owned())
|
||||
);
|
||||
println!("cargo:rerun-if-changed=../../Cargo.lock");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,17 @@ fn gil_stats(py: Python<'_>) -> PyResult<Py<PyAny>> {
|
|||
Ok(stats.into_any().unbind())
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn build_info(py: Python<'_>) -> PyResult<Py<PyAny>> {
|
||||
let info = PyDict::new(py);
|
||||
info.set_item("profile", env!("LITELLM_NATIVE_PROFILE"))?;
|
||||
info.set_item("pyo3", env!("LITELLM_PYO3_VERSION"))?;
|
||||
info.set_item("abi3", cfg!(Py_LIMITED_API))?;
|
||||
info.set_item("gil_disabled", cfg!(Py_GIL_DISABLED))?;
|
||||
info.set_item("debug_assertions", cfg!(debug_assertions))?;
|
||||
Ok(info.into_any().unbind())
|
||||
}
|
||||
|
||||
#[cfg(feature = "panic-test")]
|
||||
#[pyfunction]
|
||||
fn _panic_for_test() {
|
||||
|
|
@ -17,6 +28,7 @@ fn _panic_for_test() {
|
|||
|
||||
pub(crate) fn register(module: &Bound<'_, PyModule>) -> PyResult<()> {
|
||||
module.add_function(wrap_pyfunction!(gil_stats, module)?)?;
|
||||
module.add_function(wrap_pyfunction!(build_info, module)?)?;
|
||||
#[cfg(feature = "panic-test")]
|
||||
module.add_function(wrap_pyfunction!(_panic_for_test, module)?)?;
|
||||
Ok(())
|
||||
|
|
|
|||
|
|
@ -68,6 +68,7 @@ mod _native {
|
|||
|
||||
#[pymodule_init]
|
||||
fn init(module: &Bound<'_, PyModule>) -> PyResult<()> {
|
||||
module.add("__version__", env!("CARGO_PKG_VERSION"))?;
|
||||
super::errors::register(module)?;
|
||||
super::routes::register(module)?;
|
||||
module.add_class::<super::ResponsesWebSocketConnection>()?;
|
||||
|
|
@ -107,6 +108,7 @@ mod tests {
|
|||
"achat_completions",
|
||||
"ResponsesWebSocketConnection",
|
||||
"gil_stats",
|
||||
"build_info",
|
||||
];
|
||||
|
||||
let public_names: Vec<String> = module
|
||||
|
|
@ -118,6 +120,58 @@ mod tests {
|
|||
.filter(|name| !name.starts_with("__"))
|
||||
.collect();
|
||||
assert_eq!(public_names, expected);
|
||||
|
||||
let version = module
|
||||
.getattr("__version__")
|
||||
.expect("module should expose __version__")
|
||||
.extract::<String>()
|
||||
.expect("__version__ should be a string");
|
||||
assert_eq!(version, env!("CARGO_PKG_VERSION"));
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn version_and_build_info_report_expected_shape() {
|
||||
Python::initialize();
|
||||
Python::attach(|py| {
|
||||
let module = pyo3::wrap_pymodule!(_native)(py).into_bound(py);
|
||||
|
||||
let version = module
|
||||
.getattr("__version__")
|
||||
.expect("module should expose __version__")
|
||||
.extract::<String>()
|
||||
.expect("__version__ should be a string");
|
||||
let segments: Vec<&str> = version.split('.').collect();
|
||||
assert_eq!(segments.len(), 3, "__version__ should be x.y.z: {version}");
|
||||
for segment in segments {
|
||||
assert!(
|
||||
!segment.is_empty() && segment.bytes().all(|b| b.is_ascii_digit()),
|
||||
"__version__ segments should be numeric: {version}"
|
||||
);
|
||||
}
|
||||
|
||||
let build_info = module
|
||||
.getattr("build_info")
|
||||
.expect("module should expose build_info")
|
||||
.call0()
|
||||
.expect("build_info should be callable")
|
||||
.cast_into::<PyDict>()
|
||||
.expect("build_info should return a dict");
|
||||
let mut keys: Vec<String> = build_info
|
||||
.keys()
|
||||
.extract::<Vec<String>>()
|
||||
.expect("build_info keys should be strings");
|
||||
keys.sort();
|
||||
assert_eq!(
|
||||
keys,
|
||||
[
|
||||
"abi3",
|
||||
"debug_assertions",
|
||||
"gil_disabled",
|
||||
"profile",
|
||||
"pyo3"
|
||||
]
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue