mirror of https://github.com/astral-sh/uv
Strip query parameters when parsing source URL (#14224)
## Summary Closes https://github.com/astral-sh/uv/issues/14217.
This commit is contained in:
parent
d9351d52fc
commit
aa2448ef83
|
|
@ -2371,7 +2371,13 @@ impl Package {
|
||||||
let sdist = match &self.id.source {
|
let sdist = match &self.id.source {
|
||||||
Source::Path(path) => {
|
Source::Path(path) => {
|
||||||
// A direct path source can also be a wheel, so validate the extension.
|
// A direct path source can also be a wheel, so validate the extension.
|
||||||
let DistExtension::Source(ext) = DistExtension::from_path(path)? else {
|
let DistExtension::Source(ext) = DistExtension::from_path(path).map_err(|err| {
|
||||||
|
LockErrorKind::MissingExtension {
|
||||||
|
id: self.id.clone(),
|
||||||
|
err,
|
||||||
|
}
|
||||||
|
})?
|
||||||
|
else {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
};
|
};
|
||||||
let install_path = absolute_path(workspace_root, path)?;
|
let install_path = absolute_path(workspace_root, path)?;
|
||||||
|
|
@ -2444,7 +2450,14 @@ impl Package {
|
||||||
}
|
}
|
||||||
Source::Direct(url, direct) => {
|
Source::Direct(url, direct) => {
|
||||||
// A direct URL source can also be a wheel, so validate the extension.
|
// A direct URL source can also be a wheel, so validate the extension.
|
||||||
let DistExtension::Source(ext) = DistExtension::from_path(url.as_ref())? else {
|
let DistExtension::Source(ext) =
|
||||||
|
DistExtension::from_path(url.base_str()).map_err(|err| {
|
||||||
|
LockErrorKind::MissingExtension {
|
||||||
|
id: self.id.clone(),
|
||||||
|
err,
|
||||||
|
}
|
||||||
|
})?
|
||||||
|
else {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
};
|
};
|
||||||
let location = url.to_url().map_err(LockErrorKind::InvalidUrl)?;
|
let location = url.to_url().map_err(LockErrorKind::InvalidUrl)?;
|
||||||
|
|
@ -2483,7 +2496,12 @@ impl Package {
|
||||||
.ok_or_else(|| LockErrorKind::MissingFilename {
|
.ok_or_else(|| LockErrorKind::MissingFilename {
|
||||||
id: self.id.clone(),
|
id: self.id.clone(),
|
||||||
})?;
|
})?;
|
||||||
let ext = SourceDistExtension::from_path(filename.as_ref())?;
|
let ext = SourceDistExtension::from_path(filename.as_ref()).map_err(|err| {
|
||||||
|
LockErrorKind::MissingExtension {
|
||||||
|
id: self.id.clone(),
|
||||||
|
err,
|
||||||
|
}
|
||||||
|
})?;
|
||||||
let file = Box::new(uv_distribution_types::File {
|
let file = Box::new(uv_distribution_types::File {
|
||||||
dist_info_metadata: false,
|
dist_info_metadata: false,
|
||||||
filename: SmallString::from(filename),
|
filename: SmallString::from(filename),
|
||||||
|
|
@ -2535,7 +2553,12 @@ impl Package {
|
||||||
.ok_or_else(|| LockErrorKind::MissingFilename {
|
.ok_or_else(|| LockErrorKind::MissingFilename {
|
||||||
id: self.id.clone(),
|
id: self.id.clone(),
|
||||||
})?;
|
})?;
|
||||||
let ext = SourceDistExtension::from_path(filename.as_ref())?;
|
let ext = SourceDistExtension::from_path(filename.as_ref()).map_err(|err| {
|
||||||
|
LockErrorKind::MissingExtension {
|
||||||
|
id: self.id.clone(),
|
||||||
|
err,
|
||||||
|
}
|
||||||
|
})?;
|
||||||
let file = Box::new(uv_distribution_types::File {
|
let file = Box::new(uv_distribution_types::File {
|
||||||
dist_info_metadata: false,
|
dist_info_metadata: false,
|
||||||
filename: SmallString::from(filename),
|
filename: SmallString::from(filename),
|
||||||
|
|
@ -5222,8 +5245,13 @@ enum LockErrorKind {
|
||||||
),
|
),
|
||||||
/// An error that occurs when the extension can't be determined
|
/// An error that occurs when the extension can't be determined
|
||||||
/// for a given wheel or source distribution.
|
/// for a given wheel or source distribution.
|
||||||
#[error("Failed to parse file extension; expected one of: {0}")]
|
#[error("Failed to parse file extension for `{id}`; expected one of: {err}", id = id.cyan())]
|
||||||
MissingExtension(#[from] ExtensionError),
|
MissingExtension {
|
||||||
|
/// The filename that was expected to have an extension.
|
||||||
|
id: PackageId,
|
||||||
|
/// The list of valid extensions that were expected.
|
||||||
|
err: ExtensionError,
|
||||||
|
},
|
||||||
/// Failed to parse a Git source URL.
|
/// Failed to parse a Git source URL.
|
||||||
#[error("Failed to parse Git URL")]
|
#[error("Failed to parse Git URL")]
|
||||||
InvalidGitSourceUrl(
|
InvalidGitSourceUrl(
|
||||||
|
|
|
||||||
|
|
@ -9943,3 +9943,32 @@ fn sync_required_environment_hint() -> Result<()> {
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn sync_url_with_query_parameters() -> Result<()> {
|
||||||
|
let context = TestContext::new("3.13").with_exclude_newer("2025-03-24T19:00:00Z");
|
||||||
|
|
||||||
|
let pyproject_toml = context.temp_dir.child("pyproject.toml");
|
||||||
|
pyproject_toml.write_str(r#"
|
||||||
|
[project]
|
||||||
|
name = "example"
|
||||||
|
version = "0.1.0"
|
||||||
|
requires-python = ">=3.13.2"
|
||||||
|
dependencies = ["source-distribution @ https://files.pythonhosted.org/packages/1f/e5/5b016c945d745f8b108e759d428341488a6aee8f51f07c6c4e33498bb91f/source_distribution-0.0.3.tar.gz?foo=bar"]
|
||||||
|
"#
|
||||||
|
)?;
|
||||||
|
|
||||||
|
uv_snapshot!(context.filters(), context.sync(), @r"
|
||||||
|
success: true
|
||||||
|
exit_code: 0
|
||||||
|
----- stdout -----
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
Resolved 2 packages in [TIME]
|
||||||
|
Prepared 1 package in [TIME]
|
||||||
|
Installed 1 package in [TIME]
|
||||||
|
+ source-distribution==0.0.3 (from https://files.pythonhosted.org/packages/1f/e5/5b016c945d745f8b108e759d428341488a6aee8f51f07c6c4e33498bb91f/source_distribution-0.0.3.tar.gz?foo=bar)
|
||||||
|
");
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue