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 std::hash::BuildHasherDefault;
use anyhow::Result; 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. /// Write the graph in the `{name}=={version}` format of requirements.txt that pip uses.
impl std::fmt::Display for DisplayResolutionGraph<'_> { impl std::fmt::Display for DisplayResolutionGraph<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 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 let mut nodes = self
.resolution .resolution
.petgraph .petgraph
.node_indices() .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<_>>(); .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. // Print out the dependency graph.
for (index, dist) in nodes { for (index, node) in nodes {
// Display the node itself. // Display the node itself.
if let Some((editable, _)) = self.resolution.editables.get(dist.name()) { match node {
write!(f, "-e {}", editable.verbatim())?; Node::Distribution(_, dist) => {
} else { write!(f, "{}", dist.verbatim())?;
write!(f, "{}", dist.verbatim())?; }
Node::Editable(_, editable) => {
write!(f, "-e {}", editable.verbatim())?;
}
} }
// Display the distribution hashes, if any. // Display the distribution hashes, if any.
@ -278,7 +327,7 @@ impl std::fmt::Display for DisplayResolutionGraph<'_> {
if let Some(hashes) = self if let Some(hashes) = self
.resolution .resolution
.hashes .hashes
.get(dist.name()) .get(node.name())
.filter(|hashes| !hashes.is_empty()) .filter(|hashes| !hashes.is_empty())
{ {
for hash in hashes { for hash in hashes {

View File

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