Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions crates/uv-cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4429,6 +4429,14 @@ pub struct FormatArgs {
/// `uv format -- src/module/foo.py` to format a specific file.
#[arg(last = true)]
pub extra_args: Vec<String>,

/// 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)]
Expand Down
10 changes: 8 additions & 2 deletions crates/uv/src/commands/project/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ pub(crate) async fn format(
cache: Cache,
printer: Printer,
preview: Preview,
no_project: bool,
) -> Result<ExitStatus> {
// Check if the format feature is in preview
if !preview.is_enabled(PreviewFeatures::FORMAT) {
Expand All @@ -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
{
Expand All @@ -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()?;
Expand Down
1 change: 1 addition & 0 deletions crates/uv/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2283,6 +2283,7 @@ async fn run_project(
cache,
printer,
globals.preview,
args.no_project,
))
.await
}
Expand Down
3 changes: 3 additions & 0 deletions crates/uv/src/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1908,6 +1908,7 @@ pub(crate) struct FormatSettings {
pub(crate) diff: bool,
pub(crate) extra_args: Vec<String>,
pub(crate) version: Option<String>,
pub(crate) no_project: bool,
}

impl FormatSettings {
Expand All @@ -1918,13 +1919,15 @@ impl FormatSettings {
diff,
extra_args,
version,
no_project,
} = args;

Self {
check,
diff,
extra_args,
version,
no_project,
}
}
}
Expand Down
28 changes: 28 additions & 0 deletions crates/uv/tests/it/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(&[]);
Expand Down
4 changes: 3 additions & 1 deletion docs/reference/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -2277,7 +2277,9 @@ uv format [OPTIONS] [-- <EXTRA_ARGS>...]
<p>Instead, uv will search for a suitable Python version on the system.</p>
<p>May also be set with the <code>UV_NO_MANAGED_PYTHON</code> environment variable.</p></dd><dt id="uv-format--no-progress"><a href="#uv-format--no-progress"><code>--no-progress</code></a></dt><dd><p>Hide all progress outputs.</p>
<p>For example, spinners or progress bars.</p>
<p>May also be set with the <code>UV_NO_PROGRESS</code> environment variable.</p></dd><dt id="uv-format--no-python-downloads"><a href="#uv-format--no-python-downloads"><code>--no-python-downloads</code></a></dt><dd><p>Disable automatic downloads of Python.</p>
<p>May also be set with the <code>UV_NO_PROGRESS</code> environment variable.</p></dd><dt id="uv-format--no-project"><a href="#uv-format--no-project"><code>--no-project</code></a></dt><dd><p>Avoid discovering a project or workspace.</p>
<p>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.</p>
</dd><dt id="uv-format--no-python-downloads"><a href="#uv-format--no-python-downloads"><code>--no-python-downloads</code></a></dt><dd><p>Disable automatic downloads of Python.</p>
</dd><dt id="uv-format--offline"><a href="#uv-format--offline"><code>--offline</code></a></dt><dd><p>Disable network access.</p>
<p>When disabled, uv will only use locally cached data and locally available files.</p>
<p>May also be set with the <code>UV_OFFLINE</code> environment variable.</p></dd><dt id="uv-format--project"><a href="#uv-format--project"><code>--project</code></a> <i>project</i></dt><dd><p>Run the command within the given project directory.</p>
Expand Down
Loading