3549d9638e
Right now, we're inconsistent between checking in and inlining these. The outputs are small in Puffin, so let's just inline them in all cases.
2441 lines
78 KiB
Rust
2441 lines
78 KiB
Rust
#![cfg(all(feature = "python", feature = "pypi"))]
|
||
|
||
use std::process::Command;
|
||
|
||
use anyhow::Result;
|
||
use assert_cmd::prelude::*;
|
||
use assert_fs::prelude::*;
|
||
use assert_fs::TempDir;
|
||
use insta_cmd::_macro_support::insta;
|
||
use insta_cmd::{assert_cmd_snapshot, get_cargo_bin};
|
||
|
||
use common::{create_venv_py312, BIN_NAME, INSTA_FILTERS};
|
||
|
||
mod common;
|
||
|
||
// Exclude any packages uploaded after this date.
|
||
static EXCLUDE_NEWER: &str = "2023-11-18T12:00:00Z";
|
||
|
||
/// Resolve a specific version of Django from a `requirements.in` file.
|
||
#[test]
|
||
fn compile_requirements_in() -> Result<()> {
|
||
let temp_dir = TempDir::new()?;
|
||
let cache_dir = TempDir::new()?;
|
||
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
||
|
||
let requirements_in = temp_dir.child("requirements.in");
|
||
requirements_in.write_str("django==5.0b1")?;
|
||
|
||
insta::with_settings!({
|
||
filters => INSTA_FILTERS.to_vec()
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip-compile")
|
||
.arg("requirements.in")
|
||
.arg("--cache-dir")
|
||
.arg(cache_dir.path())
|
||
.arg("--exclude-newer")
|
||
.arg(EXCLUDE_NEWER)
|
||
.env("VIRTUAL_ENV", venv.as_os_str())
|
||
.current_dir(&temp_dir), @r###"
|
||
success: true
|
||
exit_code: 0
|
||
----- stdout -----
|
||
# This file was autogenerated by Puffin v0.0.1 via the following command:
|
||
# puffin pip-compile requirements.in --cache-dir [CACHE_DIR]
|
||
asgiref==3.7.2
|
||
# via django
|
||
django==5.0b1
|
||
sqlparse==0.4.4
|
||
# via django
|
||
|
||
----- stderr -----
|
||
Resolved 3 packages in [TIME]
|
||
"###);
|
||
});
|
||
|
||
Ok(())
|
||
}
|
||
|
||
#[test]
|
||
fn missing_requirements_in() -> Result<()> {
|
||
let temp_dir = TempDir::new()?;
|
||
let cache_dir = TempDir::new()?;
|
||
let requirements_in = temp_dir.child("requirements.in");
|
||
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip-compile")
|
||
.arg("requirements.in")
|
||
.arg("--cache-dir")
|
||
.arg(cache_dir.path())
|
||
.current_dir(&temp_dir), @r###"
|
||
success: false
|
||
exit_code: 2
|
||
----- stdout -----
|
||
|
||
----- stderr -----
|
||
error: failed to open file `requirements.in`
|
||
Caused by: No such file or directory (os error 2)
|
||
"###);
|
||
|
||
requirements_in.assert(predicates::path::missing());
|
||
|
||
Ok(())
|
||
}
|
||
|
||
#[test]
|
||
fn missing_venv() -> Result<()> {
|
||
let temp_dir = TempDir::new()?;
|
||
let cache_dir = TempDir::new()?;
|
||
let venv = temp_dir.child(".venv");
|
||
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip-compile")
|
||
.arg("requirements.in")
|
||
.arg("--cache-dir")
|
||
.arg(cache_dir.path())
|
||
.env("VIRTUAL_ENV", venv.as_os_str())
|
||
.current_dir(&temp_dir), @r###"
|
||
success: false
|
||
exit_code: 2
|
||
----- stdout -----
|
||
|
||
----- stderr -----
|
||
error: failed to open file `requirements.in`
|
||
Caused by: No such file or directory (os error 2)
|
||
"###);
|
||
|
||
venv.assert(predicates::path::missing());
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// Resolve a specific version of Django from a `pyproject.toml` file.
|
||
#[test]
|
||
fn compile_pyproject_toml() -> Result<()> {
|
||
let temp_dir = TempDir::new()?;
|
||
let cache_dir = TempDir::new()?;
|
||
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
||
|
||
let pyproject_toml = temp_dir.child("pyproject.toml");
|
||
pyproject_toml.write_str(
|
||
r#"[build-system]
|
||
requires = ["setuptools", "wheel"]
|
||
|
||
[project]
|
||
name = "project"
|
||
dependencies = [
|
||
"django==5.0b1",
|
||
]
|
||
"#,
|
||
)?;
|
||
|
||
insta::with_settings!({
|
||
filters => INSTA_FILTERS.to_vec()
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip-compile")
|
||
.arg("pyproject.toml")
|
||
.arg("--cache-dir")
|
||
.arg(cache_dir.path())
|
||
.arg("--exclude-newer")
|
||
.arg(EXCLUDE_NEWER)
|
||
.env("VIRTUAL_ENV", venv.as_os_str())
|
||
.current_dir(&temp_dir), @r###"
|
||
success: true
|
||
exit_code: 0
|
||
----- stdout -----
|
||
# This file was autogenerated by Puffin v0.0.1 via the following command:
|
||
# puffin pip-compile pyproject.toml --cache-dir [CACHE_DIR]
|
||
asgiref==3.7.2
|
||
# via django
|
||
django==5.0b1
|
||
sqlparse==0.4.4
|
||
# via django
|
||
|
||
----- stderr -----
|
||
Resolved 3 packages in [TIME]
|
||
"###);
|
||
});
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// Resolve a package from a `requirements.in` file, with a `constraints.txt` file.
|
||
#[test]
|
||
fn compile_constraints_txt() -> Result<()> {
|
||
let temp_dir = TempDir::new()?;
|
||
let cache_dir = TempDir::new()?;
|
||
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
||
|
||
let requirements_in = temp_dir.child("requirements.in");
|
||
requirements_in.write_str("django==5.0b1")?;
|
||
|
||
let constraints_txt = temp_dir.child("constraints.txt");
|
||
constraints_txt.write_str("sqlparse<0.4.4")?;
|
||
|
||
insta::with_settings!({
|
||
filters => INSTA_FILTERS.to_vec()
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip-compile")
|
||
.arg("requirements.in")
|
||
.arg("--constraint")
|
||
.arg("constraints.txt")
|
||
.arg("--cache-dir")
|
||
.arg(cache_dir.path())
|
||
.arg("--exclude-newer")
|
||
.arg(EXCLUDE_NEWER)
|
||
.env("VIRTUAL_ENV", venv.as_os_str())
|
||
.current_dir(&temp_dir), @r###"
|
||
success: true
|
||
exit_code: 0
|
||
----- stdout -----
|
||
# This file was autogenerated by Puffin v0.0.1 via the following command:
|
||
# puffin pip-compile requirements.in --constraint constraints.txt --cache-dir [CACHE_DIR]
|
||
asgiref==3.7.2
|
||
# via django
|
||
django==5.0b1
|
||
sqlparse==0.4.3
|
||
# via django
|
||
|
||
----- stderr -----
|
||
Resolved 3 packages in [TIME]
|
||
"###);
|
||
});
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// Resolve a package from a `requirements.in` file, with an inline constraint.
|
||
#[test]
|
||
fn compile_constraints_inline() -> Result<()> {
|
||
let temp_dir = TempDir::new()?;
|
||
let cache_dir = TempDir::new()?;
|
||
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
||
|
||
let requirements_in = temp_dir.child("requirements.in");
|
||
requirements_in.write_str("django==5.0b1")?;
|
||
requirements_in.write_str("-c constraints.txt")?;
|
||
|
||
let constraints_txt = temp_dir.child("constraints.txt");
|
||
constraints_txt.write_str("sqlparse<0.4.4")?;
|
||
|
||
insta::with_settings!({
|
||
filters => INSTA_FILTERS.to_vec()
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip-compile")
|
||
.arg("requirements.in")
|
||
.arg("--cache-dir")
|
||
.arg(cache_dir.path())
|
||
.arg("--exclude-newer")
|
||
.arg(EXCLUDE_NEWER)
|
||
.env("VIRTUAL_ENV", venv.as_os_str())
|
||
.current_dir(&temp_dir), @r###"
|
||
success: true
|
||
exit_code: 0
|
||
----- stdout -----
|
||
# This file was autogenerated by Puffin v0.0.1 via the following command:
|
||
# puffin pip-compile requirements.in --cache-dir [CACHE_DIR]
|
||
|
||
----- stderr -----
|
||
Resolved 0 packages in [TIME]
|
||
"###);
|
||
});
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// Resolve a package from a `requirements.in` file, with a `constraints.txt` file that
|
||
/// uses markers.
|
||
#[test]
|
||
fn compile_constraints_markers() -> Result<()> {
|
||
let temp_dir = TempDir::new()?;
|
||
let cache_dir = TempDir::new()?;
|
||
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
||
|
||
let requirements_in = temp_dir.child("requirements.in");
|
||
requirements_in.write_str("anyio")?;
|
||
|
||
// Constrain a transitive dependency based on the Python version
|
||
let constraints_txt = temp_dir.child("constraints.txt");
|
||
// If constraints are ignored, these will conflict
|
||
constraints_txt.write_str("sniffio==1.2.0;python_version<='3.7'")?;
|
||
constraints_txt.write_str("sniffio==1.3.0;python_version>'3.7'")?;
|
||
|
||
insta::with_settings!({
|
||
filters => INSTA_FILTERS.to_vec()
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip-compile")
|
||
.arg("requirements.in")
|
||
.arg("--constraint")
|
||
.arg("constraints.txt")
|
||
.arg("--cache-dir")
|
||
.arg(cache_dir.path())
|
||
.arg("--exclude-newer")
|
||
.arg(EXCLUDE_NEWER)
|
||
.env("VIRTUAL_ENV", venv.as_os_str())
|
||
.current_dir(&temp_dir), @r###"
|
||
success: true
|
||
exit_code: 0
|
||
----- stdout -----
|
||
# This file was autogenerated by Puffin v0.0.1 via the following command:
|
||
# puffin pip-compile requirements.in --constraint constraints.txt --cache-dir [CACHE_DIR]
|
||
anyio==4.0.0
|
||
idna==3.4
|
||
# via anyio
|
||
sniffio==1.3.0
|
||
# via anyio
|
||
|
||
----- stderr -----
|
||
Resolved 3 packages in [TIME]
|
||
"###);
|
||
});
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// Resolve a package from an optional dependency group in a `pyproject.toml` file.
|
||
#[test]
|
||
fn compile_pyproject_toml_extra() -> Result<()> {
|
||
let temp_dir = TempDir::new()?;
|
||
let cache_dir = TempDir::new()?;
|
||
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
||
|
||
let pyproject_toml = temp_dir.child("pyproject.toml");
|
||
pyproject_toml.write_str(
|
||
r#"[build-system]
|
||
requires = ["setuptools", "wheel"]
|
||
|
||
[project]
|
||
name = "project"
|
||
dependencies = []
|
||
optional-dependencies.foo = [
|
||
"django==5.0b1",
|
||
]
|
||
"#,
|
||
)?;
|
||
|
||
insta::with_settings!({
|
||
filters => INSTA_FILTERS.to_vec()
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip-compile")
|
||
.arg("pyproject.toml")
|
||
.arg("--extra")
|
||
.arg("foo")
|
||
.arg("--cache-dir")
|
||
.arg(cache_dir.path())
|
||
.arg("--exclude-newer")
|
||
.arg(EXCLUDE_NEWER)
|
||
.env("VIRTUAL_ENV", venv.as_os_str())
|
||
.current_dir(&temp_dir), @r###"
|
||
success: true
|
||
exit_code: 0
|
||
----- stdout -----
|
||
# This file was autogenerated by Puffin v0.0.1 via the following command:
|
||
# puffin pip-compile pyproject.toml --extra foo --cache-dir [CACHE_DIR]
|
||
asgiref==3.7.2
|
||
# via django
|
||
django==5.0b1
|
||
sqlparse==0.4.4
|
||
# via django
|
||
|
||
----- stderr -----
|
||
Resolved 3 packages in [TIME]
|
||
"###);
|
||
});
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// Resolve a package from an extra with unnormalized names in a `pyproject.toml` file.
|
||
#[test]
|
||
fn compile_pyproject_toml_extra_name_normalization() -> Result<()> {
|
||
let temp_dir = TempDir::new()?;
|
||
let cache_dir = TempDir::new()?;
|
||
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
||
|
||
let pyproject_toml = temp_dir.child("pyproject.toml");
|
||
pyproject_toml.write_str(
|
||
r#"[build-system]
|
||
requires = ["setuptools", "wheel"]
|
||
|
||
[project]
|
||
name = "project"
|
||
dependencies = []
|
||
optional-dependencies."FrIeNdLy-._.-bArD" = [
|
||
"django==5.0b1",
|
||
]
|
||
"#,
|
||
)?;
|
||
|
||
insta::with_settings!({
|
||
filters => INSTA_FILTERS.to_vec()
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip-compile")
|
||
.arg("pyproject.toml")
|
||
.arg("--extra")
|
||
.arg("FRiENDlY-...-_-BARd")
|
||
.arg("--cache-dir")
|
||
.arg(cache_dir.path())
|
||
.arg("--exclude-newer")
|
||
.arg(EXCLUDE_NEWER)
|
||
.env("VIRTUAL_ENV", venv.as_os_str())
|
||
.current_dir(&temp_dir), @r###"
|
||
success: true
|
||
exit_code: 0
|
||
----- stdout -----
|
||
# This file was autogenerated by Puffin v0.0.1 via the following command:
|
||
# puffin pip-compile pyproject.toml --extra FRiENDlY-...-_-BARd --cache-dir [CACHE_DIR]
|
||
asgiref==3.7.2
|
||
# via django
|
||
django==5.0b1
|
||
sqlparse==0.4.4
|
||
# via django
|
||
|
||
----- stderr -----
|
||
Resolved 3 packages in [TIME]
|
||
"###);
|
||
});
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// Request an extra that does not exist as a dependency group in a `pyproject.toml` file.
|
||
#[test]
|
||
fn compile_pyproject_toml_extra_missing() -> Result<()> {
|
||
let temp_dir = TempDir::new()?;
|
||
let cache_dir = TempDir::new()?;
|
||
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
||
|
||
let pyproject_toml = temp_dir.child("pyproject.toml");
|
||
pyproject_toml.write_str(
|
||
r#"[build-system]
|
||
requires = ["setuptools", "wheel"]
|
||
|
||
[project]
|
||
name = "project"
|
||
dependencies = []
|
||
optional-dependencies.foo = [
|
||
"django==5.0b1",
|
||
]
|
||
"#,
|
||
)?;
|
||
|
||
insta::with_settings!({
|
||
filters => INSTA_FILTERS.to_vec()
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip-compile")
|
||
.arg("pyproject.toml")
|
||
.arg("--extra")
|
||
.arg("bar")
|
||
.arg("--cache-dir")
|
||
.arg(cache_dir.path())
|
||
.arg("--exclude-newer")
|
||
.arg(EXCLUDE_NEWER)
|
||
.env("VIRTUAL_ENV", venv.as_os_str())
|
||
.current_dir(&temp_dir), @r###"
|
||
success: false
|
||
exit_code: 2
|
||
----- stdout -----
|
||
|
||
----- stderr -----
|
||
error: Requested extra not found: bar
|
||
"###);
|
||
});
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// Request multiple extras that do not exist as a dependency group in a `pyproject.toml` file.
|
||
#[test]
|
||
fn compile_pyproject_toml_extras_missing() -> Result<()> {
|
||
let temp_dir = TempDir::new()?;
|
||
let cache_dir = TempDir::new()?;
|
||
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
||
|
||
let pyproject_toml = temp_dir.child("pyproject.toml");
|
||
pyproject_toml.write_str(
|
||
r#"[build-system]
|
||
requires = ["setuptools", "wheel"]
|
||
|
||
[project]
|
||
name = "project"
|
||
dependencies = []
|
||
optional-dependencies.foo = [
|
||
"django==5.0b1",
|
||
]
|
||
"#,
|
||
)?;
|
||
|
||
insta::with_settings!({
|
||
filters => INSTA_FILTERS.to_vec()
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip-compile")
|
||
.arg("pyproject.toml")
|
||
.arg("--extra")
|
||
.arg("foo")
|
||
.arg("--extra")
|
||
.arg("bar")
|
||
.arg("--extra")
|
||
.arg("foobar")
|
||
.arg("--cache-dir")
|
||
.arg(cache_dir.path())
|
||
.arg("--exclude-newer")
|
||
.arg(EXCLUDE_NEWER)
|
||
.env("VIRTUAL_ENV", venv.as_os_str())
|
||
.current_dir(&temp_dir), @r###"
|
||
success: false
|
||
exit_code: 2
|
||
----- stdout -----
|
||
|
||
----- stderr -----
|
||
error: Requested extras not found: bar, foobar
|
||
"###);
|
||
});
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// Request extras when using a `requirements.in` file which does not support extras.
|
||
#[test]
|
||
fn compile_requirements_file_extra() -> Result<()> {
|
||
let temp_dir = TempDir::new()?;
|
||
let cache_dir = TempDir::new()?;
|
||
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
||
|
||
let requirements_in = temp_dir.child("requirements.in");
|
||
requirements_in.write_str("django==5.0b1")?;
|
||
|
||
insta::with_settings!({
|
||
filters => INSTA_FILTERS.to_vec()
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip-compile")
|
||
.arg("requirements.in")
|
||
.arg("--cache-dir")
|
||
.arg(cache_dir.path())
|
||
.arg("--exclude-newer")
|
||
.arg(EXCLUDE_NEWER)
|
||
.arg("--all-extras")
|
||
.env("VIRTUAL_ENV", venv.as_os_str())
|
||
.current_dir(&temp_dir),
|
||
@r###"
|
||
success: false
|
||
exit_code: 2
|
||
----- stdout -----
|
||
|
||
----- stderr -----
|
||
error: Requesting extras requires a pyproject.toml input file.
|
||
"###);
|
||
});
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// Request an extra with a name that does not conform to the specification.
|
||
#[test]
|
||
fn invalid_extra_name() -> Result<()> {
|
||
let temp_dir = TempDir::new()?;
|
||
let cache_dir = TempDir::new()?;
|
||
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
||
|
||
let pyproject_toml = temp_dir.child("pyproject.toml");
|
||
pyproject_toml.write_str(
|
||
r#"[build-system]
|
||
requires = ["setuptools", "wheel"]
|
||
|
||
[project]
|
||
name = "project"
|
||
dependencies = []
|
||
optional-dependencies.foo = [
|
||
"django==5.0b1",
|
||
]
|
||
"#,
|
||
)?;
|
||
|
||
insta::with_settings!({
|
||
filters => INSTA_FILTERS.to_vec()
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip-compile")
|
||
.arg("pyproject.toml")
|
||
.arg("--extra")
|
||
.arg("invalid name!")
|
||
.arg("--cache-dir")
|
||
.arg(cache_dir.path())
|
||
.arg("--exclude-newer")
|
||
.arg(EXCLUDE_NEWER)
|
||
.env("VIRTUAL_ENV", venv.as_os_str())
|
||
.current_dir(&temp_dir), @r###"
|
||
success: false
|
||
exit_code: 2
|
||
----- stdout -----
|
||
|
||
----- stderr -----
|
||
error: invalid value 'invalid name!' for '--extra <EXTRA>': Extra names must start and end with a letter or digit and may only contain -, _, ., and alphanumeric characters
|
||
|
||
For more information, try '--help'.
|
||
"###);
|
||
});
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// Resolve a specific version of Black at Python 3.12.
|
||
#[test]
|
||
fn compile_python_312() -> Result<()> {
|
||
let temp_dir = TempDir::new()?;
|
||
let cache_dir = TempDir::new()?;
|
||
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
||
|
||
let requirements_in = temp_dir.child("requirements.in");
|
||
requirements_in.write_str("black==23.10.1")?;
|
||
|
||
insta::with_settings!({
|
||
filters => INSTA_FILTERS.to_vec()
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip-compile")
|
||
.arg("requirements.in")
|
||
.arg("--python-version")
|
||
.arg("3.12")
|
||
.arg("--cache-dir")
|
||
.arg(cache_dir.path())
|
||
.arg("--exclude-newer")
|
||
.arg(EXCLUDE_NEWER)
|
||
.env("VIRTUAL_ENV", venv.as_os_str())
|
||
.current_dir(&temp_dir), @r###"
|
||
success: true
|
||
exit_code: 0
|
||
----- stdout -----
|
||
# This file was autogenerated by Puffin v0.0.1 via the following command:
|
||
# puffin pip-compile requirements.in --python-version 3.12 --cache-dir [CACHE_DIR]
|
||
black==23.10.1
|
||
click==8.1.7
|
||
# via black
|
||
mypy-extensions==1.0.0
|
||
# via black
|
||
packaging==23.2
|
||
# via black
|
||
pathspec==0.11.2
|
||
# via black
|
||
platformdirs==4.0.0
|
||
# via black
|
||
|
||
----- stderr -----
|
||
Resolved 6 packages in [TIME]
|
||
"###);
|
||
});
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// Resolve a specific version of Black at Python 3.7.
|
||
#[test]
|
||
fn compile_python_37() -> Result<()> {
|
||
let temp_dir = TempDir::new()?;
|
||
let cache_dir = TempDir::new()?;
|
||
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
||
|
||
let requirements_in = temp_dir.child("requirements.in");
|
||
requirements_in.write_str("black==23.10.1")?;
|
||
|
||
insta::with_settings!({
|
||
filters => INSTA_FILTERS.to_vec()
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip-compile")
|
||
.arg("requirements.in")
|
||
.arg("--python-version")
|
||
.arg("3.7")
|
||
.arg("--cache-dir")
|
||
.arg(cache_dir.path())
|
||
.arg("--exclude-newer")
|
||
.arg(EXCLUDE_NEWER)
|
||
.env("VIRTUAL_ENV", venv.as_os_str())
|
||
.current_dir(&temp_dir), @r###"
|
||
success: false
|
||
exit_code: 1
|
||
----- stdout -----
|
||
|
||
----- stderr -----
|
||
× No solution found when resolving dependencies:
|
||
╰─▶ Because there is no version of black available matching ==23.10.1 and
|
||
root depends on black==23.10.1, version solving failed.
|
||
"###);
|
||
});
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// Resolve a specific version of Black against an invalid Python version.
|
||
#[test]
|
||
fn compile_python_invalid_version() -> Result<()> {
|
||
let temp_dir = TempDir::new()?;
|
||
|
||
let requirements_in = temp_dir.child("requirements.in");
|
||
requirements_in.write_str("black==23.10.1")?;
|
||
|
||
insta::with_settings!({
|
||
filters => INSTA_FILTERS.to_vec()
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip-compile")
|
||
.arg("requirements.in")
|
||
.arg("--python-version")
|
||
.arg("3.7.x")
|
||
.current_dir(&temp_dir), @r###"
|
||
success: false
|
||
exit_code: 2
|
||
----- stdout -----
|
||
|
||
----- stderr -----
|
||
error: invalid value '3.7.x' for '--python-version <PYTHON_VERSION>': Version `3.7.x` doesn't match PEP 440 rules
|
||
|
||
For more information, try '--help'.
|
||
"###);
|
||
});
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// Resolve a specific version of Black against an invalid Python version.
|
||
#[test]
|
||
fn compile_python_dev_version() -> Result<()> {
|
||
let temp_dir = TempDir::new()?;
|
||
|
||
let requirements_in = temp_dir.child("requirements.in");
|
||
requirements_in.write_str("black==23.10.1")?;
|
||
|
||
insta::with_settings!({
|
||
filters => INSTA_FILTERS.to_vec()
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip-compile")
|
||
.arg("requirements.in")
|
||
.arg("--python-version")
|
||
.arg("3.7-dev")
|
||
.current_dir(&temp_dir), @r###"
|
||
success: false
|
||
exit_code: 2
|
||
----- stdout -----
|
||
|
||
----- stderr -----
|
||
error: invalid value '3.7-dev' for '--python-version <PYTHON_VERSION>': Python version 3.7-dev is a development release
|
||
|
||
For more information, try '--help'.
|
||
"###);
|
||
});
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// Test that we select the last 3.8 compatible numpy version instead of trying to compile an
|
||
/// incompatible sdist <https://github.com/astral-sh/puffin/issues/388>
|
||
#[test]
|
||
fn compile_numpy_py38() -> Result<()> {
|
||
let temp_dir = TempDir::new()?;
|
||
let cache_dir = TempDir::new()?;
|
||
let venv = temp_dir.child(".venv");
|
||
|
||
Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("venv")
|
||
.arg(venv.as_os_str())
|
||
.arg("--cache-dir")
|
||
.arg(cache_dir.path())
|
||
.arg("--python")
|
||
.arg("python3.8")
|
||
.current_dir(&temp_dir)
|
||
.assert()
|
||
.success();
|
||
venv.assert(predicates::path::is_dir());
|
||
let venv = venv.to_path_buf();
|
||
|
||
let requirements_in = temp_dir.child("requirements.in");
|
||
requirements_in.write_str("numpy")?;
|
||
|
||
insta::with_settings!({
|
||
filters => INSTA_FILTERS.to_vec()
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip-compile")
|
||
.arg("requirements.in")
|
||
.arg("--cache-dir")
|
||
.arg(cache_dir.path())
|
||
.arg("--exclude-newer")
|
||
.arg(EXCLUDE_NEWER)
|
||
.arg("--no-build")
|
||
.env("VIRTUAL_ENV", venv.as_os_str())
|
||
.current_dir(&temp_dir), @r###"
|
||
success: true
|
||
exit_code: 0
|
||
----- stdout -----
|
||
# This file was autogenerated by Puffin v0.0.1 via the following command:
|
||
# puffin pip-compile requirements.in --cache-dir [CACHE_DIR]
|
||
numpy==1.24.4
|
||
|
||
----- stderr -----
|
||
Resolved 1 package in [TIME]
|
||
"###);
|
||
});
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// Resolve a specific Flask wheel via a URL dependency.
|
||
#[test]
|
||
fn compile_wheel_url_dependency() -> Result<()> {
|
||
let temp_dir = TempDir::new()?;
|
||
let cache_dir = TempDir::new()?;
|
||
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
||
|
||
let requirements_in = temp_dir.child("requirements.in");
|
||
requirements_in.write_str("flask @ https://files.pythonhosted.org/packages/36/42/015c23096649b908c809c69388a805a571a3bea44362fe87e33fc3afa01f/flask-3.0.0-py3-none-any.whl")?;
|
||
|
||
insta::with_settings!({
|
||
filters => INSTA_FILTERS.to_vec()
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip-compile")
|
||
.arg("requirements.in")
|
||
.arg("--cache-dir")
|
||
.arg(cache_dir.path())
|
||
.arg("--exclude-newer")
|
||
.arg(EXCLUDE_NEWER)
|
||
.env("VIRTUAL_ENV", venv.as_os_str())
|
||
.current_dir(&temp_dir), @r###"
|
||
success: true
|
||
exit_code: 0
|
||
----- stdout -----
|
||
# This file was autogenerated by Puffin v0.0.1 via the following command:
|
||
# puffin pip-compile requirements.in --cache-dir [CACHE_DIR]
|
||
blinker==1.7.0
|
||
# via flask
|
||
click==8.1.7
|
||
# via flask
|
||
flask @ https://files.pythonhosted.org/packages/36/42/015c23096649b908c809c69388a805a571a3bea44362fe87e33fc3afa01f/flask-3.0.0-py3-none-any.whl
|
||
itsdangerous==2.1.2
|
||
# via flask
|
||
jinja2==3.1.2
|
||
# via flask
|
||
markupsafe==2.1.3
|
||
# via
|
||
# jinja2
|
||
# werkzeug
|
||
werkzeug==3.0.1
|
||
# via flask
|
||
|
||
----- stderr -----
|
||
Resolved 7 packages in [TIME]
|
||
"###);
|
||
});
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// Resolve a specific Flask source distribution via a URL dependency.
|
||
#[test]
|
||
fn compile_sdist_url_dependency() -> Result<()> {
|
||
let temp_dir = TempDir::new()?;
|
||
let cache_dir = TempDir::new()?;
|
||
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
||
|
||
let requirements_in = temp_dir.child("requirements.in");
|
||
requirements_in.write_str("flask @ https://files.pythonhosted.org/packages/d8/09/c1a7354d3925a3c6c8cfdebf4245bae67d633ffda1ba415add06ffc839c5/flask-3.0.0.tar.gz")?;
|
||
|
||
insta::with_settings!({
|
||
filters => INSTA_FILTERS.to_vec()
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip-compile")
|
||
.arg("requirements.in")
|
||
.arg("--cache-dir")
|
||
.arg(cache_dir.path())
|
||
.arg("--exclude-newer")
|
||
.arg(EXCLUDE_NEWER)
|
||
.env("VIRTUAL_ENV", venv.as_os_str())
|
||
.current_dir(&temp_dir), @r###"
|
||
success: true
|
||
exit_code: 0
|
||
----- stdout -----
|
||
# This file was autogenerated by Puffin v0.0.1 via the following command:
|
||
# puffin pip-compile requirements.in --cache-dir [CACHE_DIR]
|
||
blinker==1.7.0
|
||
# via flask
|
||
click==8.1.7
|
||
# via flask
|
||
flask @ https://files.pythonhosted.org/packages/d8/09/c1a7354d3925a3c6c8cfdebf4245bae67d633ffda1ba415add06ffc839c5/flask-3.0.0.tar.gz
|
||
itsdangerous==2.1.2
|
||
# via flask
|
||
jinja2==3.1.2
|
||
# via flask
|
||
markupsafe==2.1.3
|
||
# via
|
||
# jinja2
|
||
# werkzeug
|
||
werkzeug==3.0.1
|
||
# via flask
|
||
|
||
----- stderr -----
|
||
Resolved 7 packages in [TIME]
|
||
"###);
|
||
});
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// Resolve a specific Flask source distribution via a Git HTTPS dependency.
|
||
#[test]
|
||
#[cfg(feature = "git")]
|
||
fn compile_git_https_dependency() -> Result<()> {
|
||
let temp_dir = TempDir::new()?;
|
||
let cache_dir = TempDir::new()?;
|
||
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
||
|
||
let requirements_in = temp_dir.child("requirements.in");
|
||
requirements_in.write_str("flask @ git+https://github.com/pallets/flask.git")?;
|
||
|
||
// In addition to the standard filters, remove the `main` commit, which will change frequently.
|
||
let mut filters = INSTA_FILTERS.to_vec();
|
||
filters.push((r"@(\d|\w){40}", "@[COMMIT]"));
|
||
|
||
insta::with_settings!({
|
||
filters => filters
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip-compile")
|
||
.arg("requirements.in")
|
||
.arg("--cache-dir")
|
||
.arg(cache_dir.path())
|
||
.arg("--exclude-newer")
|
||
.arg(EXCLUDE_NEWER)
|
||
.env("VIRTUAL_ENV", venv.as_os_str())
|
||
.current_dir(&temp_dir), @r###"
|
||
success: true
|
||
exit_code: 0
|
||
----- stdout -----
|
||
# This file was autogenerated by Puffin v0.0.1 via the following command:
|
||
# puffin pip-compile requirements.in --cache-dir [CACHE_DIR]
|
||
blinker==1.7.0
|
||
# via flask
|
||
click==8.1.7
|
||
# via flask
|
||
flask @ git+https://github.com/pallets/flask.git@[COMMIT]
|
||
itsdangerous==2.1.2
|
||
# via flask
|
||
jinja2==3.1.2
|
||
# via flask
|
||
markupsafe==2.1.3
|
||
# via
|
||
# jinja2
|
||
# werkzeug
|
||
werkzeug==3.0.1
|
||
# via flask
|
||
|
||
----- stderr -----
|
||
Resolved 7 packages in [TIME]
|
||
"###);
|
||
});
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// Resolve a specific Flask branch via a Git HTTPS dependency.
|
||
#[test]
|
||
#[cfg(feature = "git")]
|
||
fn compile_git_branch_https_dependency() -> Result<()> {
|
||
let temp_dir = TempDir::new()?;
|
||
let cache_dir = TempDir::new()?;
|
||
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
||
|
||
let requirements_in = temp_dir.child("requirements.in");
|
||
requirements_in.write_str("flask @ git+https://github.com/pallets/flask.git@1.0.x")?;
|
||
|
||
insta::with_settings!({
|
||
filters => INSTA_FILTERS.to_vec()
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip-compile")
|
||
.arg("requirements.in")
|
||
.arg("--cache-dir")
|
||
.arg(cache_dir.path())
|
||
.arg("--exclude-newer")
|
||
.arg(EXCLUDE_NEWER)
|
||
.env("VIRTUAL_ENV", venv.as_os_str())
|
||
.current_dir(&temp_dir), @r###"
|
||
success: true
|
||
exit_code: 0
|
||
----- stdout -----
|
||
# This file was autogenerated by Puffin v0.0.1 via the following command:
|
||
# puffin pip-compile requirements.in --cache-dir [CACHE_DIR]
|
||
click==8.1.7
|
||
# via flask
|
||
flask @ git+https://github.com/pallets/flask.git@d92b64aa275841b0c9aea3903aba72fbc4275d91
|
||
itsdangerous==2.1.2
|
||
# via flask
|
||
jinja2==3.1.2
|
||
# via flask
|
||
markupsafe==2.1.3
|
||
# via
|
||
# jinja2
|
||
# werkzeug
|
||
werkzeug==3.0.1
|
||
# via flask
|
||
|
||
----- stderr -----
|
||
Resolved 6 packages in [TIME]
|
||
"###);
|
||
});
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// Resolve a specific Flask tag via a Git HTTPS dependency.
|
||
#[test]
|
||
#[cfg(feature = "git")]
|
||
fn compile_git_tag_https_dependency() -> Result<()> {
|
||
let temp_dir = TempDir::new()?;
|
||
let cache_dir = TempDir::new()?;
|
||
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
||
|
||
let requirements_in = temp_dir.child("requirements.in");
|
||
requirements_in.write_str("flask @ git+https://github.com/pallets/flask.git@3.0.0")?;
|
||
|
||
insta::with_settings!({
|
||
filters => INSTA_FILTERS.to_vec()
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip-compile")
|
||
.arg("requirements.in")
|
||
.arg("--cache-dir")
|
||
.arg(cache_dir.path())
|
||
.arg("--exclude-newer")
|
||
.arg(EXCLUDE_NEWER)
|
||
.env("VIRTUAL_ENV", venv.as_os_str())
|
||
.current_dir(&temp_dir), @r###"
|
||
success: true
|
||
exit_code: 0
|
||
----- stdout -----
|
||
# This file was autogenerated by Puffin v0.0.1 via the following command:
|
||
# puffin pip-compile requirements.in --cache-dir [CACHE_DIR]
|
||
blinker==1.7.0
|
||
# via flask
|
||
click==8.1.7
|
||
# via flask
|
||
flask @ git+https://github.com/pallets/flask.git@735a4701d6d5e848241e7d7535db898efb62d400
|
||
itsdangerous==2.1.2
|
||
# via flask
|
||
jinja2==3.1.2
|
||
# via flask
|
||
markupsafe==2.1.3
|
||
# via
|
||
# jinja2
|
||
# werkzeug
|
||
werkzeug==3.0.1
|
||
# via flask
|
||
|
||
----- stderr -----
|
||
Resolved 7 packages in [TIME]
|
||
"###);
|
||
});
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// Resolve a specific Flask commit via a Git HTTPS dependency.
|
||
#[test]
|
||
#[cfg(feature = "git")]
|
||
fn compile_git_long_commit_https_dependency() -> Result<()> {
|
||
let temp_dir = TempDir::new()?;
|
||
let cache_dir = TempDir::new()?;
|
||
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
||
|
||
let requirements_in = temp_dir.child("requirements.in");
|
||
requirements_in.write_str(
|
||
"flask @ git+https://github.com/pallets/flask.git@d92b64aa275841b0c9aea3903aba72fbc4275d91",
|
||
)?;
|
||
|
||
insta::with_settings!({
|
||
filters => INSTA_FILTERS.to_vec()
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip-compile")
|
||
.arg("requirements.in")
|
||
.arg("--cache-dir")
|
||
.arg(cache_dir.path())
|
||
.arg("--exclude-newer")
|
||
.arg(EXCLUDE_NEWER)
|
||
.env("VIRTUAL_ENV", venv.as_os_str())
|
||
.current_dir(&temp_dir), @r###"
|
||
success: true
|
||
exit_code: 0
|
||
----- stdout -----
|
||
# This file was autogenerated by Puffin v0.0.1 via the following command:
|
||
# puffin pip-compile requirements.in --cache-dir [CACHE_DIR]
|
||
click==8.1.7
|
||
# via flask
|
||
flask @ git+https://github.com/pallets/flask.git@d92b64aa275841b0c9aea3903aba72fbc4275d91
|
||
itsdangerous==2.1.2
|
||
# via flask
|
||
jinja2==3.1.2
|
||
# via flask
|
||
markupsafe==2.1.3
|
||
# via
|
||
# jinja2
|
||
# werkzeug
|
||
werkzeug==3.0.1
|
||
# via flask
|
||
|
||
----- stderr -----
|
||
Resolved 6 packages in [TIME]
|
||
"###);
|
||
});
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// Resolve a specific Flask commit via a Git HTTPS dependency.
|
||
#[test]
|
||
#[cfg(feature = "git")]
|
||
fn compile_git_short_commit_https_dependency() -> Result<()> {
|
||
let temp_dir = TempDir::new()?;
|
||
let cache_dir = TempDir::new()?;
|
||
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
||
|
||
let requirements_in = temp_dir.child("requirements.in");
|
||
requirements_in.write_str("flask @ git+https://github.com/pallets/flask.git@d92b64a")?;
|
||
|
||
insta::with_settings!({
|
||
filters => INSTA_FILTERS.to_vec()
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip-compile")
|
||
.arg("requirements.in")
|
||
.arg("--cache-dir")
|
||
.arg(cache_dir.path())
|
||
.arg("--exclude-newer")
|
||
.arg(EXCLUDE_NEWER)
|
||
.env("VIRTUAL_ENV", venv.as_os_str())
|
||
.current_dir(&temp_dir), @r###"
|
||
success: true
|
||
exit_code: 0
|
||
----- stdout -----
|
||
# This file was autogenerated by Puffin v0.0.1 via the following command:
|
||
# puffin pip-compile requirements.in --cache-dir [CACHE_DIR]
|
||
click==8.1.7
|
||
# via flask
|
||
flask @ git+https://github.com/pallets/flask.git@d92b64aa275841b0c9aea3903aba72fbc4275d91
|
||
itsdangerous==2.1.2
|
||
# via flask
|
||
jinja2==3.1.2
|
||
# via flask
|
||
markupsafe==2.1.3
|
||
# via
|
||
# jinja2
|
||
# werkzeug
|
||
werkzeug==3.0.1
|
||
# via flask
|
||
|
||
----- stderr -----
|
||
Resolved 6 packages in [TIME]
|
||
"###);
|
||
});
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// Resolve a specific Flask ref via a Git HTTPS dependency.
|
||
#[test]
|
||
#[cfg(feature = "git")]
|
||
fn compile_git_refs_https_dependency() -> Result<()> {
|
||
let temp_dir = TempDir::new()?;
|
||
let cache_dir = TempDir::new()?;
|
||
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
||
|
||
let requirements_in = temp_dir.child("requirements.in");
|
||
requirements_in
|
||
.write_str("flask @ git+https://github.com/pallets/flask.git@refs/pull/5313/head")?;
|
||
|
||
insta::with_settings!({
|
||
filters => INSTA_FILTERS.to_vec()
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip-compile")
|
||
.arg("requirements.in")
|
||
.arg("--cache-dir")
|
||
.arg(cache_dir.path())
|
||
.arg("--exclude-newer")
|
||
.arg(EXCLUDE_NEWER)
|
||
.env("VIRTUAL_ENV", venv.as_os_str())
|
||
.current_dir(&temp_dir), @r###"
|
||
success: true
|
||
exit_code: 0
|
||
----- stdout -----
|
||
# This file was autogenerated by Puffin v0.0.1 via the following command:
|
||
# puffin pip-compile requirements.in --cache-dir [CACHE_DIR]
|
||
blinker==1.7.0
|
||
# via flask
|
||
click==8.1.7
|
||
# via flask
|
||
flask @ git+https://github.com/pallets/flask.git@7af0271f4703a71beef8e26d1f5f6f8da04100e6
|
||
itsdangerous==2.1.2
|
||
# via flask
|
||
jinja2==3.1.2
|
||
# via flask
|
||
markupsafe==2.1.3
|
||
# via
|
||
# jinja2
|
||
# werkzeug
|
||
werkzeug==3.0.1
|
||
# via flask
|
||
|
||
----- stderr -----
|
||
Resolved 7 packages in [TIME]
|
||
"###);
|
||
});
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// Resolve a specific Git dependency with a subdirectory.
|
||
#[test]
|
||
#[cfg(feature = "git")]
|
||
fn compile_git_subdirectory_dependency() -> Result<()> {
|
||
let temp_dir = TempDir::new()?;
|
||
let cache_dir = TempDir::new()?;
|
||
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
||
|
||
let requirements_in = temp_dir.child("requirements.in");
|
||
requirements_in.write_str("example-pkg-a @ git+https://github.com/pypa/sample-namespace-packages.git@df7530eeb8fa0cb7dbb8ecb28363e8e36bfa2f45#subdirectory=pkg_resources/pkg_a")?;
|
||
|
||
insta::with_settings!({
|
||
filters => INSTA_FILTERS.to_vec()
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip-compile")
|
||
.arg("requirements.in")
|
||
.arg("--cache-dir")
|
||
.arg(cache_dir.path())
|
||
.arg("--exclude-newer")
|
||
.arg(EXCLUDE_NEWER)
|
||
.env("VIRTUAL_ENV", venv.as_os_str())
|
||
.current_dir(&temp_dir), @r###"
|
||
success: true
|
||
exit_code: 0
|
||
----- stdout -----
|
||
# This file was autogenerated by Puffin v0.0.1 via the following command:
|
||
# puffin pip-compile requirements.in --cache-dir [CACHE_DIR]
|
||
example-pkg-a @ git+https://github.com/pypa/sample-namespace-packages.git@df7530eeb8fa0cb7dbb8ecb28363e8e36bfa2f45#subdirectory=pkg_resources/pkg_a
|
||
|
||
----- stderr -----
|
||
Resolved 1 package in [TIME]
|
||
"###);
|
||
});
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// Resolve two packages from a `requirements.in` file with the same Git HTTPS dependency.
|
||
#[test]
|
||
#[cfg(feature = "git")]
|
||
fn compile_git_concurrent_access() -> Result<()> {
|
||
let temp_dir = TempDir::new()?;
|
||
let cache_dir = TempDir::new()?;
|
||
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
||
|
||
let requirements_in = temp_dir.child("requirements.in");
|
||
requirements_in
|
||
.write_str("example-pkg-a @ git+https://github.com/pypa/sample-namespace-packages.git@df7530eeb8fa0cb7dbb8ecb28363e8e36bfa2f45#subdirectory=pkg_resources/pkg_a\nexample-pkg-b @ git+https://github.com/pypa/sample-namespace-packages.git@df7530eeb8fa0cb7dbb8ecb28363e8e36bfa2f45#subdirectory=pkg_resources/pkg_b")?;
|
||
|
||
insta::with_settings!({
|
||
filters => INSTA_FILTERS.to_vec()
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip-compile")
|
||
.arg("requirements.in")
|
||
.arg("--cache-dir")
|
||
.arg(cache_dir.path())
|
||
.arg("--exclude-newer")
|
||
.arg(EXCLUDE_NEWER)
|
||
.env("VIRTUAL_ENV", venv.as_os_str())
|
||
.current_dir(&temp_dir), @r###"
|
||
success: true
|
||
exit_code: 0
|
||
----- stdout -----
|
||
# This file was autogenerated by Puffin v0.0.1 via the following command:
|
||
# puffin pip-compile requirements.in --cache-dir [CACHE_DIR]
|
||
example-pkg-a @ git+https://github.com/pypa/sample-namespace-packages.git@df7530eeb8fa0cb7dbb8ecb28363e8e36bfa2f45#subdirectory=pkg_resources/pkg_a
|
||
example-pkg-b @ git+https://github.com/pypa/sample-namespace-packages.git@df7530eeb8fa0cb7dbb8ecb28363e8e36bfa2f45#subdirectory=pkg_resources/pkg_b
|
||
|
||
----- stderr -----
|
||
Resolved 2 packages in [TIME]
|
||
"###);
|
||
});
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// Resolve a Git dependency with a declared name that differs from the true name of the package.
|
||
#[test]
|
||
#[cfg(feature = "git")]
|
||
fn compile_git_mismatched_name() -> Result<()> {
|
||
let temp_dir = TempDir::new()?;
|
||
let cache_dir = TempDir::new()?;
|
||
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
||
|
||
let requirements_in = temp_dir.child("requirements.in");
|
||
requirements_in
|
||
.write_str("flask @ git+https://github.com/pallets/flask.git@2.0.0\ndask @ git+https://github.com/pallets/flask.git@3.0.0")?;
|
||
|
||
insta::with_settings!({
|
||
filters => INSTA_FILTERS.to_vec()
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip-compile")
|
||
.arg("requirements.in")
|
||
.arg("--cache-dir")
|
||
.arg(cache_dir.path())
|
||
.arg("--exclude-newer")
|
||
.arg(EXCLUDE_NEWER)
|
||
.env("VIRTUAL_ENV", venv.as_os_str())
|
||
.current_dir(&temp_dir), @r###"
|
||
success: false
|
||
exit_code: 2
|
||
----- stdout -----
|
||
|
||
----- stderr -----
|
||
error: Failed to download and build: dask @ git+https://github.com/pallets/flask.git@3.0.0
|
||
Caused by: Package metadata name `flask` does not match given name `dask`
|
||
"###);
|
||
});
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// Request Flask, but include a URL dependency for Werkzeug, which should avoid adding a
|
||
/// duplicate dependency from `PyPI`.
|
||
#[test]
|
||
fn mixed_url_dependency() -> Result<()> {
|
||
let temp_dir = TempDir::new()?;
|
||
let cache_dir = TempDir::new()?;
|
||
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
||
|
||
let requirements_in = temp_dir.child("requirements.in");
|
||
requirements_in.write_str("flask==3.0.0\nwerkzeug @ https://files.pythonhosted.org/packages/c3/fc/254c3e9b5feb89ff5b9076a23218dafbc99c96ac5941e900b71206e6313b/werkzeug-3.0.1-py3-none-any.whl")?;
|
||
|
||
insta::with_settings!({
|
||
filters => INSTA_FILTERS.to_vec()
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip-compile")
|
||
.arg("requirements.in")
|
||
.arg("--cache-dir")
|
||
.arg(cache_dir.path())
|
||
.arg("--exclude-newer")
|
||
.arg(EXCLUDE_NEWER)
|
||
.env("VIRTUAL_ENV", venv.as_os_str())
|
||
.current_dir(&temp_dir), @r###"
|
||
success: true
|
||
exit_code: 0
|
||
----- stdout -----
|
||
# This file was autogenerated by Puffin v0.0.1 via the following command:
|
||
# puffin pip-compile requirements.in --cache-dir [CACHE_DIR]
|
||
blinker==1.7.0
|
||
# via flask
|
||
click==8.1.7
|
||
# via flask
|
||
flask==3.0.0
|
||
itsdangerous==2.1.2
|
||
# via flask
|
||
jinja2==3.1.2
|
||
# via flask
|
||
markupsafe==2.1.3
|
||
# via
|
||
# jinja2
|
||
# werkzeug
|
||
werkzeug @ https://files.pythonhosted.org/packages/c3/fc/254c3e9b5feb89ff5b9076a23218dafbc99c96ac5941e900b71206e6313b/werkzeug-3.0.1-py3-none-any.whl
|
||
# via flask
|
||
|
||
----- stderr -----
|
||
Resolved 7 packages in [TIME]
|
||
"###);
|
||
});
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// Request Werkzeug via both a version and a URL dependency at a _different_ version, which
|
||
/// should result in a conflict.
|
||
#[test]
|
||
fn conflicting_direct_url_dependency() -> Result<()> {
|
||
let temp_dir = TempDir::new()?;
|
||
let cache_dir = TempDir::new()?;
|
||
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
||
|
||
let requirements_in = temp_dir.child("requirements.in");
|
||
requirements_in.write_str("werkzeug==3.0.0\nwerkzeug @ https://files.pythonhosted.org/packages/ff/1d/960bb4017c68674a1cb099534840f18d3def3ce44aed12b5ed8b78e0153e/Werkzeug-2.0.0-py3-none-any.whl")?;
|
||
|
||
insta::with_settings!({
|
||
filters => INSTA_FILTERS.to_vec()
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip-compile")
|
||
.arg("requirements.in")
|
||
.arg("--cache-dir")
|
||
.arg(cache_dir.path())
|
||
.arg("--exclude-newer")
|
||
.arg(EXCLUDE_NEWER)
|
||
.env("VIRTUAL_ENV", venv.as_os_str())
|
||
.current_dir(&temp_dir), @r###"
|
||
success: false
|
||
exit_code: 1
|
||
----- stdout -----
|
||
|
||
----- stderr -----
|
||
× No solution found when resolving dependencies:
|
||
╰─▶ Because there is no version of werkzeug available matching ==3.0.0 and
|
||
root depends on werkzeug==3.0.0, version solving failed.
|
||
"###);
|
||
});
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// Request Werkzeug via both a version and a URL dependency at _the same_ version, which
|
||
/// should prefer the direct URL dependency.
|
||
#[test]
|
||
fn compatible_direct_url_dependency() -> Result<()> {
|
||
let temp_dir = TempDir::new()?;
|
||
let cache_dir = TempDir::new()?;
|
||
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
||
|
||
let requirements_in = temp_dir.child("requirements.in");
|
||
requirements_in.write_str("werkzeug==2.0.0\nwerkzeug @ https://files.pythonhosted.org/packages/ff/1d/960bb4017c68674a1cb099534840f18d3def3ce44aed12b5ed8b78e0153e/Werkzeug-2.0.0-py3-none-any.whl")?;
|
||
|
||
insta::with_settings!({
|
||
filters => INSTA_FILTERS.to_vec()
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip-compile")
|
||
.arg("requirements.in")
|
||
.arg("--cache-dir")
|
||
.arg(cache_dir.path())
|
||
.arg("--exclude-newer")
|
||
.arg(EXCLUDE_NEWER)
|
||
.env("VIRTUAL_ENV", venv.as_os_str())
|
||
.current_dir(&temp_dir), @r###"
|
||
success: true
|
||
exit_code: 0
|
||
----- stdout -----
|
||
# This file was autogenerated by Puffin v0.0.1 via the following command:
|
||
# puffin pip-compile requirements.in --cache-dir [CACHE_DIR]
|
||
werkzeug @ https://files.pythonhosted.org/packages/ff/1d/960bb4017c68674a1cb099534840f18d3def3ce44aed12b5ed8b78e0153e/Werkzeug-2.0.0-py3-none-any.whl
|
||
|
||
----- stderr -----
|
||
Resolved 1 package in [TIME]
|
||
"###);
|
||
});
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// Request Werkzeug via two different URLs at different versions, which should result in a conflict.
|
||
#[test]
|
||
fn conflicting_repeated_url_dependency_version_mismatch() -> Result<()> {
|
||
let temp_dir = TempDir::new()?;
|
||
let cache_dir = TempDir::new()?;
|
||
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
||
|
||
let requirements_in = temp_dir.child("requirements.in");
|
||
requirements_in.write_str("werkzeug @ https://files.pythonhosted.org/packages/bd/24/11c3ea5a7e866bf2d97f0501d0b4b1c9bbeade102bb4b588f0d2919a5212/Werkzeug-2.0.1-py3-none-any.whl\nwerkzeug @ https://files.pythonhosted.org/packages/ff/1d/960bb4017c68674a1cb099534840f18d3def3ce44aed12b5ed8b78e0153e/Werkzeug-2.0.0-py3-none-any.whl")?;
|
||
|
||
insta::with_settings!({
|
||
filters => INSTA_FILTERS.to_vec()
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip-compile")
|
||
.arg("requirements.in")
|
||
.arg("--cache-dir")
|
||
.arg(cache_dir.path())
|
||
.arg("--exclude-newer")
|
||
.arg(EXCLUDE_NEWER)
|
||
.env("VIRTUAL_ENV", venv.as_os_str())
|
||
.current_dir(&temp_dir), @r###"
|
||
success: false
|
||
exit_code: 1
|
||
----- stdout -----
|
||
|
||
----- stderr -----
|
||
× No solution found when resolving dependencies:
|
||
╰─▶ root dependencies are unusable: Conflicting URLs for package `werkzeug`:
|
||
- https://files.pythonhosted.org/packages/bd/24/11c3ea5a7e866bf2d97f0501d0b4b1c9bbeade102bb4b588f0d2919a5212/Werkzeug-2.0.1-py3-none-any.whl
|
||
- https://files.pythonhosted.org/packages/ff/1d/960bb4017c68674a1cb099534840f18d3def3ce44aed12b5ed8b78e0153e/Werkzeug-2.0.0-py3-none-any.whl
|
||
"###);
|
||
});
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// Request Werkzeug via two different URLs at the same version. Despite mapping to the same
|
||
/// version, it should still result in a conflict.
|
||
#[test]
|
||
#[cfg(feature = "git")]
|
||
fn conflicting_repeated_url_dependency_version_match() -> Result<()> {
|
||
let temp_dir = TempDir::new()?;
|
||
let cache_dir = TempDir::new()?;
|
||
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
||
|
||
let requirements_in = temp_dir.child("requirements.in");
|
||
requirements_in.write_str("werkzeug @ git+https://github.com/pallets/werkzeug.git@2.0.0\nwerkzeug @ https://files.pythonhosted.org/packages/ff/1d/960bb4017c68674a1cb099534840f18d3def3ce44aed12b5ed8b78e0153e/Werkzeug-2.0.0-py3-none-any.whl")?;
|
||
|
||
insta::with_settings!({
|
||
filters => INSTA_FILTERS.to_vec()
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip-compile")
|
||
.arg("requirements.in")
|
||
.arg("--cache-dir")
|
||
.arg(cache_dir.path())
|
||
.arg("--exclude-newer")
|
||
.arg(EXCLUDE_NEWER)
|
||
.env("VIRTUAL_ENV", venv.as_os_str())
|
||
.current_dir(&temp_dir), @r###"
|
||
success: false
|
||
exit_code: 1
|
||
----- stdout -----
|
||
|
||
----- stderr -----
|
||
× No solution found when resolving dependencies:
|
||
╰─▶ root dependencies are unusable: Conflicting URLs for package `werkzeug`:
|
||
- git+https://github.com/pallets/werkzeug.git@2.0.0
|
||
- https://files.pythonhosted.org/packages/ff/1d/960bb4017c68674a1cb099534840f18d3def3ce44aed12b5ed8b78e0153e/Werkzeug-2.0.0-py3-none-any.whl
|
||
"###);
|
||
});
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// Request Flask, but include a URL dependency for a conflicting version of Werkzeug.
|
||
#[test]
|
||
fn conflicting_transitive_url_dependency() -> Result<()> {
|
||
let temp_dir = TempDir::new()?;
|
||
let cache_dir = TempDir::new()?;
|
||
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
||
|
||
let requirements_in = temp_dir.child("requirements.in");
|
||
requirements_in.write_str("flask==3.0.0\nwerkzeug @ https://files.pythonhosted.org/packages/ff/1d/960bb4017c68674a1cb099534840f18d3def3ce44aed12b5ed8b78e0153e/Werkzeug-2.0.0-py3-none-any.whl")?;
|
||
|
||
insta::with_settings!({
|
||
filters => INSTA_FILTERS.to_vec()
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip-compile")
|
||
.arg("requirements.in")
|
||
.arg("--cache-dir")
|
||
.arg(cache_dir.path())
|
||
.arg("--exclude-newer")
|
||
.arg(EXCLUDE_NEWER)
|
||
.env("VIRTUAL_ENV", venv.as_os_str())
|
||
.current_dir(&temp_dir), @r###"
|
||
success: false
|
||
exit_code: 1
|
||
----- stdout -----
|
||
|
||
----- stderr -----
|
||
× No solution found when resolving dependencies:
|
||
╰─▶ Because there is no version of werkzeug available matching >=3.0.0 and
|
||
flask==3.0.0 depends on werkzeug>=3.0.0, flask==3.0.0 is forbidden.
|
||
And because root depends on flask==3.0.0, version solving failed.
|
||
"###);
|
||
});
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// Request `transitive_url_dependency`, which depends on `git+https://github.com/pallets/werkzeug@2.0.0`.
|
||
/// Since this URL isn't declared upfront, we should reject it.
|
||
#[test]
|
||
#[cfg(feature = "git")]
|
||
fn disallowed_transitive_url_dependency() -> Result<()> {
|
||
let temp_dir = TempDir::new()?;
|
||
let cache_dir = TempDir::new()?;
|
||
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
||
|
||
let requirements_in = temp_dir.child("requirements.in");
|
||
requirements_in.write_str("transitive_url_dependency @ https://github.com/astral-sh/ruff/files/13257454/transitive_url_dependency.zip")?;
|
||
|
||
insta::with_settings!({
|
||
filters => INSTA_FILTERS.to_vec()
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip-compile")
|
||
.arg("requirements.in")
|
||
.arg("--cache-dir")
|
||
.arg(cache_dir.path())
|
||
.arg("--exclude-newer")
|
||
.arg(EXCLUDE_NEWER)
|
||
.env("VIRTUAL_ENV", venv.as_os_str())
|
||
.current_dir(&temp_dir), @r###"
|
||
success: false
|
||
exit_code: 2
|
||
----- stdout -----
|
||
|
||
----- stderr -----
|
||
error: Package `werkzeug` attempted to resolve via URL: git+https://github.com/pallets/werkzeug@2.0.0. URL dependencies must be expressed as direct requirements or constraints. Consider adding `werkzeug @ git+https://github.com/pallets/werkzeug@2.0.0` to your dependencies or constraints file.
|
||
"###);
|
||
});
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// Request `transitive_url_dependency`, which depends on `git+https://github.com/pallets/werkzeug@2.0.0`.
|
||
/// Since this URL is declared as a constraint, we should accept it.
|
||
#[test]
|
||
#[cfg(feature = "git")]
|
||
fn allowed_transitive_url_dependency() -> Result<()> {
|
||
let temp_dir = TempDir::new()?;
|
||
let cache_dir = TempDir::new()?;
|
||
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
||
|
||
let requirements_in = temp_dir.child("requirements.in");
|
||
requirements_in.write_str("transitive_url_dependency @ https://github.com/astral-sh/ruff/files/13257454/transitive_url_dependency.zip")?;
|
||
|
||
let constraints_txt = temp_dir.child("constraints.txt");
|
||
constraints_txt.write_str("werkzeug @ git+https://github.com/pallets/werkzeug@2.0.0")?;
|
||
|
||
insta::with_settings!({
|
||
filters => INSTA_FILTERS.to_vec()
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip-compile")
|
||
.arg("requirements.in")
|
||
.arg("--constraint")
|
||
.arg("constraints.txt")
|
||
.arg("--cache-dir")
|
||
.arg(cache_dir.path())
|
||
.arg("--exclude-newer")
|
||
.arg(EXCLUDE_NEWER)
|
||
.env("VIRTUAL_ENV", venv.as_os_str())
|
||
.current_dir(&temp_dir), @r###"
|
||
success: true
|
||
exit_code: 0
|
||
----- stdout -----
|
||
# This file was autogenerated by Puffin v0.0.1 via the following command:
|
||
# puffin pip-compile requirements.in --constraint constraints.txt --cache-dir [CACHE_DIR]
|
||
transitive-url-dependency @ https://github.com/astral-sh/ruff/files/13257454/transitive_url_dependency.zip
|
||
werkzeug @ git+https://github.com/pallets/werkzeug@af160e0b6b7ddd81c22f1652c728ff5ac72d5c74
|
||
# via transitive-url-dependency
|
||
|
||
----- stderr -----
|
||
Resolved 2 packages in [TIME]
|
||
"###);
|
||
});
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// Request `transitive_url_dependency`, which depends on `git+https://github.com/pallets/werkzeug@2.0.0`.
|
||
/// Since this `git+https://github.com/pallets/werkzeug@2.0.0.git` is declared as a constraint, and
|
||
/// those map to the same canonical URL, we should accept it.
|
||
#[test]
|
||
#[cfg(feature = "git")]
|
||
fn allowed_transitive_canonical_url_dependency() -> Result<()> {
|
||
let temp_dir = TempDir::new()?;
|
||
let cache_dir = TempDir::new()?;
|
||
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
||
|
||
let requirements_in = temp_dir.child("requirements.in");
|
||
requirements_in.write_str("transitive_url_dependency @ https://github.com/astral-sh/ruff/files/13257454/transitive_url_dependency.zip")?;
|
||
|
||
let constraints_txt = temp_dir.child("constraints.txt");
|
||
constraints_txt.write_str("werkzeug @ git+https://github.com/pallets/werkzeug.git@2.0.0")?;
|
||
|
||
insta::with_settings!({
|
||
filters => INSTA_FILTERS.to_vec()
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip-compile")
|
||
.arg("requirements.in")
|
||
.arg("--constraint")
|
||
.arg("constraints.txt")
|
||
.arg("--cache-dir")
|
||
.arg(cache_dir.path())
|
||
.arg("--exclude-newer")
|
||
.arg(EXCLUDE_NEWER)
|
||
.env("VIRTUAL_ENV", venv.as_os_str())
|
||
.current_dir(&temp_dir), @r###"
|
||
success: true
|
||
exit_code: 0
|
||
----- stdout -----
|
||
# This file was autogenerated by Puffin v0.0.1 via the following command:
|
||
# puffin pip-compile requirements.in --constraint constraints.txt --cache-dir [CACHE_DIR]
|
||
transitive-url-dependency @ https://github.com/astral-sh/ruff/files/13257454/transitive_url_dependency.zip
|
||
werkzeug @ git+https://github.com/pallets/werkzeug@af160e0b6b7ddd81c22f1652c728ff5ac72d5c74
|
||
# via transitive-url-dependency
|
||
|
||
----- stderr -----
|
||
Resolved 2 packages in [TIME]
|
||
"###);
|
||
});
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// Resolve packages from all optional dependency groups in a `pyproject.toml` file.
|
||
#[test]
|
||
fn compile_pyproject_toml_all_extras() -> Result<()> {
|
||
let temp_dir = TempDir::new()?;
|
||
let cache_dir = TempDir::new()?;
|
||
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
||
|
||
let pyproject_toml = temp_dir.child("pyproject.toml");
|
||
pyproject_toml.write_str(
|
||
r#"[build-system]
|
||
requires = ["setuptools", "wheel"]
|
||
|
||
[project]
|
||
name = "project"
|
||
dependencies = ["django==5.0b1"]
|
||
optional-dependencies.foo = [
|
||
"anyio==4.0.0",
|
||
]
|
||
optional-dependencies.bar = [
|
||
"httpcore==0.18.0",
|
||
]
|
||
"#,
|
||
)?;
|
||
|
||
insta::with_settings!({
|
||
filters => INSTA_FILTERS.to_vec()
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip-compile")
|
||
.arg("pyproject.toml")
|
||
.arg("--all-extras")
|
||
.arg("--cache-dir")
|
||
.arg(cache_dir.path())
|
||
.arg("--exclude-newer")
|
||
.arg(EXCLUDE_NEWER)
|
||
.env("VIRTUAL_ENV", venv.as_os_str())
|
||
.current_dir(&temp_dir), @r###"
|
||
success: true
|
||
exit_code: 0
|
||
----- stdout -----
|
||
# This file was autogenerated by Puffin v0.0.1 via the following command:
|
||
# puffin pip-compile pyproject.toml --all-extras --cache-dir [CACHE_DIR]
|
||
anyio==4.0.0
|
||
# via httpcore
|
||
asgiref==3.7.2
|
||
# via django
|
||
certifi==2023.11.17
|
||
# via httpcore
|
||
django==5.0b1
|
||
h11==0.14.0
|
||
# via httpcore
|
||
httpcore==0.18.0
|
||
idna==3.4
|
||
# via anyio
|
||
sniffio==1.3.0
|
||
# via
|
||
# anyio
|
||
# httpcore
|
||
sqlparse==0.4.4
|
||
# via django
|
||
|
||
----- stderr -----
|
||
Resolved 9 packages in [TIME]
|
||
"###);
|
||
});
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// Resolve packages from all optional dependency groups in a `pyproject.toml` file.
|
||
#[test]
|
||
fn compile_does_not_allow_both_extra_and_all_extras() -> Result<()> {
|
||
let temp_dir = TempDir::new()?;
|
||
let cache_dir = TempDir::new()?;
|
||
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
||
|
||
let pyproject_toml = temp_dir.child("pyproject.toml");
|
||
pyproject_toml.write_str(
|
||
r#"[build-system]
|
||
requires = ["setuptools", "wheel"]
|
||
|
||
[project]
|
||
name = "project"
|
||
dependencies = ["django==5.0b1"]
|
||
optional-dependencies.foo = [
|
||
"anyio==4.0.0",
|
||
]
|
||
optional-dependencies.bar = [
|
||
"httpcore==0.18.0",
|
||
]
|
||
"#,
|
||
)?;
|
||
|
||
insta::with_settings!({
|
||
filters => INSTA_FILTERS.to_vec()
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip-compile")
|
||
.arg("pyproject.toml")
|
||
.arg("--all-extras")
|
||
.arg("--extra")
|
||
.arg("foo")
|
||
.arg("--cache-dir")
|
||
.arg(cache_dir.path())
|
||
.arg("--exclude-newer")
|
||
.arg(EXCLUDE_NEWER)
|
||
.env("VIRTUAL_ENV", venv.as_os_str())
|
||
.current_dir(&temp_dir),
|
||
@r###"
|
||
success: false
|
||
exit_code: 2
|
||
----- stdout -----
|
||
|
||
----- stderr -----
|
||
error: the argument '--all-extras' cannot be used with '--extra <EXTRA>'
|
||
|
||
Usage: puffin pip-compile --all-extras --cache-dir [CACHE_DIR]
|
||
|
||
For more information, try '--help'.
|
||
"###);
|
||
});
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// Compile requirements that cannot be solved due to conflict in a `pyproject.toml` fil;e.
|
||
#[test]
|
||
fn compile_unsolvable_requirements() -> Result<()> {
|
||
let temp_dir = TempDir::new()?;
|
||
let cache_dir = TempDir::new()?;
|
||
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
||
|
||
let pyproject_toml = temp_dir.child("pyproject.toml");
|
||
pyproject_toml.write_str(
|
||
r#"[build-system]
|
||
requires = ["setuptools", "wheel"]
|
||
|
||
[project]
|
||
name = "my-project"
|
||
dependencies = ["django==5.0b1", "django==5.0a1"]
|
||
"#,
|
||
)?;
|
||
|
||
insta::with_settings!({
|
||
filters => INSTA_FILTERS.to_vec()
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip-compile")
|
||
.arg("pyproject.toml")
|
||
.arg("--cache-dir")
|
||
.arg(cache_dir.path())
|
||
.arg("--exclude-newer")
|
||
.arg(EXCLUDE_NEWER)
|
||
.env("VIRTUAL_ENV", venv.as_os_str())
|
||
.current_dir(&temp_dir), @r###"
|
||
success: false
|
||
exit_code: 1
|
||
----- stdout -----
|
||
|
||
----- stderr -----
|
||
× No solution found when resolving dependencies:
|
||
╰─▶ my-project dependencies are unusable: Conflicting versions for `django`:
|
||
`django==5.0b1` does not intersect with `django==5.0a1`
|
||
"###);
|
||
});
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// Compile requirements in a `pyproject.toml` file that cannot be resolved due to
|
||
/// a requirement with a version that is not available online.
|
||
#[test]
|
||
fn compile_unsolvable_requirements_version_not_available() -> Result<()> {
|
||
let temp_dir = TempDir::new()?;
|
||
let cache_dir = TempDir::new()?;
|
||
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
||
|
||
let pyproject_toml = temp_dir.child("pyproject.toml");
|
||
pyproject_toml.write_str(
|
||
r#"[build-system]
|
||
requires = ["setuptools", "wheel"]
|
||
|
||
[project]
|
||
name = "my-project"
|
||
dependencies = ["django==300.1.4"]
|
||
"#,
|
||
)?;
|
||
|
||
insta::with_settings!({
|
||
filters => INSTA_FILTERS.to_vec()
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip-compile")
|
||
.arg("pyproject.toml")
|
||
.arg("--cache-dir")
|
||
.arg(cache_dir.path())
|
||
.arg("--exclude-newer")
|
||
.arg(EXCLUDE_NEWER)
|
||
.env("VIRTUAL_ENV", venv.as_os_str())
|
||
.current_dir(&temp_dir), @r###"
|
||
success: false
|
||
exit_code: 1
|
||
----- stdout -----
|
||
|
||
----- stderr -----
|
||
× No solution found when resolving dependencies:
|
||
╰─▶ Because there is no version of django available matching ==300.1.4 and
|
||
my-project depends on django==300.1.4, version solving failed.
|
||
"###);
|
||
});
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// Resolve at a specific time in the past
|
||
#[test]
|
||
fn compile_exclude_newer() -> Result<()> {
|
||
let temp_dir = TempDir::new()?;
|
||
let cache_dir = TempDir::new()?;
|
||
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
||
|
||
let requirements_in = temp_dir.child("requirements.in");
|
||
requirements_in.write_str("tqdm")?;
|
||
|
||
insta::with_settings!({
|
||
filters => INSTA_FILTERS.to_vec()
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip-compile")
|
||
.arg("requirements.in")
|
||
.arg("--exclude-newer")
|
||
// 4.64.0: 2022-04-04T01:48:46.194635Z1
|
||
// 4.64.1: 2022-09-03T11:10:27.148080Z
|
||
.arg("2022-04-04T12:00:00Z")
|
||
.arg("--cache-dir")
|
||
.arg(cache_dir.path())
|
||
.env("VIRTUAL_ENV", venv.as_os_str())
|
||
.current_dir(&temp_dir), @r###"
|
||
success: true
|
||
exit_code: 0
|
||
----- stdout -----
|
||
# This file was autogenerated by Puffin v0.0.1 via the following command:
|
||
# puffin pip-compile requirements.in --exclude-newer 2022-04-04T12:00:00Z --cache-dir [CACHE_DIR]
|
||
tqdm==4.64.0
|
||
|
||
----- stderr -----
|
||
Resolved 1 package in [TIME]
|
||
"###);
|
||
});
|
||
|
||
insta::with_settings!({
|
||
filters => INSTA_FILTERS.to_vec()
|
||
}, {
|
||
// Use a date as input instead.
|
||
// We interpret a date as including this day
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip-compile")
|
||
.arg("requirements.in")
|
||
.arg("--exclude-newer")
|
||
.arg("2022-04-04")
|
||
.arg("--cache-dir")
|
||
.arg(cache_dir.path())
|
||
.env("VIRTUAL_ENV", venv.as_os_str())
|
||
.current_dir(&temp_dir), @r###"
|
||
success: true
|
||
exit_code: 0
|
||
----- stdout -----
|
||
# This file was autogenerated by Puffin v0.0.1 via the following command:
|
||
# puffin pip-compile requirements.in --exclude-newer 2022-04-04 --cache-dir [CACHE_DIR]
|
||
tqdm==4.64.0
|
||
|
||
----- stderr -----
|
||
Resolved 1 package in [TIME]
|
||
"###);
|
||
});
|
||
|
||
insta::with_settings!({
|
||
filters => INSTA_FILTERS.to_vec()
|
||
}, {
|
||
// Check the error message for invalid datetime
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip-compile")
|
||
.arg("requirements.in")
|
||
.arg("--exclude-newer")
|
||
.arg("2022-04-04+02:00")
|
||
.arg("--cache-dir")
|
||
.arg(cache_dir.path())
|
||
.env("VIRTUAL_ENV", venv.as_os_str())
|
||
.current_dir(&temp_dir), @r###"
|
||
success: false
|
||
exit_code: 2
|
||
----- stdout -----
|
||
|
||
----- stderr -----
|
||
error: invalid value '2022-04-04+02:00' for '--exclude-newer <EXCLUDE_NEWER>': Neither a valid date (trailing input) not a valid datetime (input contains invalid characters)
|
||
|
||
For more information, try '--help'.
|
||
"###);
|
||
});
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// Resolve a local path dependency on a specific wheel.
|
||
#[test]
|
||
fn compile_wheel_path_dependency() -> Result<()> {
|
||
let temp_dir = TempDir::new()?;
|
||
let cache_dir = TempDir::new()?;
|
||
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
||
|
||
// Download a wheel.
|
||
let response = reqwest::blocking::get("https://files.pythonhosted.org/packages/36/42/015c23096649b908c809c69388a805a571a3bea44362fe87e33fc3afa01f/flask-3.0.0-py3-none-any.whl")?;
|
||
let flask_wheel = temp_dir.child("flask-3.0.0-py3-none-any.whl");
|
||
let mut flask_wheel_file = std::fs::File::create(&flask_wheel)?;
|
||
std::io::copy(&mut response.bytes()?.as_ref(), &mut flask_wheel_file)?;
|
||
|
||
let requirements_in = temp_dir.child("requirements.in");
|
||
requirements_in.write_str(&format!("flask @ file://{}", flask_wheel.path().display()))?;
|
||
|
||
// In addition to the standard filters, remove the temporary directory from the snapshot.
|
||
let mut filters = INSTA_FILTERS.to_vec();
|
||
filters.push((r"file://.*/", "file://[TEMP_DIR]/"));
|
||
|
||
insta::with_settings!({
|
||
filters => filters
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip-compile")
|
||
.arg("requirements.in")
|
||
.arg("--cache-dir")
|
||
.arg(cache_dir.path())
|
||
.arg("--exclude-newer")
|
||
.arg(EXCLUDE_NEWER)
|
||
.env("VIRTUAL_ENV", venv.as_os_str())
|
||
.current_dir(&temp_dir), @r###"
|
||
success: true
|
||
exit_code: 0
|
||
----- stdout -----
|
||
# This file was autogenerated by Puffin v0.0.1 via the following command:
|
||
# puffin pip-compile requirements.in --cache-dir [CACHE_DIR]
|
||
blinker==1.7.0
|
||
# via flask
|
||
click==8.1.7
|
||
# via flask
|
||
flask @ file://[TEMP_DIR]/flask-3.0.0-py3-none-any.whl
|
||
itsdangerous==2.1.2
|
||
# via flask
|
||
jinja2==3.1.2
|
||
# via flask
|
||
markupsafe==2.1.3
|
||
# via
|
||
# jinja2
|
||
# werkzeug
|
||
werkzeug==3.0.1
|
||
# via flask
|
||
|
||
----- stderr -----
|
||
Resolved 7 packages in [TIME]
|
||
"###);
|
||
});
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// Resolve a local path dependency on a specific source distribution.
|
||
#[test]
|
||
fn compile_source_distribution_path_dependency() -> Result<()> {
|
||
let temp_dir = TempDir::new()?;
|
||
let cache_dir = TempDir::new()?;
|
||
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
||
|
||
// Download a source distribution.
|
||
let response = reqwest::blocking::get("https://files.pythonhosted.org/packages/d8/09/c1a7354d3925a3c6c8cfdebf4245bae67d633ffda1ba415add06ffc839c5/flask-3.0.0.tar.gz")?;
|
||
let flask_wheel = temp_dir.child("flask-3.0.0.tar.gz");
|
||
let mut flask_wheel_file = std::fs::File::create(&flask_wheel)?;
|
||
std::io::copy(&mut response.bytes()?.as_ref(), &mut flask_wheel_file)?;
|
||
|
||
let requirements_in = temp_dir.child("requirements.in");
|
||
requirements_in.write_str(&format!("flask @ file://{}", flask_wheel.path().display()))?;
|
||
|
||
// In addition to the standard filters, remove the temporary directory from the snapshot.
|
||
let mut filters = INSTA_FILTERS.to_vec();
|
||
filters.push((r"file://.*/", "file://[TEMP_DIR]/"));
|
||
|
||
insta::with_settings!({
|
||
filters => filters
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip-compile")
|
||
.arg("requirements.in")
|
||
.arg("--cache-dir")
|
||
.arg(cache_dir.path())
|
||
.arg("--exclude-newer")
|
||
.arg(EXCLUDE_NEWER)
|
||
.env("VIRTUAL_ENV", venv.as_os_str())
|
||
.current_dir(&temp_dir), @r###"
|
||
success: true
|
||
exit_code: 0
|
||
----- stdout -----
|
||
# This file was autogenerated by Puffin v0.0.1 via the following command:
|
||
# puffin pip-compile requirements.in --cache-dir [CACHE_DIR]
|
||
blinker==1.7.0
|
||
# via flask
|
||
click==8.1.7
|
||
# via flask
|
||
flask @ file://[TEMP_DIR]/flask-3.0.0.tar.gz
|
||
itsdangerous==2.1.2
|
||
# via flask
|
||
jinja2==3.1.2
|
||
# via flask
|
||
markupsafe==2.1.3
|
||
# via
|
||
# jinja2
|
||
# werkzeug
|
||
werkzeug==3.0.1
|
||
# via flask
|
||
|
||
----- stderr -----
|
||
Resolved 7 packages in [TIME]
|
||
"###);
|
||
});
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// Resolve a local path dependency to a non-existent file.
|
||
#[test]
|
||
fn compile_wheel_path_dependency_missing() -> Result<()> {
|
||
let temp_dir = TempDir::new()?;
|
||
let cache_dir = TempDir::new()?;
|
||
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
||
|
||
let requirements_in = temp_dir.child("requirements.in");
|
||
requirements_in.write_str("flask @ file:///path/to/flask-3.0.0-py3-none-any.whl")?;
|
||
|
||
// In addition to the standard filters, remove the temporary directory from the snapshot.
|
||
let mut filters = INSTA_FILTERS.to_vec();
|
||
filters.push((r"file://.*/", "file://[TEMP_DIR]/"));
|
||
|
||
insta::with_settings!({
|
||
filters => filters
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip-compile")
|
||
.arg("requirements.in")
|
||
.arg("--cache-dir")
|
||
.arg(cache_dir.path())
|
||
.arg("--exclude-newer")
|
||
.arg(EXCLUDE_NEWER)
|
||
.env("VIRTUAL_ENV", venv.as_os_str())
|
||
.current_dir(&temp_dir), @r###"
|
||
success: false
|
||
exit_code: 2
|
||
----- stdout -----
|
||
|
||
----- stderr -----
|
||
error: Unable to locate distribution at: file://[TEMP_DIR]/flask-3.0.0-py3-none-any.whl
|
||
Caused by: No such file or directory (os error 2)
|
||
"###);
|
||
});
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// Resolve a yanked version of `attrs` by specifying the version directly.
|
||
#[test]
|
||
fn compile_yanked_version_direct() -> Result<()> {
|
||
let temp_dir = TempDir::new()?;
|
||
let cache_dir = TempDir::new()?;
|
||
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
||
|
||
let requirements_in = temp_dir.child("requirements.in");
|
||
requirements_in.write_str("attrs==21.1.0")?;
|
||
|
||
insta::with_settings!({
|
||
filters => INSTA_FILTERS.to_vec()
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip-compile")
|
||
.arg("requirements.in")
|
||
.arg("--cache-dir")
|
||
.arg(cache_dir.path())
|
||
.arg("--exclude-newer")
|
||
.arg(EXCLUDE_NEWER)
|
||
.env("VIRTUAL_ENV", venv.as_os_str())
|
||
.current_dir(&temp_dir), @r###"
|
||
success: true
|
||
exit_code: 0
|
||
----- stdout -----
|
||
# This file was autogenerated by Puffin v0.0.1 via the following command:
|
||
# puffin pip-compile requirements.in --cache-dir [CACHE_DIR]
|
||
attrs==21.1.0
|
||
|
||
----- stderr -----
|
||
Resolved 1 package in [TIME]
|
||
"###);
|
||
});
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// Fail to resolve `attrs` due to the indirect use of a yanked version (`21.1.0`).
|
||
#[test]
|
||
fn compile_yanked_version_indirect() -> Result<()> {
|
||
let temp_dir = TempDir::new()?;
|
||
let cache_dir = TempDir::new()?;
|
||
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
||
|
||
let requirements_in = temp_dir.child("requirements.in");
|
||
requirements_in.write_str("attrs>20.3.0,<21.2.0")?;
|
||
|
||
insta::with_settings!({
|
||
filters => INSTA_FILTERS.to_vec()
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip-compile")
|
||
.arg("requirements.in")
|
||
.arg("--cache-dir")
|
||
.arg(cache_dir.path())
|
||
.arg("--exclude-newer")
|
||
.arg(EXCLUDE_NEWER)
|
||
.env("VIRTUAL_ENV", venv.as_os_str())
|
||
.current_dir(&temp_dir), @r###"
|
||
success: false
|
||
exit_code: 1
|
||
----- stdout -----
|
||
|
||
----- stderr -----
|
||
× No solution found when resolving dependencies:
|
||
╰─▶ Because there is no version of attrs available matching >20.3.0, <21.2.0
|
||
and root depends on attrs>20.3.0, <21.2.0, version solving failed.
|
||
"###);
|
||
});
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// Flask==3.0.0 depends on Werkzeug>=3.0.0. Demonstrate that we can override this
|
||
/// requirement with an incompatible version.
|
||
#[test]
|
||
fn override_dependency() -> Result<()> {
|
||
let temp_dir = TempDir::new()?;
|
||
let cache_dir = TempDir::new()?;
|
||
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
||
|
||
let requirements_in = temp_dir.child("requirements.in");
|
||
requirements_in.write_str("flask==3.0.0")?;
|
||
|
||
let overrides_txt = temp_dir.child("overrides.txt");
|
||
overrides_txt.write_str("werkzeug==2.3.0")?;
|
||
|
||
insta::with_settings!({
|
||
filters => INSTA_FILTERS.to_vec()
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip-compile")
|
||
.arg("requirements.in")
|
||
.arg("--override")
|
||
.arg("overrides.txt")
|
||
.arg("--cache-dir")
|
||
.arg(cache_dir.path())
|
||
.arg("--exclude-newer")
|
||
.arg(EXCLUDE_NEWER)
|
||
.env("VIRTUAL_ENV", venv.as_os_str())
|
||
.current_dir(&temp_dir), @r###"
|
||
success: true
|
||
exit_code: 0
|
||
----- stdout -----
|
||
# This file was autogenerated by Puffin v0.0.1 via the following command:
|
||
# puffin pip-compile requirements.in --override overrides.txt --cache-dir [CACHE_DIR]
|
||
blinker==1.7.0
|
||
# via flask
|
||
click==8.1.7
|
||
# via flask
|
||
flask==3.0.0
|
||
itsdangerous==2.1.2
|
||
# via flask
|
||
jinja2==3.1.2
|
||
# via flask
|
||
markupsafe==2.1.3
|
||
# via
|
||
# jinja2
|
||
# werkzeug
|
||
werkzeug==2.3.0
|
||
# via flask
|
||
|
||
----- stderr -----
|
||
Resolved 7 packages in [TIME]
|
||
"###);
|
||
});
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// Black==23.10.1 depends on tomli>=1.1.0 for Python versions below 3.11. Demonstrate that we can
|
||
/// override it with a multi-line override.
|
||
#[test]
|
||
fn override_multi_dependency() -> Result<()> {
|
||
let temp_dir = TempDir::new()?;
|
||
let cache_dir = TempDir::new()?;
|
||
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
||
|
||
let requirements_in = temp_dir.child("requirements.in");
|
||
requirements_in.write_str("black==23.10.1")?;
|
||
|
||
let overrides_txt = temp_dir.child("overrides.txt");
|
||
overrides_txt.write_str(
|
||
"tomli>=1.1.0; python_version >= '3.11'\ntomli<1.0.0; python_version < '3.11'",
|
||
)?;
|
||
|
||
insta::with_settings!({
|
||
filters => INSTA_FILTERS.to_vec()
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip-compile")
|
||
.arg("requirements.in")
|
||
.arg("--override")
|
||
.arg("overrides.txt")
|
||
.arg("--cache-dir")
|
||
.arg(cache_dir.path())
|
||
.arg("--exclude-newer")
|
||
.arg(EXCLUDE_NEWER)
|
||
.env("VIRTUAL_ENV", venv.as_os_str())
|
||
.current_dir(&temp_dir), @r###"
|
||
success: true
|
||
exit_code: 0
|
||
----- stdout -----
|
||
# This file was autogenerated by Puffin v0.0.1 via the following command:
|
||
# puffin pip-compile requirements.in --override overrides.txt --cache-dir [CACHE_DIR]
|
||
black==23.10.1
|
||
click==8.1.7
|
||
# via black
|
||
mypy-extensions==1.0.0
|
||
# via black
|
||
packaging==23.2
|
||
# via black
|
||
pathspec==0.11.2
|
||
# via black
|
||
platformdirs==4.0.0
|
||
# via black
|
||
tomli==2.0.1
|
||
# via black
|
||
|
||
----- stderr -----
|
||
Resolved 7 packages in [TIME]
|
||
"###);
|
||
});
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// Request an extra that doesn't exist on the specified package.
|
||
#[test]
|
||
fn missing_registry_extra() -> Result<()> {
|
||
let temp_dir = TempDir::new()?;
|
||
let cache_dir = TempDir::new()?;
|
||
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
||
|
||
let requirements_in = temp_dir.child("requirements.in");
|
||
requirements_in.write_str("black[tensorboard]==23.10.1")?;
|
||
|
||
insta::with_settings!({
|
||
filters => INSTA_FILTERS.to_vec()
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip-compile")
|
||
.arg("requirements.in")
|
||
.arg("--cache-dir")
|
||
.arg(cache_dir.path())
|
||
.arg("--exclude-newer")
|
||
.arg(EXCLUDE_NEWER)
|
||
.env("VIRTUAL_ENV", venv.as_os_str())
|
||
.current_dir(&temp_dir), @r###"
|
||
success: true
|
||
exit_code: 0
|
||
----- stdout -----
|
||
# This file was autogenerated by Puffin v0.0.1 via the following command:
|
||
# puffin pip-compile requirements.in --cache-dir [CACHE_DIR]
|
||
black==23.10.1
|
||
click==8.1.7
|
||
# via black
|
||
mypy-extensions==1.0.0
|
||
# via black
|
||
packaging==23.2
|
||
# via black
|
||
pathspec==0.11.2
|
||
# via black
|
||
platformdirs==4.0.0
|
||
# via black
|
||
|
||
----- stderr -----
|
||
Resolved 6 packages in [TIME]
|
||
warning: The package `black==23.10.1` does not have an extra named `tensorboard`.
|
||
"###);
|
||
});
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// Request an extra that doesn't exist on the specified package.
|
||
#[test]
|
||
fn missing_url_extra() -> Result<()> {
|
||
let temp_dir = TempDir::new()?;
|
||
let cache_dir = TempDir::new()?;
|
||
let venv = create_venv_py312(&temp_dir, &cache_dir);
|
||
|
||
let requirements_in = temp_dir.child("requirements.in");
|
||
requirements_in.write_str("flask[tensorboard] @ https://files.pythonhosted.org/packages/36/42/015c23096649b908c809c69388a805a571a3bea44362fe87e33fc3afa01f/flask-3.0.0-py3-none-any.whl")?;
|
||
|
||
insta::with_settings!({
|
||
filters => INSTA_FILTERS.to_vec()
|
||
}, {
|
||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||
.arg("pip-compile")
|
||
.arg("requirements.in")
|
||
.arg("--cache-dir")
|
||
.arg(cache_dir.path())
|
||
.arg("--exclude-newer")
|
||
.arg(EXCLUDE_NEWER)
|
||
.env("VIRTUAL_ENV", venv.as_os_str())
|
||
.current_dir(&temp_dir), @r###"
|
||
success: true
|
||
exit_code: 0
|
||
----- stdout -----
|
||
# This file was autogenerated by Puffin v0.0.1 via the following command:
|
||
# puffin pip-compile requirements.in --cache-dir [CACHE_DIR]
|
||
blinker==1.7.0
|
||
# via flask
|
||
click==8.1.7
|
||
# via flask
|
||
flask @ https://files.pythonhosted.org/packages/36/42/015c23096649b908c809c69388a805a571a3bea44362fe87e33fc3afa01f/flask-3.0.0-py3-none-any.whl
|
||
itsdangerous==2.1.2
|
||
# via flask
|
||
jinja2==3.1.2
|
||
# via flask
|
||
markupsafe==2.1.3
|
||
# via
|
||
# jinja2
|
||
# werkzeug
|
||
werkzeug==3.0.1
|
||
# via flask
|
||
|
||
----- stderr -----
|
||
Resolved 7 packages in [TIME]
|
||
warning: The package `flask @ https://files.pythonhosted.org/packages/36/42/015c23096649b908c809c69388a805a571a3bea44362fe87e33fc3afa01f/flask-3.0.0-py3-none-any.whl` does not have an extra named `tensorboard`.
|
||
"###);
|
||
});
|
||
|
||
Ok(())
|
||
}
|