mirror of
https://github.com/astral-sh/uv.git
synced 2025-07-07 21:35:00 +00:00
Accept dependencies from pyproject.toml
(#141)
Doesn't support extras yet. It's also supported for `pip uninstall`, which `pip` itself doesn't support, but whatever. Closes #127.
This commit is contained in:
parent
385345807c
commit
ba181eacdd
3 changed files with 52 additions and 20 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -2028,9 +2028,11 @@ dependencies = [
|
||||||
"puffin-package",
|
"puffin-package",
|
||||||
"puffin-resolver",
|
"puffin-resolver",
|
||||||
"puffin-workspace",
|
"puffin-workspace",
|
||||||
|
"pyproject-toml",
|
||||||
"tempfile",
|
"tempfile",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
"toml 0.8.2",
|
||||||
"tracing",
|
"tracing",
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
"tracing-tree",
|
"tracing-tree",
|
||||||
|
|
|
@ -33,9 +33,11 @@ indicatif = { workspace = true }
|
||||||
itertools = { workspace = true }
|
itertools = { workspace = true }
|
||||||
miette = { workspace = true, features = ["fancy"] }
|
miette = { workspace = true, features = ["fancy"] }
|
||||||
owo-colors = { workspace = true }
|
owo-colors = { workspace = true }
|
||||||
|
pyproject-toml = { workspace = true }
|
||||||
tempfile = { workspace = true }
|
tempfile = { workspace = true }
|
||||||
thiserror = { workspace = true }
|
thiserror = { workspace = true }
|
||||||
tokio = { workspace = true }
|
tokio = { workspace = true }
|
||||||
|
toml = { workspace = true }
|
||||||
tracing = { workspace = true }
|
tracing = { workspace = true }
|
||||||
tracing-subscriber = { workspace = true }
|
tracing-subscriber = { workspace = true }
|
||||||
tracing-tree = { workspace = true }
|
tracing-tree = { workspace = true }
|
||||||
|
|
|
@ -2,7 +2,7 @@ use std::path::PathBuf;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use anyhow::{bail, Result};
|
use anyhow::{bail, Result};
|
||||||
use itertools::Either;
|
use fs_err as fs;
|
||||||
|
|
||||||
use pep508_rs::Requirement;
|
use pep508_rs::Requirement;
|
||||||
use puffin_package::requirements_txt::RequirementsTxt;
|
use puffin_package::requirements_txt::RequirementsTxt;
|
||||||
|
@ -12,7 +12,9 @@ pub(crate) enum RequirementsSource {
|
||||||
/// A dependency was provided on the command line (e.g., `pip install flask`).
|
/// A dependency was provided on the command line (e.g., `pip install flask`).
|
||||||
Name(String),
|
Name(String),
|
||||||
/// Dependencies were provided via a `requirements.txt` file (e.g., `pip install -r requirements.txt`).
|
/// Dependencies were provided via a `requirements.txt` file (e.g., `pip install -r requirements.txt`).
|
||||||
Path(PathBuf),
|
RequirementsTxt(PathBuf),
|
||||||
|
/// Dependencies were provided via a `pyproject.toml` file (e.g., `pip-compile pyproject.toml`).
|
||||||
|
PyprojectToml(PathBuf),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<String> for RequirementsSource {
|
impl From<String> for RequirementsSource {
|
||||||
|
@ -23,30 +25,56 @@ impl From<String> for RequirementsSource {
|
||||||
|
|
||||||
impl From<PathBuf> for RequirementsSource {
|
impl From<PathBuf> for RequirementsSource {
|
||||||
fn from(path: PathBuf) -> Self {
|
fn from(path: PathBuf) -> Self {
|
||||||
Self::Path(path)
|
if path.ends_with("pyproject.toml") {
|
||||||
|
Self::PyprojectToml(path)
|
||||||
|
} else {
|
||||||
|
Self::RequirementsTxt(path)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RequirementsSource {
|
impl RequirementsSource {
|
||||||
/// Return an iterator over the requirements in this source.
|
/// Return an iterator over the requirements in this source.
|
||||||
pub(crate) fn requirements(&self) -> Result<impl Iterator<Item = Requirement>> {
|
pub(crate) fn requirements(&self) -> Result<impl Iterator<Item = Requirement>> {
|
||||||
match self {
|
let iter_name = if let Self::Name(name) = self {
|
||||||
Self::Name(name) => {
|
let requirement = Requirement::from_str(name)?;
|
||||||
let requirement = Requirement::from_str(name)?;
|
Some(std::iter::once(requirement))
|
||||||
Ok(Either::Left(std::iter::once(requirement)))
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
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");
|
||||||
}
|
}
|
||||||
Self::Path(path) => {
|
Some(
|
||||||
let requirements_txt = RequirementsTxt::parse(path, std::env::current_dir()?)?;
|
requirements_txt
|
||||||
if !requirements_txt.constraints.is_empty() {
|
.requirements
|
||||||
bail!("Constraints in requirements files are not supported");
|
.into_iter()
|
||||||
}
|
.map(|entry| entry.requirement),
|
||||||
Ok(Either::Right(
|
)
|
||||||
requirements_txt
|
} else {
|
||||||
.requirements
|
None
|
||||||
.into_iter()
|
};
|
||||||
.map(|entry| entry.requirement),
|
|
||||||
))
|
let iter_pyproject_toml = if let Self::PyprojectToml(path) = self {
|
||||||
}
|
let pyproject_toml =
|
||||||
}
|
toml::from_str::<pyproject_toml::PyProjectToml>(&fs::read_to_string(path)?)?;
|
||||||
|
Some(
|
||||||
|
pyproject_toml
|
||||||
|
.project
|
||||||
|
.into_iter()
|
||||||
|
.flat_map(|project| project.dependencies.into_iter().flatten()),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(iter_name
|
||||||
|
.into_iter()
|
||||||
|
.flatten()
|
||||||
|
.chain(iter_requirements_txt.into_iter().flatten())
|
||||||
|
.chain(iter_pyproject_toml.into_iter().flatten()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue