Skip to content

Commit

Permalink
Restore hash annotations in lockfile
Browse files Browse the repository at this point in the history
  • Loading branch information
charliermarsh committed Sep 29, 2024
1 parent a928cd5 commit d2510e4
Show file tree
Hide file tree
Showing 2 changed files with 185 additions and 14 deletions.
31 changes: 23 additions & 8 deletions rye/src/lock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -474,23 +474,32 @@ fn finalize_lockfile(
writeln!(rv)?;
}

let mut exclude = false;
for line in fs::read_to_string(generated)
.path_context(generated, "unable to parse resolver output")?
.lines()
{
// we deal with this explicitly.
let line = line.trim();
if line.is_empty()
let trimmed = line.trim();

// if we're in an exclusion, continue to skip lines
if exclude {
exclude = trimmed.ends_with('\\');
continue;
}

// we deal with these settings explicitly.
if trimmed.is_empty()
|| line.starts_with("--index-url ")
|| line.starts_with("--extra-index-url ")
|| line.starts_with("--find-links ")
|| line.starts_with("--hash=")
{
continue;
}

// Strip trailing backslashes.
let line = line.strip_suffix('\\').unwrap_or(line);
let stripped = trimmed
.strip_suffix('\\')
.map_or(trimmed, |rest| rest.trim());

if let Some(m) = FILE_EDITABLE_RE.captures(line) {
let url = Url::parse(&m[1]).context("invalid editable URL generated")?;
Expand All @@ -499,14 +508,20 @@ fn finalize_lockfile(
writeln!(rv, "-e {rel_url}")?;
continue;
}
} else if let Ok(ref req) = line.parse::<Requirement>() {
} else if let Ok(ref req) = stripped.parse::<Requirement>() {
// TODO: this does not evaluate markers
if exclusions.iter().any(|x| {
normalize_package_name(&x.name) == normalize_package_name(&req.name)
&& (x.version_or_url.is_none() || x.version_or_url == req.version_or_url)
}) {
// skip exclusions
writeln!(rv, "# {line} (excluded)")?;
// skip exclusions.
writeln!(rv, "# {stripped} (excluded)")?;

// if the exclusion is followed by hashes, we need to comment out the hashes too.
if trimmed.ends_with('\\') {
exclude = true;
}

continue;
}
} else if let Some(m) = DEP_COMMENT_RE.captures(line) {
Expand Down
168 changes: 162 additions & 6 deletions rye/tests/test_sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ fn test_exclude_hashes() {
[project]
name = "exclude-rye-test"
version = "0.1.0"
dependencies = ["jinja2"]
dependencies = ["anyio==4.0.0"]
readme = "README.md"
requires-python = ">= 3.8"
Expand All @@ -286,7 +286,7 @@ fn test_exclude_hashes() {
[tool.rye]
generate-hashes = true
excluded-dependencies = ["markupsafe"]
excluded-dependencies = ["idna"]
[tool.hatch.metadata]
allow-direct-references = true
Expand All @@ -309,10 +309,166 @@ fn test_exclude_hashes() {
Done!
----- stderr -----
Resolved 2 packages in [EXECUTION_TIME]
Prepared 2 packages in [EXECUTION_TIME]
Installed 2 packages in [EXECUTION_TIME]
Resolved 3 packages in [EXECUTION_TIME]
Prepared 3 packages in [EXECUTION_TIME]
Installed 3 packages in [EXECUTION_TIME]
+ anyio==4.0.0
+ exclude-rye-test==0.1.0 (from file:[TEMP_PATH]/project)
+ jinja2==3.1.2
+ sniffio==1.3.0
"###);

assert_snapshot!(space.read_string(space.project_path().join("requirements.lock")), @r###"
# generated by rye
# use `rye lock` or `rye sync` to update this lockfile
#
# last locked with the following flags:
# pre: false
# features: []
# all-features: false
# with-sources: false
# generate-hashes: true
# universal: false
-e file:.
anyio==4.0.0 \
--hash=sha256:cfdb2b588b9fc25ede96d8db56ed50848b0b649dca3dd1df0b11f683bb9e0b5f \
--hash=sha256:f7ed51751b2c2add651e5747c891b47e26d2a21be5d32d9311dfe9692f3e5d7a
# via exclude-rye-test
# idna==3.4 (excluded)
# via anyio
sniffio==1.3.0 \
--hash=sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101 \
--hash=sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384
# via anyio
"###);
}

#[test]
fn test_lockfile() {
let space = Space::new();
space.init("my-project");

rye_cmd_snapshot!(space.rye_cmd().arg("add").arg("anyio==4.0.0"), @r###"
success: true
exit_code: 0
----- stdout -----
Initializing new virtualenv in [TEMP_PATH]/project/.venv
Python version: [email protected]
Added anyio==4.0.0 as regular dependency
Reusing already existing virtualenv
Generating production lockfile: [TEMP_PATH]/project/requirements.lock
Generating dev lockfile: [TEMP_PATH]/project/requirements-dev.lock
Installing dependencies
Done!
----- stderr -----
Resolved 4 packages in [EXECUTION_TIME]
Prepared 4 packages in [EXECUTION_TIME]
Installed 4 packages in [EXECUTION_TIME]
+ anyio==4.0.0
+ idna==3.4
+ my-project==0.1.0 (from file:[TEMP_PATH]/project)
+ sniffio==1.3.0
"###);

assert_snapshot!(space.read_string(space.project_path().join("requirements.lock")), @r###"
# generated by rye
# use `rye lock` or `rye sync` to update this lockfile
#
# last locked with the following flags:
# pre: false
# features: []
# all-features: false
# with-sources: false
# generate-hashes: false
# universal: false
-e file:.
anyio==4.0.0
# via my-project
idna==3.4
# via anyio
sniffio==1.3.0
# via anyio
"###);
}

#[test]
fn test_generate_hashes() {
let space = Space::new();
space.init("my-project");

fs::write(
space.project_path().join("pyproject.toml"),
r###"
[project]
name = "exclude-rye-test"
version = "0.1.0"
dependencies = ["anyio==4.0.0"]
readme = "README.md"
requires-python = ">= 3.8"
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[tool.rye]
generate-hashes = true
[tool.hatch.metadata]
allow-direct-references = true
[tool.hatch.build.targets.wheel]
packages = ["src/exclude_rye_test"]
"###,
)
.unwrap();

rye_cmd_snapshot!(space.rye_cmd().arg("sync"), @r###"
success: true
exit_code: 0
----- stdout -----
Initializing new virtualenv in [TEMP_PATH]/project/.venv
Python version: [email protected]
Generating production lockfile: [TEMP_PATH]/project/requirements.lock
Generating dev lockfile: [TEMP_PATH]/project/requirements-dev.lock
Installing dependencies
Done!
----- stderr -----
Resolved 4 packages in [EXECUTION_TIME]
Prepared 4 packages in [EXECUTION_TIME]
Installed 4 packages in [EXECUTION_TIME]
+ anyio==4.0.0
+ exclude-rye-test==0.1.0 (from file:[TEMP_PATH]/project)
+ idna==3.4
+ sniffio==1.3.0
"###);

assert_snapshot!(space.read_string(space.project_path().join("requirements.lock")), @r###"
# generated by rye
# use `rye lock` or `rye sync` to update this lockfile
#
# last locked with the following flags:
# pre: false
# features: []
# all-features: false
# with-sources: false
# generate-hashes: true
# universal: false
-e file:.
anyio==4.0.0 \
--hash=sha256:cfdb2b588b9fc25ede96d8db56ed50848b0b649dca3dd1df0b11f683bb9e0b5f \
--hash=sha256:f7ed51751b2c2add651e5747c891b47e26d2a21be5d32d9311dfe9692f3e5d7a
# via exclude-rye-test
idna==3.4 \
--hash=sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4 \
--hash=sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2
# via anyio
sniffio==1.3.0 \
--hash=sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101 \
--hash=sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384
# via anyio
"###);
}

0 comments on commit d2510e4

Please sign in to comment.