Allow relative paths and environment variables in all editable representations (#1000)

## Summary

I don't know if this is actually a good change, but it tries to make the
editable install experience more consistent. Specifically, we now
support...

```
# Use a relative path with a `file://` prefix.
# Prior to this PR, we supported `file:../foo`, but not `file://../foo`, which felt inconsistent.
-e file://../foo

# Use environment variables with paths, not just URLs.
# Prior to this PR, we supported `file://${PROJECT_ROOT}/../foo`, but not the below.
-e ${PROJECT_ROOT}/../foo
```

Importantly, `-e file://../foo` is actually not supported by pip... `-e
file:../foo` _is_ supported though. We support both, as of this PR. Open
to feedback.
This commit is contained in:
Charlie Marsh 2024-01-19 09:00:37 -05:00 committed by GitHub
parent cd2fb6fd60
commit 5adb08a304
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 174 additions and 198 deletions

View file

@ -1,45 +1,40 @@
use std::borrow::Cow;
use std::path::{Path, PathBuf};
use std::path::PathBuf;
use url::Url;
use pep508_rs::VerbatimUrl;
use requirements_txt::EditableRequirement;
use crate::Verbatim;
#[derive(Debug, Clone)]
pub struct LocalEditable {
pub requirement: EditableRequirement,
/// The underlying [`EditableRequirement`] from the `requirements.txt` file.
pub url: VerbatimUrl,
/// Either the path to the editable or its checkout.
pub path: PathBuf,
}
impl LocalEditable {
/// Return the [`VerbatimUrl`] of the editable.
/// Return the editable as a [`Url`].
pub fn url(&self) -> &VerbatimUrl {
self.requirement.url()
}
/// Return the underlying [`Url`] of the editable.
pub fn raw(&self) -> &Url {
self.requirement.raw()
&self.url
}
/// Return the resolved path to the editable.
pub fn path(&self) -> &Path {
&self.path
pub fn raw(&self) -> &Url {
self.url.raw()
}
}
impl Verbatim for LocalEditable {
fn verbatim(&self) -> Cow<'_, str> {
self.url().verbatim()
self.url.verbatim()
}
}
impl std::fmt::Display for LocalEditable {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.requirement.fmt(f)
std::fmt::Display::fmt(&self.url, f)
}
}

View file

@ -43,7 +43,6 @@ use distribution_filename::{DistFilename, SourceDistFilename, WheelFilename};
use pep440_rs::Version;
use pep508_rs::VerbatimUrl;
use puffin_normalize::PackageName;
use requirements_txt::EditableRequirement;
pub use crate::any::*;
pub use crate::cached::*;
@ -272,24 +271,13 @@ impl Dist {
/// Create a [`Dist`] for a local editable distribution.
pub fn from_editable(name: PackageName, editable: LocalEditable) -> Result<Self, Error> {
match editable.requirement {
EditableRequirement::Path { url, path } => {
Ok(Self::Source(SourceDist::Path(PathSourceDist {
name,
url,
path,
editable: true,
})))
}
EditableRequirement::Url { url, path } => {
Ok(Self::Source(SourceDist::Path(PathSourceDist {
name,
path,
url,
editable: true,
})))
}
}
let LocalEditable { url, path } = editable;
Ok(Self::Source(SourceDist::Path(PathSourceDist {
name,
url,
path,
editable: true,
})))
}
/// Returns the [`File`] instance, if this dist is from a registry with simple json api support
@ -353,11 +341,7 @@ impl SourceDist {
url: VerbatimUrl::unknown(url),
..dist
}),
SourceDist::Path(dist) => SourceDist::Path(PathSourceDist {
url: VerbatimUrl::unknown(url),
..dist
}),
dist @ SourceDist::Registry(_) => dist,
dist => dist,
}
}
}