mirror of
https://github.com/astral-sh/uv.git
synced 2025-07-07 21:35:00 +00:00
Improve static metadata extraction for Poetry projects (#4182)
## Summary Adds handling for a few cases to improve interoperability with Poetry: - If the `project` schema is invalid, we now raise a hard error, rather than treating the metadata as dynamic and then falling back to the build backend. This could cause problems, I'm not sure. It's stricter than before. - If the project contains `tool.poetry` but omits `project.dependencies`, we now treat it as dynamic. We could go even further and treat _any_ Poetry project as dynamic, but then we'd be ignoring user-declared dependencies, which is also confusing. Closes https://github.com/astral-sh/uv/issues/4142.
This commit is contained in:
parent
c6da4f15b7
commit
125a4b220e
4 changed files with 166 additions and 14 deletions
|
@ -60,6 +60,8 @@ pub enum MetadataError {
|
|||
UnsupportedMetadataVersion(String),
|
||||
#[error("The following field was marked as dynamic: {0}")]
|
||||
DynamicField(&'static str),
|
||||
#[error("The project uses Poetry's syntax to declare its dependencies, despite including a `project` table in `pyproject.toml`")]
|
||||
PoetrySyntax,
|
||||
}
|
||||
|
||||
impl From<Pep508Error<VerbatimParsedUrl>> for MetadataError {
|
||||
|
@ -210,6 +212,15 @@ impl Metadata23 {
|
|||
}
|
||||
}
|
||||
|
||||
// If dependencies are declared with Poetry, and `project.dependencies` is omitted, treat
|
||||
// the dependencies as dynamic. The inclusion of a `project` table without defining
|
||||
// `project.dependencies` is almost certainly an error.
|
||||
if project.dependencies.is_none()
|
||||
&& pyproject_toml.tool.and_then(|tool| tool.poetry).is_some()
|
||||
{
|
||||
return Err(MetadataError::PoetrySyntax);
|
||||
}
|
||||
|
||||
let name = project.name;
|
||||
let version = project
|
||||
.version
|
||||
|
@ -257,11 +268,11 @@ impl Metadata23 {
|
|||
}
|
||||
|
||||
/// A `pyproject.toml` as specified in PEP 517.
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
#[derive(Deserialize, Debug)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
struct PyProjectToml {
|
||||
/// Project metadata
|
||||
project: Option<Project>,
|
||||
tool: Option<Tool>,
|
||||
}
|
||||
|
||||
/// PEP 621 project metadata.
|
||||
|
@ -270,7 +281,7 @@ struct PyProjectToml {
|
|||
/// relevant for dependency resolution.
|
||||
///
|
||||
/// See <https://packaging.python.org/en/latest/specifications/pyproject-toml>.
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
#[derive(Deserialize, Debug)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
struct Project {
|
||||
/// The name of the project
|
||||
|
@ -288,6 +299,17 @@ struct Project {
|
|||
dynamic: Option<Vec<String>>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
struct Tool {
|
||||
poetry: Option<ToolPoetry>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
#[allow(clippy::empty_structs_with_brackets)]
|
||||
struct ToolPoetry {}
|
||||
|
||||
/// Python Package Metadata 1.0 and later as specified in
|
||||
/// <https://peps.python.org/pep-0241/>.
|
||||
///
|
||||
|
@ -369,6 +391,15 @@ impl RequiresDist {
|
|||
}
|
||||
}
|
||||
|
||||
// If dependencies are declared with Poetry, and `project.dependencies` is omitted, treat
|
||||
// the dependencies as dynamic. The inclusion of a `project` table without defining
|
||||
// `project.dependencies` is almost certainly an error.
|
||||
if project.dependencies.is_none()
|
||||
&& pyproject_toml.tool.and_then(|tool| tool.poetry).is_some()
|
||||
{
|
||||
return Err(MetadataError::PoetrySyntax);
|
||||
}
|
||||
|
||||
let name = project.name;
|
||||
|
||||
// Extract the requirements.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue