mirror of
https://github.com/astral-sh/uv.git
synced 2025-10-27 18:36:44 +00:00
Allow uv format in unmanaged projects (#15553)
Some checks are pending
CI / Determine changes (push) Waiting to run
CI / lint (push) Waiting to run
CI / cargo clippy | ubuntu (push) Blocked by required conditions
CI / cargo test | ubuntu (push) Blocked by required conditions
CI / cargo test | windows (push) Blocked by required conditions
CI / check windows trampoline | aarch64 (push) Blocked by required conditions
CI / check windows trampoline | i686 (push) Blocked by required conditions
CI / test windows trampoline | aarch64 (push) Blocked by required conditions
CI / build binary | linux aarch64 (push) Blocked by required conditions
CI / build binary | macos x86_64 (push) Blocked by required conditions
CI / build binary | windows x86_64 (push) Blocked by required conditions
CI / build binary | windows aarch64 (push) Blocked by required conditions
CI / ecosystem test | pydantic/pydantic-core (push) Blocked by required conditions
CI / ecosystem test | prefecthq/prefect (push) Blocked by required conditions
CI / ecosystem test | pallets/flask (push) Blocked by required conditions
CI / smoke test | linux aarch64 (push) Blocked by required conditions
CI / check system | alpine (push) Blocked by required conditions
CI / cargo clippy | windows (push) Blocked by required conditions
CI / cargo dev generate-all (push) Blocked by required conditions
CI / cargo shear (push) Waiting to run
CI / cargo test | macos (push) Blocked by required conditions
CI / check windows trampoline | x86_64 (push) Blocked by required conditions
CI / test windows trampoline | i686 (push) Blocked by required conditions
CI / test windows trampoline | x86_64 (push) Blocked by required conditions
CI / typos (push) Waiting to run
CI / mkdocs (push) Waiting to run
CI / build binary | linux libc (push) Blocked by required conditions
CI / build binary | linux musl (push) Blocked by required conditions
CI / build binary | macos aarch64 (push) Blocked by required conditions
CI / build binary | msrv (push) Blocked by required conditions
CI / build binary | freebsd (push) Blocked by required conditions
CI / smoke test | linux (push) Blocked by required conditions
CI / smoke test | macos (push) Blocked by required conditions
CI / smoke test | windows x86_64 (push) Blocked by required conditions
CI / smoke test | windows aarch64 (push) Blocked by required conditions
CI / integration test | conda on ubuntu (push) Blocked by required conditions
CI / integration test | deadsnakes python3.9 on ubuntu (push) Blocked by required conditions
CI / integration test | pypy on windows (push) Blocked by required conditions
CI / integration test | free-threaded on windows (push) Blocked by required conditions
CI / integration test | aarch64 windows implicit (push) Blocked by required conditions
CI / integration test | aarch64 windows explicit (push) Blocked by required conditions
CI / integration test | pypy on ubuntu (push) Blocked by required conditions
CI / integration test | graalpy on ubuntu (push) Blocked by required conditions
CI / integration test | graalpy on windows (push) Blocked by required conditions
CI / integration test | pyodide on ubuntu (push) Blocked by required conditions
CI / integration test | github actions (push) Blocked by required conditions
CI / integration test | free-threaded python on github actions (push) Blocked by required conditions
CI / check system | python on debian (push) Blocked by required conditions
CI / check system | python on fedora (push) Blocked by required conditions
CI / check system | python on ubuntu (push) Blocked by required conditions
CI / check system | python on rocky linux 8 (push) Blocked by required conditions
CI / check system | python on rocky linux 9 (push) Blocked by required conditions
CI / check system | graalpy on ubuntu (push) Blocked by required conditions
CI / check system | pypy on ubuntu (push) Blocked by required conditions
CI / check system | pyston (push) Blocked by required conditions
CI / check system | python on macos aarch64 (push) Blocked by required conditions
CI / check system | homebrew python on macos aarch64 (push) Blocked by required conditions
CI / check system | x86-64 python on macos aarch64 (push) Blocked by required conditions
CI / check system | python on macos x86-64 (push) Blocked by required conditions
CI / check system | python3.10 on windows x86-64 (push) Blocked by required conditions
CI / check system | python3.10 on windows x86 (push) Blocked by required conditions
CI / check system | python3.13 on windows x86-64 (push) Blocked by required conditions
CI / check system | x86-64 python3.13 on windows aarch64 (push) Blocked by required conditions
CI / check system | aarch64 python3.13 on windows aarch64 (push) Blocked by required conditions
CI / check system | windows registry (push) Blocked by required conditions
CI / check system | python3.12 via chocolatey (push) Blocked by required conditions
CI / check system | python3.9 via pyenv (push) Blocked by required conditions
CI / integration test | pyenv on wsl x86-64 (push) Blocked by required conditions
CI / integration test | determine publish changes (push) Blocked by required conditions
CI / integration test | registries (push) Blocked by required conditions
CI / integration test | uv publish (push) Blocked by required conditions
CI / integration test | uv_build (push) Blocked by required conditions
CI / check cache | ubuntu (push) Blocked by required conditions
CI / check cache | macos aarch64 (push) Blocked by required conditions
CI / check system | python3.13 (push) Blocked by required conditions
CI / check system | conda3.11 on macos aarch64 (push) Blocked by required conditions
CI / check system | conda3.8 on macos aarch64 (push) Blocked by required conditions
CI / check system | conda3.11 on linux x86-64 (push) Blocked by required conditions
CI / check system | conda3.8 on linux x86-64 (push) Blocked by required conditions
CI / check system | conda3.11 on windows x86-64 (push) Blocked by required conditions
CI / check system | conda3.8 on windows x86-64 (push) Blocked by required conditions
CI / check system | amazonlinux (push) Blocked by required conditions
CI / check system | embedded python3.10 on windows x86-64 (push) Blocked by required conditions
CI / benchmarks | walltime aarch64 linux (push) Blocked by required conditions
CI / benchmarks | instrumented (push) Blocked by required conditions
zizmor / Run zizmor (push) Waiting to run
Some checks are pending
CI / Determine changes (push) Waiting to run
CI / lint (push) Waiting to run
CI / cargo clippy | ubuntu (push) Blocked by required conditions
CI / cargo test | ubuntu (push) Blocked by required conditions
CI / cargo test | windows (push) Blocked by required conditions
CI / check windows trampoline | aarch64 (push) Blocked by required conditions
CI / check windows trampoline | i686 (push) Blocked by required conditions
CI / test windows trampoline | aarch64 (push) Blocked by required conditions
CI / build binary | linux aarch64 (push) Blocked by required conditions
CI / build binary | macos x86_64 (push) Blocked by required conditions
CI / build binary | windows x86_64 (push) Blocked by required conditions
CI / build binary | windows aarch64 (push) Blocked by required conditions
CI / ecosystem test | pydantic/pydantic-core (push) Blocked by required conditions
CI / ecosystem test | prefecthq/prefect (push) Blocked by required conditions
CI / ecosystem test | pallets/flask (push) Blocked by required conditions
CI / smoke test | linux aarch64 (push) Blocked by required conditions
CI / check system | alpine (push) Blocked by required conditions
CI / cargo clippy | windows (push) Blocked by required conditions
CI / cargo dev generate-all (push) Blocked by required conditions
CI / cargo shear (push) Waiting to run
CI / cargo test | macos (push) Blocked by required conditions
CI / check windows trampoline | x86_64 (push) Blocked by required conditions
CI / test windows trampoline | i686 (push) Blocked by required conditions
CI / test windows trampoline | x86_64 (push) Blocked by required conditions
CI / typos (push) Waiting to run
CI / mkdocs (push) Waiting to run
CI / build binary | linux libc (push) Blocked by required conditions
CI / build binary | linux musl (push) Blocked by required conditions
CI / build binary | macos aarch64 (push) Blocked by required conditions
CI / build binary | msrv (push) Blocked by required conditions
CI / build binary | freebsd (push) Blocked by required conditions
CI / smoke test | linux (push) Blocked by required conditions
CI / smoke test | macos (push) Blocked by required conditions
CI / smoke test | windows x86_64 (push) Blocked by required conditions
CI / smoke test | windows aarch64 (push) Blocked by required conditions
CI / integration test | conda on ubuntu (push) Blocked by required conditions
CI / integration test | deadsnakes python3.9 on ubuntu (push) Blocked by required conditions
CI / integration test | pypy on windows (push) Blocked by required conditions
CI / integration test | free-threaded on windows (push) Blocked by required conditions
CI / integration test | aarch64 windows implicit (push) Blocked by required conditions
CI / integration test | aarch64 windows explicit (push) Blocked by required conditions
CI / integration test | pypy on ubuntu (push) Blocked by required conditions
CI / integration test | graalpy on ubuntu (push) Blocked by required conditions
CI / integration test | graalpy on windows (push) Blocked by required conditions
CI / integration test | pyodide on ubuntu (push) Blocked by required conditions
CI / integration test | github actions (push) Blocked by required conditions
CI / integration test | free-threaded python on github actions (push) Blocked by required conditions
CI / check system | python on debian (push) Blocked by required conditions
CI / check system | python on fedora (push) Blocked by required conditions
CI / check system | python on ubuntu (push) Blocked by required conditions
CI / check system | python on rocky linux 8 (push) Blocked by required conditions
CI / check system | python on rocky linux 9 (push) Blocked by required conditions
CI / check system | graalpy on ubuntu (push) Blocked by required conditions
CI / check system | pypy on ubuntu (push) Blocked by required conditions
CI / check system | pyston (push) Blocked by required conditions
CI / check system | python on macos aarch64 (push) Blocked by required conditions
CI / check system | homebrew python on macos aarch64 (push) Blocked by required conditions
CI / check system | x86-64 python on macos aarch64 (push) Blocked by required conditions
CI / check system | python on macos x86-64 (push) Blocked by required conditions
CI / check system | python3.10 on windows x86-64 (push) Blocked by required conditions
CI / check system | python3.10 on windows x86 (push) Blocked by required conditions
CI / check system | python3.13 on windows x86-64 (push) Blocked by required conditions
CI / check system | x86-64 python3.13 on windows aarch64 (push) Blocked by required conditions
CI / check system | aarch64 python3.13 on windows aarch64 (push) Blocked by required conditions
CI / check system | windows registry (push) Blocked by required conditions
CI / check system | python3.12 via chocolatey (push) Blocked by required conditions
CI / check system | python3.9 via pyenv (push) Blocked by required conditions
CI / integration test | pyenv on wsl x86-64 (push) Blocked by required conditions
CI / integration test | determine publish changes (push) Blocked by required conditions
CI / integration test | registries (push) Blocked by required conditions
CI / integration test | uv publish (push) Blocked by required conditions
CI / integration test | uv_build (push) Blocked by required conditions
CI / check cache | ubuntu (push) Blocked by required conditions
CI / check cache | macos aarch64 (push) Blocked by required conditions
CI / check system | python3.13 (push) Blocked by required conditions
CI / check system | conda3.11 on macos aarch64 (push) Blocked by required conditions
CI / check system | conda3.8 on macos aarch64 (push) Blocked by required conditions
CI / check system | conda3.11 on linux x86-64 (push) Blocked by required conditions
CI / check system | conda3.8 on linux x86-64 (push) Blocked by required conditions
CI / check system | conda3.11 on windows x86-64 (push) Blocked by required conditions
CI / check system | conda3.8 on windows x86-64 (push) Blocked by required conditions
CI / check system | amazonlinux (push) Blocked by required conditions
CI / check system | embedded python3.10 on windows x86-64 (push) Blocked by required conditions
CI / benchmarks | walltime aarch64 linux (push) Blocked by required conditions
CI / benchmarks | instrumented (push) Blocked by required conditions
zizmor / Run zizmor (push) Waiting to run
Closes #15550 --------- Co-authored-by: Zanie Blue <contact@zanie.dev>
This commit is contained in:
parent
6eefde28e7
commit
c59ead398d
2 changed files with 163 additions and 6 deletions
|
|
@ -11,7 +11,7 @@ use uv_client::{BaseClientBuilder, retries_from_env};
|
|||
use uv_pep440::Version;
|
||||
use uv_preview::{Preview, PreviewFeatures};
|
||||
use uv_warnings::warn_user;
|
||||
use uv_workspace::{DiscoveryOptions, VirtualProject, WorkspaceCache};
|
||||
use uv_workspace::{DiscoveryOptions, VirtualProject, WorkspaceCache, WorkspaceError};
|
||||
|
||||
use crate::child::run_to_completion;
|
||||
use crate::commands::ExitStatus;
|
||||
|
|
@ -39,9 +39,21 @@ pub(crate) async fn format(
|
|||
}
|
||||
|
||||
let workspace_cache = WorkspaceCache::default();
|
||||
let project =
|
||||
VirtualProject::discover(project_dir, &DiscoveryOptions::default(), &workspace_cache)
|
||||
.await?;
|
||||
let target_dir =
|
||||
match VirtualProject::discover(project_dir, &DiscoveryOptions::default(), &workspace_cache)
|
||||
.await
|
||||
{
|
||||
// If we found a project, we use the project root
|
||||
Ok(proj) => proj.root().to_owned(),
|
||||
// If there is a problem finding a project, we just use the provided directory,
|
||||
// e.g., for unmanaged projects
|
||||
Err(
|
||||
WorkspaceError::MissingPyprojectToml
|
||||
| WorkspaceError::MissingProject(_)
|
||||
| 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()?;
|
||||
|
|
@ -67,8 +79,7 @@ pub(crate) async fn format(
|
|||
.with_context(|| format!("Failed to install ruff {version}"))?;
|
||||
|
||||
let mut command = Command::new(&ruff_path);
|
||||
// Run ruff in the project root
|
||||
command.current_dir(project.root());
|
||||
command.current_dir(target_dir);
|
||||
command.arg("format");
|
||||
|
||||
if check {
|
||||
|
|
|
|||
|
|
@ -43,6 +43,108 @@ fn format_project() -> Result<()> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn format_missing_pyproject_toml() -> Result<()> {
|
||||
let context = TestContext::new_with_versions(&[]);
|
||||
|
||||
// Create an unformatted Python file
|
||||
let main_py = context.temp_dir.child("main.py");
|
||||
main_py.write_str(indoc! {r"
|
||||
x = 1
|
||||
"})?;
|
||||
|
||||
uv_snapshot!(context.filters(), context.format(), @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_missing_project_in_pyproject_toml() -> Result<()> {
|
||||
let context = TestContext::new_with_versions(&[]);
|
||||
|
||||
// Create an empty pyproject.toml with no [project] section
|
||||
context.temp_dir.child("pyproject.toml");
|
||||
|
||||
// Create an unformatted Python file
|
||||
let main_py = context.temp_dir.child("main.py");
|
||||
main_py.write_str(indoc! {r"
|
||||
x = 1
|
||||
"})?;
|
||||
|
||||
uv_snapshot!(context.filters(), context.format(), @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_unmanaged_project() -> Result<()> {
|
||||
let context = TestContext::new_with_versions(&[]);
|
||||
|
||||
let pyproject_toml = context.temp_dir.child("pyproject.toml");
|
||||
pyproject_toml.write_str(indoc! {r#"
|
||||
[project]
|
||||
name = "project"
|
||||
version = "0.1.0"
|
||||
requires-python = ">=3.12"
|
||||
dependencies = []
|
||||
|
||||
[tool.uv]
|
||||
managed = false
|
||||
"#})?;
|
||||
|
||||
// Create an unformatted Python file
|
||||
let main_py = context.temp_dir.child("main.py");
|
||||
main_py.write_str(indoc! {r"
|
||||
x = 1
|
||||
"})?;
|
||||
|
||||
uv_snapshot!(context.filters(), context.format(), @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_from_project_root() -> Result<()> {
|
||||
let context = TestContext::new_with_versions(&[]);
|
||||
|
|
@ -135,6 +237,50 @@ fn format_relative_project() -> Result<()> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn format_fails_malformed_pyproject() -> Result<()> {
|
||||
let context = TestContext::new_with_versions(&[]);
|
||||
|
||||
let pyproject_toml = context.temp_dir.child("pyproject.toml");
|
||||
pyproject_toml.write_str("malformed pyproject.toml")?;
|
||||
|
||||
// Create an unformatted Python file
|
||||
let main_py = context.temp_dir.child("main.py");
|
||||
main_py.write_str(indoc! {r"
|
||||
x = 1
|
||||
"})?;
|
||||
|
||||
uv_snapshot!(context.filters(), context.format(), @r"
|
||||
success: false
|
||||
exit_code: 2
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
warning: Failed to parse `pyproject.toml` during settings discovery:
|
||||
TOML parse error at line 1, column 11
|
||||
|
|
||||
1 | malformed pyproject.toml
|
||||
| ^
|
||||
key with no value, expected `=`
|
||||
|
||||
warning: `uv format` is experimental and may change without warning. Pass `--preview-features format` to disable this warning.
|
||||
error: Failed to parse: `pyproject.toml`
|
||||
Caused by: TOML parse error at line 1, column 11
|
||||
|
|
||||
1 | malformed pyproject.toml
|
||||
| ^
|
||||
key with no value, expected `=`
|
||||
");
|
||||
|
||||
// Check that the file is not formatted
|
||||
let formatted_content = fs_err::read_to_string(&main_py)?;
|
||||
assert_snapshot!(formatted_content, @r"
|
||||
x = 1
|
||||
");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn format_check() -> Result<()> {
|
||||
let context = TestContext::new_with_versions(&[]);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue