Make DisplaySafeUrlRef Copy and other minor PR follow-ups (#13683)

This PR implements a few review follow-ups from #13560. In particular,
it
* Makes `DisplaySafeUrlRef` implement `Copy` so that it can be passed by
value.
* Updates `to_string_with_credentials` methods with
`displayable_with_credentials`, returning an `impl Display` instead of
`String` for greater flexibility.
* Updates the `DisplaySafeUrl` and `DisplaySafeUrlRef` `Debug`
implementations to match the underlying `Url` `Debug` implementation
(with the exception that credentials are masked).
* Replaces an unnecessary `DisplaySafeUrl::from(Url::from_file_path`
with `DisplaySafeUrl::from_file_path`
This commit is contained in:
John Mumm 2025-05-28 12:36:18 +02:00 committed by GitHub
parent 90a21ae46a
commit 410dc33574
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 1610 additions and 167 deletions

View file

@ -145,7 +145,7 @@ impl Credentials {
/// If a username is provided, it must match the login in the netrc file or [`None`] is returned. /// If a username is provided, it must match the login in the netrc file or [`None`] is returned.
pub(crate) fn from_netrc( pub(crate) fn from_netrc(
netrc: &Netrc, netrc: &Netrc,
url: &DisplaySafeUrlRef<'_>, url: DisplaySafeUrlRef<'_>,
username: Option<&str>, username: Option<&str>,
) -> Option<Self> { ) -> Option<Self> {
let host = url.host_str()?; let host = url.host_str()?;

View file

@ -38,7 +38,7 @@ impl KeyringProvider {
#[instrument(skip_all, fields(url = % url.to_string(), username))] #[instrument(skip_all, fields(url = % url.to_string(), username))]
pub async fn fetch( pub async fn fetch(
&self, &self,
url: &DisplaySafeUrlRef<'_>, url: DisplaySafeUrlRef<'_>,
username: Option<&str>, username: Option<&str>,
) -> Option<Credentials> { ) -> Option<Credentials> {
// Validate the request // Validate the request
@ -229,7 +229,7 @@ mod tests {
let keyring = KeyringProvider::empty(); let keyring = KeyringProvider::empty();
// Panics due to debug assertion; returns `None` in production // Panics due to debug assertion; returns `None` in production
let result = std::panic::AssertUnwindSafe( let result = std::panic::AssertUnwindSafe(
keyring.fetch(&DisplaySafeUrlRef::from(&url), Some("user")), keyring.fetch(DisplaySafeUrlRef::from(&url), Some("user")),
) )
.catch_unwind() .catch_unwind()
.await; .await;
@ -242,7 +242,7 @@ mod tests {
let keyring = KeyringProvider::empty(); let keyring = KeyringProvider::empty();
// Panics due to debug assertion; returns `None` in production // Panics due to debug assertion; returns `None` in production
let result = std::panic::AssertUnwindSafe( let result = std::panic::AssertUnwindSafe(
keyring.fetch(&DisplaySafeUrlRef::from(&url), Some(url.username())), keyring.fetch(DisplaySafeUrlRef::from(&url), Some(url.username())),
) )
.catch_unwind() .catch_unwind()
.await; .await;
@ -255,7 +255,7 @@ mod tests {
let keyring = KeyringProvider::empty(); let keyring = KeyringProvider::empty();
// Panics due to debug assertion; returns `None` in production // Panics due to debug assertion; returns `None` in production
let result = std::panic::AssertUnwindSafe( let result = std::panic::AssertUnwindSafe(
keyring.fetch(&DisplaySafeUrlRef::from(&url), Some(url.username())), keyring.fetch(DisplaySafeUrlRef::from(&url), Some(url.username())),
) )
.catch_unwind() .catch_unwind()
.await; .await;
@ -267,7 +267,7 @@ mod tests {
let url = Url::parse("https://example.com").unwrap(); let url = Url::parse("https://example.com").unwrap();
let url = DisplaySafeUrlRef::from(&url); let url = DisplaySafeUrlRef::from(&url);
let keyring = KeyringProvider::empty(); let keyring = KeyringProvider::empty();
let credentials = keyring.fetch(&url, Some("user")); let credentials = keyring.fetch(url, Some("user"));
assert!(credentials.await.is_none()); assert!(credentials.await.is_none());
} }
@ -277,7 +277,7 @@ mod tests {
let keyring = KeyringProvider::dummy([(url.host_str().unwrap(), "user", "password")]); let keyring = KeyringProvider::dummy([(url.host_str().unwrap(), "user", "password")]);
assert_eq!( assert_eq!(
keyring keyring
.fetch(&DisplaySafeUrlRef::from(&url), Some("user")) .fetch(DisplaySafeUrlRef::from(&url), Some("user"))
.await, .await,
Some(Credentials::basic( Some(Credentials::basic(
Some("user".to_string()), Some("user".to_string()),
@ -287,7 +287,7 @@ mod tests {
assert_eq!( assert_eq!(
keyring keyring
.fetch( .fetch(
&DisplaySafeUrlRef::from(&url.join("test").unwrap()), DisplaySafeUrlRef::from(&url.join("test").unwrap()),
Some("user") Some("user")
) )
.await, .await,
@ -303,7 +303,7 @@ mod tests {
let url = Url::parse("https://example.com").unwrap(); let url = Url::parse("https://example.com").unwrap();
let keyring = KeyringProvider::dummy([("other.com", "user", "password")]); let keyring = KeyringProvider::dummy([("other.com", "user", "password")]);
let credentials = keyring let credentials = keyring
.fetch(&DisplaySafeUrlRef::from(&url), Some("user")) .fetch(DisplaySafeUrlRef::from(&url), Some("user"))
.await; .await;
assert_eq!(credentials, None); assert_eq!(credentials, None);
} }
@ -318,7 +318,7 @@ mod tests {
assert_eq!( assert_eq!(
keyring keyring
.fetch( .fetch(
&DisplaySafeUrlRef::from(&url.join("foo").unwrap()), DisplaySafeUrlRef::from(&url.join("foo").unwrap()),
Some("user") Some("user")
) )
.await, .await,
@ -329,7 +329,7 @@ mod tests {
); );
assert_eq!( assert_eq!(
keyring keyring
.fetch(&DisplaySafeUrlRef::from(&url), Some("user")) .fetch(DisplaySafeUrlRef::from(&url), Some("user"))
.await, .await,
Some(Credentials::basic( Some(Credentials::basic(
Some("user".to_string()), Some("user".to_string()),
@ -339,7 +339,7 @@ mod tests {
assert_eq!( assert_eq!(
keyring keyring
.fetch( .fetch(
&DisplaySafeUrlRef::from(&url.join("bar").unwrap()), DisplaySafeUrlRef::from(&url.join("bar").unwrap()),
Some("user") Some("user")
) )
.await, .await,
@ -355,7 +355,7 @@ mod tests {
let url = Url::parse("https://example.com").unwrap(); let url = Url::parse("https://example.com").unwrap();
let keyring = KeyringProvider::dummy([(url.host_str().unwrap(), "user", "password")]); let keyring = KeyringProvider::dummy([(url.host_str().unwrap(), "user", "password")]);
let credentials = keyring let credentials = keyring
.fetch(&DisplaySafeUrlRef::from(&url), Some("user")) .fetch(DisplaySafeUrlRef::from(&url), Some("user"))
.await; .await;
assert_eq!( assert_eq!(
credentials, credentials,
@ -370,7 +370,7 @@ mod tests {
async fn fetch_url_no_username() { async fn fetch_url_no_username() {
let url = Url::parse("https://example.com").unwrap(); let url = Url::parse("https://example.com").unwrap();
let keyring = KeyringProvider::dummy([(url.host_str().unwrap(), "user", "password")]); let keyring = KeyringProvider::dummy([(url.host_str().unwrap(), "user", "password")]);
let credentials = keyring.fetch(&DisplaySafeUrlRef::from(&url), None).await; let credentials = keyring.fetch(DisplaySafeUrlRef::from(&url), None).await;
assert_eq!( assert_eq!(
credentials, credentials,
Some(Credentials::basic( Some(Credentials::basic(
@ -385,14 +385,14 @@ mod tests {
let url = Url::parse("https://example.com").unwrap(); let url = Url::parse("https://example.com").unwrap();
let keyring = KeyringProvider::dummy([(url.host_str().unwrap(), "foo", "password")]); let keyring = KeyringProvider::dummy([(url.host_str().unwrap(), "foo", "password")]);
let credentials = keyring let credentials = keyring
.fetch(&DisplaySafeUrlRef::from(&url), Some("bar")) .fetch(DisplaySafeUrlRef::from(&url), Some("bar"))
.await; .await;
assert_eq!(credentials, None); assert_eq!(credentials, None);
// Still fails if we have `foo` in the URL itself // Still fails if we have `foo` in the URL itself
let url = Url::parse("https://foo@example.com").unwrap(); let url = Url::parse("https://foo@example.com").unwrap();
let credentials = keyring let credentials = keyring
.fetch(&DisplaySafeUrlRef::from(&url), Some("bar")) .fetch(DisplaySafeUrlRef::from(&url), Some("bar"))
.await; .await;
assert_eq!(credentials, None); assert_eq!(credentials, None);
} }

View file

@ -508,7 +508,7 @@ impl AuthMiddleware {
debug!("Checking netrc for credentials for {url}"); debug!("Checking netrc for credentials for {url}");
Credentials::from_netrc( Credentials::from_netrc(
netrc, netrc,
&url, url,
credentials credentials
.as_ref() .as_ref()
.and_then(|credentials| credentials.username()), .and_then(|credentials| credentials.username()),
@ -529,17 +529,17 @@ impl AuthMiddleware {
if let Some(username) = credentials.and_then(|credentials| credentials.username()) { if let Some(username) = credentials.and_then(|credentials| credentials.username()) {
if let Some(index_url) = maybe_index_url { if let Some(index_url) = maybe_index_url {
debug!("Checking keyring for credentials for index URL {}@{}", username, index_url); debug!("Checking keyring for credentials for index URL {}@{}", username, index_url);
keyring.fetch(&DisplaySafeUrlRef::from(index_url), Some(username)).await keyring.fetch(DisplaySafeUrlRef::from(index_url), Some(username)).await
} else { } else {
debug!("Checking keyring for credentials for full URL {}@{}", username, url); debug!("Checking keyring for credentials for full URL {}@{}", username, url);
keyring.fetch(&url, Some(username)).await keyring.fetch(url, Some(username)).await
} }
} else if matches!(auth_policy, AuthPolicy::Always) { } else if matches!(auth_policy, AuthPolicy::Always) {
if let Some(index_url) = maybe_index_url { if let Some(index_url) = maybe_index_url {
debug!( debug!(
"Checking keyring for credentials for index URL {index_url} without username due to `authenticate = always`" "Checking keyring for credentials for index URL {index_url} without username due to `authenticate = always`"
); );
keyring.fetch(&DisplaySafeUrlRef::from(index_url), None).await keyring.fetch(DisplaySafeUrlRef::from(index_url), None).await
} else { } else {
None None
} }

View file

@ -279,7 +279,21 @@ mod tests {
insta::assert_debug_snapshot!(result, @r#" insta::assert_debug_snapshot!(result, @r#"
SimpleHtml { SimpleHtml {
base: BaseUrl( base: BaseUrl(
https://download.pytorch.org/whl/jinja2/, DisplaySafeUrl {
scheme: "https",
cannot_be_a_base: false,
username: "",
password: None,
host: Some(
Domain(
"download.pytorch.org",
),
),
port: None,
path: "/whl/jinja2/",
query: None,
fragment: None,
},
), ),
files: [ files: [
File { File {
@ -322,7 +336,21 @@ mod tests {
insta::assert_debug_snapshot!(result, @r#" insta::assert_debug_snapshot!(result, @r#"
SimpleHtml { SimpleHtml {
base: BaseUrl( base: BaseUrl(
https://download.pytorch.org/whl/jinja2/, DisplaySafeUrl {
scheme: "https",
cannot_be_a_base: false,
username: "",
password: None,
host: Some(
Domain(
"download.pytorch.org",
),
),
port: None,
path: "/whl/jinja2/",
query: None,
fragment: None,
},
), ),
files: [ files: [
File { File {
@ -368,7 +396,21 @@ mod tests {
insta::assert_debug_snapshot!(result, @r#" insta::assert_debug_snapshot!(result, @r#"
SimpleHtml { SimpleHtml {
base: BaseUrl( base: BaseUrl(
https://index.python.org/, DisplaySafeUrl {
scheme: "https",
cannot_be_a_base: false,
username: "",
password: None,
host: Some(
Domain(
"index.python.org",
),
),
port: None,
path: "/",
query: None,
fragment: None,
},
), ),
files: [ files: [
File { File {
@ -411,7 +453,21 @@ mod tests {
insta::assert_debug_snapshot!(result, @r#" insta::assert_debug_snapshot!(result, @r#"
SimpleHtml { SimpleHtml {
base: BaseUrl( base: BaseUrl(
https://download.pytorch.org/whl/jinja2/, DisplaySafeUrl {
scheme: "https",
cannot_be_a_base: false,
username: "",
password: None,
host: Some(
Domain(
"download.pytorch.org",
),
),
port: None,
path: "/whl/jinja2/",
query: None,
fragment: None,
},
), ),
files: [ files: [
File { File {
@ -454,7 +510,21 @@ mod tests {
insta::assert_debug_snapshot!(result, @r#" insta::assert_debug_snapshot!(result, @r#"
SimpleHtml { SimpleHtml {
base: BaseUrl( base: BaseUrl(
https://download.pytorch.org/whl/jinja2/, DisplaySafeUrl {
scheme: "https",
cannot_be_a_base: false,
username: "",
password: None,
host: Some(
Domain(
"download.pytorch.org",
),
),
port: None,
path: "/whl/jinja2/",
query: None,
fragment: None,
},
), ),
files: [ files: [
File { File {
@ -497,7 +567,21 @@ mod tests {
insta::assert_debug_snapshot!(result, @r#" insta::assert_debug_snapshot!(result, @r#"
SimpleHtml { SimpleHtml {
base: BaseUrl( base: BaseUrl(
https://download.pytorch.org/whl/jinja2/, DisplaySafeUrl {
scheme: "https",
cannot_be_a_base: false,
username: "",
password: None,
host: Some(
Domain(
"download.pytorch.org",
),
),
port: None,
path: "/whl/jinja2/",
query: None,
fragment: None,
},
), ),
files: [ files: [
File { File {
@ -538,7 +622,21 @@ mod tests {
insta::assert_debug_snapshot!(result, @r#" insta::assert_debug_snapshot!(result, @r#"
SimpleHtml { SimpleHtml {
base: BaseUrl( base: BaseUrl(
https://download.pytorch.org/whl/jinja2/, DisplaySafeUrl {
scheme: "https",
cannot_be_a_base: false,
username: "",
password: None,
host: Some(
Domain(
"download.pytorch.org",
),
),
port: None,
path: "/whl/jinja2/",
query: None,
fragment: None,
},
), ),
files: [ files: [
File { File {
@ -576,14 +674,28 @@ mod tests {
"; ";
let base = Url::parse("https://download.pytorch.org/whl/jinja2/").unwrap(); let base = Url::parse("https://download.pytorch.org/whl/jinja2/").unwrap();
let result = SimpleHtml::parse(text, &base).unwrap(); let result = SimpleHtml::parse(text, &base).unwrap();
insta::assert_debug_snapshot!(result, @r" insta::assert_debug_snapshot!(result, @r#"
SimpleHtml { SimpleHtml {
base: BaseUrl( base: BaseUrl(
https://download.pytorch.org/whl/jinja2/, DisplaySafeUrl {
scheme: "https",
cannot_be_a_base: false,
username: "",
password: None,
host: Some(
Domain(
"download.pytorch.org",
),
),
port: None,
path: "/whl/jinja2/",
query: None,
fragment: None,
},
), ),
files: [], files: [],
} }
"); "#);
} }
#[test] #[test]
@ -600,14 +712,28 @@ mod tests {
"#; "#;
let base = Url::parse("https://download.pytorch.org/whl/jinja2/").unwrap(); let base = Url::parse("https://download.pytorch.org/whl/jinja2/").unwrap();
let result = SimpleHtml::parse(text, &base).unwrap(); let result = SimpleHtml::parse(text, &base).unwrap();
insta::assert_debug_snapshot!(result, @r" insta::assert_debug_snapshot!(result, @r#"
SimpleHtml { SimpleHtml {
base: BaseUrl( base: BaseUrl(
https://download.pytorch.org/whl/jinja2/, DisplaySafeUrl {
scheme: "https",
cannot_be_a_base: false,
username: "",
password: None,
host: Some(
Domain(
"download.pytorch.org",
),
),
port: None,
path: "/whl/jinja2/",
query: None,
fragment: None,
},
), ),
files: [], files: [],
} }
"); "#);
} }
#[test] #[test]
@ -627,7 +753,21 @@ mod tests {
insta::assert_debug_snapshot!(result, @r#" insta::assert_debug_snapshot!(result, @r#"
SimpleHtml { SimpleHtml {
base: BaseUrl( base: BaseUrl(
https://download.pytorch.org/whl/jinja2/, DisplaySafeUrl {
scheme: "https",
cannot_be_a_base: false,
username: "",
password: None,
host: Some(
Domain(
"download.pytorch.org",
),
),
port: None,
path: "/whl/jinja2/",
query: None,
fragment: None,
},
), ),
files: [ files: [
File { File {
@ -668,7 +808,21 @@ mod tests {
insta::assert_debug_snapshot!(result, @r#" insta::assert_debug_snapshot!(result, @r#"
SimpleHtml { SimpleHtml {
base: BaseUrl( base: BaseUrl(
https://download.pytorch.org/whl/jinja2/, DisplaySafeUrl {
scheme: "https",
cannot_be_a_base: false,
username: "",
password: None,
host: Some(
Domain(
"download.pytorch.org",
),
),
port: None,
path: "/whl/jinja2/",
query: None,
fragment: None,
},
), ),
files: [ files: [
File { File {
@ -710,7 +864,21 @@ mod tests {
Ok( Ok(
SimpleHtml { SimpleHtml {
base: BaseUrl( base: BaseUrl(
https://download.pytorch.org/whl/jinja2/, DisplaySafeUrl {
scheme: "https",
cannot_be_a_base: false,
username: "",
password: None,
host: Some(
Domain(
"download.pytorch.org",
),
),
port: None,
path: "/whl/jinja2/",
query: None,
fragment: None,
},
), ),
files: [ files: [
File { File {
@ -753,7 +921,21 @@ mod tests {
Ok( Ok(
SimpleHtml { SimpleHtml {
base: BaseUrl( base: BaseUrl(
https://download.pytorch.org/whl/jinja2/, DisplaySafeUrl {
scheme: "https",
cannot_be_a_base: false,
username: "",
password: None,
host: Some(
Domain(
"download.pytorch.org",
),
),
port: None,
path: "/whl/jinja2/",
query: None,
fragment: None,
},
), ),
files: [ files: [
File { File {
@ -813,7 +995,21 @@ mod tests {
insta::assert_debug_snapshot!(result, @r#" insta::assert_debug_snapshot!(result, @r#"
SimpleHtml { SimpleHtml {
base: BaseUrl( base: BaseUrl(
https://storage.googleapis.com/jax-releases/jax_cuda_releases.html, DisplaySafeUrl {
scheme: "https",
cannot_be_a_base: false,
username: "",
password: None,
host: Some(
Domain(
"storage.googleapis.com",
),
),
port: None,
path: "/jax-releases/jax_cuda_releases.html",
query: None,
fragment: None,
},
), ),
files: [ files: [
File { File {
@ -881,7 +1077,21 @@ mod tests {
insta::assert_debug_snapshot!(result, @r#" insta::assert_debug_snapshot!(result, @r#"
SimpleHtml { SimpleHtml {
base: BaseUrl( base: BaseUrl(
https://account.d.codeartifact.us-west-2.amazonaws.com/pypi/shared-packages-pypi/simple/flask/, DisplaySafeUrl {
scheme: "https",
cannot_be_a_base: false,
username: "",
password: None,
host: Some(
Domain(
"account.d.codeartifact.us-west-2.amazonaws.com",
),
),
port: None,
path: "/pypi/shared-packages-pypi/simple/flask/",
query: None,
fragment: None,
},
), ),
files: [ files: [
File { File {
@ -970,7 +1180,21 @@ mod tests {
insta::assert_debug_snapshot!(result, @r#" insta::assert_debug_snapshot!(result, @r#"
SimpleHtml { SimpleHtml {
base: BaseUrl( base: BaseUrl(
https://download.pytorch.org/whl/jinja2/, DisplaySafeUrl {
scheme: "https",
cannot_be_a_base: false,
username: "",
password: None,
host: Some(
Domain(
"download.pytorch.org",
),
),
port: None,
path: "/whl/jinja2/",
query: None,
fragment: None,
},
), ),
files: [ files: [
File { File {
@ -1029,7 +1253,21 @@ mod tests {
insta::assert_debug_snapshot!(result, @r#" insta::assert_debug_snapshot!(result, @r#"
SimpleHtml { SimpleHtml {
base: BaseUrl( base: BaseUrl(
https://account.d.codeartifact.us-west-2.amazonaws.com/pypi/shared-packages-pypi/simple/flask/, DisplaySafeUrl {
scheme: "https",
cannot_be_a_base: false,
username: "",
password: None,
host: Some(
Domain(
"account.d.codeartifact.us-west-2.amazonaws.com",
),
),
port: None,
path: "/pypi/shared-packages-pypi/simple/flask/",
query: None,
fragment: None,
},
), ),
files: [ files: [
File { File {

View file

@ -76,10 +76,8 @@ impl VerbatimUrl {
let (path, fragment) = split_fragment(&path); let (path, fragment) = split_fragment(&path);
// Convert to a URL. // Convert to a URL.
let mut url = DisplaySafeUrl::from( let mut url = DisplaySafeUrl::from_file_path(path.clone())
Url::from_file_path(path.clone()) .map_err(|()| VerbatimUrlError::UrlConversion(path.to_path_buf()))?;
.map_err(|()| VerbatimUrlError::UrlConversion(path.to_path_buf()))?,
);
// Set the fragment, if it exists. // Set the fragment, if it exists.
if let Some(fragment) = fragment { if let Some(fragment) = fragment {
@ -338,7 +336,7 @@ impl Pep508Url for VerbatimUrl {
} }
fn displayable_with_credentials(&self) -> impl Display { fn displayable_with_credentials(&self) -> impl Display {
self.url.to_string_with_credentials() self.url.displayable_with_credentials()
} }
} }

View file

@ -1,5 +1,5 @@
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::fmt::Write; use std::fmt::{Debug, Display};
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
use std::str::FromStr; use std::str::FromStr;
use url::Url; use url::Url;
@ -90,10 +90,10 @@ impl DisplaySafeUrl {
let _ = self.0.set_password(None); let _ = self.0.set_password(None);
} }
/// Returns string representation without masking credentials. /// Returns [`Display`] implementation that doesn't mask credentials.
#[inline] #[inline]
pub fn to_string_with_credentials(&self) -> String { pub fn displayable_with_credentials(&self) -> impl Display {
self.0.to_string() &self.0
} }
} }
@ -111,15 +111,15 @@ impl DerefMut for DisplaySafeUrl {
} }
} }
impl std::fmt::Display for DisplaySafeUrl { impl Display for DisplaySafeUrl {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
fmt_with_obfuscated_credentials(&self.0, f) display_with_redacted_credentials(&self.0, f)
} }
} }
impl std::fmt::Debug for DisplaySafeUrl { impl Debug for DisplaySafeUrl {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{self}") debug_with_redacted_credentials(&self.0, f)
} }
} }
@ -143,7 +143,10 @@ impl FromStr for DisplaySafeUrl {
} }
} }
fn fmt_with_obfuscated_credentials<W: Write>(url: &Url, mut f: W) -> std::fmt::Result { fn display_with_redacted_credentials(
url: &Url,
f: &mut std::fmt::Formatter<'_>,
) -> std::fmt::Result {
if url.password().is_none() && url.username() == "" { if url.password().is_none() && url.username() == "" {
return write!(f, "{url}"); return write!(f, "{url}");
} }
@ -176,6 +179,30 @@ fn fmt_with_obfuscated_credentials<W: Write>(url: &Url, mut f: W) -> std::fmt::R
Ok(()) Ok(())
} }
fn debug_with_redacted_credentials(url: &Url, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let (username, password) = if url.username() != "" && url.password().is_some() {
(url.username(), Some("****"))
} else if url.username() != "" {
("****", None)
} else if url.password().is_some() {
("", Some("****"))
} else {
("", None)
};
f.debug_struct("DisplaySafeUrl")
.field("scheme", &url.scheme())
.field("cannot_be_a_base", &url.cannot_be_a_base())
.field("username", &username)
.field("password", &password)
.field("host", &url.host())
.field("port", &url.port())
.field("path", &url.path())
.field("query", &url.query())
.field("fragment", &url.fragment())
.finish()
}
/// A wrapper around a [`url::Url`] ref that safely handles credentials for /// A wrapper around a [`url::Url`] ref that safely handles credentials for
/// logging purposes. /// logging purposes.
/// ///
@ -198,6 +225,7 @@ fn fmt_with_obfuscated_credentials<W: Write>(url: &Url, mut f: W) -> std::fmt::R
/// // `Deref` implementation, you can still access the username and password /// // `Deref` implementation, you can still access the username and password
/// assert_eq!(url.username(), "user"); /// assert_eq!(url.username(), "user");
/// assert_eq!(url.password(), Some("password")); /// assert_eq!(url.password(), Some("password"));
#[derive(Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash)]
pub struct DisplaySafeUrlRef<'a>(&'a Url); pub struct DisplaySafeUrlRef<'a>(&'a Url);
impl<'a> Deref for DisplaySafeUrlRef<'a> { impl<'a> Deref for DisplaySafeUrlRef<'a> {
@ -208,15 +236,15 @@ impl<'a> Deref for DisplaySafeUrlRef<'a> {
} }
} }
impl std::fmt::Display for DisplaySafeUrlRef<'_> { impl Display for DisplaySafeUrlRef<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
fmt_with_obfuscated_credentials(self.0, f) display_with_redacted_credentials(self.0, f)
} }
} }
impl std::fmt::Debug for DisplaySafeUrlRef<'_> { impl Debug for DisplaySafeUrlRef<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{self}") debug_with_redacted_credentials(self.0, f)
} }
} }
@ -317,10 +345,13 @@ mod tests {
} }
#[test] #[test]
fn to_string_with_credentials() { fn displayable_with_credentials() {
let url_str = "https://user:pass@pypi-proxy.fly.dev/basic-auth/simple"; let url_str = "https://user:pass@pypi-proxy.fly.dev/basic-auth/simple";
let log_safe_url = DisplaySafeUrl::parse(url_str).unwrap(); let log_safe_url = DisplaySafeUrl::parse(url_str).unwrap();
assert_eq!(&log_safe_url.to_string_with_credentials(), url_str); assert_eq!(
&log_safe_url.displayable_with_credentials().to_string(),
url_str
);
} }
#[test] #[test]

View file

@ -2052,14 +2052,34 @@ mod test {
url: VerbatimParsedUrl { url: VerbatimParsedUrl {
parsed_url: Directory( parsed_url: Directory(
ParsedDirectoryUrl { ParsedDirectoryUrl {
url: file:///foo/bar, url: DisplaySafeUrl {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "/foo/bar",
query: None,
fragment: None,
},
install_path: "/foo/bar", install_path: "/foo/bar",
editable: true, editable: true,
virtual: false, virtual: false,
}, },
), ),
verbatim: VerbatimUrl { verbatim: VerbatimUrl {
url: file:///foo/bar, url: DisplaySafeUrl {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "/foo/bar",
query: None,
fragment: None,
},
given: Some( given: Some(
"/foo/bar", "/foo/bar",
), ),
@ -2315,7 +2335,21 @@ mod test {
editables: [], editables: [],
index_url: Some( index_url: Some(
VerbatimUrl { VerbatimUrl {
url: https://test.pypi.org/simple/, url: DisplaySafeUrl {
scheme: "https",
cannot_be_a_base: false,
username: "",
password: None,
host: Some(
Domain(
"test.pypi.org",
),
),
port: None,
path: "/simple/",
query: None,
fragment: None,
},
given: Some( given: Some(
"https://test.pypi.org/simple/", "https://test.pypi.org/simple/",
), ),
@ -2379,13 +2413,33 @@ mod test {
url: VerbatimParsedUrl { url: VerbatimParsedUrl {
parsed_url: Path( parsed_url: Path(
ParsedPathUrl { ParsedPathUrl {
url: file://<REQUIREMENTS_DIR>/importlib_metadata-8.3.0-py3-none-any.whl, url: DisplaySafeUrl {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "<REQUIREMENTS_DIR>/importlib_metadata-8.3.0-py3-none-any.whl",
query: None,
fragment: None,
},
install_path: "<REQUIREMENTS_DIR>/importlib_metadata-8.3.0-py3-none-any.whl", install_path: "<REQUIREMENTS_DIR>/importlib_metadata-8.3.0-py3-none-any.whl",
ext: Wheel, ext: Wheel,
}, },
), ),
verbatim: VerbatimUrl { verbatim: VerbatimUrl {
url: file://<REQUIREMENTS_DIR>/importlib_metadata-8.3.0-py3-none-any.whl, url: DisplaySafeUrl {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "<REQUIREMENTS_DIR>/importlib_metadata-8.3.0-py3-none-any.whl",
query: None,
fragment: None,
},
given: Some( given: Some(
"importlib_metadata-8.3.0-py3-none-any.whl", "importlib_metadata-8.3.0-py3-none-any.whl",
), ),
@ -2408,13 +2462,33 @@ mod test {
url: VerbatimParsedUrl { url: VerbatimParsedUrl {
parsed_url: Path( parsed_url: Path(
ParsedPathUrl { ParsedPathUrl {
url: file://<REQUIREMENTS_DIR>/importlib_metadata-8.2.0-py3-none-any.whl, url: DisplaySafeUrl {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "<REQUIREMENTS_DIR>/importlib_metadata-8.2.0-py3-none-any.whl",
query: None,
fragment: None,
},
install_path: "<REQUIREMENTS_DIR>/importlib_metadata-8.2.0-py3-none-any.whl", install_path: "<REQUIREMENTS_DIR>/importlib_metadata-8.2.0-py3-none-any.whl",
ext: Wheel, ext: Wheel,
}, },
), ),
verbatim: VerbatimUrl { verbatim: VerbatimUrl {
url: file://<REQUIREMENTS_DIR>/importlib_metadata-8.2.0-py3-none-any.whl, url: DisplaySafeUrl {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "<REQUIREMENTS_DIR>/importlib_metadata-8.2.0-py3-none-any.whl",
query: None,
fragment: None,
},
given: Some( given: Some(
"importlib_metadata-8.2.0-py3-none-any.whl", "importlib_metadata-8.2.0-py3-none-any.whl",
), ),
@ -2437,13 +2511,33 @@ mod test {
url: VerbatimParsedUrl { url: VerbatimParsedUrl {
parsed_url: Path( parsed_url: Path(
ParsedPathUrl { ParsedPathUrl {
url: file://<REQUIREMENTS_DIR>/importlib_metadata-8.2.0-py3-none-any.whl, url: DisplaySafeUrl {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "<REQUIREMENTS_DIR>/importlib_metadata-8.2.0-py3-none-any.whl",
query: None,
fragment: None,
},
install_path: "<REQUIREMENTS_DIR>/importlib_metadata-8.2.0-py3-none-any.whl", install_path: "<REQUIREMENTS_DIR>/importlib_metadata-8.2.0-py3-none-any.whl",
ext: Wheel, ext: Wheel,
}, },
), ),
verbatim: VerbatimUrl { verbatim: VerbatimUrl {
url: file://<REQUIREMENTS_DIR>/importlib_metadata-8.2.0-py3-none-any.whl, url: DisplaySafeUrl {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "<REQUIREMENTS_DIR>/importlib_metadata-8.2.0-py3-none-any.whl",
query: None,
fragment: None,
},
given: Some( given: Some(
"importlib_metadata-8.2.0-py3-none-any.whl", "importlib_metadata-8.2.0-py3-none-any.whl",
), ),
@ -2470,13 +2564,33 @@ mod test {
url: VerbatimParsedUrl { url: VerbatimParsedUrl {
parsed_url: Path( parsed_url: Path(
ParsedPathUrl { ParsedPathUrl {
url: file://<REQUIREMENTS_DIR>/importlib_metadata-8.2.0+local-py3-none-any.whl, url: DisplaySafeUrl {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "<REQUIREMENTS_DIR>/importlib_metadata-8.2.0+local-py3-none-any.whl",
query: None,
fragment: None,
},
install_path: "<REQUIREMENTS_DIR>/importlib_metadata-8.2.0+local-py3-none-any.whl", install_path: "<REQUIREMENTS_DIR>/importlib_metadata-8.2.0+local-py3-none-any.whl",
ext: Wheel, ext: Wheel,
}, },
), ),
verbatim: VerbatimUrl { verbatim: VerbatimUrl {
url: file://<REQUIREMENTS_DIR>/importlib_metadata-8.2.0+local-py3-none-any.whl, url: DisplaySafeUrl {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "<REQUIREMENTS_DIR>/importlib_metadata-8.2.0+local-py3-none-any.whl",
query: None,
fragment: None,
},
given: Some( given: Some(
"importlib_metadata-8.2.0+local-py3-none-any.whl", "importlib_metadata-8.2.0+local-py3-none-any.whl",
), ),
@ -2499,13 +2613,33 @@ mod test {
url: VerbatimParsedUrl { url: VerbatimParsedUrl {
parsed_url: Path( parsed_url: Path(
ParsedPathUrl { ParsedPathUrl {
url: file://<REQUIREMENTS_DIR>/importlib_metadata-8.2.0+local-py3-none-any.whl, url: DisplaySafeUrl {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "<REQUIREMENTS_DIR>/importlib_metadata-8.2.0+local-py3-none-any.whl",
query: None,
fragment: None,
},
install_path: "<REQUIREMENTS_DIR>/importlib_metadata-8.2.0+local-py3-none-any.whl", install_path: "<REQUIREMENTS_DIR>/importlib_metadata-8.2.0+local-py3-none-any.whl",
ext: Wheel, ext: Wheel,
}, },
), ),
verbatim: VerbatimUrl { verbatim: VerbatimUrl {
url: file://<REQUIREMENTS_DIR>/importlib_metadata-8.2.0+local-py3-none-any.whl, url: DisplaySafeUrl {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "<REQUIREMENTS_DIR>/importlib_metadata-8.2.0+local-py3-none-any.whl",
query: None,
fragment: None,
},
given: Some( given: Some(
"importlib_metadata-8.2.0+local-py3-none-any.whl", "importlib_metadata-8.2.0+local-py3-none-any.whl",
), ),
@ -2528,13 +2662,33 @@ mod test {
url: VerbatimParsedUrl { url: VerbatimParsedUrl {
parsed_url: Path( parsed_url: Path(
ParsedPathUrl { ParsedPathUrl {
url: file://<REQUIREMENTS_DIR>/importlib_metadata-8.2.0+local-py3-none-any.whl, url: DisplaySafeUrl {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "<REQUIREMENTS_DIR>/importlib_metadata-8.2.0+local-py3-none-any.whl",
query: None,
fragment: None,
},
install_path: "<REQUIREMENTS_DIR>/importlib_metadata-8.2.0+local-py3-none-any.whl", install_path: "<REQUIREMENTS_DIR>/importlib_metadata-8.2.0+local-py3-none-any.whl",
ext: Wheel, ext: Wheel,
}, },
), ),
verbatim: VerbatimUrl { verbatim: VerbatimUrl {
url: file://<REQUIREMENTS_DIR>/importlib_metadata-8.2.0+local-py3-none-any.whl, url: DisplaySafeUrl {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "<REQUIREMENTS_DIR>/importlib_metadata-8.2.0+local-py3-none-any.whl",
query: None,
fragment: None,
},
given: Some( given: Some(
"importlib_metadata-8.2.0+local-py3-none-any.whl", "importlib_metadata-8.2.0+local-py3-none-any.whl",
), ),

View file

@ -39,7 +39,21 @@ RequirementsTxt {
parsed_url: Git( parsed_url: Git(
ParsedGitUrl { ParsedGitUrl {
url: GitUrl { url: GitUrl {
repository: https://github.com/pandas-dev/pandas.git, repository: DisplaySafeUrl {
scheme: "https",
cannot_be_a_base: false,
username: "",
password: None,
host: Some(
Domain(
"github.com",
),
),
port: None,
path: "/pandas-dev/pandas.git",
query: None,
fragment: None,
},
reference: DefaultBranch, reference: DefaultBranch,
precise: None, precise: None,
}, },
@ -47,7 +61,21 @@ RequirementsTxt {
}, },
), ),
verbatim: VerbatimUrl { verbatim: VerbatimUrl {
url: git+https://github.com/pandas-dev/pandas.git, url: DisplaySafeUrl {
scheme: "git+https",
cannot_be_a_base: false,
username: "",
password: None,
host: Some(
Domain(
"github.com",
),
),
port: None,
path: "/pandas-dev/pandas.git",
query: None,
fragment: None,
},
given: Some( given: Some(
"git+https://github.com/pandas-dev/pandas.git", "git+https://github.com/pandas-dev/pandas.git",
), ),

View file

@ -10,14 +10,34 @@ RequirementsTxt {
url: VerbatimParsedUrl { url: VerbatimParsedUrl {
parsed_url: Directory( parsed_url: Directory(
ParsedDirectoryUrl { ParsedDirectoryUrl {
url: file://<REQUIREMENTS_DIR>/scripts/packages/black_editable, url: DisplaySafeUrl {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "<REQUIREMENTS_DIR>/scripts/packages/black_editable",
query: None,
fragment: None,
},
install_path: "<REQUIREMENTS_DIR>/scripts/packages/black_editable", install_path: "<REQUIREMENTS_DIR>/scripts/packages/black_editable",
editable: false, editable: false,
virtual: false, virtual: false,
}, },
), ),
verbatim: VerbatimUrl { verbatim: VerbatimUrl {
url: file://<REQUIREMENTS_DIR>/scripts/packages/black_editable, url: DisplaySafeUrl {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "<REQUIREMENTS_DIR>/scripts/packages/black_editable",
query: None,
fragment: None,
},
given: Some( given: Some(
"./scripts/packages/black_editable", "./scripts/packages/black_editable",
), ),
@ -40,14 +60,34 @@ RequirementsTxt {
url: VerbatimParsedUrl { url: VerbatimParsedUrl {
parsed_url: Directory( parsed_url: Directory(
ParsedDirectoryUrl { ParsedDirectoryUrl {
url: file://<REQUIREMENTS_DIR>/scripts/packages/black_editable, url: DisplaySafeUrl {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "<REQUIREMENTS_DIR>/scripts/packages/black_editable",
query: None,
fragment: None,
},
install_path: "<REQUIREMENTS_DIR>/scripts/packages/black_editable", install_path: "<REQUIREMENTS_DIR>/scripts/packages/black_editable",
editable: false, editable: false,
virtual: false, virtual: false,
}, },
), ),
verbatim: VerbatimUrl { verbatim: VerbatimUrl {
url: file://<REQUIREMENTS_DIR>/scripts/packages/black_editable, url: DisplaySafeUrl {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "<REQUIREMENTS_DIR>/scripts/packages/black_editable",
query: None,
fragment: None,
},
given: Some( given: Some(
"./scripts/packages/black_editable", "./scripts/packages/black_editable",
), ),
@ -74,14 +114,34 @@ RequirementsTxt {
url: VerbatimParsedUrl { url: VerbatimParsedUrl {
parsed_url: Directory( parsed_url: Directory(
ParsedDirectoryUrl { ParsedDirectoryUrl {
url: file:///scripts/packages/black_editable, url: DisplaySafeUrl {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "/scripts/packages/black_editable",
query: None,
fragment: None,
},
install_path: "/scripts/packages/black_editable", install_path: "/scripts/packages/black_editable",
editable: false, editable: false,
virtual: false, virtual: false,
}, },
), ),
verbatim: VerbatimUrl { verbatim: VerbatimUrl {
url: file:///scripts/packages/black_editable, url: DisplaySafeUrl {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "/scripts/packages/black_editable",
query: None,
fragment: None,
},
given: Some( given: Some(
"file:///scripts/packages/black_editable", "file:///scripts/packages/black_editable",
), ),
@ -104,14 +164,34 @@ RequirementsTxt {
url: VerbatimParsedUrl { url: VerbatimParsedUrl {
parsed_url: Directory( parsed_url: Directory(
ParsedDirectoryUrl { ParsedDirectoryUrl {
url: file://<REQUIREMENTS_DIR>/scripts/packages/black%20editable, url: DisplaySafeUrl {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "<REQUIREMENTS_DIR>/scripts/packages/black%20editable",
query: None,
fragment: None,
},
install_path: "<REQUIREMENTS_DIR>/scripts/packages/black editable", install_path: "<REQUIREMENTS_DIR>/scripts/packages/black editable",
editable: false, editable: false,
virtual: false, virtual: false,
}, },
), ),
verbatim: VerbatimUrl { verbatim: VerbatimUrl {
url: file://<REQUIREMENTS_DIR>/scripts/packages/black%20editable, url: DisplaySafeUrl {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "<REQUIREMENTS_DIR>/scripts/packages/black%20editable",
query: None,
fragment: None,
},
given: Some( given: Some(
"./scripts/packages/black editable", "./scripts/packages/black editable",
), ),
@ -134,14 +214,34 @@ RequirementsTxt {
url: VerbatimParsedUrl { url: VerbatimParsedUrl {
parsed_url: Directory( parsed_url: Directory(
ParsedDirectoryUrl { ParsedDirectoryUrl {
url: file://<REQUIREMENTS_DIR>/scripts/packages/black%20editable, url: DisplaySafeUrl {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "<REQUIREMENTS_DIR>/scripts/packages/black%20editable",
query: None,
fragment: None,
},
install_path: "<REQUIREMENTS_DIR>/scripts/packages/black editable", install_path: "<REQUIREMENTS_DIR>/scripts/packages/black editable",
editable: false, editable: false,
virtual: false, virtual: false,
}, },
), ),
verbatim: VerbatimUrl { verbatim: VerbatimUrl {
url: file://<REQUIREMENTS_DIR>/scripts/packages/black%20editable, url: DisplaySafeUrl {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "<REQUIREMENTS_DIR>/scripts/packages/black%20editable",
query: None,
fragment: None,
},
given: Some( given: Some(
"./scripts/packages/black editable", "./scripts/packages/black editable",
), ),
@ -164,14 +264,34 @@ RequirementsTxt {
url: VerbatimParsedUrl { url: VerbatimParsedUrl {
parsed_url: Directory( parsed_url: Directory(
ParsedDirectoryUrl { ParsedDirectoryUrl {
url: file://<REQUIREMENTS_DIR>/scripts/packages/black%20editable, url: DisplaySafeUrl {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "<REQUIREMENTS_DIR>/scripts/packages/black%20editable",
query: None,
fragment: None,
},
install_path: "<REQUIREMENTS_DIR>/scripts/packages/black editable", install_path: "<REQUIREMENTS_DIR>/scripts/packages/black editable",
editable: false, editable: false,
virtual: false, virtual: false,
}, },
), ),
verbatim: VerbatimUrl { verbatim: VerbatimUrl {
url: file://<REQUIREMENTS_DIR>/scripts/packages/black%20editable, url: DisplaySafeUrl {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "<REQUIREMENTS_DIR>/scripts/packages/black%20editable",
query: None,
fragment: None,
},
given: Some( given: Some(
"./scripts/packages/black editable", "./scripts/packages/black editable",
), ),

View file

@ -12,14 +12,34 @@ RequirementsTxt {
url: VerbatimParsedUrl { url: VerbatimParsedUrl {
parsed_url: Directory( parsed_url: Directory(
ParsedDirectoryUrl { ParsedDirectoryUrl {
url: file://<REQUIREMENTS_DIR>/editable, url: DisplaySafeUrl {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "<REQUIREMENTS_DIR>/editable",
query: None,
fragment: None,
},
install_path: "<REQUIREMENTS_DIR>/editable", install_path: "<REQUIREMENTS_DIR>/editable",
editable: true, editable: true,
virtual: false, virtual: false,
}, },
), ),
verbatim: VerbatimUrl { verbatim: VerbatimUrl {
url: file://<REQUIREMENTS_DIR>/editable, url: DisplaySafeUrl {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "<REQUIREMENTS_DIR>/editable",
query: None,
fragment: None,
},
given: Some( given: Some(
"./editable", "./editable",
), ),
@ -49,14 +69,34 @@ RequirementsTxt {
url: VerbatimParsedUrl { url: VerbatimParsedUrl {
parsed_url: Directory( parsed_url: Directory(
ParsedDirectoryUrl { ParsedDirectoryUrl {
url: file://<REQUIREMENTS_DIR>/editable, url: DisplaySafeUrl {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "<REQUIREMENTS_DIR>/editable",
query: None,
fragment: None,
},
install_path: "<REQUIREMENTS_DIR>/editable", install_path: "<REQUIREMENTS_DIR>/editable",
editable: true, editable: true,
virtual: false, virtual: false,
}, },
), ),
verbatim: VerbatimUrl { verbatim: VerbatimUrl {
url: file://<REQUIREMENTS_DIR>/editable, url: DisplaySafeUrl {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "<REQUIREMENTS_DIR>/editable",
query: None,
fragment: None,
},
given: Some( given: Some(
"./editable", "./editable",
), ),
@ -86,14 +126,34 @@ RequirementsTxt {
url: VerbatimParsedUrl { url: VerbatimParsedUrl {
parsed_url: Directory( parsed_url: Directory(
ParsedDirectoryUrl { ParsedDirectoryUrl {
url: file://<REQUIREMENTS_DIR>/editable, url: DisplaySafeUrl {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "<REQUIREMENTS_DIR>/editable",
query: None,
fragment: None,
},
install_path: "<REQUIREMENTS_DIR>/editable", install_path: "<REQUIREMENTS_DIR>/editable",
editable: true, editable: true,
virtual: false, virtual: false,
}, },
), ),
verbatim: VerbatimUrl { verbatim: VerbatimUrl {
url: file://<REQUIREMENTS_DIR>/editable, url: DisplaySafeUrl {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "<REQUIREMENTS_DIR>/editable",
query: None,
fragment: None,
},
given: Some( given: Some(
"./editable", "./editable",
), ),
@ -123,14 +183,34 @@ RequirementsTxt {
url: VerbatimParsedUrl { url: VerbatimParsedUrl {
parsed_url: Directory( parsed_url: Directory(
ParsedDirectoryUrl { ParsedDirectoryUrl {
url: file://<REQUIREMENTS_DIR>/editable, url: DisplaySafeUrl {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "<REQUIREMENTS_DIR>/editable",
query: None,
fragment: None,
},
install_path: "<REQUIREMENTS_DIR>/editable", install_path: "<REQUIREMENTS_DIR>/editable",
editable: true, editable: true,
virtual: false, virtual: false,
}, },
), ),
verbatim: VerbatimUrl { verbatim: VerbatimUrl {
url: file://<REQUIREMENTS_DIR>/editable, url: DisplaySafeUrl {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "<REQUIREMENTS_DIR>/editable",
query: None,
fragment: None,
},
given: Some( given: Some(
"./editable", "./editable",
), ),
@ -160,14 +240,34 @@ RequirementsTxt {
url: VerbatimParsedUrl { url: VerbatimParsedUrl {
parsed_url: Directory( parsed_url: Directory(
ParsedDirectoryUrl { ParsedDirectoryUrl {
url: file://<REQUIREMENTS_DIR>/editable, url: DisplaySafeUrl {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "<REQUIREMENTS_DIR>/editable",
query: None,
fragment: None,
},
install_path: "<REQUIREMENTS_DIR>/editable", install_path: "<REQUIREMENTS_DIR>/editable",
editable: true, editable: true,
virtual: false, virtual: false,
}, },
), ),
verbatim: VerbatimUrl { verbatim: VerbatimUrl {
url: file://<REQUIREMENTS_DIR>/editable, url: DisplaySafeUrl {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "<REQUIREMENTS_DIR>/editable",
query: None,
fragment: None,
},
given: Some( given: Some(
"./editable", "./editable",
), ),
@ -190,14 +290,34 @@ RequirementsTxt {
url: VerbatimParsedUrl { url: VerbatimParsedUrl {
parsed_url: Directory( parsed_url: Directory(
ParsedDirectoryUrl { ParsedDirectoryUrl {
url: file://<REQUIREMENTS_DIR>/editable[d, url: DisplaySafeUrl {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "<REQUIREMENTS_DIR>/editable[d",
query: None,
fragment: None,
},
install_path: "<REQUIREMENTS_DIR>/editable[d", install_path: "<REQUIREMENTS_DIR>/editable[d",
editable: true, editable: true,
virtual: false, virtual: false,
}, },
), ),
verbatim: VerbatimUrl { verbatim: VerbatimUrl {
url: file://<REQUIREMENTS_DIR>/editable[d, url: DisplaySafeUrl {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "<REQUIREMENTS_DIR>/editable[d",
query: None,
fragment: None,
},
given: Some( given: Some(
"./editable[d", "./editable[d",
), ),
@ -220,14 +340,34 @@ RequirementsTxt {
url: VerbatimParsedUrl { url: VerbatimParsedUrl {
parsed_url: Directory( parsed_url: Directory(
ParsedDirectoryUrl { ParsedDirectoryUrl {
url: file://<REQUIREMENTS_DIR>/editable, url: DisplaySafeUrl {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "<REQUIREMENTS_DIR>/editable",
query: None,
fragment: None,
},
install_path: "<REQUIREMENTS_DIR>/editable", install_path: "<REQUIREMENTS_DIR>/editable",
editable: true, editable: true,
virtual: false, virtual: false,
}, },
), ),
verbatim: VerbatimUrl { verbatim: VerbatimUrl {
url: file://<REQUIREMENTS_DIR>/editable, url: DisplaySafeUrl {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "<REQUIREMENTS_DIR>/editable",
query: None,
fragment: None,
},
given: Some( given: Some(
"./editable", "./editable",
), ),
@ -250,14 +390,34 @@ RequirementsTxt {
url: VerbatimParsedUrl { url: VerbatimParsedUrl {
parsed_url: Directory( parsed_url: Directory(
ParsedDirectoryUrl { ParsedDirectoryUrl {
url: file://<REQUIREMENTS_DIR>/editable, url: DisplaySafeUrl {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "<REQUIREMENTS_DIR>/editable",
query: None,
fragment: None,
},
install_path: "<REQUIREMENTS_DIR>/editable", install_path: "<REQUIREMENTS_DIR>/editable",
editable: true, editable: true,
virtual: false, virtual: false,
}, },
), ),
verbatim: VerbatimUrl { verbatim: VerbatimUrl {
url: file://<REQUIREMENTS_DIR>/editable, url: DisplaySafeUrl {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "<REQUIREMENTS_DIR>/editable",
query: None,
fragment: None,
},
given: Some( given: Some(
"./editable", "./editable",
), ),

View file

@ -39,7 +39,21 @@ RequirementsTxt {
parsed_url: Git( parsed_url: Git(
ParsedGitUrl { ParsedGitUrl {
url: GitUrl { url: GitUrl {
repository: https://github.com/pandas-dev/pandas.git, repository: DisplaySafeUrl {
scheme: "https",
cannot_be_a_base: false,
username: "",
password: None,
host: Some(
Domain(
"github.com",
),
),
port: None,
path: "/pandas-dev/pandas.git",
query: None,
fragment: None,
},
reference: DefaultBranch, reference: DefaultBranch,
precise: None, precise: None,
}, },
@ -47,7 +61,21 @@ RequirementsTxt {
}, },
), ),
verbatim: VerbatimUrl { verbatim: VerbatimUrl {
url: git+https://github.com/pandas-dev/pandas.git, url: DisplaySafeUrl {
scheme: "git+https",
cannot_be_a_base: false,
username: "",
password: None,
host: Some(
Domain(
"github.com",
),
),
port: None,
path: "/pandas-dev/pandas.git",
query: None,
fragment: None,
},
given: Some( given: Some(
"git+https://github.com/pandas-dev/pandas.git", "git+https://github.com/pandas-dev/pandas.git",
), ),

View file

@ -10,14 +10,34 @@ RequirementsTxt {
url: VerbatimParsedUrl { url: VerbatimParsedUrl {
parsed_url: Directory( parsed_url: Directory(
ParsedDirectoryUrl { ParsedDirectoryUrl {
url: file:///<REQUIREMENTS_DIR>/scripts/packages/black_editable, url: DisplaySafeUrl {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "/<REQUIREMENTS_DIR>/scripts/packages/black_editable",
query: None,
fragment: None,
},
install_path: "<REQUIREMENTS_DIR>/scripts/packages/black_editable", install_path: "<REQUIREMENTS_DIR>/scripts/packages/black_editable",
editable: false, editable: false,
virtual: false, virtual: false,
}, },
), ),
verbatim: VerbatimUrl { verbatim: VerbatimUrl {
url: file:///<REQUIREMENTS_DIR>/scripts/packages/black_editable, url: DisplaySafeUrl {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "/<REQUIREMENTS_DIR>/scripts/packages/black_editable",
query: None,
fragment: None,
},
given: Some( given: Some(
"./scripts/packages/black_editable", "./scripts/packages/black_editable",
), ),
@ -40,14 +60,34 @@ RequirementsTxt {
url: VerbatimParsedUrl { url: VerbatimParsedUrl {
parsed_url: Directory( parsed_url: Directory(
ParsedDirectoryUrl { ParsedDirectoryUrl {
url: file:///<REQUIREMENTS_DIR>/scripts/packages/black_editable, url: DisplaySafeUrl {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "/<REQUIREMENTS_DIR>/scripts/packages/black_editable",
query: None,
fragment: None,
},
install_path: "<REQUIREMENTS_DIR>/scripts/packages/black_editable", install_path: "<REQUIREMENTS_DIR>/scripts/packages/black_editable",
editable: false, editable: false,
virtual: false, virtual: false,
}, },
), ),
verbatim: VerbatimUrl { verbatim: VerbatimUrl {
url: file:///<REQUIREMENTS_DIR>/scripts/packages/black_editable, url: DisplaySafeUrl {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "/<REQUIREMENTS_DIR>/scripts/packages/black_editable",
query: None,
fragment: None,
},
given: Some( given: Some(
"./scripts/packages/black_editable", "./scripts/packages/black_editable",
), ),
@ -74,14 +114,34 @@ RequirementsTxt {
url: VerbatimParsedUrl { url: VerbatimParsedUrl {
parsed_url: Directory( parsed_url: Directory(
ParsedDirectoryUrl { ParsedDirectoryUrl {
url: file:///<REQUIREMENTS_DIR>/scripts/packages/black_editable, url: DisplaySafeUrl {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "/<REQUIREMENTS_DIR>/scripts/packages/black_editable",
query: None,
fragment: None,
},
install_path: "<REQUIREMENTS_DIR>/scripts/packages/black_editable", install_path: "<REQUIREMENTS_DIR>/scripts/packages/black_editable",
editable: false, editable: false,
virtual: false, virtual: false,
}, },
), ),
verbatim: VerbatimUrl { verbatim: VerbatimUrl {
url: file:///<REQUIREMENTS_DIR>/scripts/packages/black_editable, url: DisplaySafeUrl {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "/<REQUIREMENTS_DIR>/scripts/packages/black_editable",
query: None,
fragment: None,
},
given: Some( given: Some(
"file:///scripts/packages/black_editable", "file:///scripts/packages/black_editable",
), ),
@ -104,14 +164,34 @@ RequirementsTxt {
url: VerbatimParsedUrl { url: VerbatimParsedUrl {
parsed_url: Directory( parsed_url: Directory(
ParsedDirectoryUrl { ParsedDirectoryUrl {
url: file:///<REQUIREMENTS_DIR>/scripts/packages/black%20editable, url: DisplaySafeUrl {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "/<REQUIREMENTS_DIR>/scripts/packages/black%20editable",
query: None,
fragment: None,
},
install_path: "<REQUIREMENTS_DIR>/scripts/packages/black editable", install_path: "<REQUIREMENTS_DIR>/scripts/packages/black editable",
editable: false, editable: false,
virtual: false, virtual: false,
}, },
), ),
verbatim: VerbatimUrl { verbatim: VerbatimUrl {
url: file:///<REQUIREMENTS_DIR>/scripts/packages/black%20editable, url: DisplaySafeUrl {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "/<REQUIREMENTS_DIR>/scripts/packages/black%20editable",
query: None,
fragment: None,
},
given: Some( given: Some(
"./scripts/packages/black editable", "./scripts/packages/black editable",
), ),
@ -134,14 +214,34 @@ RequirementsTxt {
url: VerbatimParsedUrl { url: VerbatimParsedUrl {
parsed_url: Directory( parsed_url: Directory(
ParsedDirectoryUrl { ParsedDirectoryUrl {
url: file:///<REQUIREMENTS_DIR>/scripts/packages/black%20editable, url: DisplaySafeUrl {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "/<REQUIREMENTS_DIR>/scripts/packages/black%20editable",
query: None,
fragment: None,
},
install_path: "<REQUIREMENTS_DIR>/scripts/packages/black editable", install_path: "<REQUIREMENTS_DIR>/scripts/packages/black editable",
editable: false, editable: false,
virtual: false, virtual: false,
}, },
), ),
verbatim: VerbatimUrl { verbatim: VerbatimUrl {
url: file:///<REQUIREMENTS_DIR>/scripts/packages/black%20editable, url: DisplaySafeUrl {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "/<REQUIREMENTS_DIR>/scripts/packages/black%20editable",
query: None,
fragment: None,
},
given: Some( given: Some(
"./scripts/packages/black editable", "./scripts/packages/black editable",
), ),
@ -164,14 +264,34 @@ RequirementsTxt {
url: VerbatimParsedUrl { url: VerbatimParsedUrl {
parsed_url: Directory( parsed_url: Directory(
ParsedDirectoryUrl { ParsedDirectoryUrl {
url: file:///<REQUIREMENTS_DIR>/scripts/packages/black%20editable, url: DisplaySafeUrl {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "/<REQUIREMENTS_DIR>/scripts/packages/black%20editable",
query: None,
fragment: None,
},
install_path: "<REQUIREMENTS_DIR>/scripts/packages/black editable", install_path: "<REQUIREMENTS_DIR>/scripts/packages/black editable",
editable: false, editable: false,
virtual: false, virtual: false,
}, },
), ),
verbatim: VerbatimUrl { verbatim: VerbatimUrl {
url: file:///<REQUIREMENTS_DIR>/scripts/packages/black%20editable, url: DisplaySafeUrl {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "/<REQUIREMENTS_DIR>/scripts/packages/black%20editable",
query: None,
fragment: None,
},
given: Some( given: Some(
"./scripts/packages/black editable", "./scripts/packages/black editable",
), ),

View file

@ -12,14 +12,34 @@ RequirementsTxt {
url: VerbatimParsedUrl { url: VerbatimParsedUrl {
parsed_url: Directory( parsed_url: Directory(
ParsedDirectoryUrl { ParsedDirectoryUrl {
url: file:///<REQUIREMENTS_DIR>/editable, url: DisplaySafeUrl {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "/<REQUIREMENTS_DIR>/editable",
query: None,
fragment: None,
},
install_path: "<REQUIREMENTS_DIR>/editable", install_path: "<REQUIREMENTS_DIR>/editable",
editable: true, editable: true,
virtual: false, virtual: false,
}, },
), ),
verbatim: VerbatimUrl { verbatim: VerbatimUrl {
url: file:///<REQUIREMENTS_DIR>/editable, url: DisplaySafeUrl {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "/<REQUIREMENTS_DIR>/editable",
query: None,
fragment: None,
},
given: Some( given: Some(
"./editable", "./editable",
), ),
@ -49,14 +69,34 @@ RequirementsTxt {
url: VerbatimParsedUrl { url: VerbatimParsedUrl {
parsed_url: Directory( parsed_url: Directory(
ParsedDirectoryUrl { ParsedDirectoryUrl {
url: file:///<REQUIREMENTS_DIR>/editable, url: DisplaySafeUrl {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "/<REQUIREMENTS_DIR>/editable",
query: None,
fragment: None,
},
install_path: "<REQUIREMENTS_DIR>/editable", install_path: "<REQUIREMENTS_DIR>/editable",
editable: true, editable: true,
virtual: false, virtual: false,
}, },
), ),
verbatim: VerbatimUrl { verbatim: VerbatimUrl {
url: file:///<REQUIREMENTS_DIR>/editable, url: DisplaySafeUrl {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "/<REQUIREMENTS_DIR>/editable",
query: None,
fragment: None,
},
given: Some( given: Some(
"./editable", "./editable",
), ),
@ -86,14 +126,34 @@ RequirementsTxt {
url: VerbatimParsedUrl { url: VerbatimParsedUrl {
parsed_url: Directory( parsed_url: Directory(
ParsedDirectoryUrl { ParsedDirectoryUrl {
url: file:///<REQUIREMENTS_DIR>/editable, url: DisplaySafeUrl {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "/<REQUIREMENTS_DIR>/editable",
query: None,
fragment: None,
},
install_path: "<REQUIREMENTS_DIR>/editable", install_path: "<REQUIREMENTS_DIR>/editable",
editable: true, editable: true,
virtual: false, virtual: false,
}, },
), ),
verbatim: VerbatimUrl { verbatim: VerbatimUrl {
url: file:///<REQUIREMENTS_DIR>/editable, url: DisplaySafeUrl {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "/<REQUIREMENTS_DIR>/editable",
query: None,
fragment: None,
},
given: Some( given: Some(
"./editable", "./editable",
), ),
@ -123,14 +183,34 @@ RequirementsTxt {
url: VerbatimParsedUrl { url: VerbatimParsedUrl {
parsed_url: Directory( parsed_url: Directory(
ParsedDirectoryUrl { ParsedDirectoryUrl {
url: file:///<REQUIREMENTS_DIR>/editable, url: DisplaySafeUrl {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "/<REQUIREMENTS_DIR>/editable",
query: None,
fragment: None,
},
install_path: "<REQUIREMENTS_DIR>/editable", install_path: "<REQUIREMENTS_DIR>/editable",
editable: true, editable: true,
virtual: false, virtual: false,
}, },
), ),
verbatim: VerbatimUrl { verbatim: VerbatimUrl {
url: file:///<REQUIREMENTS_DIR>/editable, url: DisplaySafeUrl {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "/<REQUIREMENTS_DIR>/editable",
query: None,
fragment: None,
},
given: Some( given: Some(
"./editable", "./editable",
), ),
@ -160,14 +240,34 @@ RequirementsTxt {
url: VerbatimParsedUrl { url: VerbatimParsedUrl {
parsed_url: Directory( parsed_url: Directory(
ParsedDirectoryUrl { ParsedDirectoryUrl {
url: file:///<REQUIREMENTS_DIR>/editable, url: DisplaySafeUrl {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "/<REQUIREMENTS_DIR>/editable",
query: None,
fragment: None,
},
install_path: "<REQUIREMENTS_DIR>/editable", install_path: "<REQUIREMENTS_DIR>/editable",
editable: true, editable: true,
virtual: false, virtual: false,
}, },
), ),
verbatim: VerbatimUrl { verbatim: VerbatimUrl {
url: file:///<REQUIREMENTS_DIR>/editable, url: DisplaySafeUrl {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "/<REQUIREMENTS_DIR>/editable",
query: None,
fragment: None,
},
given: Some( given: Some(
"./editable", "./editable",
), ),
@ -190,14 +290,34 @@ RequirementsTxt {
url: VerbatimParsedUrl { url: VerbatimParsedUrl {
parsed_url: Directory( parsed_url: Directory(
ParsedDirectoryUrl { ParsedDirectoryUrl {
url: file:///<REQUIREMENTS_DIR>/editable[d, url: DisplaySafeUrl {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "/<REQUIREMENTS_DIR>/editable[d",
query: None,
fragment: None,
},
install_path: "<REQUIREMENTS_DIR>/editable[d", install_path: "<REQUIREMENTS_DIR>/editable[d",
editable: true, editable: true,
virtual: false, virtual: false,
}, },
), ),
verbatim: VerbatimUrl { verbatim: VerbatimUrl {
url: file:///<REQUIREMENTS_DIR>/editable[d, url: DisplaySafeUrl {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "/<REQUIREMENTS_DIR>/editable[d",
query: None,
fragment: None,
},
given: Some( given: Some(
"./editable[d", "./editable[d",
), ),
@ -220,14 +340,34 @@ RequirementsTxt {
url: VerbatimParsedUrl { url: VerbatimParsedUrl {
parsed_url: Directory( parsed_url: Directory(
ParsedDirectoryUrl { ParsedDirectoryUrl {
url: file:///<REQUIREMENTS_DIR>/editable, url: DisplaySafeUrl {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "/<REQUIREMENTS_DIR>/editable",
query: None,
fragment: None,
},
install_path: "<REQUIREMENTS_DIR>/editable", install_path: "<REQUIREMENTS_DIR>/editable",
editable: true, editable: true,
virtual: false, virtual: false,
}, },
), ),
verbatim: VerbatimUrl { verbatim: VerbatimUrl {
url: file:///<REQUIREMENTS_DIR>/editable, url: DisplaySafeUrl {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "/<REQUIREMENTS_DIR>/editable",
query: None,
fragment: None,
},
given: Some( given: Some(
"./editable", "./editable",
), ),
@ -250,14 +390,34 @@ RequirementsTxt {
url: VerbatimParsedUrl { url: VerbatimParsedUrl {
parsed_url: Directory( parsed_url: Directory(
ParsedDirectoryUrl { ParsedDirectoryUrl {
url: file:///<REQUIREMENTS_DIR>/editable, url: DisplaySafeUrl {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "/<REQUIREMENTS_DIR>/editable",
query: None,
fragment: None,
},
install_path: "<REQUIREMENTS_DIR>/editable", install_path: "<REQUIREMENTS_DIR>/editable",
editable: true, editable: true,
virtual: false, virtual: false,
}, },
), ),
verbatim: VerbatimUrl { verbatim: VerbatimUrl {
url: file:///<REQUIREMENTS_DIR>/editable, url: DisplaySafeUrl {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "/<REQUIREMENTS_DIR>/editable",
query: None,
fragment: None,
},
given: Some( given: Some(
"./editable", "./editable",
), ),

View file

@ -296,7 +296,7 @@ async fn gather_credentials(
if let Some(username) = &username { if let Some(username) = &username {
debug!("Fetching password from keyring"); debug!("Fetching password from keyring");
if let Some(keyring_password) = keyring_provider if let Some(keyring_password) = keyring_provider
.fetch(&DisplaySafeUrlRef::from(&publish_url), Some(username)) .fetch(DisplaySafeUrlRef::from(&publish_url), Some(username))
.await .await
.as_ref() .as_ref()
.and_then(|credentials| credentials.password()) .and_then(|credentials| credentials.password())

View file

@ -15811,7 +15811,7 @@ fn lock_explicit_default_index() -> Result<()> {
DEBUG No workspace root found, using project root DEBUG No workspace root found, using project root
DEBUG Ignoring existing lockfile due to mismatched requirements for: `project==0.1.0` DEBUG Ignoring existing lockfile due to mismatched requirements for: `project==0.1.0`
Requested: {Requirement { name: PackageName("anyio"), extras: [], groups: [], marker: true, source: Registry { specifier: VersionSpecifiers([]), index: None, conflict: None }, origin: None }} Requested: {Requirement { name: PackageName("anyio"), extras: [], groups: [], marker: true, source: Registry { specifier: VersionSpecifiers([]), index: None, conflict: None }, origin: None }}
Existing: {Requirement { name: PackageName("iniconfig"), extras: [], groups: [], marker: true, source: Registry { specifier: VersionSpecifiers([VersionSpecifier { operator: Equal, version: "2.0.0" }]), index: Some(IndexMetadata { url: Url(VerbatimUrl { url: https://test.pypi.org/simple, given: None }), format: Simple }), conflict: None }, origin: None }} Existing: {Requirement { name: PackageName("iniconfig"), extras: [], groups: [], marker: true, source: Registry { specifier: VersionSpecifiers([VersionSpecifier { operator: Equal, version: "2.0.0" }]), index: Some(IndexMetadata { url: Url(VerbatimUrl { url: DisplaySafeUrl { scheme: "https", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("test.pypi.org")), port: None, path: "/simple", query: None, fragment: None }, given: None }), format: Simple }), conflict: None }, origin: None }}
DEBUG Solving with installed Python version: 3.12.[X] DEBUG Solving with installed Python version: 3.12.[X]
DEBUG Solving with target Python version: >=3.12 DEBUG Solving with target Python version: >=3.12
DEBUG Adding direct dependency: project* DEBUG Adding direct dependency: project*

View file

@ -112,7 +112,21 @@ fn resolve_uv_toml() -> anyhow::Result<()> {
name: None, name: None,
url: Pypi( url: Pypi(
VerbatimUrl { VerbatimUrl {
url: https://pypi.org/simple, url: DisplaySafeUrl {
scheme: "https",
cannot_be_a_base: false,
username: "",
password: None,
host: Some(
Domain(
"pypi.org",
),
),
port: None,
path: "/simple",
query: None,
fragment: None,
},
given: Some( given: Some(
"https://pypi.org/simple", "https://pypi.org/simple",
), ),
@ -279,7 +293,21 @@ fn resolve_uv_toml() -> anyhow::Result<()> {
name: None, name: None,
url: Pypi( url: Pypi(
VerbatimUrl { VerbatimUrl {
url: https://pypi.org/simple, url: DisplaySafeUrl {
scheme: "https",
cannot_be_a_base: false,
username: "",
password: None,
host: Some(
Domain(
"pypi.org",
),
),
port: None,
path: "/simple",
query: None,
fragment: None,
},
given: Some( given: Some(
"https://pypi.org/simple", "https://pypi.org/simple",
), ),
@ -447,7 +475,21 @@ fn resolve_uv_toml() -> anyhow::Result<()> {
name: None, name: None,
url: Pypi( url: Pypi(
VerbatimUrl { VerbatimUrl {
url: https://pypi.org/simple, url: DisplaySafeUrl {
scheme: "https",
cannot_be_a_base: false,
username: "",
password: None,
host: Some(
Domain(
"pypi.org",
),
),
port: None,
path: "/simple",
query: None,
fragment: None,
},
given: Some( given: Some(
"https://pypi.org/simple", "https://pypi.org/simple",
), ),
@ -647,7 +689,21 @@ fn resolve_pyproject_toml() -> anyhow::Result<()> {
name: None, name: None,
url: Pypi( url: Pypi(
VerbatimUrl { VerbatimUrl {
url: https://pypi.org/simple, url: DisplaySafeUrl {
scheme: "https",
cannot_be_a_base: false,
username: "",
password: None,
host: Some(
Domain(
"pypi.org",
),
),
port: None,
path: "/simple",
query: None,
fragment: None,
},
given: Some( given: Some(
"https://pypi.org/simple", "https://pypi.org/simple",
), ),
@ -976,7 +1032,21 @@ fn resolve_pyproject_toml() -> anyhow::Result<()> {
name: None, name: None,
url: Pypi( url: Pypi(
VerbatimUrl { VerbatimUrl {
url: https://pypi.org/simple, url: DisplaySafeUrl {
scheme: "https",
cannot_be_a_base: false,
username: "",
password: None,
host: Some(
Domain(
"pypi.org",
),
),
port: None,
path: "/simple",
query: None,
fragment: None,
},
given: Some( given: Some(
"https://pypi.org/simple", "https://pypi.org/simple",
), ),
@ -1170,7 +1240,21 @@ fn resolve_index_url() -> anyhow::Result<()> {
name: None, name: None,
url: Pypi( url: Pypi(
VerbatimUrl { VerbatimUrl {
url: https://pypi.org/simple, url: DisplaySafeUrl {
scheme: "https",
cannot_be_a_base: false,
username: "",
password: None,
host: Some(
Domain(
"pypi.org",
),
),
port: None,
path: "/simple",
query: None,
fragment: None,
},
given: Some( given: Some(
"https://pypi.org/simple", "https://pypi.org/simple",
), ),
@ -1188,7 +1272,21 @@ fn resolve_index_url() -> anyhow::Result<()> {
name: None, name: None,
url: Url( url: Url(
VerbatimUrl { VerbatimUrl {
url: https://test.pypi.org/simple, url: DisplaySafeUrl {
scheme: "https",
cannot_be_a_base: false,
username: "",
password: None,
host: Some(
Domain(
"test.pypi.org",
),
),
port: None,
path: "/simple",
query: None,
fragment: None,
},
given: Some( given: Some(
"https://test.pypi.org/simple", "https://test.pypi.org/simple",
), ),
@ -1357,7 +1455,21 @@ fn resolve_index_url() -> anyhow::Result<()> {
name: None, name: None,
url: Url( url: Url(
VerbatimUrl { VerbatimUrl {
url: https://test.pypi.org/simple, url: DisplaySafeUrl {
scheme: "https",
cannot_be_a_base: false,
username: "",
password: None,
host: Some(
Domain(
"test.pypi.org",
),
),
port: None,
path: "/simple",
query: None,
fragment: None,
},
given: Some( given: Some(
"https://test.pypi.org/simple", "https://test.pypi.org/simple",
), ),
@ -1377,7 +1489,21 @@ fn resolve_index_url() -> anyhow::Result<()> {
name: None, name: None,
url: Pypi( url: Pypi(
VerbatimUrl { VerbatimUrl {
url: https://pypi.org/simple, url: DisplaySafeUrl {
scheme: "https",
cannot_be_a_base: false,
username: "",
password: None,
host: Some(
Domain(
"pypi.org",
),
),
port: None,
path: "/simple",
query: None,
fragment: None,
},
given: Some( given: Some(
"https://pypi.org/simple", "https://pypi.org/simple",
), ),
@ -1395,7 +1521,21 @@ fn resolve_index_url() -> anyhow::Result<()> {
name: None, name: None,
url: Url( url: Url(
VerbatimUrl { VerbatimUrl {
url: https://test.pypi.org/simple, url: DisplaySafeUrl {
scheme: "https",
cannot_be_a_base: false,
username: "",
password: None,
host: Some(
Domain(
"test.pypi.org",
),
),
port: None,
path: "/simple",
query: None,
fragment: None,
},
given: Some( given: Some(
"https://test.pypi.org/simple", "https://test.pypi.org/simple",
), ),
@ -1588,7 +1728,21 @@ fn resolve_find_links() -> anyhow::Result<()> {
name: None, name: None,
url: Url( url: Url(
VerbatimUrl { VerbatimUrl {
url: https://download.pytorch.org/whl/torch_stable.html, url: DisplaySafeUrl {
scheme: "https",
cannot_be_a_base: false,
username: "",
password: None,
host: Some(
Domain(
"download.pytorch.org",
),
),
port: None,
path: "/whl/torch_stable.html",
query: None,
fragment: None,
},
given: Some( given: Some(
"https://download.pytorch.org/whl/torch_stable.html", "https://download.pytorch.org/whl/torch_stable.html",
), ),
@ -1943,7 +2097,21 @@ fn resolve_top_level() -> anyhow::Result<()> {
name: None, name: None,
url: Url( url: Url(
VerbatimUrl { VerbatimUrl {
url: https://download.pytorch.org/whl, url: DisplaySafeUrl {
scheme: "https",
cannot_be_a_base: false,
username: "",
password: None,
host: Some(
Domain(
"download.pytorch.org",
),
),
port: None,
path: "/whl",
query: None,
fragment: None,
},
given: Some( given: Some(
"https://download.pytorch.org/whl", "https://download.pytorch.org/whl",
), ),
@ -1961,7 +2129,21 @@ fn resolve_top_level() -> anyhow::Result<()> {
name: None, name: None,
url: Url( url: Url(
VerbatimUrl { VerbatimUrl {
url: https://test.pypi.org/simple, url: DisplaySafeUrl {
scheme: "https",
cannot_be_a_base: false,
username: "",
password: None,
host: Some(
Domain(
"test.pypi.org",
),
),
port: None,
path: "/simple",
query: None,
fragment: None,
},
given: Some( given: Some(
"https://test.pypi.org/simple", "https://test.pypi.org/simple",
), ),
@ -2128,7 +2310,21 @@ fn resolve_top_level() -> anyhow::Result<()> {
name: None, name: None,
url: Url( url: Url(
VerbatimUrl { VerbatimUrl {
url: https://download.pytorch.org/whl, url: DisplaySafeUrl {
scheme: "https",
cannot_be_a_base: false,
username: "",
password: None,
host: Some(
Domain(
"download.pytorch.org",
),
),
port: None,
path: "/whl",
query: None,
fragment: None,
},
given: Some( given: Some(
"https://download.pytorch.org/whl", "https://download.pytorch.org/whl",
), ),
@ -2146,7 +2342,21 @@ fn resolve_top_level() -> anyhow::Result<()> {
name: None, name: None,
url: Url( url: Url(
VerbatimUrl { VerbatimUrl {
url: https://test.pypi.org/simple, url: DisplaySafeUrl {
scheme: "https",
cannot_be_a_base: false,
username: "",
password: None,
host: Some(
Domain(
"test.pypi.org",
),
),
port: None,
path: "/simple",
query: None,
fragment: None,
},
given: Some( given: Some(
"https://test.pypi.org/simple", "https://test.pypi.org/simple",
), ),
@ -3327,7 +3537,21 @@ fn resolve_both() -> anyhow::Result<()> {
name: None, name: None,
url: Pypi( url: Pypi(
VerbatimUrl { VerbatimUrl {
url: https://pypi.org/simple, url: DisplaySafeUrl {
scheme: "https",
cannot_be_a_base: false,
username: "",
password: None,
host: Some(
Domain(
"pypi.org",
),
),
port: None,
path: "/simple",
query: None,
fragment: None,
},
given: Some( given: Some(
"https://pypi.org/simple", "https://pypi.org/simple",
), ),
@ -3619,7 +3843,21 @@ fn resolve_config_file() -> anyhow::Result<()> {
name: None, name: None,
url: Pypi( url: Pypi(
VerbatimUrl { VerbatimUrl {
url: https://pypi.org/simple, url: DisplaySafeUrl {
scheme: "https",
cannot_be_a_base: false,
username: "",
password: None,
host: Some(
Domain(
"pypi.org",
),
),
port: None,
path: "/simple",
query: None,
fragment: None,
},
given: Some( given: Some(
"https://pypi.org/simple", "https://pypi.org/simple",
), ),
@ -4391,7 +4629,21 @@ fn index_priority() -> anyhow::Result<()> {
name: None, name: None,
url: Url( url: Url(
VerbatimUrl { VerbatimUrl {
url: https://cli.pypi.org/simple, url: DisplaySafeUrl {
scheme: "https",
cannot_be_a_base: false,
username: "",
password: None,
host: Some(
Domain(
"cli.pypi.org",
),
),
port: None,
path: "/simple",
query: None,
fragment: None,
},
given: Some( given: Some(
"https://cli.pypi.org/simple", "https://cli.pypi.org/simple",
), ),
@ -4411,7 +4663,21 @@ fn index_priority() -> anyhow::Result<()> {
name: None, name: None,
url: Url( url: Url(
VerbatimUrl { VerbatimUrl {
url: https://file.pypi.org/simple, url: DisplaySafeUrl {
scheme: "https",
cannot_be_a_base: false,
username: "",
password: None,
host: Some(
Domain(
"file.pypi.org",
),
),
port: None,
path: "/simple",
query: None,
fragment: None,
},
given: Some( given: Some(
"https://file.pypi.org/simple", "https://file.pypi.org/simple",
), ),
@ -4578,7 +4844,21 @@ fn index_priority() -> anyhow::Result<()> {
name: None, name: None,
url: Url( url: Url(
VerbatimUrl { VerbatimUrl {
url: https://cli.pypi.org/simple, url: DisplaySafeUrl {
scheme: "https",
cannot_be_a_base: false,
username: "",
password: None,
host: Some(
Domain(
"cli.pypi.org",
),
),
port: None,
path: "/simple",
query: None,
fragment: None,
},
given: Some( given: Some(
"https://cli.pypi.org/simple", "https://cli.pypi.org/simple",
), ),
@ -4598,7 +4878,21 @@ fn index_priority() -> anyhow::Result<()> {
name: None, name: None,
url: Url( url: Url(
VerbatimUrl { VerbatimUrl {
url: https://file.pypi.org/simple, url: DisplaySafeUrl {
scheme: "https",
cannot_be_a_base: false,
username: "",
password: None,
host: Some(
Domain(
"file.pypi.org",
),
),
port: None,
path: "/simple",
query: None,
fragment: None,
},
given: Some( given: Some(
"https://file.pypi.org/simple", "https://file.pypi.org/simple",
), ),
@ -4771,7 +5065,21 @@ fn index_priority() -> anyhow::Result<()> {
name: None, name: None,
url: Url( url: Url(
VerbatimUrl { VerbatimUrl {
url: https://cli.pypi.org/simple, url: DisplaySafeUrl {
scheme: "https",
cannot_be_a_base: false,
username: "",
password: None,
host: Some(
Domain(
"cli.pypi.org",
),
),
port: None,
path: "/simple",
query: None,
fragment: None,
},
given: Some( given: Some(
"https://cli.pypi.org/simple", "https://cli.pypi.org/simple",
), ),
@ -4791,7 +5099,21 @@ fn index_priority() -> anyhow::Result<()> {
name: None, name: None,
url: Url( url: Url(
VerbatimUrl { VerbatimUrl {
url: https://file.pypi.org/simple, url: DisplaySafeUrl {
scheme: "https",
cannot_be_a_base: false,
username: "",
password: None,
host: Some(
Domain(
"file.pypi.org",
),
),
port: None,
path: "/simple",
query: None,
fragment: None,
},
given: Some( given: Some(
"https://file.pypi.org/simple", "https://file.pypi.org/simple",
), ),
@ -4959,7 +5281,21 @@ fn index_priority() -> anyhow::Result<()> {
name: None, name: None,
url: Url( url: Url(
VerbatimUrl { VerbatimUrl {
url: https://cli.pypi.org/simple, url: DisplaySafeUrl {
scheme: "https",
cannot_be_a_base: false,
username: "",
password: None,
host: Some(
Domain(
"cli.pypi.org",
),
),
port: None,
path: "/simple",
query: None,
fragment: None,
},
given: Some( given: Some(
"https://cli.pypi.org/simple", "https://cli.pypi.org/simple",
), ),
@ -4979,7 +5315,21 @@ fn index_priority() -> anyhow::Result<()> {
name: None, name: None,
url: Url( url: Url(
VerbatimUrl { VerbatimUrl {
url: https://file.pypi.org/simple, url: DisplaySafeUrl {
scheme: "https",
cannot_be_a_base: false,
username: "",
password: None,
host: Some(
Domain(
"file.pypi.org",
),
),
port: None,
path: "/simple",
query: None,
fragment: None,
},
given: Some( given: Some(
"https://file.pypi.org/simple", "https://file.pypi.org/simple",
), ),
@ -5154,7 +5504,21 @@ fn index_priority() -> anyhow::Result<()> {
name: None, name: None,
url: Url( url: Url(
VerbatimUrl { VerbatimUrl {
url: https://cli.pypi.org/simple, url: DisplaySafeUrl {
scheme: "https",
cannot_be_a_base: false,
username: "",
password: None,
host: Some(
Domain(
"cli.pypi.org",
),
),
port: None,
path: "/simple",
query: None,
fragment: None,
},
given: Some( given: Some(
"https://cli.pypi.org/simple", "https://cli.pypi.org/simple",
), ),
@ -5174,7 +5538,21 @@ fn index_priority() -> anyhow::Result<()> {
name: None, name: None,
url: Url( url: Url(
VerbatimUrl { VerbatimUrl {
url: https://file.pypi.org/simple, url: DisplaySafeUrl {
scheme: "https",
cannot_be_a_base: false,
username: "",
password: None,
host: Some(
Domain(
"file.pypi.org",
),
),
port: None,
path: "/simple",
query: None,
fragment: None,
},
given: Some( given: Some(
"https://file.pypi.org/simple", "https://file.pypi.org/simple",
), ),
@ -5342,7 +5720,21 @@ fn index_priority() -> anyhow::Result<()> {
name: None, name: None,
url: Url( url: Url(
VerbatimUrl { VerbatimUrl {
url: https://cli.pypi.org/simple, url: DisplaySafeUrl {
scheme: "https",
cannot_be_a_base: false,
username: "",
password: None,
host: Some(
Domain(
"cli.pypi.org",
),
),
port: None,
path: "/simple",
query: None,
fragment: None,
},
given: Some( given: Some(
"https://cli.pypi.org/simple", "https://cli.pypi.org/simple",
), ),
@ -5362,7 +5754,21 @@ fn index_priority() -> anyhow::Result<()> {
name: None, name: None,
url: Url( url: Url(
VerbatimUrl { VerbatimUrl {
url: https://file.pypi.org/simple, url: DisplaySafeUrl {
scheme: "https",
cannot_be_a_base: false,
username: "",
password: None,
host: Some(
Domain(
"file.pypi.org",
),
),
port: None,
path: "/simple",
query: None,
fragment: None,
},
given: Some( given: Some(
"https://file.pypi.org/simple", "https://file.pypi.org/simple",
), ),