diff --git a/Cargo.lock b/Cargo.lock index 488ef19ee592e..9e02fc56a312a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5157,7 +5157,7 @@ dependencies = [ "serde", "textwrap", "thiserror", - "toml_edit", + "toml", "tracing", "uv-cache-info", "uv-configuration", diff --git a/crates/uv-settings/Cargo.toml b/crates/uv-settings/Cargo.toml index 2cbb3320d362d..6be4b49b758f0 100644 --- a/crates/uv-settings/Cargo.toml +++ b/crates/uv-settings/Cargo.toml @@ -34,7 +34,7 @@ schemars = { workspace = true, optional = true } serde = { workspace = true } textwrap = { workspace = true } thiserror = { workspace = true } -toml_edit = { workspace = true } +toml = { workspace = true } tracing = { workspace = true } [package.metadata.cargo-shear] diff --git a/crates/uv-settings/src/lib.rs b/crates/uv-settings/src/lib.rs index 8b002aa63b0c4..6deb4c6ae0c7f 100644 --- a/crates/uv-settings/src/lib.rs +++ b/crates/uv-settings/src/lib.rs @@ -1,8 +1,6 @@ -use serde::de::IntoDeserializer; -use serde::Deserialize; use std::ops::Deref; use std::path::{Path, PathBuf}; -use std::str::FromStr; + use tracing::{debug, warn}; use uv_fs::Simplified; @@ -74,18 +72,10 @@ impl FilesystemOptions { Ok(None) => { // Continue traversing the directory tree. } - Err(Error::PyprojectTomlSchema(file, err)) => { + Err(Error::PyprojectToml(file, err)) => { // If we see an invalid `pyproject.toml`, warn but continue. warn!( - "Failed to parse `{}` during settings discovery due to invalid schema:\n{}", - file.cyan(), - textwrap::indent(&err.to_string(), " ") - ); - } - Err(Error::PyprojectTomlSyntax(file, err)) => { - // If we see an invalid `pyproject.toml`, warn but continue. - warn!( - "Failed to parse `{}` during settings discovery due to invalid syntax:\n{}", + "Failed to parse `{}` during settings discovery:\n{}", file.cyan(), textwrap::indent(&err.to_string(), " ") ); @@ -101,26 +91,20 @@ impl FilesystemOptions { /// Load a [`FilesystemOptions`] from a directory, preferring a `uv.toml` file over a /// `pyproject.toml` file. - fn from_directory(dir: impl AsRef) -> Result, Error> { + pub fn from_directory(dir: impl AsRef) -> Result, Error> { // Read a `uv.toml` file in the current directory. let path = dir.as_ref().join("uv.toml"); match fs_err::read_to_string(&path) { Ok(content) => { - let options: toml_edit::ImDocument<_> = - toml_edit::ImDocument::from_str(&content) - .map_err(|err| Error::UvTomlSyntax(path.user_display().to_string(), err))?; - let options: Options = Options::deserialize(options.into_deserializer()) - .map_err(|err| Error::UvTomlSchema(path.user_display().to_string(), err))?; + let options: Options = toml::from_str(&content) + .map_err(|err| Error::UvToml(path.user_display().to_string(), err))?; // If the directory also contains a `[tool.uv]` table in a `pyproject.toml` file, // warn. let pyproject = dir.as_ref().join("pyproject.toml"); if let Some(pyproject) = fs_err::read_to_string(pyproject) .ok() - .and_then(|content| toml_edit::ImDocument::from_str(&content).ok()) - .and_then(|pyproject| { - PyProjectToml::deserialize(pyproject.into_deserializer()).ok() - }) + .and_then(|content| toml::from_str::(&content).ok()) { if pyproject.tool.is_some_and(|tool| tool.uv.is_some()) { warn!( @@ -141,14 +125,8 @@ impl FilesystemOptions { match fs_err::read_to_string(&path) { Ok(content) => { // Parse, but skip any `pyproject.toml` that doesn't have a `[tool.uv]` section. - let pyproject: toml_edit::ImDocument<_> = toml_edit::ImDocument::from_str(&content) - .map_err(|err| { - Error::PyprojectTomlSyntax(path.user_display().to_string(), err) - })?; - let pyproject: PyProjectToml = - PyProjectToml::deserialize(pyproject.into_deserializer()).map_err(|err| { - Error::PyprojectTomlSchema(path.user_display().to_string(), err) - })?; + let pyproject: PyProjectToml = toml::from_str(&content) + .map_err(|err| Error::PyprojectToml(path.user_display().to_string(), err))?; let Some(tool) = pyproject.tool else { debug!( "Skipping `pyproject.toml` in `{}` (no `[tool]` section)", @@ -210,10 +188,8 @@ fn config_dir() -> Option { /// Load [`Options`] from a `uv.toml` file. fn read_file(path: &Path) -> Result { let content = fs_err::read_to_string(path)?; - let options: toml_edit::ImDocument<_> = toml_edit::ImDocument::from_str(&content) - .map_err(|err| Error::UvTomlSyntax(path.user_display().to_string(), err))?; - let options: Options = Options::deserialize(options.into_deserializer()) - .map_err(|err| Error::UvTomlSchema(path.user_display().to_string(), err))?; + let options: Options = toml::from_str(&content) + .map_err(|err| Error::UvToml(path.user_display().to_string(), err))?; Ok(options) } @@ -223,14 +199,8 @@ pub enum Error { Io(#[from] std::io::Error), #[error("Failed to parse: `{0}`")] - PyprojectTomlSyntax(String, #[source] toml_edit::TomlError), - - #[error("Failed to parse: `{0}`")] - PyprojectTomlSchema(String, #[source] toml_edit::de::Error), - - #[error("Failed to parse: `{0}`")] - UvTomlSyntax(String, #[source] toml_edit::TomlError), + PyprojectToml(String, #[source] toml::de::Error), #[error("Failed to parse: `{0}`")] - UvTomlSchema(String, #[source] toml_edit::de::Error), + UvToml(String, #[source] toml::de::Error), } diff --git a/crates/uv-workspace/src/workspace.rs b/crates/uv-workspace/src/workspace.rs index d07c5c54bd378..f943803ccfa80 100644 --- a/crates/uv-workspace/src/workspace.rs +++ b/crates/uv-workspace/src/workspace.rs @@ -1315,7 +1315,7 @@ fn parse_pyproject_toml( pyproject_path: &Path, contents: &str, ) -> Result { - let pyproject_toml: toml_edit::ImDocument<_> = toml_edit::ImDocument::from_str(&contents) + let pyproject_toml: toml_edit::ImDocument<_> = toml_edit::ImDocument::from_str(contents) .map_err(|err| WorkspaceError::TomlSyntax(pyproject_path.to_path_buf(), Box::new(err)))?; PyProjectToml::deserialize(pyproject_toml.into_deserializer()).map_err(|err| { // TODO(konsti): A typed error would be nicer, this can break on toml upgrades.