Skip to content

Commit

Permalink
Use VerbatimUrl for editables
Browse files Browse the repository at this point in the history
  • Loading branch information
konstin committed Dec 14, 2023
1 parent e023b8c commit ba31214
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 50 deletions.
15 changes: 10 additions & 5 deletions crates/distribution-types/src/editable.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use requirements_txt::EditableRequirement;
use std::fmt::{Display, Formatter};
use std::path::PathBuf;
use url::Url;
use std::path::{Path, PathBuf};

use pep508_rs::VerbatimUrl;
use requirements_txt::EditableRequirement;

#[derive(Debug, Clone)]
pub struct LocalEditable {
Expand All @@ -11,8 +12,12 @@ pub struct LocalEditable {
}

impl LocalEditable {
pub fn url(&self) -> Url {
Url::from_directory_path(&self.path).expect("A valid path makes a valid url")
pub fn url(&self) -> VerbatimUrl {
self.requirement.url()
}

pub fn path(&self) -> &Path {
&self.path
}
}

Expand Down
9 changes: 9 additions & 0 deletions crates/pep508-rs/src/verbatim_url.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::borrow::Cow;
use std::ops::Deref;
use std::path::Path;

use once_cell::sync::Lazy;
use regex::Regex;
Expand Down Expand Up @@ -27,6 +28,14 @@ impl VerbatimUrl {
})
}

/// Helper method `LocalEditable`
pub fn from_path(path: &Path, given: String) -> Result<Self, ()> {
Ok(Self {
url: Url::from_directory_path(path)?,
given: Some(given),
})
}

