mirror of
https://github.com/astral-sh/uv.git
synced 2025-07-07 13:25:00 +00:00
parent
58011f98b6
commit
8b83385763
16 changed files with 476 additions and 89 deletions
|
@ -16,12 +16,12 @@ use platform_tags::Tags;
|
|||
use puffin_client::RegistryClientBuilder;
|
||||
use puffin_dispatch::BuildDispatch;
|
||||
use puffin_interpreter::Virtualenv;
|
||||
use puffin_resolver::{Manifest, ResolutionMode};
|
||||
use puffin_resolver::{ResolutionManifest, ResolutionMode};
|
||||
|
||||
use crate::commands::{elapsed, ExitStatus};
|
||||
use crate::index_urls::IndexUrls;
|
||||
use crate::printer::Printer;
|
||||
use crate::requirements::RequirementsSource;
|
||||
use crate::requirements::{RequirementsSource, RequirementsSpecification};
|
||||
|
||||
const VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||
|
||||
|
@ -40,29 +40,23 @@ pub(crate) async fn pip_compile(
|
|||
let start = std::time::Instant::now();
|
||||
|
||||
// Read all requirements from the provided sources.
|
||||
let requirements = requirements
|
||||
.iter()
|
||||
.map(RequirementsSource::requirements)
|
||||
.flatten_ok()
|
||||
.collect::<Result<Vec<Requirement>>>()?;
|
||||
let constraints = constraints
|
||||
.iter()
|
||||
.map(RequirementsSource::requirements)
|
||||
.flatten_ok()
|
||||
.collect::<Result<Vec<Requirement>>>()?;
|
||||
let RequirementsSpecification {
|
||||
requirements,
|
||||
constraints,
|
||||
} = RequirementsSpecification::try_from_sources(requirements, constraints)?;
|
||||
let preferences: Vec<Requirement> = output_file
|
||||
.filter(|_| upgrade_mode.is_prefer_pinned())
|
||||
.filter(|output_file| output_file.exists())
|
||||
.map(Path::to_path_buf)
|
||||
.map(RequirementsSource::from)
|
||||
.as_ref()
|
||||
.map(RequirementsSource::requirements)
|
||||
.map(RequirementsSpecification::try_from_source)
|
||||
.transpose()?
|
||||
.map(Iterator::collect)
|
||||
.map(|spec| spec.requirements)
|
||||
.unwrap_or_default();
|
||||
|
||||
// Create a manifest of the requirements.
|
||||
let manifest = Manifest::new(requirements, constraints, preferences, resolution_mode);
|
||||
let manifest = ResolutionManifest::new(requirements, constraints, preferences, resolution_mode);
|
||||
|
||||
// Detect the current Python interpreter.
|
||||
let platform = Platform::current()?;
|
||||
|
|
|
@ -20,7 +20,7 @@ use crate::commands::reporters::{
|
|||
use crate::commands::{elapsed, ExitStatus};
|
||||
use crate::index_urls::IndexUrls;
|
||||
use crate::printer::Printer;
|
||||
use crate::requirements::RequirementsSource;
|
||||
use crate::requirements::{RequirementsSource, RequirementsSpecification};
|
||||
|
||||
/// Install a set of locked requirements into the current Python environment.
|
||||
pub(crate) async fn pip_sync(
|
||||
|
@ -31,11 +31,10 @@ pub(crate) async fn pip_sync(
|
|||
mut printer: Printer,
|
||||
) -> Result<ExitStatus> {
|
||||
// Read all requirements from the provided sources.
|
||||
let requirements = sources
|
||||
.iter()
|
||||
.map(RequirementsSource::requirements)
|
||||
.flatten_ok()
|
||||
.collect::<Result<Vec<Requirement>>>()?;
|
||||
let RequirementsSpecification {
|
||||
requirements,
|
||||
constraints: _,
|
||||
} = RequirementsSpecification::try_from_sources(sources, &[])?;
|
||||
|
||||
if requirements.is_empty() {
|
||||
writeln!(printer, "No requirements found")?;
|
||||
|
|
|
@ -3,17 +3,15 @@ use std::path::Path;
|
|||
|
||||
use anyhow::Result;
|
||||
use colored::Colorize;
|
||||
use itertools::Itertools;
|
||||
use tracing::debug;
|
||||
|
||||
use pep508_rs::Requirement;
|
||||
use platform_host::Platform;
|
||||
use puffin_interpreter::Virtualenv;
|
||||
use puffin_package::package_name::PackageName;
|
||||
|
||||
use crate::commands::{elapsed, ExitStatus};
|
||||
use crate::printer::Printer;
|
||||
use crate::requirements::RequirementsSource;
|
||||
use crate::requirements::{RequirementsSource, RequirementsSpecification};
|
||||
|
||||
/// Uninstall packages from the current environment.
|
||||
pub(crate) async fn pip_uninstall(
|
||||
|
@ -24,11 +22,10 @@ pub(crate) async fn pip_uninstall(
|
|||
let start = std::time::Instant::now();
|
||||
|
||||
// Read all requirements from the provided sources.
|
||||
let requirements = sources
|
||||
.iter()
|
||||
.map(RequirementsSource::requirements)
|
||||
.flatten_ok()
|
||||
.collect::<Result<Vec<Requirement>>>()?;
|
||||
let RequirementsSpecification {
|
||||
requirements,
|
||||
constraints: _,
|
||||
} = RequirementsSpecification::try_from_sources(sources, &[])?;
|
||||
|
||||
// Detect the current Python interpreter.
|
||||
let platform = Platform::current()?;
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
use std::path::PathBuf;
|
||||
use std::str::FromStr;
|
||||
|
||||
use anyhow::{bail, Context, Result};
|
||||
use anyhow::{Context, Result};
|
||||
use fs_err as fs;
|
||||
|
||||
use pep508_rs::Requirement;
|
||||
|
@ -35,50 +35,77 @@ impl From<PathBuf> for RequirementsSource {
|
|||
}
|
||||
}
|
||||
|
||||
impl RequirementsSource {
|
||||
/// Return an iterator over the requirements in this source.
|
||||
pub(crate) fn requirements(&self) -> Result<impl Iterator<Item = Requirement>> {
|
||||
let iter_name = if let Self::Name(name) = self {
|
||||
let requirement =
|
||||
Requirement::from_str(name).with_context(|| format!("Failed to parse `{name}`"))?;
|
||||
Some(std::iter::once(requirement))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
#[derive(Debug, Default)]
|
||||
pub(crate) struct RequirementsSpecification {
|
||||
/// The requirements for the project.
|
||||
pub(crate) requirements: Vec<Requirement>,
|
||||
/// The constraints for the project.
|
||||
pub(crate) constraints: Vec<Requirement>,
|
||||
}
|
||||
|
||||
let iter_requirements_txt = if let Self::RequirementsTxt(path) = self {
|
||||
let requirements_txt = RequirementsTxt::parse(path, std::env::current_dir()?)?;
|
||||
if !requirements_txt.constraints.is_empty() {
|
||||
bail!("Constraints in requirements files are not supported");
|
||||
impl RequirementsSpecification {
|
||||
/// Read the requirements and constraints from a source.
|
||||
pub(crate) fn try_from_source(source: &RequirementsSource) -> Result<Self> {
|
||||
Ok(match source {
|
||||
RequirementsSource::Name(name) => {
|
||||
let requirement = Requirement::from_str(name)
|
||||
.with_context(|| format!("Failed to parse `{name}`"))?;
|
||||
Self {
|
||||
requirements: vec![requirement],
|
||||
constraints: vec![],
|
||||
}
|
||||
}
|
||||
Some(
|
||||
requirements_txt
|
||||
.requirements
|
||||
.into_iter()
|
||||
.map(|entry| entry.requirement),
|
||||
)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let iter_pyproject_toml = if let Self::PyprojectToml(path) = self {
|
||||
let contents = fs::read_to_string(path)?;
|
||||
let pyproject_toml = toml::from_str::<pyproject_toml::PyProjectToml>(&contents)
|
||||
.with_context(|| format!("Failed to read `{}`", path.display()))?;
|
||||
Some(
|
||||
pyproject_toml
|
||||
RequirementsSource::RequirementsTxt(path) => {
|
||||
let requirements_txt = RequirementsTxt::parse(path, std::env::current_dir()?)?;
|
||||
Self {
|
||||
requirements: requirements_txt
|
||||
.requirements
|
||||
.into_iter()
|
||||
.map(|entry| entry.requirement)
|
||||
.collect(),
|
||||
constraints: requirements_txt.constraints.into_iter().collect(),
|
||||
}
|
||||
}
|
||||
RequirementsSource::PyprojectToml(path) => {
|
||||
let contents = fs::read_to_string(path)?;
|
||||
let pyproject_toml = toml::from_str::<pyproject_toml::PyProjectToml>(&contents)
|
||||
.with_context(|| format!("Failed to read `{}`", path.display()))?;
|
||||
let requirements = pyproject_toml
|
||||
.project
|
||||
.into_iter()
|
||||
.flat_map(|project| project.dependencies.into_iter().flatten()),
|
||||
)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
.flat_map(|project| project.dependencies.into_iter().flatten())
|
||||
.collect();
|
||||
Self {
|
||||
requirements,
|
||||
constraints: vec![],
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
Ok(iter_name
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.chain(iter_requirements_txt.into_iter().flatten())
|
||||
.chain(iter_pyproject_toml.into_iter().flatten()))
|
||||
/// Read the combined requirements and constraints from a set of sources.
|
||||
pub(crate) fn try_from_sources(
|
||||
requirements: &[RequirementsSource],
|
||||
constraints: &[RequirementsSource],
|
||||
) -> Result<Self> {
|
||||
let mut spec = Self::default();
|
||||
|
||||
// Read all requirements, and keep track of all requirements _and_ constraints.
|
||||
// A `requirements.txt` can contain a `-c constraints.txt` directive within it, so reading
|
||||
// a requirements file can also add constraints.
|
||||
for source in requirements {
|
||||
let source = Self::try_from_source(source)?;
|
||||
spec.requirements.extend(source.requirements);
|
||||
spec.constraints.extend(source.constraints);
|
||||
}
|
||||
|
||||
// Read all constraints, treating both requirements _and_ constraints as constraints.
|
||||
for source in constraints {
|
||||
let source = Self::try_from_source(source)?;
|
||||
spec.constraints.extend(source.requirements);
|
||||
spec.constraints.extend(source.constraints);
|
||||
}
|
||||
|
||||
Ok(spec)
|
||||
}
|
||||
}
|
||||
|
|
229
crates/puffin-cli/tests/pip_compile.rs
Normal file
229
crates/puffin-cli/tests/pip_compile.rs
Normal file
|
@ -0,0 +1,229 @@
|
|||
#![cfg(all(feature = "python", feature = "pypi"))]
|
||||
|
||||
use std::process::Command;
|
||||
|
||||
use anyhow::Result;
|
||||
use assert_cmd::prelude::*;
|
||||
use assert_fs::prelude::*;
|
||||
use insta_cmd::_macro_support::insta;
|
||||
use insta_cmd::{assert_cmd_snapshot, get_cargo_bin};
|
||||
|
||||
const BIN_NAME: &str = "puffin";
|
||||
|
||||
#[test]
|
||||
fn missing_requirements_in() -> Result<()> {
|
||||
let temp_dir = assert_fs::TempDir::new()?;
|
||||
let cache_dir = assert_fs::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));
|
||||
|
||||
requirements_in.assert(predicates::path::missing());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn missing_venv() -> Result<()> {
|
||||
let temp_dir = assert_fs::TempDir::new()?;
|
||||
let cache_dir = assert_fs::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));
|
||||
|
||||
venv.assert(predicates::path::missing());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Resolve a specific version of Django from a `requirements.in` file.
|
||||
#[test]
|
||||
fn compile_requirements_in() -> Result<()> {
|
||||
let temp_dir = assert_fs::TempDir::new()?;
|
||||
let cache_dir = assert_fs::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())
|
||||
.current_dir(&temp_dir)
|
||||
.assert()
|
||||
.success();
|
||||
venv.assert(predicates::path::is_dir());
|
||||
|
||||
let requirements_in = temp_dir.child("requirements.in");
|
||||
requirements_in.touch()?;
|
||||
requirements_in.write_str("django==5.0b1")?;
|
||||
|
||||
insta::with_settings!({
|
||||
filters => vec![
|
||||
(r"\d+ms", "[TIME]"),
|
||||
(r"# .* pip-compile", "# [BIN_PATH] pip-compile"),
|
||||
(r"--cache-dir .*", "--cache-dir [CACHE_DIR]"),
|
||||
]
|
||||
}, {
|
||||
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));
|
||||
});
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Resolve a specific version of Django from a `pyproject.toml` file.
|
||||
#[test]
|
||||
fn compile_pyproject_toml() -> Result<()> {
|
||||
let temp_dir = assert_fs::TempDir::new()?;
|
||||
let cache_dir = assert_fs::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())
|
||||
.current_dir(&temp_dir)
|
||||
.assert()
|
||||
.success();
|
||||
venv.assert(predicates::path::is_dir());
|
||||
|
||||
let pyproject_toml = temp_dir.child("pyproject.toml");
|
||||
pyproject_toml.touch()?;
|
||||
pyproject_toml.write_str(
|
||||
r#"[build-system]
|
||||
requires = ["setuptools", "wheel"]
|
||||
|
||||
[project]
|
||||
name = "project"
|
||||
dependencies = [
|
||||
"django==5.0b1",
|
||||
]
|
||||
"#,
|
||||
)?;
|
||||
|
||||
insta::with_settings!({
|
||||
filters => vec![
|
||||
(r"\d+ms", "[TIME]"),
|
||||
(r"# .* pip-compile", "# [BIN_PATH] pip-compile"),
|
||||
(r"--cache-dir .*", "--cache-dir [CACHE_DIR]"),
|
||||
]
|
||||
}, {
|
||||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||||
.arg("pip-compile")
|
||||
.arg("pyproject.toml")
|
||||
.arg("--cache-dir")
|
||||
.arg(cache_dir.path())
|
||||
.env("VIRTUAL_ENV", venv.as_os_str())
|
||||
.current_dir(&temp_dir));
|
||||
});
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Resolve a package from a `requirements.in` file, with a `constraints.txt` file.
|
||||
#[test]
|
||||
fn compile_constraints_txt() -> Result<()> {
|
||||
let temp_dir = assert_fs::TempDir::new()?;
|
||||
let cache_dir = assert_fs::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())
|
||||
.current_dir(&temp_dir)
|
||||
.assert()
|
||||
.success();
|
||||
venv.assert(predicates::path::is_dir());
|
||||
|
||||
let requirements_in = temp_dir.child("requirements.in");
|
||||
requirements_in.touch()?;
|
||||
requirements_in.write_str("django==5.0b1")?;
|
||||
|
||||
let constraints_txt = temp_dir.child("constraints.txt");
|
||||
constraints_txt.touch()?;
|
||||
constraints_txt.write_str("sqlparse<0.4.4")?;
|
||||
|
||||
insta::with_settings!({
|
||||
filters => vec![
|
||||
(r"\d+ms", "[TIME]"),
|
||||
(r"# .* pip-compile", "# [BIN_PATH] pip-compile"),
|
||||
(r"--cache-dir .*", "--cache-dir [CACHE_DIR]"),
|
||||
]
|
||||
}, {
|
||||
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())
|
||||
.env("VIRTUAL_ENV", venv.as_os_str())
|
||||
.current_dir(&temp_dir));
|
||||
});
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Resolve a package from a `requirements.in` file, with an inline constraint.
|
||||
#[test]
|
||||
fn compile_constraints_inline() -> Result<()> {
|
||||
let temp_dir = assert_fs::TempDir::new()?;
|
||||
let cache_dir = assert_fs::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())
|
||||
.current_dir(&temp_dir)
|
||||
.assert()
|
||||
.success();
|
||||
venv.assert(predicates::path::is_dir());
|
||||
|
||||
let requirements_in = temp_dir.child("requirements.in");
|
||||
requirements_in.touch()?;
|
||||
requirements_in.write_str("django==5.0b1")?;
|
||||
requirements_in.write_str("-c constraints.txt")?;
|
||||
|
||||
let constraints_txt = temp_dir.child("constraints.txt");
|
||||
constraints_txt.touch()?;
|
||||
constraints_txt.write_str("sqlparse<0.4.4")?;
|
||||
|
||||
insta::with_settings!({
|
||||
filters => vec![
|
||||
(r"\d+ms", "[TIME]"),
|
||||
(r"# .* pip-compile", "# [BIN_PATH] pip-compile"),
|
||||
(r"--cache-dir .*", "--cache-dir [CACHE_DIR]"),
|
||||
]
|
||||
}, {
|
||||
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));
|
||||
});
|
||||
|
||||
Ok(())
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
---
|
||||
source: crates/puffin-cli/tests/pip_compile.rs
|
||||
info:
|
||||
program: puffin
|
||||
args:
|
||||
- pip-compile
|
||||
- requirements.in
|
||||
- "--cache-dir"
|
||||
- /var/folders/nt/6gf2v7_s3k13zq_t3944rwz40000gn/T/.tmp5R6H5M
|
||||
env:
|
||||
VIRTUAL_ENV: /var/folders/nt/6gf2v7_s3k13zq_t3944rwz40000gn/T/.tmpIdL1TH/.venv
|
||||
---
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
# This file was autogenerated by Puffin v0.0.1 via the following command:
|
||||
# [BIN_PATH] pip-compile requirements.in --cache-dir [CACHE_DIR]
|
||||
|
||||
----- stderr -----
|
||||
Resolved 0 packages in [TIME]
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
---
|
||||
source: crates/puffin-cli/tests/pip_compile.rs
|
||||
info:
|
||||
program: puffin
|
||||
args:
|
||||
- pip-compile
|
||||
- requirements.in
|
||||
- "--constraint"
|
||||
- constraints.txt
|
||||
- "--cache-dir"
|
||||
- /var/folders/nt/6gf2v7_s3k13zq_t3944rwz40000gn/T/.tmpvjdHOb
|
||||
env:
|
||||
VIRTUAL_ENV: /var/folders/nt/6gf2v7_s3k13zq_t3944rwz40000gn/T/.tmpSAaWi3/.venv
|
||||
---
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
# This file was autogenerated by Puffin v0.0.1 via the following command:
|
||||
# [BIN_PATH] 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]
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
---
|
||||
source: crates/puffin-cli/tests/pip_compile.rs
|
||||
info:
|
||||
program: puffin
|
||||
args:
|
||||
- pip-compile
|
||||
- pyproject.toml
|
||||
- "--cache-dir"
|
||||
- /var/folders/nt/6gf2v7_s3k13zq_t3944rwz40000gn/T/.tmpOOTFwj
|
||||
env:
|
||||
VIRTUAL_ENV: /var/folders/nt/6gf2v7_s3k13zq_t3944rwz40000gn/T/.tmpU0VXyY/.venv
|
||||
---
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
# This file was autogenerated by Puffin v0.0.1 via the following command:
|
||||
# [BIN_PATH] 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]
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
---
|
||||
source: crates/puffin-cli/tests/pip_compile.rs
|
||||
info:
|
||||
program: puffin
|
||||
args:
|
||||
- pip-compile
|
||||
- requirements.in
|
||||
- "--cache-dir"
|
||||
- /var/folders/nt/6gf2v7_s3k13zq_t3944rwz40000gn/T/.tmpxF1zFY
|
||||
env:
|
||||
VIRTUAL_ENV: /var/folders/nt/6gf2v7_s3k13zq_t3944rwz40000gn/T/.tmp33QZdv/.venv
|
||||
---
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
# This file was autogenerated by Puffin v0.0.1 via the following command:
|
||||
# [BIN_PATH] 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]
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
---
|
||||
source: crates/puffin-cli/tests/pip_compile.rs
|
||||
info:
|
||||
program: puffin
|
||||
args:
|
||||
- pip-compile
|
||||
- requirements.in
|
||||
- "--cache-dir"
|
||||
- /var/folders/nt/6gf2v7_s3k13zq_t3944rwz40000gn/T/.tmpQVD5K4
|
||||
---
|
||||
success: false
|
||||
exit_code: 2
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
error: failed to open file `requirements.in`
|
||||
Caused by: No such file or directory (os error 2)
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
---
|
||||
source: crates/puffin-cli/tests/pip_compile.rs
|
||||
info:
|
||||
program: puffin
|
||||
args:
|
||||
- pip-compile
|
||||
- requirements.in
|
||||
- "--cache-dir"
|
||||
- /var/folders/nt/6gf2v7_s3k13zq_t3944rwz40000gn/T/.tmptw6jFz
|
||||
env:
|
||||
VIRTUAL_ENV: /var/folders/nt/6gf2v7_s3k13zq_t3944rwz40000gn/T/.tmpDn1YGM/.venv
|
||||
---
|
||||
success: false
|
||||
exit_code: 2
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
error: failed to open file `requirements.in`
|
||||
Caused by: No such file or directory (os error 2)
|
||||
|
|
@ -19,7 +19,7 @@ use puffin_installer::{
|
|||
Downloader, Installer, PartitionedRequirements, RemoteDistribution, Unzipper,
|
||||
};
|
||||
use puffin_interpreter::{InterpreterInfo, Virtualenv};
|
||||
use puffin_resolver::{Manifest, ResolutionMode, Resolver, WheelFinder};
|
||||
use puffin_resolver::{ResolutionManifest, ResolutionMode, Resolver, WheelFinder};
|
||||
use puffin_traits::BuildContext;
|
||||
|
||||
/// The main implementation of [`BuildContext`], used by the CLI, see [`BuildContext`]
|
||||
|
@ -71,7 +71,7 @@ impl BuildContext for BuildDispatch {
|
|||
self.interpreter_info.simple_version(),
|
||||
)?;
|
||||
let resolver = Resolver::new(
|
||||
Manifest::new(
|
||||
ResolutionManifest::new(
|
||||
requirements.to_vec(),
|
||||
Vec::default(),
|
||||
Vec::default(),
|
||||
|
|
|
@ -168,7 +168,9 @@ impl RequirementsTxt {
|
|||
end,
|
||||
}
|
||||
})?;
|
||||
// Here we add both to constraints
|
||||
// Treat any nested requirements or constraints as constraints. This differs
|
||||
// from `pip`, which seems to treat `-r` requirements in constraints files as
|
||||
// _requirements_, but we don't want to support that.
|
||||
data.constraints.extend(
|
||||
sub_constraints
|
||||
.requirements
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
pub use error::ResolveError;
|
||||
pub use resolution::{Graph, PinnedPackage};
|
||||
pub use resolver::{Manifest, Resolver};
|
||||
pub use resolver::{ResolutionManifest, Resolver};
|
||||
pub use selector::ResolutionMode;
|
||||
pub use source_distribution::BuiltSourceDistributionCache;
|
||||
pub use wheel_finder::{Reporter, WheelFinder};
|
||||
|
|
|
@ -41,14 +41,14 @@ use crate::BuiltSourceDistributionCache;
|
|||
|
||||
/// A manifest of requirements, constraints, and preferences.
|
||||
#[derive(Debug)]
|
||||
pub struct Manifest {
|
||||
pub struct ResolutionManifest {
|
||||
requirements: Vec<Requirement>,
|
||||
constraints: Vec<Requirement>,
|
||||
preferences: Vec<Requirement>,
|
||||
mode: ResolutionMode,
|
||||
}
|
||||
|
||||
impl Manifest {
|
||||
impl ResolutionManifest {
|
||||
pub fn new(
|
||||
requirements: Vec<Requirement>,
|
||||
constraints: Vec<Requirement>,
|
||||
|
@ -78,7 +78,7 @@ pub struct Resolver<'a, Context: BuildContext + Sync> {
|
|||
impl<'a, Context: BuildContext + Sync> Resolver<'a, Context> {
|
||||
/// Initialize a new resolver.
|
||||
pub fn new(
|
||||
manifest: Manifest,
|
||||
manifest: ResolutionManifest,
|
||||
markers: &'a MarkerEnvironment,
|
||||
tags: &'a Tags,
|
||||
client: &'a RegistryClient,
|
||||
|
|
|
@ -16,7 +16,7 @@ use platform_host::{Arch, Os, Platform};
|
|||
use platform_tags::Tags;
|
||||
use puffin_client::RegistryClientBuilder;
|
||||
use puffin_interpreter::{InterpreterInfo, Virtualenv};
|
||||
use puffin_resolver::{Manifest, ResolutionMode, Resolver};
|
||||
use puffin_resolver::{ResolutionManifest, ResolutionMode, Resolver};
|
||||
use puffin_traits::BuildContext;
|
||||
|
||||
struct DummyContext;
|
||||
|
@ -64,7 +64,7 @@ async fn pylint() -> Result<()> {
|
|||
|
||||
let client = RegistryClientBuilder::default().build();
|
||||
|
||||
let manifest = Manifest::new(
|
||||
let manifest = ResolutionManifest::new(
|
||||
vec![Requirement::from_str("pylint==2.3.0").unwrap()],
|
||||
vec![],
|
||||
vec![],
|
||||
|
@ -85,7 +85,7 @@ async fn black() -> Result<()> {
|
|||
|
||||
let client = RegistryClientBuilder::default().build();
|
||||
|
||||
let manifest = Manifest::new(
|
||||
let manifest = ResolutionManifest::new(
|
||||
vec![Requirement::from_str("black<=23.9.1").unwrap()],
|
||||
vec![],
|
||||
vec![],
|
||||
|
@ -106,7 +106,7 @@ async fn black_colorama() -> Result<()> {
|
|||
|
||||
let client = RegistryClientBuilder::default().build();
|
||||
|
||||
let manifest = Manifest::new(
|
||||
let manifest = ResolutionManifest::new(
|
||||
vec![Requirement::from_str("black[colorama]<=23.9.1").unwrap()],
|
||||
vec![],
|
||||
vec![],
|
||||
|
@ -127,7 +127,7 @@ async fn black_python_310() -> Result<()> {
|
|||
|
||||
let client = RegistryClientBuilder::default().build();
|
||||
|
||||
let manifest = Manifest::new(
|
||||
let manifest = ResolutionManifest::new(
|
||||
vec![Requirement::from_str("black<=23.9.1").unwrap()],
|
||||
vec![],
|
||||
vec![],
|
||||
|
@ -150,7 +150,7 @@ async fn black_mypy_extensions() -> Result<()> {
|
|||
|
||||
let client = RegistryClientBuilder::default().build();
|
||||
|
||||
let manifest = Manifest::new(
|
||||
let manifest = ResolutionManifest::new(
|
||||
vec![Requirement::from_str("black<=23.9.1").unwrap()],
|
||||
vec![Requirement::from_str("mypy-extensions<1").unwrap()],
|
||||
vec![],
|
||||
|
@ -173,7 +173,7 @@ async fn black_mypy_extensions_extra() -> Result<()> {
|
|||
|
||||
let client = RegistryClientBuilder::default().build();
|
||||
|
||||
let manifest = Manifest::new(
|
||||
let manifest = ResolutionManifest::new(
|
||||
vec![Requirement::from_str("black<=23.9.1").unwrap()],
|
||||
vec![Requirement::from_str("mypy-extensions[extra]<1").unwrap()],
|
||||
vec![],
|
||||
|
@ -196,7 +196,7 @@ async fn black_flake8() -> Result<()> {
|
|||
|
||||
let client = RegistryClientBuilder::default().build();
|
||||
|
||||
let manifest = Manifest::new(
|
||||
let manifest = ResolutionManifest::new(
|
||||
vec![Requirement::from_str("black<=23.9.1").unwrap()],
|
||||
vec![Requirement::from_str("flake8<1").unwrap()],
|
||||
vec![],
|
||||
|
@ -217,7 +217,7 @@ async fn black_lowest() -> Result<()> {
|
|||
|
||||
let client = RegistryClientBuilder::default().build();
|
||||
|
||||
let manifest = Manifest::new(
|
||||
let manifest = ResolutionManifest::new(
|
||||
vec![Requirement::from_str("black>21").unwrap()],
|
||||
vec![],
|
||||
vec![],
|
||||
|
@ -238,7 +238,7 @@ async fn black_lowest_direct() -> Result<()> {
|
|||
|
||||
let client = RegistryClientBuilder::default().build();
|
||||
|
||||
let manifest = Manifest::new(
|
||||
let manifest = ResolutionManifest::new(
|
||||
vec![Requirement::from_str("black>21").unwrap()],
|
||||
vec![],
|
||||
vec![],
|
||||
|
@ -259,7 +259,7 @@ async fn black_respect_preference() -> Result<()> {
|
|||
|
||||
let client = RegistryClientBuilder::default().build();
|
||||
|
||||
let manifest = Manifest::new(
|
||||
let manifest = ResolutionManifest::new(
|
||||
vec![Requirement::from_str("black<=23.9.1").unwrap()],
|
||||
vec![],
|
||||
vec![Requirement::from_str("black==23.9.0").unwrap()],
|
||||
|
@ -280,7 +280,7 @@ async fn black_ignore_preference() -> Result<()> {
|
|||
|
||||
let client = RegistryClientBuilder::default().build();
|
||||
|
||||
let manifest = Manifest::new(
|
||||
let manifest = ResolutionManifest::new(
|
||||
vec![Requirement::from_str("black<=23.9.1").unwrap()],
|
||||
vec![],
|
||||
vec![Requirement::from_str("black==23.9.2").unwrap()],
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue