Place editable requirements before non-editable requirements (#1278)

## Summary

`pip-compile` puts the editable requirements first.

Closes https://github.com/astral-sh/puffin/issues/1275.
This commit is contained in:
Charlie Marsh 2024-02-11 21:26:40 -05:00 committed by GitHub
parent a16ec45d1f
commit b7e3933fe7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 91 additions and 42 deletions

View file

@ -1,3 +1,4 @@
use std::borrow::Cow;
use std::hash::BuildHasherDefault;
use anyhow::Result;
@ -255,22 +256,70 @@ impl<'a> DisplayResolutionGraph<'a> {
/// Write the graph in the `{name}=={version}` format of requirements.txt that pip uses.
impl std::fmt::Display for DisplayResolutionGraph<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
// Collect and sort all packages.
#[derive(Debug)]
enum Node<'a> {
/// A node linked to an editable distribution.
Editable(&'a PackageName, &'a LocalEditable),
/// A node linked to a non-editable distribution.
Distribution(&'a PackageName, &'a Dist),
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
enum NodeKey<'a> {
/// A node linked to an editable distribution, sorted by verbatim representation.
Editable(Cow<'a, str>),
/// A node linked to a non-editable distribution, sorted by package name.
Distribution(&'a PackageName),
}
impl<'a> Node<'a> {
/// Return the name of the package.
fn name(&self) -> &'a PackageName {
match self {
Node::Editable(name, _) => name,
Node::Distribution(name, _) => name,
}
}
/// Return a comparable key for the node.
fn key(&self) -> NodeKey<'a> {
match self {
Node::Editable(_, editable) => NodeKey::Editable(editable.verbatim()),
Node::Distribution(name, _) => NodeKey::Distribution(name),
}
}
}
// Collect all packages.
let mut nodes = self
.resolution
.petgraph
.node_indices()
.map(|node| (node, &self.resolution.petgraph[node]))
.map(|index| {
let dist = &self.resolution.petgraph[index];
let name = dist.name();
let node = if let Some((editable, _)) = self.resolution.editables.get(name) {
Node::Editable(name, editable)
} else {
Node::Distribution(name, dist)
};
(index, node)
})
.collect::<Vec<_>>();
nodes.sort_unstable_by_key(|(_, package)| package.name());
// Sort the nodes by name, but with editable packages first.
nodes.sort_unstable_by_key(|(index, node)| (node.key(), *index));
// Print out the dependency graph.
for (index, dist) in nodes {
for (index, node) in nodes {
// Display the node itself.
if let Some((editable, _)) = self.resolution.editables.get(dist.name()) {
write!(f, "-e {}", editable.verbatim())?;
} else {
write!(f, "{}", dist.verbatim())?;
match node {
Node::Distribution(_, dist) => {
write!(f, "{}", dist.verbatim())?;
}
Node::Editable(_, editable) => {
write!(f, "-e {}", editable.verbatim())?;
}
}
// Display the distribution hashes, if any.
@ -278,7 +327,7 @@ impl std::fmt::Display for DisplayResolutionGraph<'_> {
if let Some(hashes) = self
.resolution
.hashes
.get(dist.name())
.get(node.name())
.filter(|hashes| !hashes.is_empty())
{
for hash in hashes {

View file

@ -2034,40 +2034,40 @@ fn compile_editable() -> Result<()> {
.arg("--exclude-newer")
.arg(EXCLUDE_NEWER)
.env("VIRTUAL_ENV", context.venv.as_os_str()), @r###"
success: true
exit_code: 0
----- stdout -----
# This file was autogenerated by Puffin v[VERSION] via the following command:
# puffin pip compile requirements.in --cache-dir [CACHE_DIR] --exclude-newer 2023-11-18T12:00:00Z
aiohttp==3.9.0
# via black
aiosignal==1.3.1
# via aiohttp
attrs==23.1.0
# via aiohttp
-e file://../../scripts/editable-installs/black_editable
boltons==23.1.1
frozenlist==1.4.0
# via
# aiohttp
# aiosignal
idna==3.4
# via yarl
-e ${PROJECT_ROOT}/../../scripts/editable-installs/maturin_editable
multidict==6.0.4
# via
# aiohttp
# yarl
numpy==1.26.2
# via poetry-editable
-e ../../scripts/editable-installs/poetry_editable
yarl==1.9.2
# via aiohttp
success: true
exit_code: 0
----- stdout -----
# This file was autogenerated by Puffin v[VERSION] via the following command:
# puffin pip compile requirements.in --cache-dir [CACHE_DIR] --exclude-newer 2023-11-18T12:00:00Z
-e ${PROJECT_ROOT}/../../scripts/editable-installs/maturin_editable
-e ../../scripts/editable-installs/poetry_editable
-e file://../../scripts/editable-installs/black_editable
aiohttp==3.9.0
# via black
aiosignal==1.3.1
# via aiohttp
attrs==23.1.0
# via aiohttp
boltons==23.1.1
frozenlist==1.4.0
# via
# aiohttp
# aiosignal
idna==3.4
# via yarl
multidict==6.0.4
# via
# aiohttp
# yarl
numpy==1.26.2
# via poetry-editable
yarl==1.9.2
# via aiohttp
----- stderr -----
Built 3 editables in [TIME]
Resolved 12 packages in [TIME]
"###);
----- stderr -----
Built 3 editables in [TIME]
Resolved 12 packages in [TIME]
"###);
Ok(())
}