-
Notifications
You must be signed in to change notification settings - Fork 893
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add rust tests for different URLs in forks
Rust code that uses the files added in the previous commit, currently failing.
- Loading branch information
Showing
1 changed file
with
374 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,374 @@ | ||
use std::env; | ||
use std::path::PathBuf; | ||
use std::process::Command; | ||
|
||
use anyhow::Result; | ||
use insta::assert_snapshot; | ||
|
||
use crate::common::{copy_dir_ignore, get_bin, uv_snapshot, TestContext, EXCLUDE_NEWER}; | ||
|
||
mod common; | ||
|
||
fn lock_command(context: &TestContext) -> Command { | ||
let mut command = Command::new(get_bin()); | ||
command | ||
.arg("lock") | ||
.arg("--preview") | ||
.arg("--cache-dir") | ||
.arg(context.cache_dir.path()) | ||
.arg("--exclude-newer") | ||
.arg(EXCLUDE_NEWER) | ||
.env("VIRTUAL_ENV", context.venv.as_os_str()) | ||
.env("UV_NO_WRAP", "1") | ||
.current_dir(&context.temp_dir); | ||
|
||
if cfg!(all(windows, debug_assertions)) { | ||
// TODO(konstin): Reduce stack usage in debug mode enough that the tests pass with the | ||
// default windows stack of 1MB | ||
command.env("UV_STACK_SIZE", (4 * 1024 * 1024).to_string()); | ||
} | ||
|
||
command | ||
} | ||
|
||
fn branching_urls_dir() -> PathBuf { | ||
env::current_dir() | ||
.unwrap() | ||
.parent() | ||
.unwrap() | ||
.parent() | ||
.unwrap() | ||
.join("scripts") | ||
.join("branching-urls") | ||
} | ||
|
||
/// The root package has diverging URLs for disjoint markers: | ||
/// ```toml | ||
/// dependencies = [ | ||
/// "iniconfig @ https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl ; python_version >= '3.12'", | ||
/// "iniconfig @ https://files.pythonhosted.org/packages/9b/dd/b3c12c6d707058fa947864b67f0c4e0c39ef8610988d7baea9578f3c48f3/iniconfig-1.1.1-py2.py3-none-any.whl ; python_version < '3.12'", | ||
/// ] | ||
/// ``` | ||
#[test] | ||
fn branching_urls_disjoint() -> Result<()> { | ||
let context = TestContext::new("3.12"); | ||
|
||
let scenario = "a1-root-allowed"; | ||
let sources_dir = branching_urls_dir().join(scenario); | ||
let work_dir = context.temp_dir.join(scenario); | ||
copy_dir_ignore(sources_dir, &work_dir)?; | ||
|
||
uv_snapshot!(context.filters(), lock_command(&context).current_dir(&work_dir), @r###" | ||
success: true | ||
exit_code: 0 | ||
----- stdout ----- | ||
----- stderr ----- | ||
Using Python 3.12.[X] interpreter at: [PYTHON-3.12] | ||
Resolved 3 packages in [TIME] | ||
"### | ||
); | ||
|
||
Ok(()) | ||
} | ||
|
||
/// The root package has diverging URLs, but their markers are not disjoint: | ||
/// ```toml | ||
/// dependencies = [ | ||
/// "iniconfig @ https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl ; python_version >= '3.11'", | ||
/// "iniconfig @ https://files.pythonhosted.org/packages/9b/dd/b3c12c6d707058fa947864b67f0c4e0c39ef8610988d7baea9578f3c48f3/iniconfig-1.1.1-py2.py3-none-any.whl ; python_version < '3.12'", | ||
/// ] | ||
/// ``` | ||
#[test] | ||
fn branching_urls_overlapping() -> Result<()> { | ||
let context = TestContext::new("3.12"); | ||
|
||
let scenario = "a2-root-conflict"; | ||
let sources_dir = branching_urls_dir().join(scenario); | ||
let work_dir = context.temp_dir.join(scenario); | ||
copy_dir_ignore(sources_dir, &work_dir)?; | ||
|
||
uv_snapshot!(context.filters(), lock_command(&context).current_dir(&work_dir), @r###" | ||
success: false | ||
exit_code: 2 | ||
----- stdout ----- | ||
----- stderr ----- | ||
Using Python 3.12.[X] interpreter at: [PYTHON-3.12] | ||
error: Requirements contain conflicting URLs for package `iniconfig`: | ||
- https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl | ||
- https://files.pythonhosted.org/packages/9b/dd/b3c12c6d707058fa947864b67f0c4e0c39ef8610988d7baea9578f3c48f3/iniconfig-1.1.1-py2.py3-none-any.whl | ||
"### | ||
); | ||
|
||
Ok(()) | ||
} | ||
|
||
/// The root package has diverging URLs, but transitive dependencies have conflicting URLs. | ||
/// | ||
/// Requirements: | ||
/// ```text | ||
/// a -> anyio (allowed forking urls to force a split) | ||
/// a -> b -> b1 -> https://../iniconfig-1.1.1-py3-none-any.whl | ||
/// a -> b -> b2 -> https://../iniconfig-2.0.0-py3-none-any.whl | ||
/// ``` | ||
#[test] | ||
fn root_package_splits_but_transitive_conflict() -> Result<()> { | ||
let context = TestContext::new("3.12"); | ||
|
||
let scenario = "a3-transitive-conflict"; | ||
let sources_dir = branching_urls_dir().join(scenario); | ||
let work_dir = context.temp_dir.join(scenario); | ||
copy_dir_ignore(sources_dir, &work_dir)?; | ||
|
||
uv_snapshot!(context.filters(), lock_command(&context).current_dir(&work_dir), @r###" | ||
success: false | ||
exit_code: 2 | ||
----- stdout ----- | ||
----- stderr ----- | ||
Using Python 3.12.[X] interpreter at: [PYTHON-3.12] | ||
error: Requirements contain conflicting URLs for package `iniconfig` in split `python_version < '3.12'`: | ||
- https://files.pythonhosted.org/packages/9b/dd/b3c12c6d707058fa947864b67f0c4e0c39ef8610988d7baea9578f3c48f3/iniconfig-1.1.1-py2.py3-none-any.whl | ||
- https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl | ||
"### | ||
); | ||
|
||
Ok(()) | ||
} | ||
|
||
/// The root package has diverging URLs, and transitive dependencies through an intermediate | ||
/// package have one URL for each side. | ||
/// | ||
/// Requirements: | ||
/// ```text | ||
/// a -> anyio==4.4.0 ; python_version >= '3.12' | ||
/// a -> anyio==4.3.0 ; python_version < '3.12' | ||
/// a -> b -> b1 ; python_version < '3.12' -> https://../iniconfig-1.1.1-py3-none-any.whl | ||
/// a -> b -> b2 ; python_version >= '3.12' -> https://../iniconfig-2.0.0-py3-none-any.whl | ||
/// ``` | ||
#[test] | ||
fn root_package_splits_transitive_too() -> Result<()> { | ||
let context = TestContext::new("3.12"); | ||
|
||
let scenario = "a4-transitive-allowed"; | ||
let sources_dir = branching_urls_dir().join(scenario); | ||
let work_dir = context.temp_dir.join(scenario); | ||
copy_dir_ignore(sources_dir, &work_dir)?; | ||
|
||
uv_snapshot!(context.filters(), lock_command(&context).current_dir(&work_dir), @r###" | ||
success: true | ||
exit_code: 0 | ||
----- stdout ----- | ||
----- stderr ----- | ||
Using Python 3.12.[X] interpreter at: [PYTHON-3.12] | ||
Resolved 10 packages in [TIME] | ||
"### | ||
); | ||
|
||
Ok(()) | ||
} | ||
|
||
/// The root package has diverging URLs on one package, and other dependencies have one URL | ||
/// for each side. | ||
/// | ||
/// Requirements: | ||
/// ``` | ||
/// a -> anyio==4.4.0 ; python_version >= '3.12' | ||
/// a -> anyio==4.3.0 ; python_version < '3.12' | ||
/// a -> b1 ; python_version < '3.12' -> iniconfig==1.1.1 | ||
/// a -> b2 ; python_version >= '3.12' -> iniconfig==2.0.0 | ||
/// ``` | ||
#[test] | ||
fn root_package_splits_other_dependencies_too() -> Result<()> { | ||
let context = TestContext::new("3.12"); | ||
|
||
let scenario = "a5-fork-in-root"; | ||
let sources_dir = branching_urls_dir().join(scenario); | ||
let work_dir = context.temp_dir.join(scenario); | ||
copy_dir_ignore(sources_dir, &work_dir)?; | ||
|
||
// TODO(konsti): This passes once https://github.com/astral-sh/uv/pull/4415 is merged | ||
uv_snapshot!(context.filters(), lock_command(&context).current_dir(&work_dir), @r###" | ||
success: true | ||
exit_code: 0 | ||
----- stdout ----- | ||
----- stderr ----- | ||
Using Python 3.12.[X] interpreter at: [PYTHON-3.12] | ||
Resolved 9 packages in [TIME] | ||
"### | ||
); | ||
|
||
Ok(()) | ||
} | ||
|
||
/// Whether the dependency comes from the registry or a direct URL depends on the branch. | ||
/// | ||
/// ```toml | ||
/// dependencies = [ | ||
/// "iniconfig == 1.1.1 ; python_version < '3.12'", | ||
/// "iniconfig @ https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl ; python_version >= '3.12'", | ||
/// ] | ||
/// ``` | ||
#[test] | ||
fn branching_between_registry_and_direct_url() -> Result<()> { | ||
let context = TestContext::new("3.12"); | ||
|
||
let scenario = "a6-registry-and-direct-url-mixed"; | ||
let sources_dir = branching_urls_dir().join(scenario); | ||
let work_dir = context.temp_dir.join(scenario); | ||
copy_dir_ignore(sources_dir, &work_dir)?; | ||
|
||
uv_snapshot!(context.filters(), lock_command(&context).current_dir(&work_dir), @r###" | ||
success: true | ||
exit_code: 0 | ||
----- stdout ----- | ||
----- stderr ----- | ||
Using Python 3.12.[X] interpreter at: [PYTHON-3.12] | ||
Resolved 3 packages in [TIME] | ||
"### | ||
); | ||
|
||
// We have source dist and wheel for the registry, but only the wheel for the direct URL. | ||
assert_snapshot!(fs_err::read_to_string(work_dir.join("uv.lock"))?, @r###" | ||
version = 1 | ||
requires-python = ">=3.11, <3.13" | ||
[[distribution]] | ||
name = "a" | ||
version = "0.1.0" | ||
source = "editable+." | ||
sdist = { path = "." } | ||
[[distribution.dependencies]] | ||
name = "iniconfig" | ||
version = "1.1.1" | ||
source = "registry+https://pypi.org/simple" | ||
marker = "python_version < '3.12'" | ||
[[distribution.dependencies]] | ||
name = "iniconfig" | ||
version = "2.0.0" | ||
source = "direct+https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl" | ||
marker = "python_version >= '3.12'" | ||
[[distribution]] | ||
name = "iniconfig" | ||
version = "1.1.1" | ||
source = "registry+https://pypi.org/simple" | ||
sdist = { url = "https://files.pythonhosted.org/packages/23/a2/97899f6bd0e873fed3a7e67ae8d3a08b21799430fb4da15cfedf10d6e2c2/iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32", size = 8104 } | ||
wheels = [{ url = "https://files.pythonhosted.org/packages/9b/dd/b3c12c6d707058fa947864b67f0c4e0c39ef8610988d7baea9578f3c48f3/iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3", size = 4990 }] | ||
[[distribution]] | ||
name = "iniconfig" | ||
version = "2.0.0" | ||
source = "direct+https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl" | ||
wheels = [{ url = "https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374" }] | ||
"###); | ||
|
||
Ok(()) | ||
} | ||
|
||
/// The root package has two different direct URLs for disjoint forks, but they are from different sources. | ||
/// | ||
/// ```toml | ||
/// dependencies = [ | ||
/// "iniconfig @ https://files.pythonhosted.org/packages/9b/dd/b3c12c6d707058fa947864b67f0c4e0c39ef8610988d7baea9578f3c48f3/iniconfig-1.1.1-py2.py3-none-any.whl ; python_version < '3.12'", | ||
/// "iniconfig @ git+https://github.com/pytest-dev/iniconfig@93f5930e668c0d1ddf4597e38dd0dea4e2665e7a ; python_version >= '3.12'", | ||
/// ] | ||
/// ``` | ||
#[test] | ||
fn branching_urls_of_different_sources_disjoint() -> Result<()> { | ||
let context = TestContext::new("3.12"); | ||
|
||
let scenario = "a7-different-source-types-allowed"; | ||
let sources_dir = branching_urls_dir().join(scenario); | ||
let work_dir = context.temp_dir.join(scenario); | ||
copy_dir_ignore(sources_dir, &work_dir)?; | ||
|
||
uv_snapshot!(context.filters(), lock_command(&context).current_dir(&work_dir), @r###" | ||
success: true | ||
exit_code: 0 | ||
----- stdout ----- | ||
----- stderr ----- | ||
Using Python 3.12.[X] interpreter at: [PYTHON-3.12] | ||
Resolved 3 packages in [TIME] | ||
"### | ||
); | ||
|
||
// We have source dist and wheel for the registry, but only the wheel for the direct URL. | ||
assert_snapshot!(fs_err::read_to_string(work_dir.join("uv.lock"))?, @r###" | ||
version = 1 | ||
requires-python = ">=3.11, <3.13" | ||
[[distribution]] | ||
name = "a" | ||
version = "0.1.0" | ||
source = "editable+." | ||
sdist = { path = "." } | ||
[[distribution.dependencies]] | ||
name = "iniconfig" | ||
version = "1.1.1" | ||
source = "direct+https://files.pythonhosted.org/packages/9b/dd/b3c12c6d707058fa947864b67f0c4e0c39ef8610988d7baea9578f3c48f3/iniconfig-1.1.1-py2.py3-none-any.whl" | ||
marker = "python_version < '3.12'" | ||
[[distribution.dependencies]] | ||
name = "iniconfig" | ||
version = "2.0.0" | ||
source = "git+https://github.com/pytest-dev/iniconfig?rev=93f5930e668c0d1ddf4597e38dd0dea4e2665e7a#93f5930e668c0d1ddf4597e38dd0dea4e2665e7a" | ||
marker = "python_version >= '3.12'" | ||
[[distribution]] | ||
name = "iniconfig" | ||
version = "1.1.1" | ||
source = "direct+https://files.pythonhosted.org/packages/9b/dd/b3c12c6d707058fa947864b67f0c4e0c39ef8610988d7baea9578f3c48f3/iniconfig-1.1.1-py2.py3-none-any.whl" | ||
wheels = [{ url = "https://files.pythonhosted.org/packages/9b/dd/b3c12c6d707058fa947864b67f0c4e0c39ef8610988d7baea9578f3c48f3/iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3" }] | ||
[[distribution]] | ||
name = "iniconfig" | ||
version = "2.0.0" | ||
source = "git+https://github.com/pytest-dev/iniconfig?rev=93f5930e668c0d1ddf4597e38dd0dea4e2665e7a#93f5930e668c0d1ddf4597e38dd0dea4e2665e7a" | ||
sdist = { url = "https://github.com/pytest-dev/iniconfig?rev=93f5930e668c0d1ddf4597e38dd0dea4e2665e7a#93f5930e668c0d1ddf4597e38dd0dea4e2665e7a" } | ||
"###); | ||
|
||
Ok(()) | ||
} | ||
|
||
/// The root package has two different direct URLs from different sources, but they are not | ||
/// disjoint. | ||
/// | ||
/// ```toml | ||
/// dependencies = [ | ||
/// "iniconfig @ https://files.pythonhosted.org/packages/9b/dd/b3c12c6d707058fa947864b67f0c4e0c39ef8610988d7baea9578f3c48f3/iniconfig-1.1.1-py2.py3-none-any.whl ; python_version < '3.12'", | ||
/// "iniconfig @ git+https://github.com/pytest-dev/iniconfig@93f5930e668c0d1ddf4597e38dd0dea4e2665e7a ; python_version >= '3.12'", | ||
/// ] | ||
/// ``` | ||
#[test] | ||
fn branching_urls_of_different_sources_conflict() -> Result<()> { | ||
let context = TestContext::new("3.12"); | ||
|
||
let scenario = "a8-different-source-types-conflict"; | ||
let sources_dir = branching_urls_dir().join(scenario); | ||
let work_dir = context.temp_dir.join(scenario); | ||
copy_dir_ignore(sources_dir, &work_dir)?; | ||
|
||
uv_snapshot!(context.filters(), lock_command(&context).current_dir(&work_dir), @r###" | ||
success: false | ||
exit_code: 2 | ||
----- stdout ----- | ||
----- stderr ----- | ||
Using Python 3.12.[X] interpreter at: [PYTHON-3.12] | ||
error: Requirements contain conflicting URLs for package `iniconfig`: | ||
- git+https://github.com/pytest-dev/iniconfig@93f5930e668c0d1ddf4597e38dd0dea4e2665e7a | ||
- https://files.pythonhosted.org/packages/9b/dd/b3c12c6d707058fa947864b67f0c4e0c39ef8610988d7baea9578f3c48f3/iniconfig-1.1.1-py2.py3-none-any.whl | ||
"### | ||
); | ||
|
||
Ok(()) | ||
} |