From e96354a6dd00d8362bb33388ca0466cef9517e08 Mon Sep 17 00:00:00 2001 From: Zsolt Dollenstein Date: Wed, 12 Nov 2025 17:10:15 +0000 Subject: [PATCH] Always attach linehaul data (#16705) --- crates/uv-client/src/base_client.rs | 8 +++---- crates/uv-client/src/linehaul.rs | 14 +++++------ .../uv-client/tests/it/user_agent_version.rs | 24 +++++++++++++++++-- 3 files changed, 32 insertions(+), 14 deletions(-) diff --git a/crates/uv-client/src/base_client.rs b/crates/uv-client/src/base_client.rs index a834e5e75..97192dcd8 100644 --- a/crates/uv-client/src/base_client.rs +++ b/crates/uv-client/src/base_client.rs @@ -358,11 +358,9 @@ impl<'a> BaseClientBuilder<'a> { let mut user_agent_string = format!("uv/{}", version()); // Add linehaul metadata. - if let Some(markers) = self.markers { - let linehaul = LineHaul::new(markers, self.platform); - if let Ok(output) = serde_json::to_string(&linehaul) { - let _ = write!(user_agent_string, " {output}"); - } + let linehaul = LineHaul::new(self.markers, self.platform); + if let Ok(output) = serde_json::to_string(&linehaul) { + let _ = write!(user_agent_string, " {output}"); } // Check for the presence of an `SSL_CERT_FILE`. diff --git a/crates/uv-client/src/linehaul.rs b/crates/uv-client/src/linehaul.rs index 8d159152d..4eea4f755 100644 --- a/crates/uv-client/src/linehaul.rs +++ b/crates/uv-client/src/linehaul.rs @@ -63,7 +63,7 @@ pub struct LineHaul { impl LineHaul { /// Initializes Linehaul information based on PEP 508 markers. #[instrument(name = "linehaul", skip_all)] - pub fn new(markers: &MarkerEnvironment, platform: Option<&Platform>) -> Self { + pub fn new(markers: Option<&MarkerEnvironment>, platform: Option<&Platform>) -> Self { // https://github.com/pypa/pip/blob/24.0/src/pip/_internal/network/session.py#L87 let looks_like_ci = [ EnvVars::BUILD_BUILDID, @@ -124,17 +124,17 @@ impl LineHaul { name: Some("uv".to_string()), version: Some(version().to_string()), }), - python: Some(markers.python_full_version().version.to_string()), + python: markers.map(|markers| markers.python_full_version().version.to_string()), implementation: Option::from(Implementation { - name: Some(markers.platform_python_implementation().to_string()), - version: Some(markers.python_full_version().version.to_string()), + name: markers.map(|markers| markers.platform_python_implementation().to_string()), + version: markers.map(|markers| markers.python_full_version().version.to_string()), }), distro, system: Option::from(System { - name: Some(markers.platform_system().to_string()), - release: Some(markers.platform_release().to_string()), + name: markers.map(|markers| markers.platform_system().to_string()), + release: markers.map(|markers| markers.platform_release().to_string()), }), - cpu: Some(markers.platform_machine().to_string()), + cpu: markers.map(|markers| markers.platform_machine().to_string()), // Should probably always be None in uv. openssl_version: None, // Should probably always be None in uv. diff --git a/crates/uv-client/tests/it/user_agent_version.rs b/crates/uv-client/tests/it/user_agent_version.rs index bc3e7deef..5c4a1e80c 100644 --- a/crates/uv-client/tests/it/user_agent_version.rs +++ b/crates/uv-client/tests/it/user_agent_version.rs @@ -70,8 +70,28 @@ async fn test_user_agent_has_version() -> Result<()> { // Check User Agent let body = res.text().await?; - // Verify body matches regex - assert_eq!(body, format!("uv/{}", version())); + let (uv_version, uv_linehaul) = body + .split_once(' ') + .expect("Failed to split User-Agent header"); + + // Deserializing Linehaul + let linehaul: LineHaul = serde_json::from_str(uv_linehaul)?; + + // Assert linehaul user agent + let filters = vec![(version(), "[VERSION]")]; + with_settings!({ + filters => filters + }, { + // Assert uv version + assert_snapshot!(uv_version, @"uv/[VERSION]"); + // Assert linehaul json + assert_json_snapshot!(&linehaul.installer, @r#" + { + "name": "uv", + "version": "[VERSION]" + } + "#); + }); // Wait for the server task to complete, to be a good citizen. server_task.await?;