Skip to content

Commit

Permalink
Publish: Workaround using raw filename
Browse files Browse the repository at this point in the history
Since setuptools violates the wheel filenames spec (pypa/setuptools#3777), we have to use the raw filename when publishing to get through https://github.com/pypi/warehouse/blob/50a58f3081e693a3772c0283050a275e350004bf/warehouse/forklift/legacy.py#L1133-L1155.

Tested with

```
cargo run publish aviary.gsm8k-0.7.6-py3-none-any.whl --publish-url https://test.pypi.org/legacy/
```

Fixes #8030
  • Loading branch information
konstin committed Oct 15, 2024
1 parent dda91d4 commit fe26e4f
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 12 deletions.
24 changes: 19 additions & 5 deletions crates/uv-publish/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,9 +198,15 @@ impl PublishSendError {
}
}

/// Collect the source distributions and wheels for publishing.
///
/// Returns the path, the raw filename and the parsed filename. The raw filename is a fixup for
/// <https://github.com/astral-sh/uv/issues/8030> caused by
/// <https://github.com/pypa/setuptools/issues/3777> in combination with
/// <https://github.com/pypi/warehouse/blob/50a58f3081e693a3772c0283050a275e350004bf/warehouse/forklift/legacy.py#L1133-L1155>
pub fn files_for_publishing(
paths: Vec<String>,
) -> Result<Vec<(PathBuf, DistFilename)>, PublishError> {
) -> Result<Vec<(PathBuf, String, DistFilename)>, PublishError> {
let mut seen = FxHashSet::default();
let mut files = Vec::new();
for path in paths {
Expand All @@ -212,15 +218,19 @@ pub fn files_for_publishing(
if !seen.insert(dist.clone()) {
continue;
}
let Some(filename) = dist.file_name().and_then(|filename| filename.to_str()) else {
let Some(filename) = dist
.file_name()
.and_then(|filename| filename.to_str())
.map(ToString::to_string)
else {
continue;
};
if filename == ".gitignore" {
continue;
}
let filename = DistFilename::try_from_normalized_filename(filename)
let dist_filename = DistFilename::try_from_normalized_filename(&filename)
.ok_or_else(|| PublishError::InvalidFilename(dist.clone()))?;
files.push((dist, filename));
files.push((dist, filename, dist_filename));
}
}
// TODO(konsti): Should we sort those files, e.g. wheels before sdists because they are more
Expand Down Expand Up @@ -287,6 +297,7 @@ pub async fn check_trusted_publishing(
/// Implements a custom retry flow since the request isn't cloneable.
pub async fn upload(
file: &Path,
raw_filename: &str,
filename: &DistFilename,
registry: &Url,
client: &ClientWithMiddleware,
Expand All @@ -305,6 +316,7 @@ pub async fn upload(
attempt += 1;
let (request, idx) = build_request(
file,
raw_filename,
filename,
registry,
client,
Expand Down Expand Up @@ -489,6 +501,7 @@ async fn form_metadata(
/// Returns the request and the reporter progress bar id.
async fn build_request(
file: &Path,
raw_filename: &str,
filename: &DistFilename,
registry: &Url,
client: &ClientWithMiddleware,
Expand All @@ -510,7 +523,8 @@ async fn build_request(
// Stream wrapping puts a static lifetime requirement on the reader (so the request doesn't have
// a lifetime) -> callback needs to be static -> reporter reference needs to be Arc'd.
let file_reader = Body::wrap_stream(ReaderStream::new(reader));
let part = Part::stream(file_reader).file_name(filename.to_string());
// See [`files_for_publishing`] on `raw_filename`
let part = Part::stream(file_reader).file_name(raw_filename.to_string());
form = form.part("content", part);

let url = if let Some(username) = username {
Expand Down
14 changes: 8 additions & 6 deletions crates/uv-publish/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ impl Reporter for DummyReporter {
/// Snapshot the data we send for an upload request for a source distribution.
#[tokio::test]
async fn upload_request_source_dist() {
let filename = "tqdm-999.0.0.tar.gz";
let file = PathBuf::from("../../scripts/links/").join(filename);
let filename = DistFilename::try_from_normalized_filename(filename).unwrap();
let raw_filename = "tqdm-999.0.0.tar.gz";
let file = PathBuf::from("../../scripts/links/").join(raw_filename);
let filename = DistFilename::try_from_normalized_filename(raw_filename).unwrap();

let form_metadata = form_metadata(&file, &filename).await.unwrap();

Expand Down Expand Up @@ -81,6 +81,7 @@ async fn upload_request_source_dist() {

let (request, _) = build_request(
&file,
raw_filename,
&filename,
&Url::parse("https://example.org/upload").unwrap(),
&BaseClientBuilder::new().build().client(),
Expand Down Expand Up @@ -129,10 +130,10 @@ async fn upload_request_source_dist() {
/// Snapshot the data we send for an upload request for a wheel.
#[tokio::test]
async fn upload_request_wheel() {
let filename =
let raw_filename =
"tqdm-4.66.1-py3-none-manylinux_2_12_x86_64.manylinux2010_x86_64.musllinux_1_1_x86_64.whl";
let file = PathBuf::from("../../scripts/links/").join(filename);
let filename = DistFilename::try_from_normalized_filename(filename).unwrap();
let file = PathBuf::from("../../scripts/links/").join(raw_filename);
let filename = DistFilename::try_from_normalized_filename(raw_filename).unwrap();

let form_metadata = form_metadata(&file, &filename).await.unwrap();

Expand Down Expand Up @@ -225,6 +226,7 @@ async fn upload_request_wheel() {

let (request, _) = build_request(
&file,
raw_filename,
&filename,
&Url::parse("https://example.org/upload").unwrap(),
&BaseClientBuilder::new().build().client(),
Expand Down
3 changes: 2 additions & 1 deletion crates/uv/src/commands/publish.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ pub(crate) async fn publish(
bail!("You need to provide a username with a password, use `--token` for tokens");
}

for (file, filename) in files {
for (file, raw_filename, filename) in files {
let size = fs_err::metadata(&file)?.len();
let (bytes, unit) = human_readable_bytes(size);
writeln!(
Expand All @@ -97,6 +97,7 @@ pub(crate) async fn publish(
let reporter = PublishReporter::single(printer);
let uploaded = upload(
&file,
&raw_filename,
&filename,
&publish_url,
&upload_client.client(),
Expand Down

0 comments on commit fe26e4f

Please sign in to comment.