mirror of
https://github.com/astral-sh/uv.git
synced 2025-07-08 05:45:00 +00:00
Compare commits
21 commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
7e48292fac | ||
![]() |
e31f556205 | ||
![]() |
dedced3265 | ||
![]() |
5c6d76ca8b | ||
![]() |
1d20530f2d | ||
![]() |
ddb1577a93 | ||
![]() |
d31e6ad7c7 | ||
![]() |
3a77b9cdd9 | ||
![]() |
1d027bd92a | ||
![]() |
bb738aeb44 | ||
![]() |
fc758bb755 | ||
![]() |
1308c85efe | ||
![]() |
f609e1ddaf | ||
![]() |
eaf517efd8 | ||
![]() |
e8bc3950ef | ||
![]() |
06af93fce7 | ||
![]() |
8afbd86f03 | ||
![]() |
a1cda6213c | ||
![]() |
39cdfe9981 | ||
![]() |
85c0fc963b | ||
![]() |
c3f13d2505 |
41 changed files with 459 additions and 271 deletions
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
|
@ -1585,7 +1585,7 @@ jobs:
|
||||||
run: chmod +x ./uv
|
run: chmod +x ./uv
|
||||||
|
|
||||||
- name: "Configure AWS credentials"
|
- name: "Configure AWS credentials"
|
||||||
uses: aws-actions/configure-aws-credentials@3d8cba388a057b13744d61818a337e40a119b1a7
|
uses: aws-actions/configure-aws-credentials@f503a1870408dcf2c35d5c2b8a68e69211042c7d
|
||||||
with:
|
with:
|
||||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||||
|
|
|
@ -12,7 +12,7 @@ repos:
|
||||||
- id: validate-pyproject
|
- id: validate-pyproject
|
||||||
|
|
||||||
- repo: https://github.com/crate-ci/typos
|
- repo: https://github.com/crate-ci/typos
|
||||||
rev: v1.33.1
|
rev: v1.34.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: typos
|
- id: typos
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ repos:
|
||||||
types_or: [yaml, json5]
|
types_or: [yaml, json5]
|
||||||
|
|
||||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||||
rev: v0.12.1
|
rev: v0.12.2
|
||||||
hooks:
|
hooks:
|
||||||
- id: ruff-format
|
- id: ruff-format
|
||||||
- id: ruff
|
- id: ruff
|
||||||
|
|
115
Cargo.lock
generated
115
Cargo.lock
generated
|
@ -189,9 +189,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "async-channel"
|
name = "async-channel"
|
||||||
version = "2.3.1"
|
version = "2.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a"
|
checksum = "924ed96dd52d1b75e9c1a3e6275715fd320f5f9439fb5a4a11fa51f4221158d2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"concurrent-queue",
|
"concurrent-queue",
|
||||||
"event-listener-strategy",
|
"event-listener-strategy",
|
||||||
|
@ -1165,9 +1165,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "event-listener-strategy"
|
name = "event-listener-strategy"
|
||||||
version = "0.5.3"
|
version = "0.5.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3c3e4e0dd3673c1139bf041f3008816d9cf2946bbfac2945c09e523b8d7b05b2"
|
checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"event-listener",
|
"event-listener",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
|
@ -1698,7 +1698,7 @@ dependencies = [
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-rustls",
|
"tokio-rustls",
|
||||||
"tower-service",
|
"tower-service",
|
||||||
"webpki-roots",
|
"webpki-roots 0.26.8",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1707,6 +1707,7 @@ version = "0.1.14"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dc2fdfdbff08affe55bb779f33b053aa1fe5dd5b54c257343c17edfa55711bdb"
|
checksum = "dc2fdfdbff08affe55bb779f33b053aa1fe5dd5b54c257343c17edfa55711bdb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"base64 0.22.1",
|
||||||
"bytes",
|
"bytes",
|
||||||
"futures-channel",
|
"futures-channel",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
|
@ -1714,7 +1715,9 @@ dependencies = [
|
||||||
"http",
|
"http",
|
||||||
"http-body",
|
"http-body",
|
||||||
"hyper",
|
"hyper",
|
||||||
|
"ipnet",
|
||||||
"libc",
|
"libc",
|
||||||
|
"percent-encoding",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"socket2",
|
"socket2",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
@ -1945,6 +1948,16 @@ version = "2.11.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130"
|
checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "iri-string"
|
||||||
|
version = "0.7.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dbc5ebe9c3a1a7a5127f920a418f7585e9e758e911d0466ed004f393b0e380b2"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "is-terminal"
|
name = "is-terminal"
|
||||||
version = "0.4.15"
|
version = "0.4.15"
|
||||||
|
@ -3062,9 +3075,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "reqwest"
|
name = "reqwest"
|
||||||
version = "0.12.15"
|
version = "0.12.22"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d19c46a6fdd48bc4dab94b6103fccc55d34c67cc0ad04653aad4ea2a07cd7bbb"
|
checksum = "cbc931937e6ca3a06e3b6c0aa7841849b160a90351d6ab467a8b9b9959767531"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-compression",
|
"async-compression",
|
||||||
"base64 0.22.1",
|
"base64 0.22.1",
|
||||||
|
@ -3079,18 +3092,14 @@ dependencies = [
|
||||||
"hyper",
|
"hyper",
|
||||||
"hyper-rustls",
|
"hyper-rustls",
|
||||||
"hyper-util",
|
"hyper-util",
|
||||||
"ipnet",
|
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"log",
|
"log",
|
||||||
"mime",
|
|
||||||
"mime_guess",
|
"mime_guess",
|
||||||
"once_cell",
|
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"quinn",
|
"quinn",
|
||||||
"rustls",
|
"rustls",
|
||||||
"rustls-native-certs",
|
"rustls-native-certs",
|
||||||
"rustls-pemfile",
|
|
||||||
"rustls-pki-types",
|
"rustls-pki-types",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
@ -3098,17 +3107,16 @@ dependencies = [
|
||||||
"sync_wrapper",
|
"sync_wrapper",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-rustls",
|
"tokio-rustls",
|
||||||
"tokio-socks",
|
|
||||||
"tokio-util",
|
"tokio-util",
|
||||||
"tower",
|
"tower",
|
||||||
|
"tower-http",
|
||||||
"tower-service",
|
"tower-service",
|
||||||
"url",
|
"url",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
"wasm-bindgen-futures",
|
"wasm-bindgen-futures",
|
||||||
"wasm-streams",
|
"wasm-streams",
|
||||||
"web-sys",
|
"web-sys",
|
||||||
"webpki-roots",
|
"webpki-roots 1.0.1",
|
||||||
"windows-registry 0.4.0",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -3351,15 +3359,6 @@ dependencies = [
|
||||||
"security-framework",
|
"security-framework",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rustls-pemfile"
|
|
||||||
version = "2.2.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50"
|
|
||||||
dependencies = [
|
|
||||||
"rustls-pki-types",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustls-pki-types"
|
name = "rustls-pki-types"
|
||||||
version = "1.11.0"
|
version = "1.11.0"
|
||||||
|
@ -3428,9 +3427,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "schemars"
|
name = "schemars"
|
||||||
version = "1.0.3"
|
version = "1.0.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1375ba8ef45a6f15d83fa8748f1079428295d403d6ea991d09ab100155fbc06d"
|
checksum = "82d20c4491bc164fa2f6c5d44565947a52ad80b9505d8e36f8d54c27c739fcd0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"dyn-clone",
|
"dyn-clone",
|
||||||
"ref-cast",
|
"ref-cast",
|
||||||
|
@ -3442,9 +3441,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "schemars_derive"
|
name = "schemars_derive"
|
||||||
version = "1.0.3"
|
version = "1.0.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2b13ed22d6d49fe23712e068770b5c4df4a693a2b02eeff8e7ca3135627a24f6"
|
checksum = "33d020396d1d138dc19f1165df7545479dcd58d93810dc5d646a16e55abefa80"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -3968,9 +3967,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "test-log"
|
name = "test-log"
|
||||||
version = "0.2.17"
|
version = "0.2.18"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e7f46083d221181166e5b6f6b1e5f1d499f3a76888826e6cb1d057554157cd0f"
|
checksum = "1e33b98a582ea0be1168eba097538ee8dd4bbe0f2b01b22ac92ea30054e5be7b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"test-log-macros",
|
"test-log-macros",
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
|
@ -3978,9 +3977,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "test-log-macros"
|
name = "test-log-macros"
|
||||||
version = "0.2.17"
|
version = "0.2.18"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "888d0c3c6db53c0fdab160d2ed5e12ba745383d3e85813f2ea0f2b1475ab553f"
|
checksum = "451b374529930d7601b1eef8d32bc79ae870b6079b069401709c2a8bf9e75f36"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -4172,18 +4171,6 @@ dependencies = [
|
||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "tokio-socks"
|
|
||||||
version = "0.5.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "0d4770b8024672c1101b3f6733eab95b18007dbe0847a8afe341fcf79e06043f"
|
|
||||||
dependencies = [
|
|
||||||
"either",
|
|
||||||
"futures-util",
|
|
||||||
"thiserror 1.0.69",
|
|
||||||
"tokio",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio-stream"
|
name = "tokio-stream"
|
||||||
version = "0.1.17"
|
version = "0.1.17"
|
||||||
|
@ -4266,6 +4253,24 @@ dependencies = [
|
||||||
"tower-service",
|
"tower-service",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tower-http"
|
||||||
|
version = "0.6.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.9.1",
|
||||||
|
"bytes",
|
||||||
|
"futures-util",
|
||||||
|
"http",
|
||||||
|
"http-body",
|
||||||
|
"iri-string",
|
||||||
|
"pin-project-lite",
|
||||||
|
"tower",
|
||||||
|
"tower-layer",
|
||||||
|
"tower-service",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tower-layer"
|
name = "tower-layer"
|
||||||
version = "0.3.3"
|
version = "0.3.3"
|
||||||
|
@ -5635,7 +5640,7 @@ dependencies = [
|
||||||
"uv-trampoline-builder",
|
"uv-trampoline-builder",
|
||||||
"uv-warnings",
|
"uv-warnings",
|
||||||
"which",
|
"which",
|
||||||
"windows-registry 0.5.3",
|
"windows-registry",
|
||||||
"windows-result 0.3.4",
|
"windows-result 0.3.4",
|
||||||
"windows-sys 0.59.0",
|
"windows-sys 0.59.0",
|
||||||
]
|
]
|
||||||
|
@ -5839,7 +5844,7 @@ dependencies = [
|
||||||
"tracing",
|
"tracing",
|
||||||
"uv-fs",
|
"uv-fs",
|
||||||
"uv-static",
|
"uv-static",
|
||||||
"windows-registry 0.5.3",
|
"windows-registry",
|
||||||
"windows-result 0.3.4",
|
"windows-result 0.3.4",
|
||||||
"windows-sys 0.59.0",
|
"windows-sys 0.59.0",
|
||||||
]
|
]
|
||||||
|
@ -6221,6 +6226,15 @@ dependencies = [
|
||||||
"rustls-pki-types",
|
"rustls-pki-types",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "webpki-roots"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8782dd5a41a24eed3a4f40b606249b3e236ca61adf1f25ea4d45c73de122b502"
|
||||||
|
dependencies = [
|
||||||
|
"rustls-pki-types",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "weezl"
|
name = "weezl"
|
||||||
version = "0.1.8"
|
version = "0.1.8"
|
||||||
|
@ -6448,17 +6462,6 @@ dependencies = [
|
||||||
"windows-link",
|
"windows-link",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows-registry"
|
|
||||||
version = "0.4.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "4286ad90ddb45071efd1a66dfa43eb02dd0dfbae1545ad6cc3c51cf34d7e8ba3"
|
|
||||||
dependencies = [
|
|
||||||
"windows-result 0.3.4",
|
|
||||||
"windows-strings 0.3.1",
|
|
||||||
"windows-targets 0.53.0",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-registry"
|
name = "windows-registry"
|
||||||
version = "0.5.3"
|
version = "0.5.3"
|
||||||
|
|
|
@ -142,7 +142,7 @@ ref-cast = { version = "1.0.24" }
|
||||||
reflink-copy = { version = "0.1.19" }
|
reflink-copy = { version = "0.1.19" }
|
||||||
regex = { version = "1.10.6" }
|
regex = { version = "1.10.6" }
|
||||||
regex-automata = { version = "0.4.8", default-features = false, features = ["dfa-build", "dfa-search", "perf", "std", "syntax"] }
|
regex-automata = { version = "0.4.8", default-features = false, features = ["dfa-build", "dfa-search", "perf", "std", "syntax"] }
|
||||||
reqwest = { version = "=0.12.15", default-features = false, features = ["json", "gzip", "deflate", "zstd", "stream", "rustls-tls", "rustls-tls-native-roots", "socks", "multipart", "http2", "blocking"] }
|
reqwest = { version = "0.12.22", default-features = false, features = ["json", "gzip", "deflate", "zstd", "stream", "rustls-tls", "rustls-tls-native-roots", "socks", "multipart", "http2", "blocking"] }
|
||||||
reqwest-middleware = { git = "https://github.com/astral-sh/reqwest-middleware", rev = "ad8b9d332d1773fde8b4cd008486de5973e0a3f8", features = ["multipart"] }
|
reqwest-middleware = { git = "https://github.com/astral-sh/reqwest-middleware", rev = "ad8b9d332d1773fde8b4cd008486de5973e0a3f8", features = ["multipart"] }
|
||||||
reqwest-retry = { git = "https://github.com/astral-sh/reqwest-middleware", rev = "ad8b9d332d1773fde8b4cd008486de5973e0a3f8" }
|
reqwest-retry = { git = "https://github.com/astral-sh/reqwest-middleware", rev = "ad8b9d332d1773fde8b4cd008486de5973e0a3f8" }
|
||||||
rkyv = { version = "0.8.8", features = ["bytecheck"] }
|
rkyv = { version = "0.8.8", features = ["bytecheck"] }
|
||||||
|
|
|
@ -982,6 +982,45 @@ mod tests {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_redirect_preserves_fragment() -> Result<()> {
|
||||||
|
for status in &[301, 302, 303, 307, 308] {
|
||||||
|
let server = MockServer::start().await;
|
||||||
|
Mock::given(method("GET"))
|
||||||
|
.respond_with(
|
||||||
|
ResponseTemplate::new(*status)
|
||||||
|
.insert_header("location", format!("{}/redirect", server.uri())),
|
||||||
|
)
|
||||||
|
.mount(&server)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
let request = Client::new()
|
||||||
|
.get(format!("{}#fragment", server.uri()))
|
||||||
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let response = Client::builder()
|
||||||
|
.redirect(reqwest::redirect::Policy::none())
|
||||||
|
.build()
|
||||||
|
.unwrap()
|
||||||
|
.execute(request.try_clone().unwrap())
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let redirect_request =
|
||||||
|
request_into_redirect(request, &response, CrossOriginCredentialsPolicy::Secure)?
|
||||||
|
.unwrap();
|
||||||
|
assert!(
|
||||||
|
redirect_request
|
||||||
|
.url()
|
||||||
|
.fragment()
|
||||||
|
.is_some_and(|fragment| fragment == "fragment")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_redirect_removes_authorization_header_on_cross_origin() -> Result<()> {
|
async fn test_redirect_removes_authorization_header_on_cross_origin() -> Result<()> {
|
||||||
for status in &[301, 302, 303, 307, 308] {
|
for status in &[301, 302, 303, 307, 308] {
|
||||||
|
|
|
@ -1416,44 +1416,6 @@ mod tests {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
|
||||||
async fn test_redirect_preserve_fragment() -> Result<(), Error> {
|
|
||||||
let redirect_server = MockServer::start().await;
|
|
||||||
|
|
||||||
// Configure the redirect server to respond with a 307 with a relative URL.
|
|
||||||
Mock::given(method("GET"))
|
|
||||||
.respond_with(ResponseTemplate::new(307).insert_header("Location", "/foo".to_string()))
|
|
||||||
.mount(&redirect_server)
|
|
||||||
.await;
|
|
||||||
|
|
||||||
Mock::given(method("GET"))
|
|
||||||
.and(path_regex("/foo"))
|
|
||||||
.respond_with(ResponseTemplate::new(200))
|
|
||||||
.mount(&redirect_server)
|
|
||||||
.await;
|
|
||||||
|
|
||||||
let cache = Cache::temp()?;
|
|
||||||
let registry_client = RegistryClientBuilder::new(cache).build();
|
|
||||||
let client = registry_client.cached_client().uncached();
|
|
||||||
|
|
||||||
let mut url = DisplaySafeUrl::parse(&redirect_server.uri())?;
|
|
||||||
url.set_fragment(Some("fragment"));
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
client
|
|
||||||
.for_host(&url)
|
|
||||||
.get(Url::from(url.clone()))
|
|
||||||
.send()
|
|
||||||
.await?
|
|
||||||
.url()
|
|
||||||
.to_string(),
|
|
||||||
format!("{}/foo#fragment", redirect_server.uri()),
|
|
||||||
"Requests should preserve fragment"
|
|
||||||
);
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn ignore_failing_files() {
|
fn ignore_failing_files() {
|
||||||
// 1.7.7 has an invalid requires-python field (double comma), 1.7.8 is valid
|
// 1.7.7 has an invalid requires-python field (double comma), 1.7.8 is valid
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
use std::{borrow::Cow, str::FromStr};
|
#[cfg(feature = "schemars")]
|
||||||
|
use std::borrow::Cow;
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
use uv_pep508::PackageName;
|
use uv_pep508::PackageName;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use std::str::FromStr;
|
#[cfg(feature = "schemars")]
|
||||||
use std::{borrow::Cow, fmt::Formatter};
|
use std::borrow::Cow;
|
||||||
|
use std::{fmt::Formatter, str::FromStr};
|
||||||
|
|
||||||
use uv_pep440::{Version, VersionSpecifier, VersionSpecifiers, VersionSpecifiersParseError};
|
use uv_pep440::{Version, VersionSpecifier, VersionSpecifiers, VersionSpecifiersParseError};
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
use serde::{Deserialize, Deserializer};
|
use serde::{Deserialize, Deserializer};
|
||||||
use std::{borrow::Cow, str::FromStr};
|
#[cfg(feature = "schemars")]
|
||||||
|
use std::borrow::Cow;
|
||||||
|
use std::str::FromStr;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
/// A host specification (wildcard, or host, with optional scheme and/or port) for which
|
/// A host specification (wildcard, or host, with optional scheme and/or port) for which
|
||||||
|
|
|
@ -365,7 +365,7 @@ impl InstalledDist {
|
||||||
pub fn installer(&self) -> Result<Option<String>, InstalledDistError> {
|
pub fn installer(&self) -> Result<Option<String>, InstalledDistError> {
|
||||||
let path = self.install_path().join("INSTALLER");
|
let path = self.install_path().join("INSTALLER");
|
||||||
match fs::read_to_string(path) {
|
match fs::read_to_string(path) {
|
||||||
Ok(installer) => Ok(Some(installer)),
|
Ok(installer) => Ok(Some(installer.trim().to_owned())),
|
||||||
Err(err) if err.kind() == std::io::ErrorKind::NotFound => Ok(None),
|
Err(err) if err.kind() == std::io::ErrorKind::NotFound => Ok(None),
|
||||||
Err(err) => Err(err.into()),
|
Err(err) => Err(err.into()),
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,9 @@
|
||||||
//! flags set.
|
//! flags set.
|
||||||
|
|
||||||
use serde::{Deserialize, Deserializer, Serialize};
|
use serde::{Deserialize, Deserializer, Serialize};
|
||||||
use std::{borrow::Cow, path::Path};
|
#[cfg(feature = "schemars")]
|
||||||
|
use std::borrow::Cow;
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
use crate::{Index, IndexUrl};
|
use crate::{Index, IndexUrl};
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
use std::{borrow::Cow, ops::Deref};
|
#[cfg(feature = "schemars")]
|
||||||
|
use std::borrow::Cow;
|
||||||
|
use std::ops::Deref;
|
||||||
|
|
||||||
use http::StatusCode;
|
use http::StatusCode;
|
||||||
use rustc_hash::FxHashSet;
|
use rustc_hash::FxHashSet;
|
||||||
|
|
|
@ -2,11 +2,11 @@ use std::{ffi::OsString, path::PathBuf};
|
||||||
|
|
||||||
#[derive(Debug, thiserror::Error)]
|
#[derive(Debug, thiserror::Error)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
#[error(transparent)]
|
#[error("Failed to read from zip file")]
|
||||||
Zip(#[from] zip::result::ZipError),
|
Zip(#[from] zip::result::ZipError),
|
||||||
#[error(transparent)]
|
#[error("Failed to read from zip file")]
|
||||||
AsyncZip(#[from] async_zip::error::ZipError),
|
AsyncZip(#[from] async_zip::error::ZipError),
|
||||||
#[error(transparent)]
|
#[error("I/O operation failed during extraction")]
|
||||||
Io(#[from] std::io::Error),
|
Io(#[from] std::io::Error),
|
||||||
#[error(
|
#[error(
|
||||||
"The top-level of the archive must only contain a list directory, but it contains: {0:?}"
|
"The top-level of the archive must only contain a list directory, but it contains: {0:?}"
|
||||||
|
|
|
@ -18,11 +18,16 @@ use uv_redacted::DisplaySafeUrl;
|
||||||
use crate::Pep508Url;
|
use crate::Pep508Url;
|
||||||
|
|
||||||
/// A wrapper around [`Url`] that preserves the original string.
|
/// A wrapper around [`Url`] that preserves the original string.
|
||||||
|
///
|
||||||
|
/// The original string is not preserved after serialization/deserialization.
|
||||||
#[derive(Debug, Clone, Eq)]
|
#[derive(Debug, Clone, Eq)]
|
||||||
pub struct VerbatimUrl {
|
pub struct VerbatimUrl {
|
||||||
/// The parsed URL.
|
/// The parsed URL.
|
||||||
url: DisplaySafeUrl,
|
url: DisplaySafeUrl,
|
||||||
/// The URL as it was provided by the user.
|
/// The URL as it was provided by the user.
|
||||||
|
///
|
||||||
|
/// Even if originally set, this will be [`None`] after
|
||||||
|
/// serialization/deserialization.
|
||||||
given: Option<ArcStr>,
|
given: Option<ArcStr>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33135,6 +33135,102 @@
|
||||||
"sha256": null,
|
"sha256": null,
|
||||||
"variant": "debug"
|
"variant": "debug"
|
||||||
},
|
},
|
||||||
|
"pypy-3.11.13-darwin-aarch64-none": {
|
||||||
|
"name": "pypy",
|
||||||
|
"arch": {
|
||||||
|
"family": "aarch64",
|
||||||
|
"variant": null
|
||||||
|
},
|
||||||
|
"os": "darwin",
|
||||||
|
"libc": "none",
|
||||||
|
"major": 3,
|
||||||
|
"minor": 11,
|
||||||
|
"patch": 13,
|
||||||
|
"prerelease": "",
|
||||||
|
"url": "https://downloads.python.org/pypy/pypy3.11-v7.3.20-macos_arm64.tar.bz2",
|
||||||
|
"sha256": "84a48e09c97f57df62cc9f01b7a6d8c3e306b6270671d871aa8ab8c06945940d",
|
||||||
|
"variant": null
|
||||||
|
},
|
||||||
|
"pypy-3.11.13-darwin-x86_64-none": {
|
||||||
|
"name": "pypy",
|
||||||
|
"arch": {
|
||||||
|
"family": "x86_64",
|
||||||
|
"variant": null
|
||||||
|
},
|
||||||
|
"os": "darwin",
|
||||||
|
"libc": "none",
|
||||||
|
"major": 3,
|
||||||
|
"minor": 11,
|
||||||
|
"patch": 13,
|
||||||
|
"prerelease": "",
|
||||||
|
"url": "https://downloads.python.org/pypy/pypy3.11-v7.3.20-macos_x86_64.tar.bz2",
|
||||||
|
"sha256": "bb3ae80cf5fca5044af2e42933e7692c7c5e76a828ce0eb6404a5d5da83b313c",
|
||||||
|
"variant": null
|
||||||
|
},
|
||||||
|
"pypy-3.11.13-linux-aarch64-gnu": {
|
||||||
|
"name": "pypy",
|
||||||
|
"arch": {
|
||||||
|
"family": "aarch64",
|
||||||
|
"variant": null
|
||||||
|
},
|
||||||
|
"os": "linux",
|
||||||
|
"libc": "gnu",
|
||||||
|
"major": 3,
|
||||||
|
"minor": 11,
|
||||||
|
"patch": 13,
|
||||||
|
"prerelease": "",
|
||||||
|
"url": "https://downloads.python.org/pypy/pypy3.11-v7.3.20-aarch64.tar.bz2",
|
||||||
|
"sha256": "9347fe691a07fd9df17a1b186554fb9d9e6210178ffef19520a579ce1f9eb741",
|
||||||
|
"variant": null
|
||||||
|
},
|
||||||
|
"pypy-3.11.13-linux-i686-gnu": {
|
||||||
|
"name": "pypy",
|
||||||
|
"arch": {
|
||||||
|
"family": "i686",
|
||||||
|
"variant": null
|
||||||
|
},
|
||||||
|
"os": "linux",
|
||||||
|
"libc": "gnu",
|
||||||
|
"major": 3,
|
||||||
|
"minor": 11,
|
||||||
|
"patch": 13,
|
||||||
|
"prerelease": "",
|
||||||
|
"url": "https://downloads.python.org/pypy/pypy3.11-v7.3.20-linux32.tar.bz2",
|
||||||
|
"sha256": "d08ce15dd61e9ace5e010b047104f0137110a258184e448ea8239472f10cf99b",
|
||||||
|
"variant": null
|
||||||
|
},
|
||||||
|
"pypy-3.11.13-linux-x86_64-gnu": {
|
||||||
|
"name": "pypy",
|
||||||
|
"arch": {
|
||||||
|
"family": "x86_64",
|
||||||
|
"variant": null
|
||||||
|
},
|
||||||
|
"os": "linux",
|
||||||
|
"libc": "gnu",
|
||||||
|
"major": 3,
|
||||||
|
"minor": 11,
|
||||||
|
"patch": 13,
|
||||||
|
"prerelease": "",
|
||||||
|
"url": "https://downloads.python.org/pypy/pypy3.11-v7.3.20-linux64.tar.bz2",
|
||||||
|
"sha256": "1410db3a7ae47603e2b7cbfd7ff6390b891b2e041c9eb4f1599f333677bccb3e",
|
||||||
|
"variant": null
|
||||||
|
},
|
||||||
|
"pypy-3.11.13-windows-x86_64-none": {
|
||||||
|
"name": "pypy",
|
||||||
|
"arch": {
|
||||||
|
"family": "x86_64",
|
||||||
|
"variant": null
|
||||||
|
},
|
||||||
|
"os": "windows",
|
||||||
|
"libc": "none",
|
||||||
|
"major": 3,
|
||||||
|
"minor": 11,
|
||||||
|
"patch": 13,
|
||||||
|
"prerelease": "",
|
||||||
|
"url": "https://downloads.python.org/pypy/pypy3.11-v7.3.20-win64.zip",
|
||||||
|
"sha256": "a8d36f6ceb1d9be6cf24a73b0ba103e7567e396b2f7a33426b05e4a06330755b",
|
||||||
|
"variant": null
|
||||||
|
},
|
||||||
"pypy-3.11.11-darwin-aarch64-none": {
|
"pypy-3.11.11-darwin-aarch64-none": {
|
||||||
"name": "pypy",
|
"name": "pypy",
|
||||||
"arch": {
|
"arch": {
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
#[cfg(feature = "schemars")]
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
|
|
@ -13,10 +13,9 @@ use uv_normalize::PackageName;
|
||||||
use uv_pep440::Version;
|
use uv_pep440::Version;
|
||||||
use uv_types::InstalledPackagesProvider;
|
use uv_types::InstalledPackagesProvider;
|
||||||
|
|
||||||
use crate::preferences::{Entry, Preferences};
|
use crate::preferences::{Entry, PreferenceSource, Preferences};
|
||||||
use crate::prerelease::{AllowPrerelease, PrereleaseStrategy};
|
use crate::prerelease::{AllowPrerelease, PrereleaseStrategy};
|
||||||
use crate::resolution_mode::ResolutionStrategy;
|
use crate::resolution_mode::ResolutionStrategy;
|
||||||
use crate::universal_marker::UniversalMarker;
|
|
||||||
use crate::version_map::{VersionMap, VersionMapDistHandle};
|
use crate::version_map::{VersionMap, VersionMapDistHandle};
|
||||||
use crate::{Exclusions, Manifest, Options, ResolverEnvironment};
|
use crate::{Exclusions, Manifest, Options, ResolverEnvironment};
|
||||||
|
|
||||||
|
@ -188,7 +187,7 @@ impl CandidateSelector {
|
||||||
if index.is_some_and(|index| !entry.index().matches(index)) {
|
if index.is_some_and(|index| !entry.index().matches(index)) {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
Either::Left(std::iter::once((entry.marker(), entry.pin().version())))
|
Either::Left(std::iter::once((entry.pin().version(), entry.source())))
|
||||||
}
|
}
|
||||||
[..] => {
|
[..] => {
|
||||||
type Entries<'a> = SmallVec<[&'a Entry; 3]>;
|
type Entries<'a> = SmallVec<[&'a Entry; 3]>;
|
||||||
|
@ -219,7 +218,7 @@ impl CandidateSelector {
|
||||||
Either::Right(
|
Either::Right(
|
||||||
preferences
|
preferences
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|entry| (entry.marker(), entry.pin().version())),
|
.map(|entry| (entry.pin().version(), entry.source())),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -238,7 +237,7 @@ impl CandidateSelector {
|
||||||
/// Return the first preference that satisfies the current range and is allowed.
|
/// Return the first preference that satisfies the current range and is allowed.
|
||||||
fn get_preferred_from_iter<'a, InstalledPackages: InstalledPackagesProvider>(
|
fn get_preferred_from_iter<'a, InstalledPackages: InstalledPackagesProvider>(
|
||||||
&'a self,
|
&'a self,
|
||||||
preferences: impl Iterator<Item = (&'a UniversalMarker, &'a Version)>,
|
preferences: impl Iterator<Item = (&'a Version, PreferenceSource)>,
|
||||||
package_name: &'a PackageName,
|
package_name: &'a PackageName,
|
||||||
range: &Range<Version>,
|
range: &Range<Version>,
|
||||||
version_maps: &'a [VersionMap],
|
version_maps: &'a [VersionMap],
|
||||||
|
@ -246,7 +245,7 @@ impl CandidateSelector {
|
||||||
reinstall: bool,
|
reinstall: bool,
|
||||||
env: &ResolverEnvironment,
|
env: &ResolverEnvironment,
|
||||||
) -> Option<Candidate<'a>> {
|
) -> Option<Candidate<'a>> {
|
||||||
for (marker, version) in preferences {
|
for (version, source) in preferences {
|
||||||
// Respect the version range for this requirement.
|
// Respect the version range for this requirement.
|
||||||
if !range.contains(version) {
|
if !range.contains(version) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -290,9 +289,14 @@ impl CandidateSelector {
|
||||||
let allow = match self.prerelease_strategy.allows(package_name, env) {
|
let allow = match self.prerelease_strategy.allows(package_name, env) {
|
||||||
AllowPrerelease::Yes => true,
|
AllowPrerelease::Yes => true,
|
||||||
AllowPrerelease::No => false,
|
AllowPrerelease::No => false,
|
||||||
// If the pre-release is "global" (i.e., provided via a lockfile, rather than
|
// If the pre-release was provided via an existing file, rather than from the
|
||||||
// a fork), accept it unless pre-releases are completely banned.
|
// current solve, accept it unless pre-releases are completely banned.
|
||||||
AllowPrerelease::IfNecessary => marker.is_true(),
|
AllowPrerelease::IfNecessary => match source {
|
||||||
|
PreferenceSource::Resolver => false,
|
||||||
|
PreferenceSource::Lock
|
||||||
|
| PreferenceSource::Environment
|
||||||
|
| PreferenceSource::RequirementsTxt => true,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
if !allow {
|
if !allow {
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -3,6 +3,7 @@ use std::fmt::Formatter;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use indexmap::IndexSet;
|
use indexmap::IndexSet;
|
||||||
|
use itertools::Itertools;
|
||||||
use owo_colors::OwoColorize;
|
use owo_colors::OwoColorize;
|
||||||
use pubgrub::{
|
use pubgrub::{
|
||||||
DefaultStringReporter, DerivationTree, Derived, External, Range, Ranges, Reporter, Term,
|
DefaultStringReporter, DerivationTree, Derived, External, Range, Ranges, Reporter, Term,
|
||||||
|
@ -156,7 +157,7 @@ impl<T> From<tokio::sync::mpsc::error::SendError<T>> for ResolveError {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) type ErrorTree = DerivationTree<PubGrubPackage, Range<Version>, UnavailableReason>;
|
pub type ErrorTree = DerivationTree<PubGrubPackage, Range<Version>, UnavailableReason>;
|
||||||
|
|
||||||
/// A wrapper around [`pubgrub::error::NoSolutionError`] that displays a resolution failure report.
|
/// A wrapper around [`pubgrub::error::NoSolutionError`] that displays a resolution failure report.
|
||||||
pub struct NoSolutionError {
|
pub struct NoSolutionError {
|
||||||
|
@ -367,6 +368,11 @@ impl NoSolutionError {
|
||||||
NoSolutionHeader::new(self.env.clone())
|
NoSolutionHeader::new(self.env.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the conflict derivation tree for external analysis
|
||||||
|
pub fn derivation_tree(&self) -> &ErrorTree {
|
||||||
|
&self.error
|
||||||
|
}
|
||||||
|
|
||||||
/// Hint at limiting the resolver environment if universal resolution failed for a target
|
/// Hint at limiting the resolver environment if universal resolution failed for a target
|
||||||
/// that is not the current platform or not the current Python version.
|
/// that is not the current platform or not the current Python version.
|
||||||
fn hint_disjoint_targets(&self, f: &mut Formatter) -> std::fmt::Result {
|
fn hint_disjoint_targets(&self, f: &mut Formatter) -> std::fmt::Result {
|
||||||
|
@ -404,6 +410,15 @@ impl NoSolutionError {
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the packages that are involved in this error.
|
||||||
|
pub fn packages(&self) -> impl Iterator<Item = &PackageName> {
|
||||||
|
self.error
|
||||||
|
.packages()
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(|p| p.name())
|
||||||
|
.unique()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::fmt::Debug for NoSolutionError {
|
impl std::fmt::Debug for NoSolutionError {
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
use std::{borrow::Cow, str::FromStr};
|
#[cfg(feature = "schemars")]
|
||||||
|
use std::borrow::Cow;
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
use jiff::{Timestamp, ToSpan, tz::TimeZone};
|
use jiff::{Timestamp, ToSpan, tz::TimeZone};
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
pub use dependency_mode::DependencyMode;
|
pub use dependency_mode::DependencyMode;
|
||||||
pub use error::{NoSolutionError, NoSolutionHeader, ResolveError, SentinelRange};
|
pub use error::{ErrorTree, NoSolutionError, NoSolutionHeader, ResolveError, SentinelRange};
|
||||||
pub use exclude_newer::ExcludeNewer;
|
pub use exclude_newer::ExcludeNewer;
|
||||||
pub use exclusions::Exclusions;
|
pub use exclusions::Exclusions;
|
||||||
pub use flat_index::{FlatDistributions, FlatIndex};
|
pub use flat_index::{FlatDistributions, FlatIndex};
|
||||||
|
@ -54,7 +54,7 @@ mod options;
|
||||||
mod pins;
|
mod pins;
|
||||||
mod preferences;
|
mod preferences;
|
||||||
mod prerelease;
|
mod prerelease;
|
||||||
mod pubgrub;
|
pub mod pubgrub;
|
||||||
mod python_requirement;
|
mod python_requirement;
|
||||||
mod redirect;
|
mod redirect;
|
||||||
mod resolution;
|
mod resolution;
|
||||||
|
|
|
@ -34,6 +34,8 @@ pub struct Preference {
|
||||||
/// is part of, otherwise `None`.
|
/// is part of, otherwise `None`.
|
||||||
fork_markers: Vec<UniversalMarker>,
|
fork_markers: Vec<UniversalMarker>,
|
||||||
hashes: HashDigests,
|
hashes: HashDigests,
|
||||||
|
/// The source of the preference.
|
||||||
|
source: PreferenceSource,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Preference {
|
impl Preference {
|
||||||
|
@ -73,6 +75,7 @@ impl Preference {
|
||||||
.map(String::as_str)
|
.map(String::as_str)
|
||||||
.map(HashDigest::from_str)
|
.map(HashDigest::from_str)
|
||||||
.collect::<Result<_, _>>()?,
|
.collect::<Result<_, _>>()?,
|
||||||
|
source: PreferenceSource::RequirementsTxt,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,6 +94,7 @@ impl Preference {
|
||||||
index: PreferenceIndex::from(package.index(install_path)?),
|
index: PreferenceIndex::from(package.index(install_path)?),
|
||||||
fork_markers: package.fork_markers().to_vec(),
|
fork_markers: package.fork_markers().to_vec(),
|
||||||
hashes: HashDigests::empty(),
|
hashes: HashDigests::empty(),
|
||||||
|
source: PreferenceSource::Lock,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,6 +116,7 @@ impl Preference {
|
||||||
// `pylock.toml` doesn't have fork annotations.
|
// `pylock.toml` doesn't have fork annotations.
|
||||||
fork_markers: vec![],
|
fork_markers: vec![],
|
||||||
hashes: HashDigests::empty(),
|
hashes: HashDigests::empty(),
|
||||||
|
source: PreferenceSource::Lock,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,6 +132,7 @@ impl Preference {
|
||||||
index: PreferenceIndex::Any,
|
index: PreferenceIndex::Any,
|
||||||
fork_markers: vec![],
|
fork_markers: vec![],
|
||||||
hashes: HashDigests::empty(),
|
hashes: HashDigests::empty(),
|
||||||
|
source: PreferenceSource::Environment,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,11 +177,24 @@ impl From<Option<IndexUrl>> for PreferenceIndex {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
pub(crate) enum PreferenceSource {
|
||||||
|
/// The preference is from an installed package in the environment.
|
||||||
|
Environment,
|
||||||
|
/// The preference is from a `uv.ock` file.
|
||||||
|
Lock,
|
||||||
|
/// The preference is from a `requirements.txt` file.
|
||||||
|
RequirementsTxt,
|
||||||
|
/// The preference is from the current solve.
|
||||||
|
Resolver,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub(crate) struct Entry {
|
pub(crate) struct Entry {
|
||||||
marker: UniversalMarker,
|
marker: UniversalMarker,
|
||||||
index: PreferenceIndex,
|
index: PreferenceIndex,
|
||||||
pin: Pin,
|
pin: Pin,
|
||||||
|
source: PreferenceSource,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Entry {
|
impl Entry {
|
||||||
|
@ -193,6 +212,11 @@ impl Entry {
|
||||||
pub(crate) fn pin(&self) -> &Pin {
|
pub(crate) fn pin(&self) -> &Pin {
|
||||||
&self.pin
|
&self.pin
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return the source of the entry.
|
||||||
|
pub(crate) fn source(&self) -> PreferenceSource {
|
||||||
|
self.source
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A set of pinned packages that should be preserved during resolution, if possible.
|
/// A set of pinned packages that should be preserved during resolution, if possible.
|
||||||
|
@ -245,6 +269,7 @@ impl Preferences {
|
||||||
version: preference.version,
|
version: preference.version,
|
||||||
hashes: preference.hashes,
|
hashes: preference.hashes,
|
||||||
},
|
},
|
||||||
|
source: preference.source,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
for fork_marker in preference.fork_markers {
|
for fork_marker in preference.fork_markers {
|
||||||
|
@ -255,6 +280,7 @@ impl Preferences {
|
||||||
version: preference.version.clone(),
|
version: preference.version.clone(),
|
||||||
hashes: preference.hashes.clone(),
|
hashes: preference.hashes.clone(),
|
||||||
},
|
},
|
||||||
|
source: preference.source,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -270,11 +296,13 @@ impl Preferences {
|
||||||
index: Option<IndexUrl>,
|
index: Option<IndexUrl>,
|
||||||
markers: UniversalMarker,
|
markers: UniversalMarker,
|
||||||
pin: impl Into<Pin>,
|
pin: impl Into<Pin>,
|
||||||
|
source: PreferenceSource,
|
||||||
) {
|
) {
|
||||||
self.0.entry(package_name).or_default().push(Entry {
|
self.0.entry(package_name).or_default().push(Entry {
|
||||||
marker: markers,
|
marker: markers,
|
||||||
index: PreferenceIndex::from(index),
|
index: PreferenceIndex::from(index),
|
||||||
pin: pin.into(),
|
pin: pin.into(),
|
||||||
|
source,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
pub(crate) use crate::pubgrub::dependencies::PubGrubDependency;
|
pub(crate) use crate::pubgrub::dependencies::PubGrubDependency;
|
||||||
pub(crate) use crate::pubgrub::distribution::PubGrubDistribution;
|
pub(crate) use crate::pubgrub::distribution::PubGrubDistribution;
|
||||||
pub(crate) use crate::pubgrub::package::{PubGrubPackage, PubGrubPackageInner, PubGrubPython};
|
pub use crate::pubgrub::package::{PubGrubPackage, PubGrubPackageInner, PubGrubPython};
|
||||||
pub(crate) use crate::pubgrub::priority::{PubGrubPriorities, PubGrubPriority, PubGrubTiebreaker};
|
pub(crate) use crate::pubgrub::priority::{PubGrubPriorities, PubGrubPriority, PubGrubTiebreaker};
|
||||||
pub(crate) use crate::pubgrub::report::PubGrubReportFormatter;
|
pub(crate) use crate::pubgrub::report::PubGrubReportFormatter;
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ use crate::python_requirement::PythonRequirement;
|
||||||
|
|
||||||
/// [`Arc`] wrapper around [`PubGrubPackageInner`] to make cloning (inside PubGrub) cheap.
|
/// [`Arc`] wrapper around [`PubGrubPackageInner`] to make cloning (inside PubGrub) cheap.
|
||||||
#[derive(Debug, Clone, Eq, Hash, PartialEq, PartialOrd, Ord)]
|
#[derive(Debug, Clone, Eq, Hash, PartialEq, PartialOrd, Ord)]
|
||||||
pub(crate) struct PubGrubPackage(Arc<PubGrubPackageInner>);
|
pub struct PubGrubPackage(Arc<PubGrubPackageInner>);
|
||||||
|
|
||||||
impl Deref for PubGrubPackage {
|
impl Deref for PubGrubPackage {
|
||||||
type Target = PubGrubPackageInner;
|
type Target = PubGrubPackageInner;
|
||||||
|
@ -39,7 +39,7 @@ impl From<PubGrubPackageInner> for PubGrubPackage {
|
||||||
/// package (e.g., `black[colorama]`), and mark it as a dependency of the real package (e.g.,
|
/// package (e.g., `black[colorama]`), and mark it as a dependency of the real package (e.g.,
|
||||||
/// `black`). We then discard the virtual packages at the end of the resolution process.
|
/// `black`). We then discard the virtual packages at the end of the resolution process.
|
||||||
#[derive(Debug, Clone, Eq, Hash, PartialEq, PartialOrd, Ord)]
|
#[derive(Debug, Clone, Eq, Hash, PartialEq, PartialOrd, Ord)]
|
||||||
pub(crate) enum PubGrubPackageInner {
|
pub enum PubGrubPackageInner {
|
||||||
/// The root package, which is used to start the resolution process.
|
/// The root package, which is used to start the resolution process.
|
||||||
Root(Option<PackageName>),
|
Root(Option<PackageName>),
|
||||||
/// A Python version.
|
/// A Python version.
|
||||||
|
@ -295,7 +295,7 @@ impl PubGrubPackage {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, PartialOrd, Hash, Ord)]
|
#[derive(Debug, Copy, Clone, Eq, PartialEq, PartialOrd, Hash, Ord)]
|
||||||
pub(crate) enum PubGrubPython {
|
pub enum PubGrubPython {
|
||||||
/// The Python version installed in the current environment.
|
/// The Python version installed in the current environment.
|
||||||
Installed,
|
Installed,
|
||||||
/// The Python version for which dependencies are being resolved.
|
/// The Python version for which dependencies are being resolved.
|
||||||
|
|
|
@ -7,7 +7,7 @@ use uv_platform_tags::{AbiTag, Tags};
|
||||||
|
|
||||||
/// The reason why a package or a version cannot be used.
|
/// The reason why a package or a version cannot be used.
|
||||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||||
pub(crate) enum UnavailableReason {
|
pub enum UnavailableReason {
|
||||||
/// The entire package cannot be used.
|
/// The entire package cannot be used.
|
||||||
Package(UnavailablePackage),
|
Package(UnavailablePackage),
|
||||||
/// A single version cannot be used.
|
/// A single version cannot be used.
|
||||||
|
@ -29,7 +29,7 @@ impl Display for UnavailableReason {
|
||||||
/// Most variant are from [`MetadataResponse`] without the error source, since we don't format
|
/// Most variant are from [`MetadataResponse`] without the error source, since we don't format
|
||||||
/// the source and we want to merge unavailable messages across versions.
|
/// the source and we want to merge unavailable messages across versions.
|
||||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||||
pub(crate) enum UnavailableVersion {
|
pub enum UnavailableVersion {
|
||||||
/// Version is incompatible because it has no usable distributions
|
/// Version is incompatible because it has no usable distributions
|
||||||
IncompatibleDist(IncompatibleDist),
|
IncompatibleDist(IncompatibleDist),
|
||||||
/// The wheel metadata was found, but could not be parsed.
|
/// The wheel metadata was found, but could not be parsed.
|
||||||
|
@ -123,7 +123,7 @@ impl From<&MetadataUnavailable> for UnavailableVersion {
|
||||||
|
|
||||||
/// The package is unavailable and cannot be used.
|
/// The package is unavailable and cannot be used.
|
||||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||||
pub(crate) enum UnavailablePackage {
|
pub enum UnavailablePackage {
|
||||||
/// Index lookups were disabled (i.e., `--no-index`) and the package was not found in a flat index (i.e. from `--find-links`).
|
/// Index lookups were disabled (i.e., `--no-index`) and the package was not found in a flat index (i.e. from `--find-links`).
|
||||||
NoIndex,
|
NoIndex,
|
||||||
/// Network requests were disabled (i.e., `--offline`), and the package was not found in the cache.
|
/// Network requests were disabled (i.e., `--offline`), and the package was not found in the cache.
|
||||||
|
|
|
@ -47,7 +47,7 @@ use crate::fork_strategy::ForkStrategy;
|
||||||
use crate::fork_urls::ForkUrls;
|
use crate::fork_urls::ForkUrls;
|
||||||
use crate::manifest::Manifest;
|
use crate::manifest::Manifest;
|
||||||
use crate::pins::FilePins;
|
use crate::pins::FilePins;
|
||||||
use crate::preferences::Preferences;
|
use crate::preferences::{PreferenceSource, Preferences};
|
||||||
use crate::pubgrub::{
|
use crate::pubgrub::{
|
||||||
PubGrubDependency, PubGrubDistribution, PubGrubPackage, PubGrubPackageInner, PubGrubPriorities,
|
PubGrubDependency, PubGrubDistribution, PubGrubPackage, PubGrubPackageInner, PubGrubPriorities,
|
||||||
PubGrubPython,
|
PubGrubPython,
|
||||||
|
@ -447,6 +447,7 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag
|
||||||
.try_universal_markers()
|
.try_universal_markers()
|
||||||
.unwrap_or(UniversalMarker::TRUE),
|
.unwrap_or(UniversalMarker::TRUE),
|
||||||
version.clone(),
|
version.clone(),
|
||||||
|
PreferenceSource::Resolver,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
//!
|
//!
|
||||||
//! Then lowers them into a dependency specification.
|
//! Then lowers them into a dependency specification.
|
||||||
|
|
||||||
|
#[cfg(feature = "schemars")]
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::fmt::Formatter;
|
use std::fmt::Formatter;
|
||||||
|
|
|
@ -933,7 +933,7 @@ impl ValidatedLock {
|
||||||
lock.prerelease_mode().cyan(),
|
lock.prerelease_mode().cyan(),
|
||||||
options.prerelease_mode.cyan()
|
options.prerelease_mode.cyan()
|
||||||
);
|
);
|
||||||
return Ok(Self::Unusable(lock));
|
return Ok(Self::Preferable(lock));
|
||||||
}
|
}
|
||||||
if lock.fork_strategy() != options.fork_strategy {
|
if lock.fork_strategy() != options.fork_strategy {
|
||||||
let _ = writeln!(
|
let _ = writeln!(
|
||||||
|
|
|
@ -1730,7 +1730,7 @@ pub(crate) async fn resolve_names(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub(crate) enum PreferenceSource<'lock> {
|
pub(crate) enum PreferenceLocation<'lock> {
|
||||||
/// The preferences should be extracted from a lockfile.
|
/// The preferences should be extracted from a lockfile.
|
||||||
Lock {
|
Lock {
|
||||||
lock: &'lock Lock,
|
lock: &'lock Lock,
|
||||||
|
@ -1745,7 +1745,7 @@ pub(crate) struct EnvironmentSpecification<'lock> {
|
||||||
/// The requirements to include in the environment.
|
/// The requirements to include in the environment.
|
||||||
requirements: RequirementsSpecification,
|
requirements: RequirementsSpecification,
|
||||||
/// The preferences to respect when resolving.
|
/// The preferences to respect when resolving.
|
||||||
preferences: Option<PreferenceSource<'lock>>,
|
preferences: Option<PreferenceLocation<'lock>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<RequirementsSpecification> for EnvironmentSpecification<'_> {
|
impl From<RequirementsSpecification> for EnvironmentSpecification<'_> {
|
||||||
|
@ -1758,9 +1758,9 @@ impl From<RequirementsSpecification> for EnvironmentSpecification<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'lock> EnvironmentSpecification<'lock> {
|
impl<'lock> EnvironmentSpecification<'lock> {
|
||||||
/// Set the [`PreferenceSource`] for the specification.
|
/// Set the [`PreferenceLocation`] for the specification.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub(crate) fn with_preferences(self, preferences: PreferenceSource<'lock>) -> Self {
|
pub(crate) fn with_preferences(self, preferences: PreferenceLocation<'lock>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
preferences: Some(preferences),
|
preferences: Some(preferences),
|
||||||
..self
|
..self
|
||||||
|
@ -1869,7 +1869,7 @@ pub(crate) async fn resolve_environment(
|
||||||
|
|
||||||
// If an existing lockfile exists, build up a set of preferences.
|
// If an existing lockfile exists, build up a set of preferences.
|
||||||
let preferences = match spec.preferences {
|
let preferences = match spec.preferences {
|
||||||
Some(PreferenceSource::Lock { lock, install_path }) => {
|
Some(PreferenceLocation::Lock { lock, install_path }) => {
|
||||||
let LockedRequirements { preferences, git } =
|
let LockedRequirements { preferences, git } =
|
||||||
read_lock_requirements(lock, install_path, &upgrade)?;
|
read_lock_requirements(lock, install_path, &upgrade)?;
|
||||||
|
|
||||||
|
@ -1881,7 +1881,7 @@ pub(crate) async fn resolve_environment(
|
||||||
|
|
||||||
preferences
|
preferences
|
||||||
}
|
}
|
||||||
Some(PreferenceSource::Entries(entries)) => entries,
|
Some(PreferenceLocation::Entries(entries)) => entries,
|
||||||
None => vec![],
|
None => vec![],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -49,7 +49,7 @@ use crate::commands::project::install_target::InstallTarget;
|
||||||
use crate::commands::project::lock::LockMode;
|
use crate::commands::project::lock::LockMode;
|
||||||
use crate::commands::project::lock_target::LockTarget;
|
use crate::commands::project::lock_target::LockTarget;
|
||||||
use crate::commands::project::{
|
use crate::commands::project::{
|
||||||
EnvironmentSpecification, PreferenceSource, ProjectEnvironment, ProjectError,
|
EnvironmentSpecification, PreferenceLocation, ProjectEnvironment, ProjectError,
|
||||||
ScriptEnvironment, ScriptInterpreter, UniversalState, WorkspacePython,
|
ScriptEnvironment, ScriptInterpreter, UniversalState, WorkspacePython,
|
||||||
default_dependency_groups, script_specification, update_environment,
|
default_dependency_groups, script_specification, update_environment,
|
||||||
validate_project_requires_python,
|
validate_project_requires_python,
|
||||||
|
@ -958,10 +958,10 @@ hint: If you are running a script with `{}` in the shebang, you may need to incl
|
||||||
let spec = EnvironmentSpecification::from(spec).with_preferences(
|
let spec = EnvironmentSpecification::from(spec).with_preferences(
|
||||||
if let Some((lock, install_path)) = base_lock.as_ref() {
|
if let Some((lock, install_path)) = base_lock.as_ref() {
|
||||||
// If we have a lockfile, use the locked versions as preferences.
|
// If we have a lockfile, use the locked versions as preferences.
|
||||||
PreferenceSource::Lock { lock, install_path }
|
PreferenceLocation::Lock { lock, install_path }
|
||||||
} else {
|
} else {
|
||||||
// Otherwise, extract preferences from the base environment.
|
// Otherwise, extract preferences from the base environment.
|
||||||
PreferenceSource::Entries(
|
PreferenceLocation::Entries(
|
||||||
base_site_packages
|
base_site_packages
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(Preference::from_installed)
|
.filter_map(Preference::from_installed)
|
||||||
|
|
|
@ -385,7 +385,7 @@ async fn lock_and_sync(
|
||||||
let default_groups = default_dependency_groups(project.pyproject_toml())?;
|
let default_groups = default_dependency_groups(project.pyproject_toml())?;
|
||||||
let default_extras = DefaultExtras::default();
|
let default_extras = DefaultExtras::default();
|
||||||
let groups = DependencyGroups::default().with_defaults(default_groups);
|
let groups = DependencyGroups::default().with_defaults(default_groups);
|
||||||
let extras = ExtrasSpecification::from_all_extras().with_defaults(default_extras);
|
let extras = ExtrasSpecification::default().with_defaults(default_extras);
|
||||||
let install_options = InstallOptions::default();
|
let install_options = InstallOptions::default();
|
||||||
|
|
||||||
// Convert to an `AddTarget` by attaching the appropriate interpreter or environment.
|
// Convert to an `AddTarget` by attaching the appropriate interpreter or environment.
|
||||||
|
|
|
@ -15,7 +15,7 @@ fn build_basic() -> Result<()> {
|
||||||
let filters = context
|
let filters = context
|
||||||
.filters()
|
.filters()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.chain([(r"exit code: 1", "exit status: 1"), (r"\\\.", "")])
|
.chain([(r"\\\.", "")])
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let project = context.temp_dir.child("project");
|
let project = context.temp_dir.child("project");
|
||||||
|
@ -133,7 +133,7 @@ fn build_sdist() -> Result<()> {
|
||||||
let filters = context
|
let filters = context
|
||||||
.filters()
|
.filters()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.chain([(r"exit code: 1", "exit status: 1"), (r"\\\.", "")])
|
.chain([(r"\\\.", "")])
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let project = context.temp_dir.child("project");
|
let project = context.temp_dir.child("project");
|
||||||
|
@ -189,7 +189,7 @@ fn build_wheel() -> Result<()> {
|
||||||
let filters = context
|
let filters = context
|
||||||
.filters()
|
.filters()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.chain([(r"exit code: 1", "exit status: 1"), (r"\\\.", "")])
|
.chain([(r"\\\.", "")])
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let project = context.temp_dir.child("project");
|
let project = context.temp_dir.child("project");
|
||||||
|
@ -245,7 +245,7 @@ fn build_sdist_wheel() -> Result<()> {
|
||||||
let filters = context
|
let filters = context
|
||||||
.filters()
|
.filters()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.chain([(r"exit code: 1", "exit status: 1"), (r"\\\.", "")])
|
.chain([(r"\\\.", "")])
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let project = context.temp_dir.child("project");
|
let project = context.temp_dir.child("project");
|
||||||
|
@ -303,7 +303,7 @@ fn build_wheel_from_sdist() -> Result<()> {
|
||||||
let filters = context
|
let filters = context
|
||||||
.filters()
|
.filters()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.chain([(r"exit code: 1", "exit status: 1"), (r"\\\.", "")])
|
.chain([(r"\\\.", "")])
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let project = context.temp_dir.child("project");
|
let project = context.temp_dir.child("project");
|
||||||
|
@ -412,7 +412,7 @@ fn build_fail() -> Result<()> {
|
||||||
let filters = context
|
let filters = context
|
||||||
.filters()
|
.filters()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.chain([(r"exit code: 1", "exit status: 1"), (r"\\\.", "")])
|
.chain([(r"\\\.", "")])
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let project = context.temp_dir.child("project");
|
let project = context.temp_dir.child("project");
|
||||||
|
@ -488,7 +488,6 @@ fn build_workspace() -> Result<()> {
|
||||||
.filters()
|
.filters()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.chain([
|
.chain([
|
||||||
(r"exit code: 1", "exit status: 1"),
|
|
||||||
(r"\\\.", ""),
|
(r"\\\.", ""),
|
||||||
(r"\[project\]", "[PKG]"),
|
(r"\[project\]", "[PKG]"),
|
||||||
(r"\[member\]", "[PKG]"),
|
(r"\[member\]", "[PKG]"),
|
||||||
|
@ -694,7 +693,6 @@ fn build_all_with_failure() -> Result<()> {
|
||||||
.filters()
|
.filters()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.chain([
|
.chain([
|
||||||
(r"exit code: 1", "exit status: 1"),
|
|
||||||
(r"\\\.", ""),
|
(r"\\\.", ""),
|
||||||
(r"\[project\]", "[PKG]"),
|
(r"\[project\]", "[PKG]"),
|
||||||
(r"\[member-\w+\]", "[PKG]"),
|
(r"\[member-\w+\]", "[PKG]"),
|
||||||
|
@ -840,7 +838,7 @@ fn build_constraints() -> Result<()> {
|
||||||
let filters = context
|
let filters = context
|
||||||
.filters()
|
.filters()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.chain([(r"exit code: 1", "exit status: 1"), (r"\\\.", "")])
|
.chain([(r"\\\.", "")])
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let project = context.temp_dir.child("project");
|
let project = context.temp_dir.child("project");
|
||||||
|
@ -901,7 +899,7 @@ fn build_sha() -> Result<()> {
|
||||||
let filters = context
|
let filters = context
|
||||||
.filters()
|
.filters()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.chain([(r"exit code: 1", "exit status: 1"), (r"\\\.", "")])
|
.chain([(r"\\\.", "")])
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let project = context.temp_dir.child("project");
|
let project = context.temp_dir.child("project");
|
||||||
|
@ -1187,7 +1185,7 @@ fn build_tool_uv_sources() -> Result<()> {
|
||||||
let filters = context
|
let filters = context
|
||||||
.filters()
|
.filters()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.chain([(r"exit code: 1", "exit status: 1"), (r"\\\.", "")])
|
.chain([(r"\\\.", "")])
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let build = context.temp_dir.child("backend");
|
let build = context.temp_dir.child("backend");
|
||||||
|
@ -1337,7 +1335,6 @@ fn build_non_package() -> Result<()> {
|
||||||
.filters()
|
.filters()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.chain([
|
.chain([
|
||||||
(r"exit code: 1", "exit status: 1"),
|
|
||||||
(r"\\\.", ""),
|
(r"\\\.", ""),
|
||||||
(r"\[project\]", "[PKG]"),
|
(r"\[project\]", "[PKG]"),
|
||||||
(r"\[member\]", "[PKG]"),
|
(r"\[member\]", "[PKG]"),
|
||||||
|
@ -1930,7 +1927,7 @@ fn build_with_nonnormalized_name() -> Result<()> {
|
||||||
let filters = context
|
let filters = context
|
||||||
.filters()
|
.filters()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.chain([(r"exit code: 1", "exit status: 1"), (r"\\\.", "")])
|
.chain([(r"\\\.", "")])
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let project = context.temp_dir.child("project");
|
let project = context.temp_dir.child("project");
|
||||||
|
@ -1981,3 +1978,60 @@ fn build_with_nonnormalized_name() -> Result<()> {
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Check that `--force-pep517` is respected.
|
||||||
|
///
|
||||||
|
/// The error messages for a broken project are different for direct builds vs. PEP 517.
|
||||||
|
#[test]
|
||||||
|
fn force_pep517() -> Result<()> {
|
||||||
|
// We need to use a real `uv_build` package.
|
||||||
|
let context = TestContext::new("3.12").with_exclude_newer("2025-05-27T00:00:00Z");
|
||||||
|
|
||||||
|
context
|
||||||
|
.init()
|
||||||
|
.arg("--build-backend")
|
||||||
|
.arg("uv")
|
||||||
|
.assert()
|
||||||
|
.success();
|
||||||
|
|
||||||
|
let pyproject_toml = context.temp_dir.child("pyproject.toml");
|
||||||
|
pyproject_toml.write_str(indoc! {r#"
|
||||||
|
[project]
|
||||||
|
name = "project"
|
||||||
|
version = "1.0.0"
|
||||||
|
|
||||||
|
[tool.uv.build-backend]
|
||||||
|
module-name = "does_not_exist"
|
||||||
|
|
||||||
|
[build-system]
|
||||||
|
requires = ["uv_build>=0.5.15,<10000"]
|
||||||
|
build-backend = "uv_build"
|
||||||
|
"#})?;
|
||||||
|
|
||||||
|
uv_snapshot!(context.filters(), context.build().env("RUST_BACKTRACE", "0"), @r"
|
||||||
|
success: false
|
||||||
|
exit_code: 2
|
||||||
|
----- stdout -----
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
Building source distribution (uv build backend)...
|
||||||
|
× Failed to build `[TEMP_DIR]/`
|
||||||
|
╰─▶ Expected a Python module at: `src/does_not_exist/__init__.py`
|
||||||
|
");
|
||||||
|
|
||||||
|
uv_snapshot!(context.filters(), context.build().arg("--force-pep517").env("RUST_BACKTRACE", "0"), @r"
|
||||||
|
success: false
|
||||||
|
exit_code: 2
|
||||||
|
----- stdout -----
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
Building source distribution...
|
||||||
|
Error: Missing module directory for `does_not_exist` in `src`. Found: `temp`
|
||||||
|
× Failed to build `[TEMP_DIR]/`
|
||||||
|
├─▶ The build backend returned an error
|
||||||
|
╰─▶ Call to `uv_build.build_sdist` failed (exit status: 1)
|
||||||
|
hint: This usually indicates a problem with the package or the build environment.
|
||||||
|
");
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
|
@ -517,6 +517,8 @@ impl TestContext {
|
||||||
if cfg!(windows) {
|
if cfg!(windows) {
|
||||||
filters.push((" --link-mode <LINK_MODE>".to_string(), String::new()));
|
filters.push((" --link-mode <LINK_MODE>".to_string(), String::new()));
|
||||||
filters.push((r#"link-mode = "copy"\n"#.to_string(), String::new()));
|
filters.push((r#"link-mode = "copy"\n"#.to_string(), String::new()));
|
||||||
|
// Unix uses "exit status", Windows uses "exit code"
|
||||||
|
filters.push((r"exit code: ".to_string(), "exit status: ".to_string()));
|
||||||
}
|
}
|
||||||
|
|
||||||
filters.extend(
|
filters.extend(
|
||||||
|
|
|
@ -7246,10 +7246,7 @@ fn fail_to_add_revert_project() -> Result<()> {
|
||||||
.child("setup.py")
|
.child("setup.py")
|
||||||
.write_str("1/0")?;
|
.write_str("1/0")?;
|
||||||
|
|
||||||
let filters = std::iter::once((r"exit code: 1", "exit status: 1"))
|
uv_snapshot!(context.filters(), context.add().arg("./child"), @r#"
|
||||||
.chain(context.filters())
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
uv_snapshot!(filters, context.add().arg("./child"), @r#"
|
|
||||||
success: false
|
success: false
|
||||||
exit_code: 1
|
exit_code: 1
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
|
@ -7351,10 +7348,7 @@ fn fail_to_edit_revert_project() -> Result<()> {
|
||||||
.child("setup.py")
|
.child("setup.py")
|
||||||
.write_str("1/0")?;
|
.write_str("1/0")?;
|
||||||
|
|
||||||
let filters = std::iter::once((r"exit code: 1", "exit status: 1"))
|
uv_snapshot!(context.filters(), context.add().arg("./child"), @r#"
|
||||||
.chain(context.filters())
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
uv_snapshot!(filters, context.add().arg("./child"), @r#"
|
|
||||||
success: false
|
success: false
|
||||||
exit_code: 1
|
exit_code: 1
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
|
|
|
@ -23617,10 +23617,7 @@ fn lock_derivation_chain_prod() -> Result<()> {
|
||||||
let filters = context
|
let filters = context
|
||||||
.filters()
|
.filters()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.chain([
|
.chain([(r"/.*/src", "/[TMP]/src")])
|
||||||
(r"exit code: 1", "exit status: 1"),
|
|
||||||
(r"/.*/src", "/[TMP]/src"),
|
|
||||||
])
|
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
uv_snapshot!(filters, context.lock(), @r###"
|
uv_snapshot!(filters, context.lock(), @r###"
|
||||||
|
@ -23677,10 +23674,7 @@ fn lock_derivation_chain_extra() -> Result<()> {
|
||||||
let filters = context
|
let filters = context
|
||||||
.filters()
|
.filters()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.chain([
|
.chain([(r"/.*/src", "/[TMP]/src")])
|
||||||
(r"exit code: 1", "exit status: 1"),
|
|
||||||
(r"/.*/src", "/[TMP]/src"),
|
|
||||||
])
|
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
uv_snapshot!(filters, context.lock(), @r###"
|
uv_snapshot!(filters, context.lock(), @r###"
|
||||||
|
@ -23739,10 +23733,7 @@ fn lock_derivation_chain_group() -> Result<()> {
|
||||||
let filters = context
|
let filters = context
|
||||||
.filters()
|
.filters()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.chain([
|
.chain([(r"/.*/src", "/[TMP]/src")])
|
||||||
(r"exit code: 1", "exit status: 1"),
|
|
||||||
(r"/.*/src", "/[TMP]/src"),
|
|
||||||
])
|
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
uv_snapshot!(filters, context.lock(), @r###"
|
uv_snapshot!(filters, context.lock(), @r###"
|
||||||
|
@ -23812,10 +23803,7 @@ fn lock_derivation_chain_extended() -> Result<()> {
|
||||||
let filters = context
|
let filters = context
|
||||||
.filters()
|
.filters()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.chain([
|
.chain([(r"/.*/src", "/[TMP]/src")])
|
||||||
(r"exit code: 1", "exit status: 1"),
|
|
||||||
(r"/.*/src", "/[TMP]/src"),
|
|
||||||
])
|
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
uv_snapshot!(filters, context.lock(), @r###"
|
uv_snapshot!(filters, context.lock(), @r###"
|
||||||
|
|
|
@ -14679,10 +14679,7 @@ fn compile_derivation_chain() -> Result<()> {
|
||||||
let filters = context
|
let filters = context
|
||||||
.filters()
|
.filters()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.chain([
|
.chain([(r"/.*/src", "/[TMP]/src")])
|
||||||
(r"exit code: 1", "exit status: 1"),
|
|
||||||
(r"/.*/src", "/[TMP]/src"),
|
|
||||||
])
|
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
uv_snapshot!(filters, context.pip_compile().arg("pyproject.toml"), @r###"
|
uv_snapshot!(filters, context.pip_compile().arg("pyproject.toml"), @r###"
|
||||||
|
|
|
@ -342,10 +342,7 @@ dependencies = ["flask==1.0.x"]
|
||||||
let requirements_txt = context.temp_dir.child("requirements.txt");
|
let requirements_txt = context.temp_dir.child("requirements.txt");
|
||||||
requirements_txt.write_str("./path_dep")?;
|
requirements_txt.write_str("./path_dep")?;
|
||||||
|
|
||||||
let filters = std::iter::once((r"exit code: 1", "exit status: 1"))
|
uv_snapshot!(context.filters(), context.pip_install()
|
||||||
.chain(context.filters())
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
uv_snapshot!(filters, context.pip_install()
|
|
||||||
.arg("-r")
|
.arg("-r")
|
||||||
.arg("requirements.txt"), @r###"
|
.arg("requirements.txt"), @r###"
|
||||||
success: false
|
success: false
|
||||||
|
@ -4930,10 +4927,7 @@ fn no_build_isolation() -> Result<()> {
|
||||||
requirements_in.write_str("anyio @ https://files.pythonhosted.org/packages/db/4d/3970183622f0330d3c23d9b8a5f52e365e50381fd484d08e3285104333d3/anyio-4.3.0.tar.gz")?;
|
requirements_in.write_str("anyio @ https://files.pythonhosted.org/packages/db/4d/3970183622f0330d3c23d9b8a5f52e365e50381fd484d08e3285104333d3/anyio-4.3.0.tar.gz")?;
|
||||||
|
|
||||||
// We expect the build to fail, because `setuptools` is not installed.
|
// We expect the build to fail, because `setuptools` is not installed.
|
||||||
let filters = std::iter::once((r"exit code: 1", "exit status: 1"))
|
uv_snapshot!(context.filters(), context.pip_install()
|
||||||
.chain(context.filters())
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
uv_snapshot!(filters, context.pip_install()
|
|
||||||
.arg("-r")
|
.arg("-r")
|
||||||
.arg("requirements.in")
|
.arg("requirements.in")
|
||||||
.arg("--no-build-isolation"), @r###"
|
.arg("--no-build-isolation"), @r###"
|
||||||
|
@ -5001,10 +4995,7 @@ fn respect_no_build_isolation_env_var() -> Result<()> {
|
||||||
requirements_in.write_str("anyio @ https://files.pythonhosted.org/packages/db/4d/3970183622f0330d3c23d9b8a5f52e365e50381fd484d08e3285104333d3/anyio-4.3.0.tar.gz")?;
|
requirements_in.write_str("anyio @ https://files.pythonhosted.org/packages/db/4d/3970183622f0330d3c23d9b8a5f52e365e50381fd484d08e3285104333d3/anyio-4.3.0.tar.gz")?;
|
||||||
|
|
||||||
// We expect the build to fail, because `setuptools` is not installed.
|
// We expect the build to fail, because `setuptools` is not installed.
|
||||||
let filters = std::iter::once((r"exit code: 1", "exit status: 1"))
|
uv_snapshot!(context.filters(), context.pip_install()
|
||||||
.chain(context.filters())
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
uv_snapshot!(filters, context.pip_install()
|
|
||||||
.arg("-r")
|
.arg("-r")
|
||||||
.arg("requirements.in")
|
.arg("requirements.in")
|
||||||
.env(EnvVars::UV_NO_BUILD_ISOLATION, "yes"), @r###"
|
.env(EnvVars::UV_NO_BUILD_ISOLATION, "yes"), @r###"
|
||||||
|
@ -8601,10 +8592,7 @@ fn install_build_isolation_package() -> Result<()> {
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
// Running `uv pip install` should fail for iniconfig.
|
// Running `uv pip install` should fail for iniconfig.
|
||||||
let filters = std::iter::once((r"exit code: 1", "exit status: 1"))
|
uv_snapshot!(context.filters(), context.pip_install()
|
||||||
.chain(context.filters())
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
uv_snapshot!(filters, context.pip_install()
|
|
||||||
.arg("--no-build-isolation-package")
|
.arg("--no-build-isolation-package")
|
||||||
.arg("iniconfig")
|
.arg("iniconfig")
|
||||||
.arg(package.path()), @r###"
|
.arg(package.path()), @r###"
|
||||||
|
@ -8931,10 +8919,7 @@ fn missing_top_level() {
|
||||||
fn sklearn() {
|
fn sklearn() {
|
||||||
let context = TestContext::new("3.12");
|
let context = TestContext::new("3.12");
|
||||||
|
|
||||||
let filters = std::iter::once((r"exit code: 1", "exit status: 1"))
|
uv_snapshot!(context.filters(), context.pip_install().arg("sklearn"), @r###"
|
||||||
.chain(context.filters())
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
uv_snapshot!(filters, context.pip_install().arg("sklearn"), @r###"
|
|
||||||
success: false
|
success: false
|
||||||
exit_code: 1
|
exit_code: 1
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
|
@ -8984,10 +8969,7 @@ fn resolve_derivation_chain() -> Result<()> {
|
||||||
let filters = context
|
let filters = context
|
||||||
.filters()
|
.filters()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.chain([
|
.chain([(r"/.*/src", "/[TMP]/src")])
|
||||||
(r"exit code: 1", "exit status: 1"),
|
|
||||||
(r"/.*/src", "/[TMP]/src"),
|
|
||||||
])
|
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
uv_snapshot!(filters, context.pip_install()
|
uv_snapshot!(filters, context.pip_install()
|
||||||
|
|
|
@ -1122,10 +1122,7 @@ fn sync_build_isolation_package() -> Result<()> {
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
// Running `uv sync` should fail for iniconfig.
|
// Running `uv sync` should fail for iniconfig.
|
||||||
let filters = std::iter::once((r"exit code: 1", "exit status: 1"))
|
uv_snapshot!(context.filters(), context.sync().arg("--no-build-isolation-package").arg("source-distribution"), @r###"
|
||||||
.chain(context.filters())
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
uv_snapshot!(filters, context.sync().arg("--no-build-isolation-package").arg("source-distribution"), @r###"
|
|
||||||
success: false
|
success: false
|
||||||
exit_code: 1
|
exit_code: 1
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
|
@ -1215,10 +1212,7 @@ fn sync_build_isolation_extra() -> Result<()> {
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
// Running `uv sync` should fail for the `compile` extra.
|
// Running `uv sync` should fail for the `compile` extra.
|
||||||
let filters = std::iter::once((r"exit code: 1", "exit status: 1"))
|
uv_snapshot!(context.filters(), context.sync().arg("--extra").arg("compile"), @r###"
|
||||||
.chain(context.filters())
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
uv_snapshot!(&filters, context.sync().arg("--extra").arg("compile"), @r###"
|
|
||||||
success: false
|
success: false
|
||||||
exit_code: 1
|
exit_code: 1
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
|
@ -1239,7 +1233,7 @@ fn sync_build_isolation_extra() -> Result<()> {
|
||||||
"###);
|
"###);
|
||||||
|
|
||||||
// Running `uv sync` with `--all-extras` should also fail.
|
// Running `uv sync` with `--all-extras` should also fail.
|
||||||
uv_snapshot!(&filters, context.sync().arg("--all-extras"), @r###"
|
uv_snapshot!(context.filters(), context.sync().arg("--all-extras"), @r###"
|
||||||
success: false
|
success: false
|
||||||
exit_code: 1
|
exit_code: 1
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
|
@ -6985,10 +6979,7 @@ fn sync_derivation_chain() -> Result<()> {
|
||||||
let filters = context
|
let filters = context
|
||||||
.filters()
|
.filters()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.chain([
|
.chain([(r"/.*/src", "/[TMP]/src")])
|
||||||
(r"exit code: 1", "exit status: 1"),
|
|
||||||
(r"/.*/src", "/[TMP]/src"),
|
|
||||||
])
|
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
uv_snapshot!(filters, context.sync(), @r###"
|
uv_snapshot!(filters, context.sync(), @r###"
|
||||||
|
@ -7051,10 +7042,7 @@ fn sync_derivation_chain_extra() -> Result<()> {
|
||||||
let filters = context
|
let filters = context
|
||||||
.filters()
|
.filters()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.chain([
|
.chain([(r"/.*/src", "/[TMP]/src")])
|
||||||
(r"exit code: 1", "exit status: 1"),
|
|
||||||
(r"/.*/src", "/[TMP]/src"),
|
|
||||||
])
|
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
uv_snapshot!(filters, context.sync().arg("--extra").arg("wsgi"), @r###"
|
uv_snapshot!(filters, context.sync().arg("--extra").arg("wsgi"), @r###"
|
||||||
|
@ -7119,10 +7107,7 @@ fn sync_derivation_chain_group() -> Result<()> {
|
||||||
let filters = context
|
let filters = context
|
||||||
.filters()
|
.filters()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.chain([
|
.chain([(r"/.*/src", "/[TMP]/src")])
|
||||||
(r"exit code: 1", "exit status: 1"),
|
|
||||||
(r"/.*/src", "/[TMP]/src"),
|
|
||||||
])
|
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
uv_snapshot!(filters, context.sync().arg("--group").arg("wsgi"), @r###"
|
uv_snapshot!(filters, context.sync().arg("--group").arg("wsgi"), @r###"
|
||||||
|
|
|
@ -1682,7 +1682,6 @@ fn tool_install_uninstallable() {
|
||||||
.filters()
|
.filters()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.chain([
|
.chain([
|
||||||
(r"exit code: 1", "exit status: 1"),
|
|
||||||
(r"bdist\.[^/\\\s]+(-[^/\\\s]+)?", "bdist.linux-x86_64"),
|
(r"bdist\.[^/\\\s]+(-[^/\\\s]+)?", "bdist.linux-x86_64"),
|
||||||
(r"\\\.", ""),
|
(r"\\\.", ""),
|
||||||
(r"#+", "#"),
|
(r"#+", "#"),
|
||||||
|
|
|
@ -1958,3 +1958,57 @@ fn version_set_evil_constraints() -> Result<()> {
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Bump the version with conflicting extras, to ensure we're activating the correct subset of
|
||||||
|
/// extras during the resolve.
|
||||||
|
#[test]
|
||||||
|
fn version_extras() -> Result<()> {
|
||||||
|
let context = TestContext::new("3.12");
|
||||||
|
|
||||||
|
let pyproject_toml = context.temp_dir.child("pyproject.toml");
|
||||||
|
pyproject_toml.write_str(
|
||||||
|
r#"
|
||||||
|
[project]
|
||||||
|
name = "myproject"
|
||||||
|
version = "1.10.31"
|
||||||
|
requires-python = ">=3.12"
|
||||||
|
|
||||||
|
[project.optional-dependencies]
|
||||||
|
foo = ["requests"]
|
||||||
|
bar = ["httpx"]
|
||||||
|
baz = ["flask"]
|
||||||
|
|
||||||
|
[tool.uv]
|
||||||
|
conflicts = [[{"extra" = "foo"}, {"extra" = "bar"}]]
|
||||||
|
"#,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
uv_snapshot!(context.filters(), context.version()
|
||||||
|
.arg("--bump").arg("patch"), @r"
|
||||||
|
success: true
|
||||||
|
exit_code: 0
|
||||||
|
----- stdout -----
|
||||||
|
myproject 1.10.31 => 1.10.32
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
Resolved 19 packages in [TIME]
|
||||||
|
Audited in [TIME]
|
||||||
|
");
|
||||||
|
|
||||||
|
// Sync an extra, we should not remove it.
|
||||||
|
context.sync().arg("--extra").arg("foo").assert().success();
|
||||||
|
|
||||||
|
uv_snapshot!(context.filters(), context.version()
|
||||||
|
.arg("--bump").arg("patch"), @r"
|
||||||
|
success: true
|
||||||
|
exit_code: 0
|
||||||
|
----- stdout -----
|
||||||
|
myproject 1.10.32 => 1.10.33
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
Resolved 19 packages in [TIME]
|
||||||
|
Audited in [TIME]
|
||||||
|
");
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ jobs:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Install uv
|
- name: Install uv
|
||||||
uses: astral-sh/setup-uv@v5
|
uses: astral-sh/setup-uv@v6
|
||||||
```
|
```
|
||||||
|
|
||||||
It is considered best practice to pin to a specific uv version, e.g., with:
|
It is considered best practice to pin to a specific uv version, e.g., with:
|
||||||
|
@ -44,7 +44,7 @@ jobs:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Install uv
|
- name: Install uv
|
||||||
uses: astral-sh/setup-uv@v5
|
uses: astral-sh/setup-uv@v6
|
||||||
with:
|
with:
|
||||||
# Install a specific version of uv.
|
# Install a specific version of uv.
|
||||||
version: "0.7.19"
|
version: "0.7.19"
|
||||||
|
@ -66,7 +66,7 @@ jobs:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Install uv
|
- name: Install uv
|
||||||
uses: astral-sh/setup-uv@v5
|
uses: astral-sh/setup-uv@v6
|
||||||
|
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
run: uv python install
|
run: uv python install
|
||||||
|
@ -93,10 +93,10 @@ jobs:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Install uv
|
- name: Install uv
|
||||||
uses: astral-sh/setup-uv@v5
|
uses: astral-sh/setup-uv@v6
|
||||||
|
|
||||||
- name: "Set up Python"
|
- name: "Set up Python"
|
||||||
uses: actions/setup-python@v5
|
uses: actions/setup-python@v6
|
||||||
with:
|
with:
|
||||||
python-version-file: ".python-version"
|
python-version-file: ".python-version"
|
||||||
```
|
```
|
||||||
|
@ -116,10 +116,10 @@ jobs:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Install uv
|
- name: Install uv
|
||||||
uses: astral-sh/setup-uv@v5
|
uses: astral-sh/setup-uv@v6
|
||||||
|
|
||||||
- name: "Set up Python"
|
- name: "Set up Python"
|
||||||
uses: actions/setup-python@v5
|
uses: actions/setup-python@v6
|
||||||
with:
|
with:
|
||||||
python-version-file: "pyproject.toml"
|
python-version-file: "pyproject.toml"
|
||||||
```
|
```
|
||||||
|
@ -146,7 +146,7 @@ jobs:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Install uv and set the python version
|
- name: Install uv and set the python version
|
||||||
uses: astral-sh/setup-uv@v5
|
uses: astral-sh/setup-uv@v6
|
||||||
with:
|
with:
|
||||||
python-version: ${{ matrix.python-version }}
|
python-version: ${{ matrix.python-version }}
|
||||||
```
|
```
|
||||||
|
@ -187,7 +187,7 @@ jobs:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Install uv
|
- name: Install uv
|
||||||
uses: astral-sh/setup-uv@v5
|
uses: astral-sh/setup-uv@v6
|
||||||
|
|
||||||
- name: Install the project
|
- name: Install the project
|
||||||
run: uv sync --locked --all-extras --dev
|
run: uv sync --locked --all-extras --dev
|
||||||
|
@ -212,44 +212,11 @@ persisting the cache:
|
||||||
|
|
||||||
```yaml title="example.yml"
|
```yaml title="example.yml"
|
||||||
- name: Enable caching
|
- name: Enable caching
|
||||||
uses: astral-sh/setup-uv@v5
|
uses: astral-sh/setup-uv@v6
|
||||||
with:
|
with:
|
||||||
enable-cache: true
|
enable-cache: true
|
||||||
```
|
```
|
||||||
|
|
||||||
You can configure the action to use a custom cache directory on the runner:
|
|
||||||
|
|
||||||
```yaml title="example.yml"
|
|
||||||
- name: Define a custom uv cache path
|
|
||||||
uses: astral-sh/setup-uv@v5
|
|
||||||
with:
|
|
||||||
enable-cache: true
|
|
||||||
cache-local-path: "/path/to/cache"
|
|
||||||
```
|
|
||||||
|
|
||||||
Or invalidate it when the lockfile changes:
|
|
||||||
|
|
||||||
```yaml title="example.yml"
|
|
||||||
- name: Define a cache dependency glob
|
|
||||||
uses: astral-sh/setup-uv@v5
|
|
||||||
with:
|
|
||||||
enable-cache: true
|
|
||||||
cache-dependency-glob: "uv.lock"
|
|
||||||
```
|
|
||||||
|
|
||||||
Or when any requirements file changes:
|
|
||||||
|
|
||||||
```yaml title="example.yml"
|
|
||||||
- name: Define a cache dependency glob
|
|
||||||
uses: astral-sh/setup-uv@v5
|
|
||||||
with:
|
|
||||||
enable-cache: true
|
|
||||||
cache-dependency-glob: "requirements**.txt"
|
|
||||||
```
|
|
||||||
|
|
||||||
Note that `astral-sh/setup-uv` will automatically use a separate cache key for each host
|
|
||||||
architecture and platform.
|
|
||||||
|
|
||||||
Alternatively, you can manage the cache manually with the `actions/cache` action:
|
Alternatively, you can manage the cache manually with the `actions/cache` action:
|
||||||
|
|
||||||
```yaml title="example.yml"
|
```yaml title="example.yml"
|
||||||
|
|
|
@ -324,7 +324,7 @@ so multiple files are not needed to lock development dependencies.
|
||||||
The uv lockfile is always [universal](../../concepts/resolution.md#universal-resolution), so
|
The uv lockfile is always [universal](../../concepts/resolution.md#universal-resolution), so
|
||||||
multiple files are not needed to
|
multiple files are not needed to
|
||||||
[lock dependencies for each platform](#platform-specific-dependencies). This ensures that all
|
[lock dependencies for each platform](#platform-specific-dependencies). This ensures that all
|
||||||
developers
|
developers are using consistent, locked versions of dependencies regardless of their machine.
|
||||||
|
|
||||||
The uv lockfile also supports concepts like
|
The uv lockfile also supports concepts like
|
||||||
[pinning packages to specific indexes](../../concepts/indexes.md#pinning-a-package-to-an-index),
|
[pinning packages to specific indexes](../../concepts/indexes.md#pinning-a-package-to-an-index),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue