mirror of https://github.com/astral-sh/uv
Track editable requirements in lockfile (#3725)
## Summary This PR adds editables using a new source type (`editable+...`), and then extracts the editables from the lockfile in `uv sync`. Closes https://github.com/astral-sh/uv/issues/3695.
This commit is contained in:
parent
472ab144d5
commit
e398444f2f
|
|
@ -1,8 +1,12 @@
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
|
|
||||||
|
use pep508_rs::VerbatimUrl;
|
||||||
use uv_normalize::PackageName;
|
use uv_normalize::PackageName;
|
||||||
|
|
||||||
use crate::{BuiltDist, Dist, Name, Requirement, RequirementSource, ResolvedDist, SourceDist};
|
use crate::{
|
||||||
|
BuiltDist, DirectorySourceDist, Dist, InstalledDirectUrlDist, InstalledDist, LocalEditable,
|
||||||
|
Name, Requirement, RequirementSource, ResolvedDist, SourceDist,
|
||||||
|
};
|
||||||
|
|
||||||
/// A set of packages pinned at specific versions.
|
/// A set of packages pinned at specific versions.
|
||||||
#[derive(Debug, Default, Clone)]
|
#[derive(Debug, Default, Clone)]
|
||||||
|
|
@ -68,6 +72,35 @@ impl Resolution {
|
||||||
requirements.sort_unstable_by(|a, b| a.name.cmp(&b.name));
|
requirements.sort_unstable_by(|a, b| a.name.cmp(&b.name));
|
||||||
requirements
|
requirements
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return an iterator over the [`LocalEditable`] entities in this resolution.
|
||||||
|
pub fn editables(&self) -> impl Iterator<Item = LocalEditable> + '_ {
|
||||||
|
self.0.values().filter_map(|dist| match dist {
|
||||||
|
ResolvedDist::Installable(Dist::Source(SourceDist::Directory(
|
||||||
|
DirectorySourceDist {
|
||||||
|
path,
|
||||||
|
url,
|
||||||
|
editable: true,
|
||||||
|
..
|
||||||
|
},
|
||||||
|
))) => Some(LocalEditable {
|
||||||
|
url: url.clone(),
|
||||||
|
path: path.clone(),
|
||||||
|
extras: vec![],
|
||||||
|
}),
|
||||||
|
ResolvedDist::Installed(InstalledDist::Url(InstalledDirectUrlDist {
|
||||||
|
path,
|
||||||
|
url,
|
||||||
|
editable: true,
|
||||||
|
..
|
||||||
|
})) => Some(LocalEditable {
|
||||||
|
url: VerbatimUrl::from_url(url.clone()),
|
||||||
|
path: path.clone(),
|
||||||
|
extras: vec![],
|
||||||
|
}),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&ResolvedDist> for Requirement {
|
impl From<&ResolvedDist> for Requirement {
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,10 @@ use pep508_rs::PackageName;
|
||||||
use rustc_hash::FxHashSet;
|
use rustc_hash::FxHashSet;
|
||||||
|
|
||||||
/// Whether to reinstall packages.
|
/// Whether to reinstall packages.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Default, Clone)]
|
||||||
pub enum Reinstall {
|
pub enum Reinstall {
|
||||||
/// Don't reinstall any packages; respect the existing installation.
|
/// Don't reinstall any packages; respect the existing installation.
|
||||||
|
#[default]
|
||||||
None,
|
None,
|
||||||
|
|
||||||
/// Reinstall all packages in the plan.
|
/// Reinstall all packages in the plan.
|
||||||
|
|
|
||||||
|
|
@ -277,6 +277,9 @@ impl Distribution {
|
||||||
SourceKind::Directory => {
|
SourceKind::Directory => {
|
||||||
unreachable!("Wheels cannot come from directory sources")
|
unreachable!("Wheels cannot come from directory sources")
|
||||||
}
|
}
|
||||||
|
SourceKind::Editable => {
|
||||||
|
unreachable!("Wheels cannot come from editable sources")
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -301,6 +304,16 @@ impl Distribution {
|
||||||
let source_dist = distribution_types::SourceDist::Directory(dir_dist);
|
let source_dist = distribution_types::SourceDist::Directory(dir_dist);
|
||||||
Dist::Source(source_dist)
|
Dist::Source(source_dist)
|
||||||
}
|
}
|
||||||
|
SourceKind::Editable => {
|
||||||
|
let dir_dist = DirectorySourceDist {
|
||||||
|
name: self.id.name.clone(),
|
||||||
|
url: VerbatimUrl::from_url(self.id.source.url.clone()),
|
||||||
|
path: self.id.source.url.to_file_path().unwrap(),
|
||||||
|
editable: true,
|
||||||
|
};
|
||||||
|
let source_dist = distribution_types::SourceDist::Directory(dir_dist);
|
||||||
|
Dist::Source(source_dist)
|
||||||
|
}
|
||||||
SourceKind::Git(git) => {
|
SourceKind::Git(git) => {
|
||||||
// Reconstruct the `GitUrl` from the `GitSource`.
|
// Reconstruct the `GitUrl` from the `GitSource`.
|
||||||
let git_url = uv_git::GitUrl::new(
|
let git_url = uv_git::GitUrl::new(
|
||||||
|
|
@ -513,7 +526,11 @@ impl Source {
|
||||||
|
|
||||||
fn from_directory_source_dist(directory_dist: &DirectorySourceDist) -> Source {
|
fn from_directory_source_dist(directory_dist: &DirectorySourceDist) -> Source {
|
||||||
Source {
|
Source {
|
||||||
kind: SourceKind::Directory,
|
kind: if directory_dist.editable {
|
||||||
|
SourceKind::Editable
|
||||||
|
} else {
|
||||||
|
SourceKind::Directory
|
||||||
|
},
|
||||||
url: directory_dist.url.to_url(),
|
url: directory_dist.url.to_url(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -583,6 +600,10 @@ impl std::str::FromStr for Source {
|
||||||
kind: SourceKind::Directory,
|
kind: SourceKind::Directory,
|
||||||
url,
|
url,
|
||||||
}),
|
}),
|
||||||
|
"editable" => Ok(Source {
|
||||||
|
kind: SourceKind::Editable,
|
||||||
|
url,
|
||||||
|
}),
|
||||||
name => Err(SourceParseError::unrecognized_source_name(s, name)),
|
name => Err(SourceParseError::unrecognized_source_name(s, name)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -624,6 +645,7 @@ pub(crate) enum SourceKind {
|
||||||
Direct(DirectSource),
|
Direct(DirectSource),
|
||||||
Path,
|
Path,
|
||||||
Directory,
|
Directory,
|
||||||
|
Editable,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SourceKind {
|
impl SourceKind {
|
||||||
|
|
@ -634,6 +656,7 @@ impl SourceKind {
|
||||||
SourceKind::Direct(_) => "direct",
|
SourceKind::Direct(_) => "direct",
|
||||||
SourceKind::Path => "path",
|
SourceKind::Path => "path",
|
||||||
SourceKind::Directory => "directory",
|
SourceKind::Directory => "directory",
|
||||||
|
SourceKind::Editable => "editable",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -644,7 +667,7 @@ impl SourceKind {
|
||||||
fn requires_hash(&self) -> bool {
|
fn requires_hash(&self) -> bool {
|
||||||
match *self {
|
match *self {
|
||||||
SourceKind::Registry | SourceKind::Direct(_) | SourceKind::Path => true,
|
SourceKind::Registry | SourceKind::Direct(_) | SourceKind::Path => true,
|
||||||
SourceKind::Git(_) | SourceKind::Directory => false,
|
SourceKind::Git(_) | SourceKind::Directory | SourceKind::Editable => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ use install_wheel_rs::linker::LinkMode;
|
||||||
use uv_cache::Cache;
|
use uv_cache::Cache;
|
||||||
use uv_client::RegistryClientBuilder;
|
use uv_client::RegistryClientBuilder;
|
||||||
use uv_configuration::{
|
use uv_configuration::{
|
||||||
Concurrency, ConfigSettings, NoBinary, NoBuild, PreviewMode, SetupPyStrategy,
|
Concurrency, ConfigSettings, NoBinary, NoBuild, PreviewMode, Reinstall, SetupPyStrategy,
|
||||||
};
|
};
|
||||||
use uv_dispatch::BuildDispatch;
|
use uv_dispatch::BuildDispatch;
|
||||||
use uv_installer::SitePackages;
|
use uv_installer::SitePackages;
|
||||||
|
|
@ -65,6 +65,7 @@ pub(crate) async fn sync(
|
||||||
let no_build = NoBuild::default();
|
let no_build = NoBuild::default();
|
||||||
let setup_py = SetupPyStrategy::default();
|
let setup_py = SetupPyStrategy::default();
|
||||||
let concurrency = Concurrency::default();
|
let concurrency = Concurrency::default();
|
||||||
|
let reinstall = Reinstall::default();
|
||||||
|
|
||||||
// Create a build dispatch.
|
// Create a build dispatch.
|
||||||
let build_dispatch = BuildDispatch::new(
|
let build_dispatch = BuildDispatch::new(
|
||||||
|
|
@ -84,8 +85,23 @@ pub(crate) async fn sync(
|
||||||
concurrency,
|
concurrency,
|
||||||
);
|
);
|
||||||
|
|
||||||
// TODO(konsti): Read editables from lockfile.
|
let site_packages = SitePackages::from_executable(&venv)?;
|
||||||
let editables = ResolvedEditables::default();
|
|
||||||
|
// Build any editables.
|
||||||
|
let editables = ResolvedEditables::resolve(
|
||||||
|
resolution.editables(),
|
||||||
|
&site_packages,
|
||||||
|
&reinstall,
|
||||||
|
&hasher,
|
||||||
|
venv.interpreter(),
|
||||||
|
tags,
|
||||||
|
cache,
|
||||||
|
&client,
|
||||||
|
&build_dispatch,
|
||||||
|
concurrency,
|
||||||
|
printer,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
let site_packages = SitePackages::from_executable(&venv)?;
|
let site_packages = SitePackages::from_executable(&venv)?;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue