diff --git a/crates/uv-cli/src/lib.rs b/crates/uv-cli/src/lib.rs index 8f85f567c..196509877 100644 --- a/crates/uv-cli/src/lib.rs +++ b/crates/uv-cli/src/lib.rs @@ -4461,6 +4461,14 @@ pub struct FormatArgs { /// `uv format -- src/module/foo.py` to format a specific file. #[arg(last = true)] pub extra_args: Vec, + + /// Avoid discovering a project or workspace. + /// + /// Instead of running the formatter in the context of the current project, run it in the + /// context of the current directory. This is useful when the current directory is not a + /// project. + #[arg(long)] + pub no_project: bool, } #[derive(Args)] diff --git a/crates/uv/src/commands/project/format.rs b/crates/uv/src/commands/project/format.rs index 5a2caf19c..f63c74d0e 100644 --- a/crates/uv/src/commands/project/format.rs +++ b/crates/uv/src/commands/project/format.rs @@ -29,6 +29,7 @@ pub(crate) async fn format( cache: Cache, printer: Printer, preview: Preview, + no_project: bool, ) -> Result { // Check if the format feature is in preview if !preview.is_enabled(PreviewFeatures::FORMAT) { @@ -39,7 +40,11 @@ pub(crate) async fn format( } let workspace_cache = WorkspaceCache::default(); - let target_dir = + // If `no_project` is provided, we use the provided directory + // Otherwise, we discover the project and use the project root. + let target_dir = if no_project { + project_dir.to_owned() + } else { match VirtualProject::discover(project_dir, &DiscoveryOptions::default(), &workspace_cache) .await { @@ -53,7 +58,8 @@ pub(crate) async fn format( | WorkspaceError::NonWorkspace(_), ) => project_dir.to_owned(), Err(err) => return Err(err.into()), - }; + } + }; // Parse version if provided let version = version.as_deref().map(Version::from_str).transpose()?; diff --git a/crates/uv/src/lib.rs b/crates/uv/src/lib.rs index d062c6208..95d636732 100644 --- a/crates/uv/src/lib.rs +++ b/crates/uv/src/lib.rs @@ -2283,6 +2283,7 @@ async fn run_project( cache, printer, globals.preview, + args.no_project, )) .await } diff --git a/crates/uv/src/settings.rs b/crates/uv/src/settings.rs index cc597a43b..e3c71649e 100644 --- a/crates/uv/src/settings.rs +++ b/crates/uv/src/settings.rs @@ -1911,6 +1911,7 @@ pub(crate) struct FormatSettings { pub(crate) diff: bool, pub(crate) extra_args: Vec, pub(crate) version: Option, + pub(crate) no_project: bool, } impl FormatSettings { @@ -1921,6 +1922,7 @@ impl FormatSettings { diff, extra_args, version, + no_project, } = args; Self { @@ -1928,6 +1930,7 @@ impl FormatSettings { diff, extra_args, version, + no_project, } } } diff --git a/crates/uv/tests/it/format.rs b/crates/uv/tests/it/format.rs index fe8251e75..78e72ce22 100644 --- a/crates/uv/tests/it/format.rs +++ b/crates/uv/tests/it/format.rs @@ -187,6 +187,34 @@ fn format_from_project_root() -> Result<()> { Ok(()) } +#[test] +fn format_no_project() -> Result<()> { + let context = TestContext::new_with_versions(&[]); + + let main_py = context.temp_dir.child("main.py"); + main_py.write_str(indoc! {r" + x = 1 + "})?; + + uv_snapshot!(context.filters(), context.format().arg("--no-project"), @r" + success: true + exit_code: 0 + ----- stdout ----- + 1 file reformatted + + ----- stderr ----- + warning: `uv format` is experimental and may change without warning. Pass `--preview-features format` to disable this warning. + "); + + // Check that the file was formatted + let formatted_content = fs_err::read_to_string(&main_py)?; + assert_snapshot!(formatted_content, @r" + x = 1 + "); + + Ok(()) +} + #[test] fn format_relative_project() -> Result<()> { let context = TestContext::new_with_versions(&[]); diff --git a/docs/reference/cli.md b/docs/reference/cli.md index 6903c7a79..c494cb4d2 100644 --- a/docs/reference/cli.md +++ b/docs/reference/cli.md @@ -2279,7 +2279,9 @@ uv format [OPTIONS] [-- ...]

Instead, uv will search for a suitable Python version on the system.

May also be set with the UV_NO_MANAGED_PYTHON environment variable.

--no-progress

Hide all progress outputs.

For example, spinners or progress bars.

-

May also be set with the UV_NO_PROGRESS environment variable.

--no-python-downloads

Disable automatic downloads of Python.

+

May also be set with the UV_NO_PROGRESS environment variable.

--no-project

Avoid discovering a project or workspace.

+

Instead of running the formatter in the context of the current project, run it in the context of the current directory. This is useful when the current directory is not a project.

+
--no-python-downloads

Disable automatic downloads of Python.

--offline

Disable network access.

When disabled, uv will only use locally cached data and locally available files.

May also be set with the UV_OFFLINE environment variable.

--project project

Run the command within the given project directory.