Use inline table for dependencies in lockfile (#4581)

Use indented inline tables for `distribution.dependencies`,
`distribution.optional-dependencies` and
`distribution.dev-dependencies`.

The new style is more concise (see examples below) and it makes the
association between a distribution and its dependencies clearer
(previously, they were both individual `[[...]]` blocks separated by
newlines). The style is optimized for small, meaningful diffs by placing
each dependency on a single line with a final trailing comma. Whenever a
dependency is added, removed or changed, there should be a one line diff
in `distribution.dependencies`. The final trailing comma ensures that
adding a dependency doesn't change the line ahead.

Part of #3611

## Examples

### Simple workspace package

Before:
```toml
[[distribution]]
name = "bird-feeder"
version = "1.0.0"
source = "editable+packages/bird-feeder"

[[distribution.dependencies]]
name = "anyio"

[[distribution.dependencies]]
name = "seeds"
```

After:
```toml
[[distribution]]
name = "bird-feeder"
version = "1.0.0"
source = "editable+packages/bird-feeder"
dependencies = [
    { name = "anyio" },
    { name = "seeds" },
]
```

### Flask

Before:
```toml
[[distribution]]
name = "flask"
version = "3.0.2"
source = "registry+https://pypi.org/simple"
sdist = { url = "https://files.pythonhosted.org/packages/3f/e0/a89e8120faea1edbfca1a9b171cff7f2bf62ec860bbafcb2c2387c0317be/flask-3.0.2.tar.gz", hash = "sha256:822c03f4b799204250a7ee84b1eddc40665395333973dfb9deebfe425fefcb7d", size = 675248 }
wheels = [{ url = "https://files.pythonhosted.org/packages/93/a6/aa98bfe0eb9b8b15d36cdfd03c8ca86a03968a87f27ce224fb4f766acb23/flask-3.0.2-py3-none-any.whl", hash = "sha256:3232e0e9c850d781933cf0207523d1ece087eb8d87b23777ae38456e2fbe7c6e", size = 101300 }]

[[distribution.dependencies]]
name = "blinker"

[[distribution.dependencies]]
name = "click"

[[distribution.dependencies]]
name = "itsdangerous"

[[distribution.dependencies]]
name = "jinja2"

[[distribution.dependencies]]
name = "werkzeug"

[distribution.optional-dependencies]

[[distribution.optional-dependencies.dotenv]]
name = "python-dotenv"
```

After:
```toml
[[distribution]]
name = "flask"
version = "3.0.2"
source = "registry+https://pypi.org/simple"
sdist = { url = "https://files.pythonhosted.org/packages/3f/e0/a89e8120faea1edbfca1a9b171cff7f2bf62ec860bbafcb2c2387c0317be/flask-3.0.2.tar.gz", hash = "sha256:822c03f4b799204250a7ee84b1eddc40665395333973dfb9deebfe425fefcb7d", size = 675248 }
dependencies = [
    { name = "blinker" },
    { name = "click" },
    { name = "itsdangerous" },
    { name = "jinja2" },
    { name = "werkzeug" },
]
wheels = [{ url = "https://files.pythonhosted.org/packages/93/a6/aa98bfe0eb9b8b15d36cdfd03c8ca86a03968a87f27ce224fb4f766acb23/flask-3.0.2-py3-none-any.whl", hash = "sha256:3232e0e9c850d781933cf0207523d1ece087eb8d87b23777ae38456e2fbe7c6e", size = 101300 }]

[distribution.optional-dependencies]
dotenv = [
    { name = "python-dotenv" },
]
```

### Forking

Before:
```toml
[[distribution]]
name = "project"
version = "0.1.0"
source = "editable+."

[[distribution.dependencies]]
name = "package-a"
version = "4.3.0"
source = "registry+https://astral-sh.github.io/packse/0.3.29/simple-html/"
marker = "sys_platform == 'darwin'"

[[distribution.dependencies]]
name = "package-a"
version = "4.4.0"
source = "registry+https://astral-sh.github.io/packse/0.3.29/simple-html/"
marker = "sys_platform == 'linux'"

[[distribution.dependencies]]
name = "package-b"
marker = "sys_platform == 'linux'"

[[distribution.dependencies]]
name = "package-c"
marker = "sys_platform == 'darwin'"
```

After:
```toml
[[distribution]]
name = "project"
version = "0.1.0"
source = "editable+."
dependencies = [
    { name = "package-a", version = "4.3.0", source = "registry+https://astral-sh.github.io/packse/0.3.29/simple-html/", marker = "sys_platform == 'darwin'" },
    { name = "package-a", version = "4.4.0", source = "registry+https://astral-sh.github.io/packse/0.3.29/simple-html/", marker = "sys_platform == 'linux'" },
    { name = "package-b", marker = "sys_platform == 'linux'" },
    { name = "package-c", marker = "sys_platform == 'darwin'" },
]
```
This commit is contained in:
konsti
2024-06-27 20:06:45 +02:00
committed by GitHub
parent bf46792839
commit 86e6f76836
5 changed files with 442 additions and 706 deletions
+42 -16
View File
@@ -415,22 +415,22 @@ impl Lock {
}
if !dist.dependencies.is_empty() {
let deps = dist
.dependencies
.iter()
.map(|dep| dep.to_toml(&dist_count_by_name))
.collect::<ArrayOfTables>();
table.insert("dependencies", Item::ArrayOfTables(deps));
let deps = each_element_on_its_line_array(
dist.dependencies
.iter()
.map(|dep| dep.to_toml(&dist_count_by_name).into_inline_table()),
);
table.insert("dependencies", value(deps));
}
if !dist.optional_dependencies.is_empty() {
let mut optional_deps = Table::new();
for (extra, deps) in &dist.optional_dependencies {
let deps = deps
.iter()
.map(|dep| dep.to_toml(&dist_count_by_name))
.collect::<ArrayOfTables>();
optional_deps.insert(extra.as_ref(), Item::ArrayOfTables(deps));
let deps = each_element_on_its_line_array(
deps.iter()
.map(|dep| dep.to_toml(&dist_count_by_name).into_inline_table()),
);
optional_deps.insert(extra.as_ref(), value(deps));
}
table.insert("optional-dependencies", Item::Table(optional_deps));
}
@@ -438,11 +438,11 @@ impl Lock {
if !dist.dev_dependencies.is_empty() {
let mut dev_dependencies = Table::new();
for (extra, deps) in &dist.dev_dependencies {
let deps = deps
.iter()
.map(|dep| dep.to_toml(&dist_count_by_name))
.collect::<ArrayOfTables>();
dev_dependencies.insert(extra.as_ref(), Item::ArrayOfTables(deps));
let deps = each_element_on_its_line_array(
deps.iter()
.map(|dep| dep.to_toml(&dist_count_by_name).into_inline_table()),
);
dev_dependencies.insert(extra.as_ref(), value(deps));
}
table.insert("dev-dependencies", Item::Table(dev_dependencies));
}
@@ -2139,6 +2139,32 @@ impl std::fmt::Display for HashParseError {
}
}
/// Format an array so that each element is on its own line and has a trailing comma.
///
/// Example:
///
/// ```toml
/// dependencies = [
/// { name = "idna" },
/// { name = "sniffio" },
/// ]
/// ```
fn each_element_on_its_line_array(elements: impl Iterator<Item = InlineTable>) -> Array {
let mut array = elements
.map(|mut inline_table| {
// Each dependency is on its own line and indented.
inline_table.decor_mut().set_prefix("\n ");
inline_table
})
.collect::<Array>();
// With a trailing comma, inserting another entry doesn't change the preceding line,
// reducing the diff noise.
array.set_trailing_comma(true);
// The line break between the last element's comma and the closing square bracket.
array.set_trailing("\n");
array
}
#[cfg(test)]
mod tests {
use super::*;