/// Return the underlying [`Url`].
pub fn raw(&self) -> &Url {
&self.url
Expand Down
3 changes: 1 addition & 2 deletions crates/puffin-distribution/src/source_dist.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ use distribution_types::{
Dist, GitSourceDist, LocalEditable, Metadata, PathSourceDist, RemoteSource, SourceDist,
};
use install_wheel_rs::read_dist_info;
use pep508_rs::VerbatimUrl;
use platform_tags::Tags;
use puffin_cache::{
digest, CacheBucket, CacheEntry, CacheShard, CachedByTimestamp, CanonicalUrl, WheelCache,
Expand Down Expand Up @@ -688,7 +687,7 @@ impl<'a, T: BuildContext> SourceDistCachedBuilder<'a, T> {
// We finally have the name of the package and can construct the dist
let dist = Dist::Source(SourceDist::Path(PathSourceDist {
name: filename.name.clone(),
url: VerbatimUrl::unknown(editable.url()),
url: editable.url(),
path: editable.path.clone(),
editable: true,
}));
Expand Down
2 changes: 1 addition & 1 deletion crates/puffin-installer/src/plan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ impl InstallPlan {
for editable in editable_requirements {
let editable_dist = site_packages
.editables()
.find(|(_dist, url, _dir_info)| *url == &editable.url())
.find(|(_dist, url, _dir_info)| url == &editable.url().raw())
.map(|(dist, _url, _dir_info)| dist.clone());
if let Some(dist) = editable_dist {
debug!("Treating editable requirement as immutable: {editable}");
Expand Down
17 changes: 5 additions & 12 deletions crates/puffin-resolver/src/resolver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use distribution_types::{
BuiltDist, Dist, DistributionId, Identifier, LocalEditable, Metadata, PackageId, SourceDist,
VersionOrUrl,
};
use pep508_rs::{MarkerEnvironment, Requirement, VerbatimUrl};
use pep508_rs::{MarkerEnvironment, Requirement};
use platform_tags::Tags;
use puffin_cache::CanonicalUrl;
use puffin_client::RegistryClient;
Expand Down Expand Up @@ -202,11 +202,8 @@ impl<'a, Provider: ResolverProvider> Resolver<'a, Provider> {
let index = Index::default();
let mut editables = FxHashMap::default();
for (editable_requirement, metadata) in &manifest.editables {
let dist = Dist::from_url(
metadata.name.clone(),
VerbatimUrl::unknown(editable_requirement.url()),
)
.expect("This is a valid distribution");
let dist = Dist::from_url(metadata.name.clone(), editable_requirement.url())
.expect("This is a valid distribution");
// Mock editable responses
index.distributions.register(&dist.package_id());
index
Expand Down Expand Up @@ -237,7 +234,7 @@ impl<'a, Provider: ResolverProvider> Resolver<'a, Provider> {
manifest
.editables
.iter()
.map(|(editable, _)| editable.url()),
.map(|(editable, _)| editable.url().raw().clone()),
)
.collect(),
project: manifest.project,
Expand Down Expand Up @@ -638,11 +635,7 @@ impl<'a, Provider: ResolverProvider> Resolver<'a, Provider> {

for (editable, metadata) in self.editables.values() {
constraints.insert(
PubGrubPackage::Package(
metadata.name.clone(),
None,
Some(VerbatimUrl::unknown(editable.url())),
),
PubGrubPackage::Package(metadata.name.clone(), None, Some(editable.url())),
Range::singleton(PubGrubVersion::from(metadata.version.clone())),
);
}
Expand Down
51 changes: 21 additions & 30 deletions crates/requirements-txt/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,8 @@ use fs_err as fs;
use serde::{Deserialize, Serialize};
use tracing::warn;
use unscanny::{Pattern, Scanner};
use url::Url;

use pep508_rs::{Pep508Error, Requirement};
use pep508_rs::{Pep508Error, Requirement, VerbatimUrl};

/// We emit one of those for each requirements.txt entry
enum RequirementsTxtStatement {
Expand All @@ -68,61 +67,53 @@ enum RequirementsTxtStatement {
EditableRequirement(ParsedEditableRequirement),
}

#[derive(Debug, Deserialize, Clone, Eq, PartialEq, Serialize)]
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum EditableRequirement {
Path {
/// The absolute path, resolved from the current dir if the path in the requirements file was relative
resolved: PathBuf,
/// The relative path as it is written in the requirements file
original: PathBuf,
original: String,
},
Url(Url),
Url(VerbatimUrl),
}

impl EditableRequirement {
pub fn url(&self) -> Url {
pub fn url(&self) -> VerbatimUrl {
match self {
EditableRequirement::Path {
resolved,
original: _,
} => Url::from_directory_path(resolved).expect("Path valid for url"),
EditableRequirement::Path { resolved, original } => {
VerbatimUrl::from_path(resolved, original.clone())
.expect("A valid path makes a valid url")
}
EditableRequirement::Url(url) => url.clone(),
}
}
}

/// Relative paths aren't resolved with the current dir yet
#[derive(Debug, Deserialize, Clone, Eq, PartialEq, Serialize)]
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum ParsedEditableRequirement {
Path(PathBuf),
Url(Url),
Path(String),
Url(VerbatimUrl),
}

impl ParsedEditableRequirement {
pub fn unwrap_path(&self) -> &Path {
match self {
ParsedEditableRequirement::Path(path) => path,
ParsedEditableRequirement::Url(_) => {
todo!("url editables")
}
}
}

pub fn with_working_dir(
self,
working_dir: impl AsRef<Path>,
) -> io::Result<EditableRequirement> {
Ok(match self {
ParsedEditableRequirement::Path(path) => {
if path.is_absolute() {
let path_buf = PathBuf::from(&path);
if path_buf.is_absolute() {
EditableRequirement::Path {
resolved: path.clone(),
resolved: path_buf,
original: path,
}
} else {
EditableRequirement::Path {
// Avoid paths like `/home/ferris/project/scripts/../editable/`
resolved: fs::canonicalize(working_dir.as_ref().join(&path))?,
resolved: fs::canonicalize(working_dir.as_ref().join(&path_buf))?,
original: path,
}
}
Expand All @@ -136,7 +127,7 @@ impl ParsedEditableRequirement {
impl Display for ParsedEditableRequirement {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
ParsedEditableRequirement::Path(path) => path.display().fmt(f),
ParsedEditableRequirement::Path(path) => path.fmt(f),
ParsedEditableRequirement::Url(url) => url.fmt(f),
}
}
Expand All @@ -148,7 +139,7 @@ impl Display for EditableRequirement {
EditableRequirement::Path {
original,
resolved: _,
} => original.display().fmt(f),
} => original.fmt(f),
EditableRequirement::Url(url) => url.fmt(f),
}
}
Expand Down Expand Up @@ -180,7 +171,7 @@ impl Display for RequirementEntry {
}

/// Parsed and flattened requirements.txt with requirements and constraints
#[derive(Debug, Deserialize, Clone, Default, Eq, PartialEq, Serialize)]
#[derive(Debug, Clone, Default, Eq, PartialEq)]
pub struct RequirementsTxt {
/// The actual requirements with the hashes
pub requirements: Vec<RequirementEntry>,
Expand Down Expand Up @@ -326,10 +317,10 @@ fn parse_entry(
}
} else if s.eat_if("-e") {
let path_or_url = parse_value(s, |c: char| !['\n', '\r'].contains(&c))?;
let editable_requirement = if let Ok(url) = Url::from_str(path_or_url) {
let editable_requirement = if let Ok(url) = VerbatimUrl::from_str(path_or_url) {
ParsedEditableRequirement::Url(url)
} else {
ParsedEditableRequirement::Path(PathBuf::from(path_or_url))
ParsedEditableRequirement::Path(path_or_url.to_string())
};
RequirementsTxtStatement::EditableRequirement(editable_requirement)
} else if s.at(char::is_ascii_alphanumeric) {
Expand Down

0 comments on commit ba31214

Please sign in to comment.