From edbaa1d35b879d0336e5fc1504d3fb69fcf4270b Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Thu, 29 Aug 2024 10:45:08 -0400 Subject: [PATCH] Hint at --no-workspace in uv init failures --- crates/uv-workspace/src/workspace.rs | 8 ++--- crates/uv/src/commands/project/init.rs | 5 ++- crates/uv/tests/init.rs | 48 ++++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 5 deletions(-) diff --git a/crates/uv-workspace/src/workspace.rs b/crates/uv-workspace/src/workspace.rs index d385bdfdcb8a..1d547aaa718a 100644 --- a/crates/uv-workspace/src/workspace.rs +++ b/crates/uv-workspace/src/workspace.rs @@ -158,7 +158,7 @@ impl Workspace { workspace } else if pyproject_toml.project.is_none() { // Without a project, it can't be an implicit root - return Err(WorkspaceError::MissingProject(project_path)); + return Err(WorkspaceError::MissingProject(pyproject_path)); } else if let Some(workspace) = find_workspace(&project_path, options).await? { // We have found an explicit root above. workspace @@ -610,7 +610,7 @@ impl Workspace { }; let pyproject_toml = PyProjectToml::from_string(contents) - .map_err(|err| WorkspaceError::Toml(pyproject_path, Box::new(err)))?; + .map_err(|err| WorkspaceError::Toml(pyproject_path.clone(), Box::new(err)))?; // Check if the current project is explicitly marked as unmanaged. if pyproject_toml @@ -629,7 +629,7 @@ impl Workspace { // Extract the package name. let Some(project) = pyproject_toml.project.clone() else { - return Err(WorkspaceError::MissingProject(member_root)); + return Err(WorkspaceError::MissingProject(pyproject_path)); }; debug!( @@ -825,7 +825,7 @@ impl ProjectWorkspace { let project = pyproject_toml .project .clone() - .ok_or_else(|| WorkspaceError::MissingProject(pyproject_path.clone()))?; + .ok_or_else(|| WorkspaceError::MissingProject(pyproject_path))?; Self::from_project(project_root, &project, &pyproject_toml, options).await } diff --git a/crates/uv/src/commands/project/init.rs b/crates/uv/src/commands/project/init.rs index ef0b89b12474..b5247113ad2b 100644 --- a/crates/uv/src/commands/project/init.rs +++ b/crates/uv/src/commands/project/init.rs @@ -169,7 +169,10 @@ async fn init_project( warn!("Ignoring workspace discovery error due to `--no-workspace`: {err}"); None } else { - return Err(err.into()); + return Err(anyhow::Error::from(err).context(format!( + "Failed to discover parent workspace; use `{}` to ignore", + "uv init --no-workspace".green() + ))); } } } diff --git a/crates/uv/tests/init.rs b/crates/uv/tests/init.rs index aef72a66ceb0..a5e1ad100b17 100644 --- a/crates/uv/tests/init.rs +++ b/crates/uv/tests/init.rs @@ -1767,3 +1767,51 @@ fn init_hidden() { error: Not a valid package or extra name: ".foo". Names must start and end with a letter or digit and may only contain -, _, ., and alphanumeric characters. "###); } + +/// Run `uv init` with an invalid `pyproject.toml` in a parent directory. +#[test] +fn init_failure() -> Result<()> { + let context = TestContext::new("3.12"); + + // Create an empty `pyproject.toml`. + let pyproject_toml = context.temp_dir.child("pyproject.toml"); + pyproject_toml.touch()?; + + uv_snapshot!(context.filters(), context.init().arg("foo"), @r###" + success: false + exit_code: 2 + ----- stdout ----- + + ----- stderr ----- + error: Failed to discover parent workspace; use `uv init --no-workspace` to ignore + Caused by: No `project` table found in: `[TEMP_DIR]/pyproject.toml` + "###); + + uv_snapshot!(context.filters(), context.init().arg("foo").arg("--no-workspace"), @r###" + success: true + exit_code: 0 + ----- stdout ----- + + ----- stderr ----- + Initialized project `foo` at `[TEMP_DIR]/foo` + "###); + + let workspace = fs_err::read_to_string(context.temp_dir.join("foo").join("pyproject.toml"))?; + insta::with_settings!({ + filters => context.filters(), + }, { + assert_snapshot!( + workspace, @r###" + [project] + name = "foo" + version = "0.1.0" + description = "Add your description here" + readme = "README.md" + requires-python = ">=3.12" + dependencies = [] + "### + ); + }); + + Ok(()) +}