Remove subdirectory from direct wheel URL type (#3667)

## Summary

Closes #3665.
This commit is contained in:
Charlie Marsh 2024-05-19 22:01:57 -04:00 committed by GitHub
parent d8971c1eb0
commit 1124df9bc5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 31 additions and 39 deletions

View File

@ -202,9 +202,7 @@ pub struct DirectUrlBuiltDist {
pub filename: WheelFilename, pub filename: WheelFilename,
/// The URL without the subdirectory fragment. /// The URL without the subdirectory fragment.
pub location: Url, pub location: Url,
/// The subdirectory fragment, if any. /// The URL as it was provided by the user.
pub subdirectory: Option<PathBuf>,
/// The URL with the subdirectory fragment.
pub url: VerbatimUrl, pub url: VerbatimUrl,
} }
@ -212,8 +210,10 @@ pub struct DirectUrlBuiltDist {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct PathBuiltDist { pub struct PathBuiltDist {
pub filename: WheelFilename, pub filename: WheelFilename,
pub url: VerbatimUrl, /// The path to the wheel.
pub path: PathBuf, pub path: PathBuf,
/// The URL as it was provided by the user.
pub url: VerbatimUrl,
} }
/// A source distribution that exists in a registry, like `PyPI`. /// A source distribution that exists in a registry, like `PyPI`.
@ -240,8 +240,9 @@ pub struct DirectUrlSourceDist {
pub name: PackageName, pub name: PackageName,
/// The URL without the subdirectory fragment. /// The URL without the subdirectory fragment.
pub location: Url, pub location: Url,
/// The subdirectory within the archive in which the source distribution is located.
pub subdirectory: Option<PathBuf>, pub subdirectory: Option<PathBuf>,
/// The URL with the subdirectory fragment. /// The URL as it was provided by the user, including the subdirectory fragment.
pub url: VerbatimUrl, pub url: VerbatimUrl,
} }
@ -251,8 +252,9 @@ pub struct GitSourceDist {
pub name: PackageName, pub name: PackageName,
/// The URL without the revision and subdirectory fragment. /// The URL without the revision and subdirectory fragment.
pub git: Box<GitUrl>, pub git: Box<GitUrl>,
/// The subdirectory within the Git repository in which the source distribution is located.
pub subdirectory: Option<PathBuf>, pub subdirectory: Option<PathBuf>,
/// The URL with the revision and subdirectory fragment. /// The URL as it was provided by the user, including the revision and subdirectory fragment.
pub url: VerbatimUrl, pub url: VerbatimUrl,
} }
@ -260,17 +262,22 @@ pub struct GitSourceDist {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct PathSourceDist { pub struct PathSourceDist {
pub name: PackageName, pub name: PackageName,
pub url: VerbatimUrl, /// The path to the archive.
pub path: PathBuf, pub path: PathBuf,
/// The URL as it was provided by the user.
pub url: VerbatimUrl,
} }
/// A source distribution that exists in a local directory. /// A source distribution that exists in a local directory.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct DirectorySourceDist { pub struct DirectorySourceDist {
pub name: PackageName, pub name: PackageName,
pub url: VerbatimUrl, /// The path to the directory.
pub path: PathBuf, pub path: PathBuf,
/// Whether the package should be installed in editable mode.
pub editable: bool, pub editable: bool,
/// The URL as it was provided by the user.
pub url: VerbatimUrl,
} }
impl Dist { impl Dist {
@ -299,7 +306,6 @@ impl Dist {
Ok(Self::Built(BuiltDist::DirectUrl(DirectUrlBuiltDist { Ok(Self::Built(BuiltDist::DirectUrl(DirectUrlBuiltDist {
filename, filename,
location, location,
subdirectory,
url, url,
}))) })))
} else { } else {
@ -332,9 +338,9 @@ impl Dist {
if path.is_dir() { if path.is_dir() {
Ok(Self::Source(SourceDist::Directory(DirectorySourceDist { Ok(Self::Source(SourceDist::Directory(DirectorySourceDist {
name, name,
url,
path, path,
editable, editable,
url,
}))) })))
} else if path } else if path
.extension() .extension()
@ -356,8 +362,8 @@ impl Dist {
Ok(Self::Built(BuiltDist::Path(PathBuiltDist { Ok(Self::Built(BuiltDist::Path(PathBuiltDist {
filename, filename,
url,
path, path,
url,
}))) })))
} else { } else {
if editable { if editable {
@ -366,8 +372,8 @@ impl Dist {
Ok(Self::Source(SourceDist::Path(PathSourceDist { Ok(Self::Source(SourceDist::Path(PathSourceDist {
name, name,
url,
path, path,
url,
}))) })))
} }
} }

View File

@ -33,7 +33,8 @@ pub struct VerbatimParsedUrl {
/// * The path to a file or directory (`file://`) /// * The path to a file or directory (`file://`)
/// * A Git repository (`git+https://` or `git+ssh://`), optionally with a subdirectory and/or /// * A Git repository (`git+https://` or `git+ssh://`), optionally with a subdirectory and/or
/// string to checkout. /// string to checkout.
/// * A remote archive (`https://`), optional with a subdirectory (source dist only) /// * A remote archive (`https://`), optional with a subdirectory (source dist only).
///
/// A URL in a requirement `foo @ <url>` must be one of the above. /// A URL in a requirement `foo @ <url>` must be one of the above.
#[derive(Debug, Clone, Eq, PartialEq, Hash)] #[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub enum ParsedUrl { pub enum ParsedUrl {
@ -41,7 +42,8 @@ pub enum ParsedUrl {
Path(ParsedPathUrl), Path(ParsedPathUrl),
/// The direct URL is path to a Git repository. /// The direct URL is path to a Git repository.
Git(ParsedGitUrl), Git(ParsedGitUrl),
/// The direct URL is a URL to an archive. /// The direct URL is a URL to a source archive (e.g., a `.tar.gz` file) or built archive
/// (i.e., a `.whl` file).
Archive(ParsedArchiveUrl), Archive(ParsedArchiveUrl),
} }
@ -88,12 +90,12 @@ impl TryFrom<Url> for ParsedGitUrl {
} }
} }
/// An archive URL. /// A URL to a source or built archive.
/// ///
/// Examples: /// Examples:
/// * wheel: `https://download.pytorch.org/whl/torch-2.0.1-cp39-cp39-manylinux2014_aarch64.whl#sha256=423e0ae257b756bb45a4b49072046772d1ad0c592265c5080070e0767da4e490` /// * A built distribution: `https://files.pythonhosted.org/packages/62/06/d5604a70d160f6a6ca5fd2ba25597c24abd5c5ca5f437263d177ac242308/tqdm-4.66.1-py2.py3-none-any.whl`
/// * source dist, correctly named: `https://files.pythonhosted.org/packages/62/06/d5604a70d160f6a6ca5fd2ba25597c24abd5c5ca5f437263d177ac242308/tqdm-4.66.1.tar.gz` /// * A source distribution with a valid name: `https://files.pythonhosted.org/packages/62/06/d5604a70d160f6a6ca5fd2ba25597c24abd5c5ca5f437263d177ac242308/tqdm-4.66.1.tar.gz`
/// * source dist, only extension recognizable: `https://github.com/foo-labs/foo/archive/master.zip#egg=pkg&subdirectory=packages/bar` /// * A source dist with a recognizable extension but invalid name: `https://github.com/foo-labs/foo/archive/master.zip#egg=pkg&subdirectory=packages/bar`
#[derive(Debug, Clone, Eq, PartialEq, Hash)] #[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct ParsedArchiveUrl { pub struct ParsedArchiveUrl {
pub url: Url, pub url: Url,

View File

@ -88,7 +88,7 @@ impl From<&ResolvedDist> for Requirement {
RequirementSource::Url { RequirementSource::Url {
url: wheel.url.clone(), url: wheel.url.clone(),
location, location,
subdirectory: wheel.subdirectory.clone(), subdirectory: None,
} }
} }
Dist::Built(BuiltDist::Path(wheel)) => RequirementSource::Path { Dist::Built(BuiltDist::Path(wheel)) => RequirementSource::Path {

View File

@ -22,7 +22,6 @@ async fn remote_metadata_with_and_without_cache() -> Result<()> {
let dist = BuiltDist::DirectUrl(DirectUrlBuiltDist { let dist = BuiltDist::DirectUrl(DirectUrlBuiltDist {
filename, filename,
location: Url::parse(url).unwrap(), location: Url::parse(url).unwrap(),
subdirectory: None,
url: VerbatimUrl::from_str(url).unwrap(), url: VerbatimUrl::from_str(url).unwrap(),
}); });
let metadata = client.wheel_metadata(&dist).await.unwrap(); let metadata = client.wheel_metadata(&dist).await.unwrap();

View File

@ -5,7 +5,7 @@ use anyhow::{bail, Result};
use clap::Parser; use clap::Parser;
use distribution_filename::WheelFilename; use distribution_filename::WheelFilename;
use distribution_types::{BuiltDist, DirectUrlBuiltDist, ParsedUrl}; use distribution_types::{BuiltDist, DirectUrlBuiltDist, ParsedUrl, RemoteSource};
use pep508_rs::VerbatimUrl; use pep508_rs::VerbatimUrl;
use uv_cache::{Cache, CacheArgs}; use uv_cache::{Cache, CacheArgs};
use uv_client::RegistryClientBuilder; use uv_client::RegistryClientBuilder;
@ -21,13 +21,7 @@ pub(crate) async fn wheel_metadata(args: WheelMetadataArgs) -> Result<()> {
let cache = Cache::try_from(args.cache_args)?.init()?; let cache = Cache::try_from(args.cache_args)?.init()?;
let client = RegistryClientBuilder::new(cache).build(); let client = RegistryClientBuilder::new(cache).build();
let filename = WheelFilename::from_str( let filename = WheelFilename::from_str(&args.url.filename()?)?;
args.url
.path()
.rsplit_once('/')
.unwrap_or(("", args.url.path()))
.1,
)?;
let ParsedUrl::Archive(archive) = ParsedUrl::try_from(args.url.to_url())? else { let ParsedUrl::Archive(archive) = ParsedUrl::try_from(args.url.to_url())? else {
bail!("Only HTTPS is supported"); bail!("Only HTTPS is supported");
@ -37,7 +31,6 @@ pub(crate) async fn wheel_metadata(args: WheelMetadataArgs) -> Result<()> {
.wheel_metadata(&BuiltDist::DirectUrl(DirectUrlBuiltDist { .wheel_metadata(&BuiltDist::DirectUrl(DirectUrlBuiltDist {
filename, filename,
location: archive.url, location: archive.url,
subdirectory: archive.subdirectory,
url: args.url, url: args.url,
})) }))
.await?; .await?;

View File

@ -247,7 +247,6 @@ impl<'a> Planner<'a> {
let wheel = DirectUrlBuiltDist { let wheel = DirectUrlBuiltDist {
filename, filename,
location: location.clone(), location: location.clone(),
subdirectory: subdirectory.clone(),
url: url.clone(), url: url.clone(),
}; };

View File

@ -261,12 +261,11 @@ impl Distribution {
let filename: WheelFilename = self.wheels[best_wheel_index].filename.clone(); let filename: WheelFilename = self.wheels[best_wheel_index].filename.clone();
let url = Url::from(ParsedArchiveUrl { let url = Url::from(ParsedArchiveUrl {
url: self.id.source.url.clone(), url: self.id.source.url.clone(),
subdirectory: direct.subdirectory.as_ref().map(PathBuf::from), subdirectory: None,
}); });
let direct_dist = DirectUrlBuiltDist { let direct_dist = DirectUrlBuiltDist {
filename, filename,
location: self.id.source.url.clone(), location: self.id.source.url.clone(),
subdirectory: direct.subdirectory.as_ref().map(PathBuf::from),
url: VerbatimUrl::from_url(url), url: VerbatimUrl::from_url(url),
}; };
let built_dist = BuiltDist::DirectUrl(direct_dist); let built_dist = BuiltDist::DirectUrl(direct_dist);
@ -483,13 +482,7 @@ impl Source {
fn from_direct_built_dist(direct_dist: &DirectUrlBuiltDist) -> Source { fn from_direct_built_dist(direct_dist: &DirectUrlBuiltDist) -> Source {
Source { Source {
kind: SourceKind::Direct(DirectSource { kind: SourceKind::Direct(DirectSource { subdirectory: None }),
subdirectory: direct_dist
.subdirectory
.as_deref()
.and_then(Path::to_str)
.map(ToString::to_string),
}),
url: direct_dist.url.to_url(), url: direct_dist.url.to_url(),
} }
} }